| version 1.218.2.1, 2006/06/21 15:11:01 |
version 1.218.2.2, 2006/12/30 20:50:33 |
| 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> |
| Line 376 static struct ip_srcrt { |
|
| Line 377 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 = { "internet", "rx" }; |
struct mowner ip_rx_mowner = MOWNER_INIT("internet", "rx"); |
| struct mowner ip_tx_mowner = { "internet", "tx" }; |
struct mowner ip_tx_mowner = MOWNER_INIT("internet", "tx"); |
| #endif |
#endif |
| |
|
| /* |
/* |
|
|
| #endif /* MBUFTRACE */ |
#endif /* MBUFTRACE */ |
| } |
} |
| |
|
| struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET }; |
struct sockaddr_in ipaddr = { |
| |
.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 (1) { |
while (!IF_IS_EMPTY(&ipintrq)) { |
| s = splnet(); |
s = splnet(); |
| IF_DEQUEUE(&ipintrq, m); |
IF_DEQUEUE(&ipintrq, m); |
| splx(s); |
splx(s); |
| Line 484 ip_input(struct mbuf *m) |
|
| Line 488 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 s, error; |
int error; |
| #endif /* FAST_IPSEC */ |
#endif /* FAST_IPSEC */ |
| |
|
| MCLAIM(m, &ip_rx_mowner); |
MCLAIM(m, &ip_rx_mowner); |
|
|
| */ |
*/ |
| 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(); |
| Line 1051 ip_reass(struct ipqent *ipqe, struct ipq |
|
| Line 1058 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; |
int i, next, s; |
| |
|
| IPQ_LOCK_CHECK(); |
IPQ_LOCK_CHECK(); |
| |
|
| Line 1156 ip_reass(struct ipqent *ipqe, struct ipq |
|
| Line 1163 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 1249 ip_freef(struct ipq *fp) |
|
| Line 1264 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 1257 ip_freef(struct ipq *fp) |
|
| Line 1273 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 1661 ip_rtaddr(struct in_addr dst) |
|
| Line 1679 ip_rtaddr(struct in_addr dst) |
|
| |
|
| sin = satosin(&ipforward_rt.ro_dst); |
sin = satosin(&ipforward_rt.ro_dst); |
| |
|
| if (ipforward_rt.ro_rt == 0 || !in_hosteq(dst, sin->sin_addr)) { |
if (!in_hosteq(dst, sin->sin_addr)) |
| if (ipforward_rt.ro_rt) { |
rtcache_free(&ipforward_rt); |
| RTFREE(ipforward_rt.ro_rt); |
else |
| ipforward_rt.ro_rt = 0; |
rtcache_check(&ipforward_rt); |
| } |
if (ipforward_rt.ro_rt == NULL) { |
| sin->sin_family = AF_INET; |
sin->sin_family = AF_INET; |
| sin->sin_len = sizeof(*sin); |
sin->sin_len = sizeof(*sin); |
| sin->sin_addr = dst; |
sin->sin_addr = dst; |
| |
|
| rtalloc(&ipforward_rt); |
rtcache_init(&ipforward_rt); |
| |
if (ipforward_rt.ro_rt == NULL) |
| |
return NULL; |
| } |
} |
| if (ipforward_rt.ro_rt == 0) |
|
| return ((struct in_ifaddr *)0); |
|
| return (ifatoia(ipforward_rt.ro_rt->rt_ifa)); |
return (ifatoia(ipforward_rt.ro_rt->rt_ifa)); |
| } |
} |
| |
|
| Line 1710 ip_srcroute(void) |
|
| Line 1728 ip_srcroute(void) |
|
| struct mbuf *m; |
struct mbuf *m; |
| |
|
| if (ip_nhops == 0) |
if (ip_nhops == 0) |
| return ((struct mbuf *)0); |
return NULL; |
| m = m_get(M_DONTWAIT, MT_SOOPTS); |
m = m_get(M_DONTWAIT, MT_SOOPTS); |
| if (m == 0) |
if (m == 0) |
| return ((struct mbuf *)0); |
return NULL; |
| |
|
| 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 1855 ip_forward(struct mbuf *m, int srcrt) |
|
| Line 1873 ip_forward(struct mbuf *m, int srcrt) |
|
| } |
} |
| |
|
| sin = satosin(&ipforward_rt.ro_dst); |
sin = satosin(&ipforward_rt.ro_dst); |
| if ((rt = ipforward_rt.ro_rt) == 0 || |
if (!in_hosteq(ip->ip_dst, sin->sin_addr)) |
| !in_hosteq(ip->ip_dst, sin->sin_addr)) { |
rtcache_free(&ipforward_rt); |
| if (ipforward_rt.ro_rt) { |
else |
| RTFREE(ipforward_rt.ro_rt); |
rtcache_check(&ipforward_rt); |
| ipforward_rt.ro_rt = 0; |
if (ipforward_rt.ro_rt == NULL) { |
| } |
|
| sin->sin_family = AF_INET; |
sin->sin_family = AF_INET; |
| sin->sin_len = sizeof(struct sockaddr_in); |
sin->sin_len = sizeof(struct sockaddr_in); |
| sin->sin_addr = ip->ip_dst; |
sin->sin_addr = ip->ip_dst; |
| |
|
| rtalloc(&ipforward_rt); |
rtcache_init(&ipforward_rt); |
| if (ipforward_rt.ro_rt == 0) { |
if (ipforward_rt.ro_rt == NULL) { |
| icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, dest, 0); |
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, dest, 0); |
| return; |
return; |
| } |
} |
| rt = ipforward_rt.ro_rt; |
|
| } |
} |
| |
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 1917 ip_forward(struct mbuf *m, int srcrt) |
|
| Line 1934 ip_forward(struct mbuf *m, int srcrt) |
|
| } |
} |
| } |
} |
| |
|
| error = ip_output(m, (struct mbuf *)0, &ipforward_rt, |
error = ip_output(m, NULL, &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 1960 ip_forward(struct mbuf *m, int srcrt) |
|
| Line 1977 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) |
if (ipforward_rt.ro_rt != NULL) |
| destmtu = ipforward_rt.ro_rt->rt_ifp->if_mtu; |
destmtu = ipforward_rt.ro_rt->rt_ifp->if_mtu; |
| #else |
#else |
| /* |
/* |
| Line 1969 ip_forward(struct mbuf *m, int srcrt) |
|
| Line 1986 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) { |
if (ipforward_rt.ro_rt != NULL) { |
| struct secpolicy *sp; |
struct secpolicy *sp; |
| int ipsecerror; |
int ipsecerror; |
| size_t ipsechdr; |
size_t ipsechdr; |
| Line 2093 ip_savecontrol(struct inpcb *inp, struct |
|
| Line 2110 ip_savecontrol(struct inpcb *inp, struct |
|
| } |
} |
| |
|
| /* |
/* |
| |
* 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 2193 SYSCTL_SETUP(sysctl_net_inet_ip_setup, " |
|
| Line 2235 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_READONLY1, |
CTLFLAG_PERMANENT|CTLFLAG_READWRITE, |
| CTLTYPE_INT, "forwsrcrt", |
CTLTYPE_INT, "forwsrcrt", |
| SYSCTL_DESCR("Enable forwarding of source-routed " |
SYSCTL_DESCR("Enable forwarding of source-routed " |
| "datagrams"), |
"datagrams"), |
| NULL, 0, &ip_forwsrcrt, 0, |
sysctl_net_inet_ip_forwsrcrt, 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, |