version 1.160, 2016/06/10 13:31:44 |
version 1.168, 2016/09/07 15:41:44 |
Line 87 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 87 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <sys/proc.h> |
#include <sys/proc.h> |
#include <sys/sysctl.h> |
#include <sys/sysctl.h> |
#include <sys/cprng.h> |
#include <sys/cprng.h> |
|
#include <sys/percpu.h> |
|
|
#include <net/if.h> |
#include <net/if.h> |
#include <net/if_types.h> |
#include <net/if_types.h> |
Line 133 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 134 __KERNEL_RCSID(0, "$NetBSD$"); |
|
extern struct domain inet6domain; |
extern struct domain inet6domain; |
|
|
u_char ip6_protox[IPPROTO_MAX]; |
u_char ip6_protox[IPPROTO_MAX]; |
struct in6_ifaddr *in6_ifaddr; |
|
pktqueue_t *ip6_pktq __read_mostly; |
pktqueue_t *ip6_pktq __read_mostly; |
|
|
int ip6_forward_srcrt; /* XXX */ |
int ip6_forward_srcrt; /* XXX */ |
Line 144 pfil_head_t *inet6_pfil_hook; |
|
Line 144 pfil_head_t *inet6_pfil_hook; |
|
|
|
percpu_t *ip6stat_percpu; |
percpu_t *ip6stat_percpu; |
|
|
|
percpu_t *ip6_forward_rt_percpu __cacheline_aligned; |
|
|
static void ip6_init2(void); |
static void ip6_init2(void); |
static void ip6intr(void *); |
static void ip6intr(void *); |
static struct m_tag *ip6_setdstifaddr(struct mbuf *, const struct in6_ifaddr *); |
static struct m_tag *ip6_setdstifaddr(struct mbuf *, const struct in6_ifaddr *); |
|
|
const struct ip6protosw *pr; |
const struct ip6protosw *pr; |
int i; |
int i; |
|
|
|
in6_init(); |
|
|
sysctl_net_inet6_ip6_setup(NULL); |
sysctl_net_inet6_ip6_setup(NULL); |
pr = (const struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW); |
pr = (const struct ip6protosw *)pffindproto(PF_INET6, IPPROTO_RAW, SOCK_RAW); |
if (pr == 0) |
if (pr == 0) |
|
|
KASSERT(inet6_pfil_hook != NULL); |
KASSERT(inet6_pfil_hook != NULL); |
|
|
ip6stat_percpu = percpu_alloc(sizeof(uint64_t) * IP6_NSTATS); |
ip6stat_percpu = percpu_alloc(sizeof(uint64_t) * IP6_NSTATS); |
|
|
|
ip6_forward_rt_percpu = percpu_alloc(sizeof(struct route)); |
|
if (ip6_forward_rt_percpu == NULL) |
|
panic("failed to alllocate ip6_forward_rt_percpu"); |
} |
} |
|
|
static void |
static void |
Line 238 ip6intr(void *arg __unused) |
|
Line 246 ip6intr(void *arg __unused) |
|
mutex_exit(softnet_lock); |
mutex_exit(softnet_lock); |
} |
} |
|
|
extern struct route ip6_forward_rt; |
|
|
|
void |
void |
ip6_input(struct mbuf *m, struct ifnet *rcvif) |
ip6_input(struct mbuf *m, struct ifnet *rcvif) |
{ |
{ |
Line 255 ip6_input(struct mbuf *m, struct ifnet * |
|
Line 261 ip6_input(struct mbuf *m, struct ifnet * |
|
struct sockaddr dst; |
struct sockaddr dst; |
struct sockaddr_in6 dst6; |
struct sockaddr_in6 dst6; |
} u; |
} u; |
|
struct route *ro; |
|
|
/* |
/* |
* make sure we don't have onion peering information into m_tag. |
* make sure we don't have onion peering information into m_tag. |
Line 460 ip6_input(struct mbuf *m, struct ifnet * |
|
Line 467 ip6_input(struct mbuf *m, struct ifnet * |
|
/* |
/* |
* Unicast check |
* Unicast check |
*/ |
*/ |
rt = rtcache_lookup2(&ip6_forward_rt, &u.dst, 1, &hit); |
ro = percpu_getref(ip6_forward_rt_percpu); |
|
rt = rtcache_lookup2(ro, &u.dst, 1, &hit); |
|
percpu_putref(ip6_forward_rt_percpu); |
if (hit) |
if (hit) |
IP6_STATINC(IP6_STAT_FORWARD_CACHEHIT); |
IP6_STATINC(IP6_STAT_FORWARD_CACHEHIT); |
else |
else |
Line 495 ip6_input(struct mbuf *m, struct ifnet * |
|
Line 504 ip6_input(struct mbuf *m, struct ifnet * |
|
* packets to a tentative, duplicated, or somehow invalid |
* packets to a tentative, duplicated, or somehow invalid |
* address must not be accepted. |
* address must not be accepted. |
*/ |
*/ |
if (!(ia6->ia6_flags & IN6_IFF_NOTREADY)) { |
if (!(ia6->ia6_flags & (IN6_IFF_NOTREADY | IN6_IFF_DETACHED))) { |
/* this address is ready */ |
/* this address is ready */ |
ours = 1; |
ours = 1; |
deliverifp = ia6->ia_ifp; /* correct? */ |
deliverifp = ia6->ia_ifp; /* correct? */ |
Line 533 ip6_input(struct mbuf *m, struct ifnet * |
|
Line 542 ip6_input(struct mbuf *m, struct ifnet * |
|
* working right. |
* working right. |
*/ |
*/ |
struct ifaddr *ifa; |
struct ifaddr *ifa; |
IFADDR_FOREACH(ifa, rcvif) { |
IFADDR_READER_FOREACH(ifa, rcvif) { |
if (ifa->ifa_addr == NULL) |
|
continue; /* just for safety */ |
|
if (ifa->ifa_addr->sa_family != AF_INET6) |
if (ifa->ifa_addr->sa_family != AF_INET6) |
continue; |
continue; |
if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &ip6->ip6_dst)) { |
if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa), &ip6->ip6_dst)) { |
Line 566 ip6_input(struct mbuf *m, struct ifnet * |
|
Line 573 ip6_input(struct mbuf *m, struct ifnet * |
|
*/ |
*/ |
if (deliverifp && ip6_getdstifaddr(m) == NULL) { |
if (deliverifp && ip6_getdstifaddr(m) == NULL) { |
struct in6_ifaddr *ia6; |
struct in6_ifaddr *ia6; |
|
int s = pserialize_read_enter(); |
|
|
ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst); |
ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst); |
|
/* Depends on ip6_setdstifaddr never sleep */ |
if (ia6 != NULL && ip6_setdstifaddr(m, ia6) == NULL) { |
if (ia6 != NULL && ip6_setdstifaddr(m, ia6) == NULL) { |
/* |
/* |
* XXX maybe we should drop the packet here, |
* XXX maybe we should drop the packet here, |
Line 575 ip6_input(struct mbuf *m, struct ifnet * |
|
Line 584 ip6_input(struct mbuf *m, struct ifnet * |
|
* to the upper layers. |
* to the upper layers. |
*/ |
*/ |
} |
} |
|
pserialize_read_exit(s); |
} |
} |
|
|
/* |
/* |
Line 702 ip6_input(struct mbuf *m, struct ifnet * |
|
Line 712 ip6_input(struct mbuf *m, struct ifnet * |
|
#ifdef IFA_STATS |
#ifdef IFA_STATS |
if (deliverifp != NULL) { |
if (deliverifp != NULL) { |
struct in6_ifaddr *ia6; |
struct in6_ifaddr *ia6; |
|
int s = pserialize_read_enter(); |
ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst); |
ia6 = in6_ifawithifp(deliverifp, &ip6->ip6_dst); |
if (ia6) |
if (ia6) |
ia6->ia_ifa.ifa_data.ifad_inbytes += m->m_pkthdr.len; |
ia6->ia_ifa.ifa_data.ifad_inbytes += m->m_pkthdr.len; |
|
pserialize_read_exit(s); |
} |
} |
#endif |
#endif |
IP6_STATINC(IP6_STAT_DELIVERED); |
IP6_STATINC(IP6_STAT_DELIVERED); |
Line 1526 ip6_delaux(struct mbuf *m) |
|
Line 1538 ip6_delaux(struct mbuf *m) |
|
m_tag_delete(m, mtag); |
m_tag_delete(m, mtag); |
} |
} |
|
|
#ifdef GATEWAY |
|
/* |
|
* sysctl helper routine for net.inet.ip6.maxflows. Since |
|
* we could reduce this value, call ip6flow_reap(); |
|
*/ |
|
static int |
|
sysctl_net_inet6_ip6_maxflows(SYSCTLFN_ARGS) |
|
{ |
|
int error; |
|
|
|
error = sysctl_lookup(SYSCTLFN_CALL(rnode)); |
|
if (error || newp == NULL) |
|
return (error); |
|
|
|
mutex_enter(softnet_lock); |
|
KERNEL_LOCK(1, NULL); |
|
|
|
ip6flow_reap(0); |
|
|
|
KERNEL_UNLOCK_ONE(NULL); |
|
mutex_exit(softnet_lock); |
|
|
|
return (0); |
|
} |
|
|
|
static int |
|
sysctl_net_inet6_ip6_hashsize(SYSCTLFN_ARGS) |
|
{ |
|
int error, tmp; |
|
struct sysctlnode node; |
|
|
|
node = *rnode; |
|
tmp = ip6_hashsize; |
|
node.sysctl_data = &tmp; |
|
error = sysctl_lookup(SYSCTLFN_CALL(&node)); |
|
if (error || newp == NULL) |
|
return (error); |
|
|
|
if ((tmp & (tmp - 1)) == 0 && tmp != 0) { |
|
/* |
|
* Can only fail due to malloc() |
|
*/ |
|
mutex_enter(softnet_lock); |
|
KERNEL_LOCK(1, NULL); |
|
|
|
error = ip6flow_invalidate_all(tmp); |
|
|
|
KERNEL_UNLOCK_ONE(NULL); |
|
mutex_exit(softnet_lock); |
|
} else { |
|
/* |
|
* EINVAL if not a power of 2 |
|
*/ |
|
error = EINVAL; |
|
} |
|
|
|
return error; |
|
} |
|
#endif /* GATEWAY */ |
|
|
|
/* |
/* |
* System control for IP6 |
* System control for IP6 |
*/ |
*/ |
Line 1904 sysctl_net_inet6_ip6_setup(struct sysctl |
|
Line 1856 sysctl_net_inet6_ip6_setup(struct sysctl |
|
NULL, 0, &ip6_mcast_pmtu, 0, |
NULL, 0, &ip6_mcast_pmtu, 0, |
CTL_NET, PF_INET6, IPPROTO_IPV6, |
CTL_NET, PF_INET6, IPPROTO_IPV6, |
CTL_CREATE, CTL_EOL); |
CTL_CREATE, CTL_EOL); |
#ifdef GATEWAY |
|
sysctl_createv(clog, 0, NULL, NULL, |
|
CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
|
CTLTYPE_INT, "maxflows", |
|
SYSCTL_DESCR("Number of flows for fast forwarding (IPv6)"), |
|
sysctl_net_inet6_ip6_maxflows, 0, &ip6_maxflows, 0, |
|
CTL_NET, PF_INET6, IPPROTO_IPV6, |
|
CTL_CREATE, CTL_EOL); |
|
sysctl_createv(clog, 0, NULL, NULL, |
|
CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
|
CTLTYPE_INT, "hashsize", |
|
SYSCTL_DESCR("Size of hash table for fast forwarding (IPv6)"), |
|
sysctl_net_inet6_ip6_hashsize, 0, &ip6_hashsize, 0, |
|
CTL_NET, PF_INET6, IPPROTO_IPV6, |
|
CTL_CREATE, CTL_EOL); |
|
#endif |
|
/* anonportalgo RFC6056 subtree */ |
/* anonportalgo RFC6056 subtree */ |
const struct sysctlnode *portalgo_node; |
const struct sysctlnode *portalgo_node; |
sysctl_createv(clog, 0, NULL, &portalgo_node, |
sysctl_createv(clog, 0, NULL, &portalgo_node, |