| version 1.118, 2008/04/24 11:38:38 |
version 1.118.2.3, 2010/03/11 15:04:29 |
|
|
| #include <sys/cdefs.h> |
#include <sys/cdefs.h> |
| __KERNEL_RCSID(0, "$NetBSD$"); |
__KERNEL_RCSID(0, "$NetBSD$"); |
| |
|
| |
#include "opt_gateway.h" |
| #include "opt_inet.h" |
#include "opt_inet.h" |
| #include "opt_inet6.h" |
#include "opt_inet6.h" |
| #include "opt_ipsec.h" |
#include "opt_ipsec.h" |
| #include "opt_pfil_hooks.h" |
#include "opt_pfil_hooks.h" |
| |
#include "opt_compat_netbsd.h" |
| |
|
| #include <sys/param.h> |
#include <sys/param.h> |
| #include <sys/systm.h> |
#include <sys/systm.h> |
| Line 120 __KERNEL_RCSID(0, "$NetBSD$"); |
|
| Line 122 __KERNEL_RCSID(0, "$NetBSD$"); |
|
| #include <netipsec/key.h> |
#include <netipsec/key.h> |
| #endif /* FAST_IPSEC */ |
#endif /* FAST_IPSEC */ |
| |
|
| |
#ifdef COMPAT_50 |
| |
#include <compat/sys/time.h> |
| |
#include <compat/sys/socket.h> |
| |
#endif |
| |
|
| #include <netinet6/ip6protosw.h> |
#include <netinet6/ip6protosw.h> |
| |
|
| #include "faith.h" |
#include "faith.h" |
| Line 155 static struct m_tag *ip6_setdstifaddr(st |
|
| Line 162 static struct m_tag *ip6_setdstifaddr(st |
|
| |
|
| static int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *); |
static int ip6_hopopts_input(u_int32_t *, u_int32_t *, struct mbuf **, int *); |
| static struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int); |
static struct mbuf *ip6_pullexthdr(struct mbuf *, size_t, int); |
| |
static void sysctl_net_inet6_ip6_setup(struct sysctllog **); |
| |
|
| /* |
/* |
| * IP6 initialization: fill in IP6 protocol switch table. |
* IP6 initialization: fill in IP6 protocol switch table. |
|
|
| const struct ip6protosw *pr; |
const struct ip6protosw *pr; |
| int i; |
int i; |
| |
|
| |
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) |
| panic("ip6_init"); |
panic("ip6_init"); |
| Line 954 ip6_process_hopopts(struct mbuf *m, u_in |
|
| Line 963 ip6_process_hopopts(struct mbuf *m, u_in |
|
| return (-1); |
return (-1); |
| } |
} |
| optlen = IP6OPT_RTALERT_LEN; |
optlen = IP6OPT_RTALERT_LEN; |
| bcopy((void *)(opt + 2), (void *)&rtalert_val, 2); |
memcpy((void *)&rtalert_val, (void *)(opt + 2), 2); |
| *rtalertp = ntohs(rtalert_val); |
*rtalertp = ntohs(rtalert_val); |
| break; |
break; |
| case IP6OPT_JUMBO: |
case IP6OPT_JUMBO: |
| Line 989 ip6_process_hopopts(struct mbuf *m, u_in |
|
| Line 998 ip6_process_hopopts(struct mbuf *m, u_in |
|
| * We may see jumbolen in unaligned location, so |
* We may see jumbolen in unaligned location, so |
| * we'd need to perform bcopy(). |
* we'd need to perform bcopy(). |
| */ |
*/ |
| bcopy(opt + 2, &jumboplen, sizeof(jumboplen)); |
memcpy(&jumboplen, opt + 2, sizeof(jumboplen)); |
| jumboplen = (u_int32_t)htonl(jumboplen); |
jumboplen = (u_int32_t)htonl(jumboplen); |
| |
|
| #if 1 |
#if 1 |
| Line 1102 ip6_savecontrol(struct in6pcb *in6p, str |
|
| Line 1111 ip6_savecontrol(struct in6pcb *in6p, str |
|
| #define IS2292(x, y) (y) |
#define IS2292(x, y) (y) |
| #endif |
#endif |
| |
|
| #ifdef SO_TIMESTAMP |
if (in6p->in6p_socket->so_options & SO_TIMESTAMP |
| if (in6p->in6p_socket->so_options & SO_TIMESTAMP) { |
#ifdef SO_OTIMESTAMP |
| |
|| in6p->in6p_socket->so_options & SO_OTIMESTAMP |
| |
#endif |
| |
) { |
| struct timeval tv; |
struct timeval tv; |
| |
|
| microtime(&tv); |
microtime(&tv); |
| |
#ifdef SO_OTIMESTAMP |
| |
if (in6p->in6p_socket->so_options & SO_OTIMESTAMP) { |
| |
struct timeval50 tv50; |
| |
timeval_to_timeval50(&tv, &tv50); |
| |
*mp = sbcreatecontrol((void *) &tv50, sizeof(tv50), |
| |
SCM_OTIMESTAMP, SOL_SOCKET); |
| |
} else |
| |
#endif |
| *mp = sbcreatecontrol((void *) &tv, sizeof(tv), |
*mp = sbcreatecontrol((void *) &tv, sizeof(tv), |
| SCM_TIMESTAMP, SOL_SOCKET); |
SCM_TIMESTAMP, SOL_SOCKET); |
| if (*mp) |
if (*mp) |
| mp = &(*mp)->m_next; |
mp = &(*mp)->m_next; |
| } |
} |
| #endif |
|
| |
|
| /* some OSes call this logic with IPv4 packet, for SO_TIMESTAMP */ |
/* some OSes call this logic with IPv4 packet, for SO_TIMESTAMP */ |
| if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) |
if ((ip6->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) |
| Line 1122 ip6_savecontrol(struct in6pcb *in6p, str |
|
| Line 1141 ip6_savecontrol(struct in6pcb *in6p, str |
|
| if ((in6p->in6p_flags & IN6P_PKTINFO) != 0) { |
if ((in6p->in6p_flags & IN6P_PKTINFO) != 0) { |
| struct in6_pktinfo pi6; |
struct in6_pktinfo pi6; |
| |
|
| bcopy(&ip6->ip6_dst, &pi6.ipi6_addr, sizeof(struct in6_addr)); |
memcpy(&pi6.ipi6_addr, &ip6->ip6_dst, sizeof(struct in6_addr)); |
| in6_clearscope(&pi6.ipi6_addr); /* XXX */ |
in6_clearscope(&pi6.ipi6_addr); /* XXX */ |
| pi6.ipi6_ifindex = m->m_pkthdr.rcvif ? |
pi6.ipi6_ifindex = m->m_pkthdr.rcvif ? |
| m->m_pkthdr.rcvif->if_index : 0; |
m->m_pkthdr.rcvif->if_index : 0; |
| Line 1257 ip6_savecontrol(struct in6pcb *in6p, str |
|
| Line 1276 ip6_savecontrol(struct in6pcb *in6p, str |
|
| |
|
| switch (nxt) { |
switch (nxt) { |
| case IPPROTO_DSTOPTS: |
case IPPROTO_DSTOPTS: |
| if (!in6p->in6p_flags & IN6P_DSTOPTS) |
if (!(in6p->in6p_flags & IN6P_DSTOPTS)) |
| break; |
break; |
| |
|
| *mp = sbcreatecontrol((void *)ip6e, elen, |
*mp = sbcreatecontrol((void *)ip6e, elen, |
| Line 1268 ip6_savecontrol(struct in6pcb *in6p, str |
|
| Line 1287 ip6_savecontrol(struct in6pcb *in6p, str |
|
| break; |
break; |
| |
|
| case IPPROTO_ROUTING: |
case IPPROTO_ROUTING: |
| if (!in6p->in6p_flags & IN6P_RTHDR) |
if (!(in6p->in6p_flags & IN6P_RTHDR)) |
| break; |
break; |
| |
|
| *mp = sbcreatecontrol((void *)ip6e, elen, |
*mp = sbcreatecontrol((void *)ip6e, elen, |
| Line 1562 ip6_addaux(struct mbuf *m) |
|
| Line 1581 ip6_addaux(struct mbuf *m) |
|
| M_NOWAIT); |
M_NOWAIT); |
| if (mtag) { |
if (mtag) { |
| m_tag_prepend(m, mtag); |
m_tag_prepend(m, mtag); |
| bzero(mtag + 1, sizeof(struct ip6aux)); |
memset(mtag + 1, 0, sizeof(struct ip6aux)); |
| } |
} |
| } |
} |
| return mtag; |
return mtag; |
| Line 1595 ip6_delaux(struct mbuf *m) |
|
| Line 1614 ip6_delaux(struct mbuf *m) |
|
| static int |
static int |
| sysctl_net_inet6_ip6_maxflows(SYSCTLFN_ARGS) |
sysctl_net_inet6_ip6_maxflows(SYSCTLFN_ARGS) |
| { |
{ |
| int s; |
int error; |
| |
|
| s = sysctl_lookup(SYSCTLFN_CALL(rnode)); |
error = sysctl_lookup(SYSCTLFN_CALL(rnode)); |
| if (s || newp == NULL) |
if (error || newp == NULL) |
| return (s); |
return (error); |
| |
|
| s = splsoftnet(); |
mutex_enter(softnet_lock); |
| ip6flow_reap(0); |
KERNEL_LOCK(1, NULL); |
| splx(s); |
|
| |
ip6flow_reap(0); |
| |
|
| |
KERNEL_UNLOCK_ONE(NULL); |
| |
mutex_exit(softnet_lock); |
| |
|
| return (0); |
return (0); |
| } |
} |
| |
|
| static int |
static int |
| Line 1625 sysctl_net_inet6_ip6_hashsize(SYSCTLFN_A |
|
| Line 1648 sysctl_net_inet6_ip6_hashsize(SYSCTLFN_A |
|
| /* |
/* |
| * Can only fail due to malloc() |
* Can only fail due to malloc() |
| */ |
*/ |
| if (ip6flow_invalidate_all(tmp)) |
mutex_enter(softnet_lock); |
| return ENOMEM; |
KERNEL_LOCK(1, NULL); |
| |
|
| |
error = ip6flow_invalidate_all(tmp); |
| |
|
| |
KERNEL_UNLOCK_ONE(NULL); |
| |
mutex_exit(softnet_lock); |
| } else { |
} else { |
| /* |
/* |
| * EINVAL if not a power of 2 |
* EINVAL if not a power of 2 |
| */ |
*/ |
| return EINVAL; |
error = EINVAL; |
| } |
} |
| |
|
| return (0); |
return error; |
| } |
} |
| #endif /* GATEWAY */ |
#endif /* GATEWAY */ |
| |
|
| Line 1642 sysctl_net_inet6_ip6_hashsize(SYSCTLFN_A |
|
| Line 1670 sysctl_net_inet6_ip6_hashsize(SYSCTLFN_A |
|
| * System control for IP6 |
* System control for IP6 |
| */ |
*/ |
| |
|
| u_char inet6ctlerrmap[PRC_NCMDS] = { |
const u_char inet6ctlerrmap[PRC_NCMDS] = { |
| 0, 0, 0, 0, |
0, 0, 0, 0, |
| 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH, |
0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH, |
| EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED, |
EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED, |
| Line 1654 u_char inet6ctlerrmap[PRC_NCMDS] = { |
|
| Line 1682 u_char inet6ctlerrmap[PRC_NCMDS] = { |
|
| static int |
static int |
| sysctl_net_inet6_ip6_stats(SYSCTLFN_ARGS) |
sysctl_net_inet6_ip6_stats(SYSCTLFN_ARGS) |
| { |
{ |
| netstat_sysctl_context ctx; |
|
| uint64_t ip6s[IP6_NSTATS]; |
|
| |
|
| ctx.ctx_stat = ip6stat_percpu; |
return (NETSTAT_SYSCTL(ip6stat_percpu, IP6_NSTATS)); |
| ctx.ctx_counters = ip6s; |
|
| ctx.ctx_ncounters = IP6_NSTATS; |
|
| return (NETSTAT_SYSCTL(&ctx)); |
|
| } |
} |
| |
|
| SYSCTL_SETUP(sysctl_net_inet6_ip6_setup, "sysctl net.inet6.ip6 subtree setup") |
static void |
| |
sysctl_net_inet6_ip6_setup(struct sysctllog **clog) |
| { |
{ |
| #ifdef RFC2292 |
#ifdef RFC2292 |
| #define IS2292(x, y) ((in6p->in6p_flags & IN6P_RFC2292) ? (x) : (y)) |
#define IS2292(x, y) ((in6p->in6p_flags & IN6P_RFC2292) ? (x) : (y)) |