version 1.218.2.4, 2007/09/03 14:42:58 |
version 1.224, 2006/02/18 17:47:07 |
Line 121 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 121 __KERNEL_RCSID(0, "$NetBSD$"); |
|
#include <sys/kernel.h> |
#include <sys/kernel.h> |
#include <sys/pool.h> |
#include <sys/pool.h> |
#include <sys/sysctl.h> |
#include <sys/sysctl.h> |
#include <sys/kauth.h> |
|
|
|
#include <net/if.h> |
#include <net/if.h> |
#include <net/if_dl.h> |
#include <net/if_dl.h> |
|
|
|
|
#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); |
IPL_SOFTNET); |
POOL_INIT(ipqent_pool, sizeof(struct ipqent), 0, 0, 0, "ipqepl", NULL); |
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> |
Line 379 static struct ip_srcrt { |
|
Line 376 static struct ip_srcrt { |
|
static void save_rte(u_char *, struct in_addr); |
static void save_rte(u_char *, struct in_addr); |
|
|
#ifdef MBUFTRACE |
#ifdef MBUFTRACE |
struct mowner ip_rx_mowner = MOWNER_INIT("internet", "rx"); |
struct mowner ip_rx_mowner = { "internet", "rx" }; |
struct mowner ip_tx_mowner = MOWNER_INIT("internet", "tx"); |
struct mowner ip_tx_mowner = { "internet", "tx" }; |
#endif |
#endif |
|
|
/* |
/* |
|
|
for (i = 0; i < IPREASS_NHASH; i++) |
for (i = 0; i < IPREASS_NHASH; i++) |
LIST_INIT(&ipq[i]); |
LIST_INIT(&ipq[i]); |
|
|
ip_id = time_second & 0xfffff; |
ip_id = time.tv_sec & 0xfffff; |
|
|
ipintrq.ifq_maxlen = ipqmaxlen; |
ipintrq.ifq_maxlen = ipqmaxlen; |
ip_nmbclusters_changed(); |
ip_nmbclusters_changed(); |
|
|
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 |
|
|
#endif /* MBUFTRACE */ |
#endif /* MBUFTRACE */ |
} |
} |
|
|
struct sockaddr_in ipaddr = { |
struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET }; |
.sin_len = sizeof(ipaddr), |
|
.sin_family = AF_INET, |
|
}; |
|
struct route ipforward_rt; |
struct route ipforward_rt; |
|
|
/* |
/* |
|
|
int s; |
int s; |
struct mbuf *m; |
struct mbuf *m; |
|
|
while (!IF_IS_EMPTY(&ipintrq)) { |
while (1) { |
s = splnet(); |
s = splnet(); |
IF_DEQUEUE(&ipintrq, m); |
IF_DEQUEUE(&ipintrq, m); |
splx(s); |
splx(s); |
Line 490 ip_input(struct mbuf *m) |
|
Line 484 ip_input(struct mbuf *m) |
|
int downmatch; |
int downmatch; |
int checkif; |
int checkif; |
int srcrt = 0; |
int srcrt = 0; |
int s; |
|
u_int hash; |
u_int hash; |
#ifdef FAST_IPSEC |
#ifdef FAST_IPSEC |
struct m_tag *mtag; |
struct m_tag *mtag; |
struct tdb_ident *tdbi; |
struct tdb_ident *tdbi; |
struct secpolicy *sp; |
struct secpolicy *sp; |
int error; |
int s, error; |
#endif /* FAST_IPSEC */ |
#endif /* FAST_IPSEC */ |
|
|
MCLAIM(m, &ip_rx_mowner); |
MCLAIM(m, &ip_rx_mowner); |
Line 518 ip_input(struct mbuf *m) |
|
Line 511 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, void *)) == 0) { |
if (IP_HDR_ALIGNED_P(mtod(m, caddr_t)) == 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 739 ip_input(struct mbuf *m) |
|
Line 732 ip_input(struct mbuf *m) |
|
} |
} |
if (ia != NULL) |
if (ia != NULL) |
goto ours; |
goto ours; |
if (m->m_pkthdr.rcvif && m->m_pkthdr.rcvif->if_flags & IFF_BROADCAST) { |
if (m->m_pkthdr.rcvif->if_flags & IFF_BROADCAST) { |
IFADDR_FOREACH(ifa, m->m_pkthdr.rcvif) { |
IFADDR_FOREACH(ifa, m->m_pkthdr.rcvif) { |
if (ifa->ifa_addr->sa_family != AF_INET) |
if (ifa->ifa_addr->sa_family != AF_INET) |
continue; |
continue; |
|
|
*/ |
*/ |
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) && |
|
|
*/ |
*/ |
if (mff || ip->ip_off != htons(0)) { |
if (mff || ip->ip_off != htons(0)) { |
ipstat.ips_fragments++; |
ipstat.ips_fragments++; |
s = splvm(); |
|
ipqe = pool_get(&ipqent_pool, PR_NOWAIT); |
ipqe = pool_get(&ipqent_pool, PR_NOWAIT); |
splx(s); |
|
if (ipqe == NULL) { |
if (ipqe == NULL) { |
ipstat.ips_rcvmemdrop++; |
ipstat.ips_rcvmemdrop++; |
IPQ_UNLOCK(); |
IPQ_UNLOCK(); |
|
|
goto bad; |
goto bad; |
} |
} |
#endif |
#endif |
#ifdef FAST_IPSEC |
#if FAST_IPSEC |
/* |
/* |
* enforce IPsec policy checking if we are seeing last header. |
* enforce IPsec policy checking if we are seeing last header. |
* note that we do not visit this with protocols with pcb layer |
* note that we do not visit this with protocols with pcb layer |
Line 1058 ip_reass(struct ipqent *ipqe, struct ipq |
|
Line 1051 ip_reass(struct ipqent *ipqe, struct ipq |
|
struct ip *ip; |
struct ip *ip; |
struct mbuf *t; |
struct mbuf *t; |
int hlen = ipqe->ipqe_ip->ip_hl << 2; |
int hlen = ipqe->ipqe_ip->ip_hl << 2; |
int i, next, s; |
int i, next; |
|
|
IPQ_LOCK_CHECK(); |
IPQ_LOCK_CHECK(); |
|
|
Line 1163 ip_reass(struct ipqent *ipqe, struct ipq |
|
Line 1156 ip_reass(struct ipqent *ipqe, struct ipq |
|
nq = TAILQ_NEXT(q, ipqe_q); |
nq = TAILQ_NEXT(q, ipqe_q); |
m_freem(q->ipqe_m); |
m_freem(q->ipqe_m); |
TAILQ_REMOVE(&fp->ipq_fragq, q, ipqe_q); |
TAILQ_REMOVE(&fp->ipq_fragq, q, ipqe_q); |
s = splvm(); |
|
pool_put(&ipqent_pool, q); |
pool_put(&ipqent_pool, q); |
splx(s); |
|
fp->ipq_nfrags--; |
fp->ipq_nfrags--; |
ip_nfrags--; |
ip_nfrags--; |
} |
} |
|
|
m->m_next = 0; |
m->m_next = 0; |
m_cat(m, t); |
m_cat(m, t); |
nq = TAILQ_NEXT(q, ipqe_q); |
nq = TAILQ_NEXT(q, ipqe_q); |
s = splvm(); |
|
pool_put(&ipqent_pool, q); |
pool_put(&ipqent_pool, q); |
splx(s); |
|
for (q = nq; q != NULL; q = nq) { |
for (q = nq; q != NULL; q = nq) { |
t = q->ipqe_m; |
t = q->ipqe_m; |
nq = TAILQ_NEXT(q, ipqe_q); |
nq = TAILQ_NEXT(q, ipqe_q); |
s = splvm(); |
|
pool_put(&ipqent_pool, q); |
pool_put(&ipqent_pool, q); |
splx(s); |
|
m_cat(m, t); |
m_cat(m, t); |
} |
} |
ip_nfrags -= fp->ipq_nfrags; |
ip_nfrags -= fp->ipq_nfrags; |
|
|
ip_nfrags--; |
ip_nfrags--; |
ipstat.ips_fragdropped++; |
ipstat.ips_fragdropped++; |
m_freem(m); |
m_freem(m); |
s = splvm(); |
|
pool_put(&ipqent_pool, ipqe); |
pool_put(&ipqent_pool, ipqe); |
splx(s); |
|
return (0); |
return (0); |
} |
} |
|
|
Line 1264 ip_freef(struct ipq *fp) |
|
Line 1249 ip_freef(struct ipq *fp) |
|
{ |
{ |
struct ipqent *q, *p; |
struct ipqent *q, *p; |
u_int nfrags = 0; |
u_int nfrags = 0; |
int s; |
|
|
|
IPQ_LOCK_CHECK(); |
IPQ_LOCK_CHECK(); |
|
|
Line 1273 ip_freef(struct ipq *fp) |
|
Line 1257 ip_freef(struct ipq *fp) |
|
m_freem(q->ipqe_m); |
m_freem(q->ipqe_m); |
nfrags++; |
nfrags++; |
TAILQ_REMOVE(&fp->ipq_fragq, q, ipqe_q); |
TAILQ_REMOVE(&fp->ipq_fragq, q, ipqe_q); |
s = splvm(); |
|
pool_put(&ipqent_pool, q); |
pool_put(&ipqent_pool, q); |
splx(s); |
|
} |
} |
|
|
if (nfrags != fp->ipq_nfrags) |
if (nfrags != fp->ipq_nfrags) |
Line 1407 ip_slowtimo(void) |
|
Line 1389 ip_slowtimo(void) |
|
dropscanidx = i; |
dropscanidx = i; |
} |
} |
IPQ_UNLOCK(); |
IPQ_UNLOCK(); |
|
#ifdef GATEWAY |
|
ipflow_slowtimo(); |
|
#endif |
splx(s); |
splx(s); |
} |
} |
|
|
Line 1525 ip_dooptions(struct mbuf *m) |
|
Line 1510 ip_dooptions(struct mbuf *m) |
|
/* |
/* |
* locate outgoing interface |
* locate outgoing interface |
*/ |
*/ |
bcopy((void *)(cp + off), (void *)&ipaddr.sin_addr, |
bcopy((caddr_t)(cp + off), (caddr_t)&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 1537 ip_dooptions(struct mbuf *m) |
|
Line 1522 ip_dooptions(struct mbuf *m) |
|
goto bad; |
goto bad; |
} |
} |
ip->ip_dst = ipaddr.sin_addr; |
ip->ip_dst = ipaddr.sin_addr; |
bcopy((void *)&ia->ia_addr.sin_addr, |
bcopy((caddr_t)&ia->ia_addr.sin_addr, |
(void *)(cp + off), sizeof(struct in_addr)); |
(caddr_t)(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 1561 ip_dooptions(struct mbuf *m) |
|
Line 1546 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((void *)(&ip->ip_dst), (void *)&ipaddr.sin_addr, |
bcopy((caddr_t)(&ip->ip_dst), (caddr_t)&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 1574 ip_dooptions(struct mbuf *m) |
|
Line 1559 ip_dooptions(struct mbuf *m) |
|
code = ICMP_UNREACH_HOST; |
code = ICMP_UNREACH_HOST; |
goto bad; |
goto bad; |
} |
} |
bcopy((void *)&ia->ia_addr.sin_addr, |
bcopy((caddr_t)&ia->ia_addr.sin_addr, |
(void *)(cp + off), sizeof(struct in_addr)); |
(caddr_t)(cp + off), sizeof(struct in_addr)); |
cp[IPOPT_OFFSET] += sizeof(struct in_addr); |
cp[IPOPT_OFFSET] += sizeof(struct in_addr); |
break; |
break; |
|
|
Line 1644 ip_dooptions(struct mbuf *m) |
|
Line 1629 ip_dooptions(struct mbuf *m) |
|
} |
} |
ntime = iptime(); |
ntime = iptime(); |
cp0 = (u_char *) &ntime; /* XXX grumble, GCC... */ |
cp0 = (u_char *) &ntime; /* XXX grumble, GCC... */ |
memmove((char *)cp + ipt->ipt_ptr - 1, cp0, |
bcopy(cp0, (caddr_t)cp + ipt->ipt_ptr - 1, |
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 rtentry *rt; |
struct sockaddr_in *sin; |
union { |
|
struct sockaddr dst; |
|
struct sockaddr_in dst4; |
|
} u; |
|
|
|
sockaddr_in_init(&u.dst4, &dst, 0); |
sin = satosin(&ipforward_rt.ro_dst); |
|
|
if ((rt = rtcache_lookup(&ipforward_rt, &u.dst)) == NULL) |
if (ipforward_rt.ro_rt == 0 || !in_hosteq(dst, sin->sin_addr)) { |
return NULL; |
if (ipforward_rt.ro_rt) { |
|
RTFREE(ipforward_rt.ro_rt); |
|
ipforward_rt.ro_rt = 0; |
|
} |
|
sin->sin_family = AF_INET; |
|
sin->sin_len = sizeof(*sin); |
|
sin->sin_addr = dst; |
|
|
return ifatoia(rt->rt_ifa); |
rtalloc(&ipforward_rt); |
|
} |
|
if (ipforward_rt.ro_rt == 0) |
|
return ((struct in_ifaddr *)0); |
|
return (ifatoia(ipforward_rt.ro_rt->rt_ifa)); |
} |
} |
|
|
/* |
/* |
Line 1702 save_rte(u_char *option, struct in_addr |
|
Line 1693 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((void *)option, (void *)ip_srcrt.srcopt, olen); |
bcopy((caddr_t)option, (caddr_t)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 1719 ip_srcroute(void) |
|
Line 1710 ip_srcroute(void) |
|
struct mbuf *m; |
struct mbuf *m; |
|
|
if (ip_nhops == 0) |
if (ip_nhops == 0) |
return NULL; |
return ((struct mbuf *)0); |
m = m_get(M_DONTWAIT, MT_SOOPTS); |
m = m_get(M_DONTWAIT, MT_SOOPTS); |
if (m == 0) |
if (m == 0) |
return NULL; |
return ((struct mbuf *)0); |
|
|
MCLAIM(m, &inetdomain.dom_mowner); |
MCLAIM(m, &inetdomain.dom_mowner); |
#define OPTSIZ (sizeof(ip_srcrt.nop) + sizeof(ip_srcrt.srcopt)) |
#define OPTSIZ (sizeof(ip_srcrt.nop) + sizeof(ip_srcrt.srcopt)) |
Line 1750 ip_srcroute(void) |
|
Line 1741 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; |
memmove(mtod(m, char *) + sizeof(struct in_addr), &ip_srcrt.nop, |
bcopy((caddr_t)&ip_srcrt.nop, |
OPTSIZ); |
mtod(m, caddr_t) + sizeof(struct in_addr), OPTSIZ); |
q = (struct in_addr *)(mtod(m, char *) + |
q = (struct in_addr *)(mtod(m, caddr_t) + |
sizeof(struct in_addr) + OPTSIZ); |
sizeof(struct in_addr) + OPTSIZ); |
#undef OPTSIZ |
#undef OPTSIZ |
/* |
/* |
Line 1789 ip_stripoptions(struct mbuf *m, struct m |
|
Line 1780 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 *); |
void *opts; |
caddr_t opts; |
int olen; |
int olen; |
|
|
olen = (ip->ip_hl << 2) - sizeof (struct ip); |
olen = (ip->ip_hl << 2) - sizeof (struct ip); |
opts = (void *)(ip + 1); |
opts = (caddr_t)(ip + 1); |
i = m->m_len - (sizeof (struct ip) + olen); |
i = m->m_len - (sizeof (struct ip) + olen); |
memmove(opts, (char *)opts + olen, (unsigned)i); |
bcopy(opts + olen, opts, (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 1866 ip_forward(struct mbuf *m, int srcrt) |
|
Line 1854 ip_forward(struct mbuf *m, int srcrt) |
|
return; |
return; |
} |
} |
|
|
sockaddr_in_init(&u.dst4, &ip->ip_dst, 0); |
sin = satosin(&ipforward_rt.ro_dst); |
if ((rt = rtcache_lookup(&ipforward_rt, &u.dst)) == NULL) { |
if ((rt = ipforward_rt.ro_rt) == 0 || |
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, dest, 0); |
!in_hosteq(ip->ip_dst, sin->sin_addr)) { |
return; |
if (ipforward_rt.ro_rt) { |
|
RTFREE(ipforward_rt.ro_rt); |
|
ipforward_rt.ro_rt = 0; |
|
} |
|
sin->sin_family = AF_INET; |
|
sin->sin_len = sizeof(struct sockaddr_in); |
|
sin->sin_addr = ip->ip_dst; |
|
|
|
rtalloc(&ipforward_rt); |
|
if (ipforward_rt.ro_rt == 0) { |
|
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, dest, 0); |
|
return; |
|
} |
|
rt = ipforward_rt.ro_rt; |
} |
} |
|
|
/* |
/* |
Line 1893 ip_forward(struct mbuf *m, int srcrt) |
|
Line 1894 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 1916 ip_forward(struct mbuf *m, int srcrt) |
|
Line 1917 ip_forward(struct mbuf *m, int srcrt) |
|
} |
} |
} |
} |
|
|
error = ip_output(m, NULL, &ipforward_rt, |
error = ip_output(m, (struct mbuf *)0, &ipforward_rt, |
(IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)), |
(IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)), |
(struct ip_moptions *)NULL, (struct socket *)NULL); |
(struct ip_moptions *)NULL, (struct socket *)NULL); |
|
|
Line 1959 ip_forward(struct mbuf *m, int srcrt) |
|
Line 1960 ip_forward(struct mbuf *m, int srcrt) |
|
type = ICMP_UNREACH; |
type = ICMP_UNREACH; |
code = ICMP_UNREACH_NEEDFRAG; |
code = ICMP_UNREACH_NEEDFRAG; |
#if !defined(IPSEC) && !defined(FAST_IPSEC) |
#if !defined(IPSEC) && !defined(FAST_IPSEC) |
if (ipforward_rt.ro_rt != NULL) |
if (ipforward_rt.ro_rt) |
destmtu = ipforward_rt.ro_rt->rt_ifp->if_mtu; |
destmtu = ipforward_rt.ro_rt->rt_ifp->if_mtu; |
#else |
#else |
/* |
/* |
Line 1968 ip_forward(struct mbuf *m, int srcrt) |
|
Line 1969 ip_forward(struct mbuf *m, int srcrt) |
|
* tunnel MTU = if MTU - sizeof(IP) - ESP/AH hdrsiz |
* tunnel MTU = if MTU - sizeof(IP) - ESP/AH hdrsiz |
* XXX quickhack!!! |
* XXX quickhack!!! |
*/ |
*/ |
if (ipforward_rt.ro_rt != NULL) { |
if (ipforward_rt.ro_rt) { |
struct secpolicy *sp; |
struct secpolicy *sp; |
int ipsecerror; |
int ipsecerror; |
size_t ipsechdr; |
size_t ipsechdr; |
Line 2043 ip_savecontrol(struct inpcb *inp, struct |
|
Line 2044 ip_savecontrol(struct inpcb *inp, struct |
|
struct timeval tv; |
struct timeval tv; |
|
|
microtime(&tv); |
microtime(&tv); |
*mp = sbcreatecontrol((void *) &tv, sizeof(tv), |
*mp = sbcreatecontrol((caddr_t) &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((void *) &ip->ip_dst, |
*mp = sbcreatecontrol((caddr_t) &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 2063 ip_savecontrol(struct inpcb *inp, struct |
|
Line 2064 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((void *) opts_deleted_above, |
*mp = sbcreatecontrol((caddr_t) 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((void *) ip_srcroute(), |
*mp = sbcreatecontrol((caddr_t) 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 2079 ip_savecontrol(struct inpcb *inp, struct |
|
Line 2080 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((caddr_t) &sdl, sdl.sdl_len, |
|
IP_RECVIF, IPPROTO_IP); |
if (*mp) |
if (*mp) |
mp = &(*mp)->m_next; |
mp = &(*mp)->m_next; |
} |
} |
} |
} |
|
|
/* |
/* |
* sysctl helper routine for net.inet.ip.forwsrcrt. |
|
*/ |
|
static int |
|
sysctl_net_inet_ip_forwsrcrt(SYSCTLFN_ARGS) |
|
{ |
|
int error, tmp; |
|
struct sysctlnode node; |
|
|
|
node = *rnode; |
|
tmp = ip_forwsrcrt; |
|
node.sysctl_data = &tmp; |
|
error = sysctl_lookup(SYSCTLFN_CALL(&node)); |
|
if (error || newp == NULL) |
|
return (error); |
|
|
|
if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_FORWSRCRT, |
|
0, NULL, NULL, NULL)) |
|
return (EPERM); |
|
|
|
ip_forwsrcrt = tmp; |
|
|
|
return (0); |
|
} |
|
|
|
/* |
|
* sysctl helper routine for net.inet.ip.mtudisctimeout. checks the |
* sysctl helper routine for net.inet.ip.mtudisctimeout. checks the |
* range of the new value and tweaks timers if it changes. |
* range of the new value and tweaks timers if it changes. |
*/ |
*/ |
Line 2142 sysctl_net_inet_ip_pmtudto(SYSCTLFN_ARGS |
|
Line 2119 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 2150 sysctl_net_inet_ip_maxflows(SYSCTLFN_ARG |
|
Line 2128 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 2159 sysctl_net_inet_ip_maxflows(SYSCTLFN_ARG |
|
Line 2137 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 2244 SYSCTL_SETUP(sysctl_net_inet_ip_setup, " |
|
Line 2193 SYSCTL_SETUP(sysctl_net_inet_ip_setup, " |
|
IPCTL_DEFMTU, CTL_EOL); |
IPCTL_DEFMTU, CTL_EOL); |
#endif /* IPCTL_DEFMTU */ |
#endif /* IPCTL_DEFMTU */ |
sysctl_createv(clog, 0, NULL, NULL, |
sysctl_createv(clog, 0, NULL, NULL, |
CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
CTLFLAG_PERMANENT|CTLFLAG_READONLY1, |
CTLTYPE_INT, "forwsrcrt", |
CTLTYPE_INT, "forwsrcrt", |
SYSCTL_DESCR("Enable forwarding of source-routed " |
SYSCTL_DESCR("Enable forwarding of source-routed " |
"datagrams"), |
"datagrams"), |
sysctl_net_inet_ip_forwsrcrt, 0, &ip_forwsrcrt, 0, |
NULL, 0, &ip_forwsrcrt, 0, |
CTL_NET, PF_INET, IPPROTO_IP, |
CTL_NET, PF_INET, IPPROTO_IP, |
IPCTL_FORWSRCRT, CTL_EOL); |
IPCTL_FORWSRCRT, CTL_EOL); |
sysctl_createv(clog, 0, NULL, NULL, |
sysctl_createv(clog, 0, NULL, NULL, |
Line 2309 SYSCTL_SETUP(sysctl_net_inet_ip_setup, " |
|
Line 2258 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, |