| version 1.242, 2007/01/29 05:48:56 |
version 1.242.2.5, 2007/05/07 10:55:59 |
|
|
| |
|
| #define IPQ_UNLOCK() ipq_unlock() |
#define IPQ_UNLOCK() ipq_unlock() |
| |
|
| POOL_INIT(inmulti_pool, sizeof(struct in_multi), 0, 0, 0, "inmltpl", NULL); |
POOL_INIT(inmulti_pool, sizeof(struct in_multi), 0, 0, 0, "inmltpl", NULL, |
| POOL_INIT(ipqent_pool, sizeof(struct ipqent), 0, 0, 0, "ipqepl", NULL); |
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> |
|
|
| 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(); |
ipflow_init(ip_hashsize); |
| #endif |
#endif |
| |
|
| #ifdef PFIL_HOOKS |
#ifdef PFIL_HOOKS |
| Line 516 ip_input(struct mbuf *m) |
|
| Line 518 ip_input(struct mbuf *m) |
|
| * it. Otherwise, if it is aligned, make sure the entire |
* it. Otherwise, if it is aligned, make sure the entire |
| * base IP header is in the first mbuf of the chain. |
* base IP header is in the first mbuf of the chain. |
| */ |
*/ |
| if (IP_HDR_ALIGNED_P(mtod(m, caddr_t)) == 0) { |
if (IP_HDR_ALIGNED_P(mtod(m, void *)) == 0) { |
| if ((m = m_copyup(m, sizeof(struct ip), |
if ((m = m_copyup(m, sizeof(struct ip), |
| (max_linkhdr + 3) & ~3)) == NULL) { |
(max_linkhdr + 3) & ~3)) == NULL) { |
| /* XXXJRT new stat, please */ |
/* XXXJRT new stat, please */ |
| Line 1407 ip_slowtimo(void) |
|
| Line 1409 ip_slowtimo(void) |
|
| dropscanidx = i; |
dropscanidx = i; |
| } |
} |
| IPQ_UNLOCK(); |
IPQ_UNLOCK(); |
| #ifdef GATEWAY |
|
| ipflow_slowtimo(); |
|
| #endif |
|
| splx(s); |
splx(s); |
| } |
} |
| |
|
| Line 1528 ip_dooptions(struct mbuf *m) |
|
| Line 1527 ip_dooptions(struct mbuf *m) |
|
| /* |
/* |
| * locate outgoing interface |
* locate outgoing interface |
| */ |
*/ |
| bcopy((caddr_t)(cp + off), (caddr_t)&ipaddr.sin_addr, |
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 1540 ip_dooptions(struct mbuf *m) |
|
| Line 1539 ip_dooptions(struct mbuf *m) |
|
| goto bad; |
goto bad; |
| } |
} |
| ip->ip_dst = ipaddr.sin_addr; |
ip->ip_dst = ipaddr.sin_addr; |
| bcopy((caddr_t)&ia->ia_addr.sin_addr, |
bcopy((void *)&ia->ia_addr.sin_addr, |
| (caddr_t)(cp + off), sizeof(struct in_addr)); |
(void *)(cp + off), sizeof(struct in_addr)); |
| cp[IPOPT_OFFSET] += sizeof(struct in_addr); |
cp[IPOPT_OFFSET] += sizeof(struct in_addr); |
| /* |
/* |
| * Let ip_intr's mcast routing check handle mcast pkts |
* Let ip_intr's mcast routing check handle mcast pkts |
| Line 1564 ip_dooptions(struct mbuf *m) |
|
| Line 1563 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; |
| bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&ipaddr.sin_addr, |
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 1577 ip_dooptions(struct mbuf *m) |
|
| Line 1576 ip_dooptions(struct mbuf *m) |
|
| code = ICMP_UNREACH_HOST; |
code = ICMP_UNREACH_HOST; |
| goto bad; |
goto bad; |
| } |
} |
| bcopy((caddr_t)&ia->ia_addr.sin_addr, |
bcopy((void *)&ia->ia_addr.sin_addr, |
| (caddr_t)(cp + off), sizeof(struct in_addr)); |
(void *)(cp + off), sizeof(struct in_addr)); |
| cp[IPOPT_OFFSET] += sizeof(struct in_addr); |
cp[IPOPT_OFFSET] += sizeof(struct in_addr); |
| break; |
break; |
| |
|
| Line 1647 ip_dooptions(struct mbuf *m) |
|
| Line 1646 ip_dooptions(struct mbuf *m) |
|
| } |
} |
| ntime = iptime(); |
ntime = iptime(); |
| cp0 = (u_char *) &ntime; /* XXX grumble, GCC... */ |
cp0 = (u_char *) &ntime; /* XXX grumble, GCC... */ |
| bcopy(cp0, (caddr_t)cp + ipt->ipt_ptr - 1, |
memmove((char *)cp + ipt->ipt_ptr - 1, cp0, |
| sizeof(n_time)); |
sizeof(n_time)); |
| ipt->ipt_ptr += sizeof(n_time); |
ipt->ipt_ptr += sizeof(n_time); |
| } |
} |
|
|
| struct in_ifaddr * |
struct in_ifaddr * |
| ip_rtaddr(struct in_addr dst) |
ip_rtaddr(struct in_addr dst) |
| { |
{ |
| struct sockaddr_in *sin; |
struct rtentry *rt; |
| |
union { |
| |
struct sockaddr dst; |
| |
struct sockaddr_in dst4; |
| |
} u; |
| |
|
| sin = satosin(&ipforward_rt.ro_dst); |
sockaddr_in_init(&u.dst4, &dst, 0); |
| |
|
| if (!in_hosteq(dst, sin->sin_addr)) |
if ((rt = rtcache_lookup(&ipforward_rt, &u.dst)) == NULL) |
| rtcache_free(&ipforward_rt); |
return NULL; |
| else |
|
| rtcache_check(&ipforward_rt); |
return ifatoia(rt->rt_ifa); |
| if (ipforward_rt.ro_rt == NULL) { |
|
| sin->sin_family = AF_INET; |
|
| sin->sin_len = sizeof(*sin); |
|
| sin->sin_addr = dst; |
|
| |
|
| rtcache_init(&ipforward_rt); |
|
| if (ipforward_rt.ro_rt == NULL) |
|
| return NULL; |
|
| } |
|
| return ifatoia(ipforward_rt.ro_rt->rt_ifa); |
|
| } |
} |
| |
|
| /* |
/* |
| Line 1711 save_rte(u_char *option, struct in_addr |
|
| Line 1704 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; |
| bcopy((caddr_t)option, (caddr_t)ip_srcrt.srcopt, 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 1759 ip_srcroute(void) |
|
| Line 1752 ip_srcroute(void) |
|
| */ |
*/ |
| ip_srcrt.nop = IPOPT_NOP; |
ip_srcrt.nop = IPOPT_NOP; |
| ip_srcrt.srcopt[IPOPT_OFFSET] = IPOPT_MINOFF; |
ip_srcrt.srcopt[IPOPT_OFFSET] = IPOPT_MINOFF; |
| bcopy((caddr_t)&ip_srcrt.nop, |
memmove(mtod(m, char *) + sizeof(struct in_addr), &ip_srcrt.nop, |
| mtod(m, caddr_t) + sizeof(struct in_addr), OPTSIZ); |
OPTSIZ); |
| q = (struct in_addr *)(mtod(m, caddr_t) + |
q = (struct in_addr *)(mtod(m, char *) + |
| sizeof(struct in_addr) + OPTSIZ); |
sizeof(struct in_addr) + OPTSIZ); |
| #undef OPTSIZ |
#undef OPTSIZ |
| /* |
/* |
| Line 1798 ip_stripoptions(struct mbuf *m, struct m |
|
| Line 1791 ip_stripoptions(struct mbuf *m, struct m |
|
| { |
{ |
| int i; |
int i; |
| struct ip *ip = mtod(m, struct ip *); |
struct ip *ip = mtod(m, struct ip *); |
| caddr_t opts; |
void *opts; |
| int olen; |
int olen; |
| |
|
| olen = (ip->ip_hl << 2) - sizeof (struct ip); |
olen = (ip->ip_hl << 2) - sizeof (struct ip); |
| opts = (caddr_t)(ip + 1); |
opts = (void *)(ip + 1); |
| i = m->m_len - (sizeof (struct ip) + olen); |
i = m->m_len - (sizeof (struct ip) + olen); |
| bcopy(opts + olen, opts, (unsigned)i); |
memmove(opts, (char *)opts + olen, (unsigned)i); |
| m->m_len -= olen; |
m->m_len -= olen; |
| if (m->m_flags & M_PKTHDR) |
if (m->m_flags & M_PKTHDR) |
| m->m_pkthdr.len -= olen; |
m->m_pkthdr.len -= olen; |
|
|
| ip_forward(struct mbuf *m, int srcrt) |
ip_forward(struct mbuf *m, int srcrt) |
| { |
{ |
| struct ip *ip = mtod(m, struct ip *); |
struct ip *ip = mtod(m, struct ip *); |
| struct sockaddr_in *sin; |
|
| struct rtentry *rt; |
struct rtentry *rt; |
| 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 1872 ip_forward(struct mbuf *m, int srcrt) |
|
| Line 1868 ip_forward(struct mbuf *m, int srcrt) |
|
| return; |
return; |
| } |
} |
| |
|
| sin = satosin(&ipforward_rt.ro_dst); |
sockaddr_in_init(&u.dst4, &ip->ip_dst, 0); |
| if (!in_hosteq(ip->ip_dst, sin->sin_addr)) |
if ((rt = rtcache_lookup(&ipforward_rt, &u.dst)) == NULL) { |
| rtcache_free(&ipforward_rt); |
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, dest, 0); |
| else |
return; |
| rtcache_check(&ipforward_rt); |
|
| if (ipforward_rt.ro_rt == NULL) { |
|
| 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 2061 ip_savecontrol(struct inpcb *inp, struct |
|
| Line 2045 ip_savecontrol(struct inpcb *inp, struct |
|
| struct timeval tv; |
struct timeval tv; |
| |
|
| microtime(&tv); |
microtime(&tv); |
| *mp = sbcreatecontrol((caddr_t) &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; |
| } |
} |
| if (inp->inp_flags & INP_RECVDSTADDR) { |
if (inp->inp_flags & INP_RECVDSTADDR) { |
| *mp = sbcreatecontrol((caddr_t) &ip->ip_dst, |
*mp = sbcreatecontrol((void *) &ip->ip_dst, |
| sizeof(struct in_addr), IP_RECVDSTADDR, IPPROTO_IP); |
sizeof(struct in_addr), IP_RECVDSTADDR, IPPROTO_IP); |
| if (*mp) |
if (*mp) |
| mp = &(*mp)->m_next; |
mp = &(*mp)->m_next; |
| Line 2081 ip_savecontrol(struct inpcb *inp, struct |
|
| Line 2065 ip_savecontrol(struct inpcb *inp, struct |
|
| */ |
*/ |
| /* options were tossed already */ |
/* options were tossed already */ |
| if (inp->inp_flags & INP_RECVOPTS) { |
if (inp->inp_flags & INP_RECVOPTS) { |
| *mp = sbcreatecontrol((caddr_t) opts_deleted_above, |
*mp = sbcreatecontrol((void *) opts_deleted_above, |
| sizeof(struct in_addr), IP_RECVOPTS, IPPROTO_IP); |
sizeof(struct in_addr), IP_RECVOPTS, IPPROTO_IP); |
| if (*mp) |
if (*mp) |
| mp = &(*mp)->m_next; |
mp = &(*mp)->m_next; |
| } |
} |
| /* ip_srcroute doesn't do what we want here, need to fix */ |
/* ip_srcroute doesn't do what we want here, need to fix */ |
| if (inp->inp_flags & INP_RECVRETOPTS) { |
if (inp->inp_flags & INP_RECVRETOPTS) { |
| *mp = sbcreatecontrol((caddr_t) ip_srcroute(), |
*mp = sbcreatecontrol((void *) ip_srcroute(), |
| sizeof(struct in_addr), IP_RECVRETOPTS, IPPROTO_IP); |
sizeof(struct in_addr), IP_RECVRETOPTS, IPPROTO_IP); |
| if (*mp) |
if (*mp) |
| mp = &(*mp)->m_next; |
mp = &(*mp)->m_next; |
| Line 2102 ip_savecontrol(struct inpcb *inp, struct |
|
| Line 2086 ip_savecontrol(struct inpcb *inp, struct |
|
| sdl.sdl_index = m->m_pkthdr.rcvif ? |
sdl.sdl_index = m->m_pkthdr.rcvif ? |
| m->m_pkthdr.rcvif->if_index : 0; |
m->m_pkthdr.rcvif->if_index : 0; |
| sdl.sdl_nlen = sdl.sdl_alen = sdl.sdl_slen = 0; |
sdl.sdl_nlen = sdl.sdl_alen = sdl.sdl_slen = 0; |
| *mp = sbcreatecontrol((caddr_t) &sdl, sdl.sdl_len, |
*mp = sbcreatecontrol((void *) &sdl, sdl.sdl_len, |
| IP_RECVIF, IPPROTO_IP); |
IP_RECVIF, IPPROTO_IP); |
| if (*mp) |
if (*mp) |
| mp = &(*mp)->m_next; |
mp = &(*mp)->m_next; |
| Line 2161 sysctl_net_inet_ip_pmtudto(SYSCTLFN_ARGS |
|
| Line 2145 sysctl_net_inet_ip_pmtudto(SYSCTLFN_ARGS |
|
| |
|
| #ifdef GATEWAY |
#ifdef GATEWAY |
| /* |
/* |
| * sysctl helper routine for net.inet.ip.maxflows. apparently if |
* sysctl helper routine for net.inet.ip.maxflows. |
| * 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 2170 sysctl_net_inet_ip_maxflows(SYSCTLFN_ARG |
|
| Line 2153 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) |
if (s || newp == NULL) |
| return (s); |
return (s); |
| |
|
| s = splsoftnet(); |
s = splsoftnet(); |
| Line 2179 sysctl_net_inet_ip_maxflows(SYSCTLFN_ARG |
|
| Line 2162 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 2300 SYSCTL_SETUP(sysctl_net_inet_ip_setup, " |
|
| Line 2312 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, |