version 1.268.2.2, 2009/05/04 08:14:17 |
version 1.272, 2008/05/05 17:11:17 |
|
|
__KERNEL_RCSID(0, "$NetBSD$"); |
__KERNEL_RCSID(0, "$NetBSD$"); |
|
|
#include "opt_inet.h" |
#include "opt_inet.h" |
#include "opt_compat_netbsd.h" |
|
#include "opt_gateway.h" |
#include "opt_gateway.h" |
#include "opt_pfil_hooks.h" |
#include "opt_pfil_hooks.h" |
#include "opt_ipsec.h" |
#include "opt_ipsec.h" |
Line 174 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 173 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#define IPMTUDISCTIMEOUT (10 * 60) /* as per RFC 1191 */ |
#define IPMTUDISCTIMEOUT (10 * 60) /* as per RFC 1191 */ |
#endif |
#endif |
|
|
#ifdef COMPAT_50 |
|
#include <compat/sys/time.h> |
|
#include <compat/sys/socket.h> |
|
#endif |
|
|
|
/* |
/* |
* Note: DIRECTED_BROADCAST is handled this way so that previous |
* Note: DIRECTED_BROADCAST is handled this way so that previous |
* configuration using this option will Just Work. |
* configuration using this option will Just Work. |
|
|
|
|
#define IPQ_UNLOCK() ipq_unlock() |
#define IPQ_UNLOCK() ipq_unlock() |
|
|
struct pool inmulti_pool; |
POOL_INIT(inmulti_pool, sizeof(struct in_multi), 0, 0, 0, "inmltpl", NULL, |
struct pool ipqent_pool; |
IPL_SOFTNET); |
|
POOL_INIT(ipqent_pool, sizeof(struct ipqent), 0, 0, 0, "ipqepl", NULL, |
|
IPL_VM); |
|
|
#ifdef INET_CSUM_COUNTERS |
#ifdef INET_CSUM_COUNTERS |
#include <sys/device.h> |
#include <sys/device.h> |
|
|
const struct protosw *pr; |
const struct protosw *pr; |
int i; |
int i; |
|
|
pool_init(&inmulti_pool, sizeof(struct in_multi), 0, 0, 0, "inmltpl", |
|
NULL, IPL_SOFTNET); |
|
pool_init(&ipqent_pool, sizeof(struct ipqent), 0, 0, 0, "ipqepl", |
|
NULL, IPL_VM); |
|
|
|
pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW); |
pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW); |
if (pr == 0) |
if (pr == 0) |
panic("ip_init"); |
panic("ip_init"); |
|
|
*/ |
*/ |
if (ip->ip_tos != fp->ipq_tos) { |
if (ip->ip_tos != fp->ipq_tos) { |
IP_STATINC(IP_STAT_BADFRAGS); |
IP_STATINC(IP_STAT_BADFRAGS); |
IPQ_UNLOCK(); |
|
goto bad; |
goto bad; |
} |
} |
goto found; |
goto found; |
Line 1128 ip_reass(struct ipqent *ipqe, struct ipq |
|
Line 1118 ip_reass(struct ipqent *ipqe, struct ipq |
|
else if (ip_nfragpackets >= ip_maxfragpackets) |
else if (ip_nfragpackets >= ip_maxfragpackets) |
goto dropfrag; |
goto dropfrag; |
ip_nfragpackets++; |
ip_nfragpackets++; |
fp = malloc(sizeof (struct ipq), M_FTABLE, M_NOWAIT); |
MALLOC(fp, struct ipq *, sizeof (struct ipq), |
|
M_FTABLE, M_NOWAIT); |
if (fp == NULL) |
if (fp == NULL) |
goto dropfrag; |
goto dropfrag; |
LIST_INSERT_HEAD(ipqhead, fp, ipq_q); |
LIST_INSERT_HEAD(ipqhead, fp, ipq_q); |
|
|
ip->ip_src = fp->ipq_src; |
ip->ip_src = fp->ipq_src; |
ip->ip_dst = fp->ipq_dst; |
ip->ip_dst = fp->ipq_dst; |
LIST_REMOVE(fp, ipq_q); |
LIST_REMOVE(fp, ipq_q); |
free(fp, M_FTABLE); |
FREE(fp, M_FTABLE); |
ip_nfragpackets--; |
ip_nfragpackets--; |
m->m_len += (ip->ip_hl << 2); |
m->m_len += (ip->ip_hl << 2); |
m->m_data -= (ip->ip_hl << 2); |
m->m_data -= (ip->ip_hl << 2); |
Line 1312 ip_freef(struct ipq *fp) |
|
Line 1303 ip_freef(struct ipq *fp) |
|
printf("ip_freef: nfrags %d != %d\n", fp->ipq_nfrags, nfrags); |
printf("ip_freef: nfrags %d != %d\n", fp->ipq_nfrags, nfrags); |
ip_nfrags -= nfrags; |
ip_nfrags -= nfrags; |
LIST_REMOVE(fp, ipq_q); |
LIST_REMOVE(fp, ipq_q); |
free(fp, M_FTABLE); |
FREE(fp, M_FTABLE); |
ip_nfragpackets--; |
ip_nfragpackets--; |
} |
} |
|
|
Line 1562 ip_dooptions(struct mbuf *m) |
|
Line 1553 ip_dooptions(struct mbuf *m) |
|
/* |
/* |
* locate outgoing interface |
* locate outgoing interface |
*/ |
*/ |
memcpy((void *)&ipaddr.sin_addr, (void *)(cp + off), |
bcopy((void *)(cp + off), (void *)&ipaddr.sin_addr, |
sizeof(ipaddr.sin_addr)); |
sizeof(ipaddr.sin_addr)); |
if (opt == IPOPT_SSRR) |
if (opt == IPOPT_SSRR) |
ia = ifatoia(ifa_ifwithladdr(sintosa(&ipaddr))); |
ia = ifatoia(ifa_ifwithladdr(sintosa(&ipaddr))); |
Line 1598 ip_dooptions(struct mbuf *m) |
|
Line 1589 ip_dooptions(struct mbuf *m) |
|
off--; /* 0 origin */ |
off--; /* 0 origin */ |
if ((off + sizeof(struct in_addr)) > optlen) |
if ((off + sizeof(struct in_addr)) > optlen) |
break; |
break; |
memcpy((void *)&ipaddr.sin_addr, (void *)(&ip->ip_dst), |
bcopy((void *)(&ip->ip_dst), (void *)&ipaddr.sin_addr, |
sizeof(ipaddr.sin_addr)); |
sizeof(ipaddr.sin_addr)); |
/* |
/* |
* locate outgoing interface; if we're the destination, |
* locate outgoing interface; if we're the destination, |
Line 1665 ip_dooptions(struct mbuf *m) |
|
Line 1656 ip_dooptions(struct mbuf *m) |
|
(u_char *)ip; |
(u_char *)ip; |
goto bad; |
goto bad; |
} |
} |
memcpy(&ipaddr.sin_addr, cp0, |
bcopy(cp0, &ipaddr.sin_addr, |
sizeof(struct in_addr)); |
sizeof(struct in_addr)); |
if (ifatoia(ifa_ifwithaddr(sintosa(&ipaddr))) |
if (ifatoia(ifa_ifwithaddr(sintosa(&ipaddr))) |
== NULL) |
== NULL) |
Line 1739 save_rte(u_char *option, struct in_addr |
|
Line 1730 save_rte(u_char *option, struct in_addr |
|
#endif /* 0 */ |
#endif /* 0 */ |
if (olen > sizeof(ip_srcrt) - (1 + sizeof(dst))) |
if (olen > sizeof(ip_srcrt) - (1 + sizeof(dst))) |
return; |
return; |
memcpy((void *)ip_srcrt.srcopt, (void *)option, olen); |
bcopy((void *)option, (void *)ip_srcrt.srcopt, olen); |
ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr); |
ip_nhops = (olen - IPOPT_OFFSET - 1) / sizeof(struct in_addr); |
ip_srcrt.dst = dst; |
ip_srcrt.dst = dst; |
} |
} |
Line 1976 ip_forward(struct mbuf *m, int srcrt) |
|
Line 1967 ip_forward(struct mbuf *m, int srcrt) |
|
type = ICMP_UNREACH; |
type = ICMP_UNREACH; |
code = ICMP_UNREACH_NEEDFRAG; |
code = ICMP_UNREACH_NEEDFRAG; |
|
|
if ((rt = rtcache_validate(&ipforward_rt)) != NULL) |
if ((rt = rtcache_validate(&ipforward_rt)) != NULL) { |
destmtu = rt->rt_ifp->if_mtu; |
|
|
|
#if defined(IPSEC) || defined(FAST_IPSEC) |
#if defined(IPSEC) || defined(FAST_IPSEC) |
{ |
|
/* |
/* |
* If the packet is routed over IPsec tunnel, tell the |
* If the packet is routed over IPsec tunnel, tell the |
* originator the tunnel MTU. |
* originator the tunnel MTU. |
Line 1996 ip_forward(struct mbuf *m, int srcrt) |
|
Line 1985 ip_forward(struct mbuf *m, int srcrt) |
|
sp = ipsec4_getpolicybyaddr(mcopy, |
sp = ipsec4_getpolicybyaddr(mcopy, |
IPSEC_DIR_OUTBOUND, IP_FORWARDING, |
IPSEC_DIR_OUTBOUND, IP_FORWARDING, |
&ipsecerror); |
&ipsecerror); |
|
#endif |
|
|
|
destmtu = rt->rt_ifp->if_mtu; |
|
#if defined(IPSEC) || defined(FAST_IPSEC) |
if (sp != NULL) { |
if (sp != NULL) { |
/* count IPsec header size */ |
/* count IPsec header size */ |
ipsechdr = ipsec4_hdrsiz(mcopy, |
ipsechdr = ipsec4_hdrsiz(mcopy, |
Line 2011 ip_forward(struct mbuf *m, int srcrt) |
|
Line 2003 ip_forward(struct mbuf *m, int srcrt) |
|
&& sp->req->sav != NULL |
&& sp->req->sav != NULL |
&& sp->req->sav->sah != NULL) { |
&& sp->req->sav->sah != NULL) { |
ro = &sp->req->sav->sah->sa_route; |
ro = &sp->req->sav->sah->sa_route; |
rt = rtcache_validate(ro); |
|
if (rt && rt->rt_ifp) { |
if (rt && rt->rt_ifp) { |
destmtu = |
destmtu = |
rt->rt_rmx.rmx_mtu ? |
rt->rt_rmx.rmx_mtu ? |
Line 2027 ip_forward(struct mbuf *m, int srcrt) |
|
Line 2018 ip_forward(struct mbuf *m, int srcrt) |
|
KEY_FREESP(&sp); |
KEY_FREESP(&sp); |
#endif |
#endif |
} |
} |
} |
|
#endif /*defined(IPSEC) || defined(FAST_IPSEC)*/ |
#endif /*defined(IPSEC) || defined(FAST_IPSEC)*/ |
|
} |
IP_STATINC(IP_STAT_CANTFRAG); |
IP_STATINC(IP_STAT_CANTFRAG); |
break; |
break; |
|
|
Line 2057 ip_savecontrol(struct inpcb *inp, struct |
|
Line 2048 ip_savecontrol(struct inpcb *inp, struct |
|
struct mbuf *m) |
struct mbuf *m) |
{ |
{ |
|
|
if (inp->inp_socket->so_options & SO_TIMESTAMP |
if (inp->inp_socket->so_options & SO_TIMESTAMP) { |
#ifdef SO_OTIMESTAMP |
|
|| inp->inp_socket->so_options & SO_OTIMESTAMP |
|
#endif |
|
) { |
|
struct timeval tv; |
struct timeval tv; |
|
|
microtime(&tv); |
microtime(&tv); |
#ifdef SO_OTIMESTAMP |
|
if (inp->inp_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) |
Line 2136 sysctl_net_inet_ip_forwsrcrt(SYSCTLFN_AR |
|
Line 2115 sysctl_net_inet_ip_forwsrcrt(SYSCTLFN_AR |
|
if (error || newp == NULL) |
if (error || newp == NULL) |
return (error); |
return (error); |
|
|
error = kauth_authorize_network(l->l_cred, KAUTH_NETWORK_FORWSRCRT, |
if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_FORWSRCRT, |
0, NULL, NULL, NULL); |
0, NULL, NULL, NULL)) |
if (error) |
return (EPERM); |
return (error); |
|
|
|
ip_forwsrcrt = tmp; |
ip_forwsrcrt = tmp; |
|
|
Line 2165 sysctl_net_inet_ip_pmtudto(SYSCTLFN_ARGS |
|
Line 2143 sysctl_net_inet_ip_pmtudto(SYSCTLFN_ARGS |
|
if (tmp < 0) |
if (tmp < 0) |
return (EINVAL); |
return (EINVAL); |
|
|
mutex_enter(softnet_lock); |
|
|
|
ip_mtudisc_timeout = tmp; |
ip_mtudisc_timeout = tmp; |
rt_timer_queue_change(ip_mtudisc_timeout_q, ip_mtudisc_timeout); |
rt_timer_queue_change(ip_mtudisc_timeout_q, ip_mtudisc_timeout); |
|
|
mutex_exit(softnet_lock); |
|
|
|
return (0); |
return (0); |
} |
} |
|
|
Line 2182 sysctl_net_inet_ip_pmtudto(SYSCTLFN_ARGS |
|
Line 2156 sysctl_net_inet_ip_pmtudto(SYSCTLFN_ARGS |
|
static int |
static int |
sysctl_net_inet_ip_maxflows(SYSCTLFN_ARGS) |
sysctl_net_inet_ip_maxflows(SYSCTLFN_ARGS) |
{ |
{ |
int error; |
int s; |
|
|
error = sysctl_lookup(SYSCTLFN_CALL(rnode)); |
|
if (error || newp == NULL) |
|
return (error); |
|
|
|
mutex_enter(softnet_lock); |
s = sysctl_lookup(SYSCTLFN_CALL(rnode)); |
KERNEL_LOCK(1, NULL); |
if (s || newp == NULL) |
|
return (s); |
|
|
|
s = splsoftnet(); |
ipflow_prune(); |
ipflow_prune(); |
|
splx(s); |
KERNEL_UNLOCK_ONE(NULL); |
|
mutex_exit(softnet_lock); |
|
|
|
return (0); |
return (0); |
} |
} |
Line 2216 sysctl_net_inet_ip_hashsize(SYSCTLFN_ARG |
|
Line 2186 sysctl_net_inet_ip_hashsize(SYSCTLFN_ARG |
|
/* |
/* |
* Can only fail due to malloc() |
* Can only fail due to malloc() |
*/ |
*/ |
mutex_enter(softnet_lock); |
if (ipflow_invalidate_all(tmp)) |
KERNEL_LOCK(1, NULL); |
return ENOMEM; |
|
|
error = ipflow_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 |
*/ |
*/ |
error = EINVAL; |
return EINVAL; |
} |
} |
|
|
return error; |
return (0); |
} |
} |
#endif /* GATEWAY */ |
#endif /* GATEWAY */ |
|
|