| version 1.245.2.5, 2007/10/09 13:44:50 |
version 1.246, 2007/03/12 18:18:36 |
|
|
| M_WAITOK, &in_multihash); |
M_WAITOK, &in_multihash); |
| ip_mtudisc_timeout_q = rt_timer_queue_create(ip_mtudisc_timeout); |
ip_mtudisc_timeout_q = rt_timer_queue_create(ip_mtudisc_timeout); |
| #ifdef GATEWAY |
#ifdef GATEWAY |
| ipflow_init(ip_hashsize); |
ipflow_init(); |
| #endif |
#endif |
| |
|
| #ifdef PFIL_HOOKS |
#ifdef PFIL_HOOKS |
|
|
| */ |
*/ |
| IPQ_LOCK(); |
IPQ_LOCK(); |
| hash = IPREASS_HASH(ip->ip_src.s_addr, ip->ip_id); |
hash = IPREASS_HASH(ip->ip_src.s_addr, ip->ip_id); |
| LIST_FOREACH(fp, &ipq[hash], ipq_q) { |
/* XXX LIST_FOREACH(fp, &ipq[hash], ipq_q) */ |
| |
for (fp = LIST_FIRST(&ipq[hash]); fp != NULL; |
| |
fp = LIST_NEXT(fp, ipq_q)) { |
| if (ip->ip_id == fp->ipq_id && |
if (ip->ip_id == fp->ipq_id && |
| in_hosteq(ip->ip_src, fp->ipq_src) && |
in_hosteq(ip->ip_src, fp->ipq_src) && |
| in_hosteq(ip->ip_dst, fp->ipq_dst) && |
in_hosteq(ip->ip_dst, fp->ipq_dst) && |
|
|
| /* XXX error stat??? */ |
/* XXX error stat??? */ |
| error = EINVAL; |
error = EINVAL; |
| DPRINTF(("ip_input: no SP, packet discarded\n"));/*XXX*/ |
DPRINTF(("ip_input: no SP, packet discarded\n"));/*XXX*/ |
| |
goto bad; |
| } |
} |
| splx(s); |
splx(s); |
| if (error) |
if (error) |
|
|
| struct in_ifaddr * |
struct in_ifaddr * |
| ip_rtaddr(struct in_addr dst) |
ip_rtaddr(struct in_addr dst) |
| { |
{ |
| struct rtentry *rt; |
if (!in_hosteq(dst, satocsin(rtcache_getdst(&ipforward_rt))->sin_addr)) |
| union { |
rtcache_free(&ipforward_rt); |
| struct sockaddr dst; |
else |
| struct sockaddr_in dst4; |
rtcache_check(&ipforward_rt); |
| } u; |
|
| |
if (ipforward_rt.ro_rt == NULL) { |
| sockaddr_in_init(&u.dst4, &dst, 0); |
struct sockaddr_in *sin = satosin(&ipforward_rt.ro_dst); |
| |
|
| if ((rt = rtcache_lookup(&ipforward_rt, &u.dst)) == NULL) |
sin->sin_family = AF_INET; |
| return NULL; |
sin->sin_len = sizeof(*sin); |
| |
sin->sin_addr = dst; |
| return ifatoia(rt->rt_ifa); |
|
| |
rtcache_init(&ipforward_rt); |
| |
if (ipforward_rt.ro_rt == NULL) |
| |
return NULL; |
| |
} |
| |
return ifatoia(ipforward_rt.ro_rt->rt_ifa); |
| } |
} |
| |
|
| /* |
/* |
| Line 1776 ip_srcroute(void) |
|
| Line 1784 ip_srcroute(void) |
|
| return (m); |
return (m); |
| } |
} |
| |
|
| |
/* |
| |
* Strip out IP options, at higher |
| |
* level protocol in the kernel. |
| |
* Second argument is buffer to which options |
| |
* will be moved, and return value is their length. |
| |
* XXX should be deleted; last arg currently ignored. |
| |
*/ |
| |
void |
| |
ip_stripoptions(struct mbuf *m, struct mbuf *mopt) |
| |
{ |
| |
int i; |
| |
struct ip *ip = mtod(m, struct ip *); |
| |
void *opts; |
| |
int olen; |
| |
|
| |
olen = (ip->ip_hl << 2) - sizeof (struct ip); |
| |
opts = (void *)(ip + 1); |
| |
i = m->m_len - (sizeof (struct ip) + olen); |
| |
memmove(opts, (char *)opts + olen, (unsigned)i); |
| |
m->m_len -= olen; |
| |
if (m->m_flags & M_PKTHDR) |
| |
m->m_pkthdr.len -= olen; |
| |
ip->ip_len = htons(ntohs(ip->ip_len) - olen); |
| |
ip->ip_hl = sizeof (struct ip) >> 2; |
| |
} |
| |
|
| const int inetctlerrmap[PRC_NCMDS] = { |
const int inetctlerrmap[PRC_NCMDS] = { |
| 0, 0, 0, 0, |
0, 0, 0, 0, |
| 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH, |
0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH, |
| Line 1807 ip_forward(struct mbuf *m, int srcrt) |
|
| Line 1841 ip_forward(struct mbuf *m, int srcrt) |
|
| int error, type = 0, code = 0, destmtu = 0; |
int error, type = 0, code = 0, destmtu = 0; |
| struct mbuf *mcopy; |
struct mbuf *mcopy; |
| n_long dest; |
n_long dest; |
| union { |
|
| struct sockaddr dst; |
|
| struct sockaddr_in dst4; |
|
| } u; |
|
| |
|
| /* |
/* |
| * We are now in the output path. |
* We are now in the output path. |
| Line 1839 ip_forward(struct mbuf *m, int srcrt) |
|
| Line 1869 ip_forward(struct mbuf *m, int srcrt) |
|
| return; |
return; |
| } |
} |
| |
|
| sockaddr_in_init(&u.dst4, &ip->ip_dst, 0); |
if (!in_hosteq(ip->ip_dst, |
| if ((rt = rtcache_lookup(&ipforward_rt, &u.dst)) == NULL) { |
satocsin(rtcache_getdst(&ipforward_rt))->sin_addr)) |
| icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, dest, 0); |
rtcache_free(&ipforward_rt); |
| return; |
else |
| |
rtcache_check(&ipforward_rt); |
| |
if (ipforward_rt.ro_rt == NULL) { |
| |
struct sockaddr_in *sin = satosin(&ipforward_rt.ro_dst); |
| |
|
| |
sin->sin_family = AF_INET; |
| |
sin->sin_len = sizeof(*sin); |
| |
sin->sin_addr = ip->ip_dst; |
| |
|
| |
rtcache_init(&ipforward_rt); |
| |
if (ipforward_rt.ro_rt == NULL) { |
| |
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, dest, 0); |
| |
return; |
| |
} |
| } |
} |
| |
rt = ipforward_rt.ro_rt; |
| |
|
| /* |
/* |
| * Save at most 68 bytes of the packet in case |
* Save at most 68 bytes of the packet in case |
| Line 1866 ip_forward(struct mbuf *m, int srcrt) |
|
| Line 1910 ip_forward(struct mbuf *m, int srcrt) |
|
| */ |
*/ |
| if (rt->rt_ifp == m->m_pkthdr.rcvif && |
if (rt->rt_ifp == m->m_pkthdr.rcvif && |
| (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 && |
(rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 && |
| !in_nullhost(satocsin(rt_getkey(rt))->sin_addr) && |
!in_nullhost(satosin(rt_key(rt))->sin_addr) && |
| ipsendredirects && !srcrt) { |
ipsendredirects && !srcrt) { |
| if (rt->rt_ifa && |
if (rt->rt_ifa && |
| (ip->ip_src.s_addr & ifatoia(rt->rt_ifa)->ia_subnetmask) == |
(ip->ip_src.s_addr & ifatoia(rt->rt_ifa)->ia_subnetmask) == |
| Line 2052 ip_savecontrol(struct inpcb *inp, struct |
|
| Line 2096 ip_savecontrol(struct inpcb *inp, struct |
|
| if (inp->inp_flags & INP_RECVIF) { |
if (inp->inp_flags & INP_RECVIF) { |
| struct sockaddr_dl sdl; |
struct sockaddr_dl sdl; |
| |
|
| sockaddr_dl_init(&sdl, sizeof(sdl), |
sdl.sdl_len = offsetof(struct sockaddr_dl, sdl_data[0]); |
| (m->m_pkthdr.rcvif != NULL) |
sdl.sdl_family = AF_LINK; |
| ? m->m_pkthdr.rcvif->if_index |
sdl.sdl_index = m->m_pkthdr.rcvif ? |
| : 0, |
m->m_pkthdr.rcvif->if_index : 0; |
| 0, NULL, 0, NULL, 0); |
sdl.sdl_nlen = sdl.sdl_alen = sdl.sdl_slen = 0; |
| *mp = sbcreatecontrol(&sdl, sdl.sdl_len, IP_RECVIF, IPPROTO_IP); |
*mp = sbcreatecontrol((void *) &sdl, sdl.sdl_len, |
| |
IP_RECVIF, IPPROTO_IP); |
| if (*mp) |
if (*mp) |
| mp = &(*mp)->m_next; |
mp = &(*mp)->m_next; |
| } |
} |
| Line 2115 sysctl_net_inet_ip_pmtudto(SYSCTLFN_ARGS |
|
| Line 2160 sysctl_net_inet_ip_pmtudto(SYSCTLFN_ARGS |
|
| |
|
| #ifdef GATEWAY |
#ifdef GATEWAY |
| /* |
/* |
| * sysctl helper routine for net.inet.ip.maxflows. |
* sysctl helper routine for net.inet.ip.maxflows. apparently if |
| |
* maxflows is even looked up, we "reap flows". |
| */ |
*/ |
| static int |
static int |
| sysctl_net_inet_ip_maxflows(SYSCTLFN_ARGS) |
sysctl_net_inet_ip_maxflows(SYSCTLFN_ARGS) |
| Line 2123 sysctl_net_inet_ip_maxflows(SYSCTLFN_ARG |
|
| Line 2169 sysctl_net_inet_ip_maxflows(SYSCTLFN_ARG |
|
| int s; |
int s; |
| |
|
| s = sysctl_lookup(SYSCTLFN_CALL(rnode)); |
s = sysctl_lookup(SYSCTLFN_CALL(rnode)); |
| if (s || newp == NULL) |
if (s) |
| return (s); |
return (s); |
| |
|
| s = splsoftnet(); |
s = splsoftnet(); |
| Line 2132 sysctl_net_inet_ip_maxflows(SYSCTLFN_ARG |
|
| Line 2178 sysctl_net_inet_ip_maxflows(SYSCTLFN_ARG |
|
| |
|
| return (0); |
return (0); |
| } |
} |
| |
|
| static int |
|
| sysctl_net_inet_ip_hashsize(SYSCTLFN_ARGS) |
|
| { |
|
| int error, tmp; |
|
| struct sysctlnode node; |
|
| |
|
| node = *rnode; |
|
| tmp = ip_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() |
|
| */ |
|
| if (ipflow_invalidate_all(tmp)) |
|
| return ENOMEM; |
|
| } else { |
|
| /* |
|
| * EINVAL if not a power of 2 |
|
| */ |
|
| return EINVAL; |
|
| } |
|
| |
|
| return (0); |
|
| } |
|
| #endif /* GATEWAY */ |
#endif /* GATEWAY */ |
| |
|
| |
|
| Line 2282 SYSCTL_SETUP(sysctl_net_inet_ip_setup, " |
|
| Line 2299 SYSCTL_SETUP(sysctl_net_inet_ip_setup, " |
|
| sysctl_net_inet_ip_maxflows, 0, &ip_maxflows, 0, |
sysctl_net_inet_ip_maxflows, 0, &ip_maxflows, 0, |
| CTL_NET, PF_INET, IPPROTO_IP, |
CTL_NET, PF_INET, IPPROTO_IP, |
| IPCTL_MAXFLOWS, CTL_EOL); |
IPCTL_MAXFLOWS, CTL_EOL); |
| sysctl_createv(clog, 0, NULL, NULL, |
|
| CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
|
| CTLTYPE_INT, "hashsize", |
|
| SYSCTL_DESCR("Size of hash table for fast forwarding (IPv4)"), |
|
| sysctl_net_inet_ip_hashsize, 0, &ip_hashsize, 0, |
|
| CTL_NET, PF_INET, IPPROTO_IP, |
|
| CTL_CREATE, CTL_EOL); |
|
| #endif /* GATEWAY */ |
#endif /* GATEWAY */ |
| sysctl_createv(clog, 0, NULL, NULL, |
sysctl_createv(clog, 0, NULL, NULL, |
| CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |