Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/netinet/ip_input.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/netinet/ip_input.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.224.2.1 retrieving revision 1.246 diff -u -p -r1.224.2.1 -r1.246 --- src/sys/netinet/ip_input.c 2006/05/24 10:59:03 1.224.2.1 +++ src/sys/netinet/ip_input.c 2007/03/12 18:18:36 1.246 @@ -1,4 +1,4 @@ -/* $NetBSD: ip_input.c,v 1.224.2.1 2006/05/24 10:59:03 yamt Exp $ */ +/* $NetBSD: ip_input.c,v 1.246 2007/03/12 18:18:36 ad Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -98,7 +98,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.224.2.1 2006/05/24 10:59:03 yamt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.246 2007/03/12 18:18:36 ad Exp $"); #include "opt_inet.h" #include "opt_gateway.h" @@ -121,6 +121,7 @@ __KERNEL_RCSID(0, "$NetBSD: ip_input.c,v #include #include #include +#include #include #include @@ -333,8 +334,10 @@ do { \ #define IPQ_UNLOCK() ipq_unlock() -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); +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); #ifdef INET_CSUM_COUNTERS #include @@ -376,8 +379,8 @@ static struct ip_srcrt { static void save_rte(u_char *, struct in_addr); #ifdef MBUFTRACE -struct mowner ip_rx_mowner = { "internet", "rx" }; -struct mowner ip_tx_mowner = { "internet", "tx" }; +struct mowner ip_rx_mowner = MOWNER_INIT("internet", "rx"); +struct mowner ip_tx_mowner = MOWNER_INIT("internet", "tx"); #endif /* @@ -414,7 +417,7 @@ ip_init(void) for (i = 0; i < IPREASS_NHASH; i++) LIST_INIT(&ipq[i]); - ip_id = time.tv_sec & 0xfffff; + ip_id = time_second & 0xfffff; ipintrq.ifq_maxlen = ipqmaxlen; ip_nmbclusters_changed(); @@ -445,7 +448,10 @@ ip_init(void) #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; /* @@ -457,7 +463,7 @@ ipintr(void) int s; struct mbuf *m; - while (1) { + while (!IF_IS_EMPTY(&ipintrq)) { s = splnet(); IF_DEQUEUE(&ipintrq, m); splx(s); @@ -484,12 +490,13 @@ ip_input(struct mbuf *m) int downmatch; int checkif; int srcrt = 0; + int s; u_int hash; #ifdef FAST_IPSEC struct m_tag *mtag; struct tdb_ident *tdbi; struct secpolicy *sp; - int s, error; + int error; #endif /* FAST_IPSEC */ MCLAIM(m, &ip_rx_mowner); @@ -511,7 +518,7 @@ ip_input(struct mbuf *m) * it. Otherwise, if it is aligned, make sure the entire * 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), (max_linkhdr + 3) & ~3)) == NULL) { /* XXXJRT new stat, please */ @@ -938,7 +945,9 @@ found: */ if (mff || ip->ip_off != htons(0)) { ipstat.ips_fragments++; + s = splvm(); ipqe = pool_get(&ipqent_pool, PR_NOWAIT); + splx(s); if (ipqe == NULL) { ipstat.ips_rcvmemdrop++; IPQ_UNLOCK(); @@ -1051,7 +1060,7 @@ ip_reass(struct ipqent *ipqe, struct ipq struct ip *ip; struct mbuf *t; int hlen = ipqe->ipqe_ip->ip_hl << 2; - int i, next; + int i, next, s; IPQ_LOCK_CHECK(); @@ -1156,7 +1165,9 @@ ip_reass(struct ipqent *ipqe, struct ipq nq = TAILQ_NEXT(q, ipqe_q); m_freem(q->ipqe_m); TAILQ_REMOVE(&fp->ipq_fragq, q, ipqe_q); + s = splvm(); pool_put(&ipqent_pool, q); + splx(s); fp->ipq_nfrags--; ip_nfrags--; } @@ -1197,11 +1208,15 @@ insert: m->m_next = 0; m_cat(m, t); nq = TAILQ_NEXT(q, ipqe_q); + s = splvm(); pool_put(&ipqent_pool, q); + splx(s); for (q = nq; q != NULL; q = nq) { t = q->ipqe_m; nq = TAILQ_NEXT(q, ipqe_q); + s = splvm(); pool_put(&ipqent_pool, q); + splx(s); m_cat(m, t); } ip_nfrags -= fp->ipq_nfrags; @@ -1236,7 +1251,9 @@ dropfrag: ip_nfrags--; ipstat.ips_fragdropped++; m_freem(m); + s = splvm(); pool_put(&ipqent_pool, ipqe); + splx(s); return (0); } @@ -1249,6 +1266,7 @@ ip_freef(struct ipq *fp) { struct ipqent *q, *p; u_int nfrags = 0; + int s; IPQ_LOCK_CHECK(); @@ -1257,7 +1275,9 @@ ip_freef(struct ipq *fp) m_freem(q->ipqe_m); nfrags++; TAILQ_REMOVE(&fp->ipq_fragq, q, ipqe_q); + s = splvm(); pool_put(&ipqent_pool, q); + splx(s); } if (nfrags != fp->ipq_nfrags) @@ -1389,9 +1409,6 @@ ip_slowtimo(void) dropscanidx = i; } IPQ_UNLOCK(); -#ifdef GATEWAY - ipflow_slowtimo(); -#endif splx(s); } @@ -1510,7 +1527,7 @@ ip_dooptions(struct mbuf *m) /* * 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)); if (opt == IPOPT_SSRR) ia = ifatoia(ifa_ifwithladdr(sintosa(&ipaddr))); @@ -1522,8 +1539,8 @@ ip_dooptions(struct mbuf *m) goto bad; } ip->ip_dst = ipaddr.sin_addr; - bcopy((caddr_t)&ia->ia_addr.sin_addr, - (caddr_t)(cp + off), sizeof(struct in_addr)); + bcopy((void *)&ia->ia_addr.sin_addr, + (void *)(cp + off), sizeof(struct in_addr)); cp[IPOPT_OFFSET] += sizeof(struct in_addr); /* * Let ip_intr's mcast routing check handle mcast pkts @@ -1546,7 +1563,7 @@ ip_dooptions(struct mbuf *m) off--; /* 0 origin */ if ((off + sizeof(struct in_addr)) > optlen) 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)); /* * locate outgoing interface; if we're the destination, @@ -1559,8 +1576,8 @@ ip_dooptions(struct mbuf *m) code = ICMP_UNREACH_HOST; goto bad; } - bcopy((caddr_t)&ia->ia_addr.sin_addr, - (caddr_t)(cp + off), sizeof(struct in_addr)); + bcopy((void *)&ia->ia_addr.sin_addr, + (void *)(cp + off), sizeof(struct in_addr)); cp[IPOPT_OFFSET] += sizeof(struct in_addr); break; @@ -1629,7 +1646,7 @@ ip_dooptions(struct mbuf *m) } ntime = iptime(); 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)); ipt->ipt_ptr += sizeof(n_time); } @@ -1657,24 +1674,23 @@ bad: struct in_ifaddr * ip_rtaddr(struct in_addr dst) { - struct sockaddr_in *sin; + if (!in_hosteq(dst, satocsin(rtcache_getdst(&ipforward_rt))->sin_addr)) + rtcache_free(&ipforward_rt); + else + rtcache_check(&ipforward_rt); - sin = satosin(&ipforward_rt.ro_dst); + if (ipforward_rt.ro_rt == NULL) { + struct sockaddr_in *sin = satosin(&ipforward_rt.ro_dst); - if (ipforward_rt.ro_rt == 0 || !in_hosteq(dst, sin->sin_addr)) { - 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; - 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); } /* @@ -1693,7 +1709,7 @@ save_rte(u_char *option, struct in_addr #endif /* 0 */ if (olen > sizeof(ip_srcrt) - (1 + sizeof(dst))) 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_srcrt.dst = dst; } @@ -1710,10 +1726,10 @@ ip_srcroute(void) struct mbuf *m; if (ip_nhops == 0) - return ((struct mbuf *)0); + return NULL; m = m_get(M_DONTWAIT, MT_SOOPTS); if (m == 0) - return ((struct mbuf *)0); + return NULL; MCLAIM(m, &inetdomain.dom_mowner); #define OPTSIZ (sizeof(ip_srcrt.nop) + sizeof(ip_srcrt.srcopt)) @@ -1741,9 +1757,9 @@ ip_srcroute(void) */ ip_srcrt.nop = IPOPT_NOP; ip_srcrt.srcopt[IPOPT_OFFSET] = IPOPT_MINOFF; - bcopy((caddr_t)&ip_srcrt.nop, - mtod(m, caddr_t) + sizeof(struct in_addr), OPTSIZ); - q = (struct in_addr *)(mtod(m, caddr_t) + + memmove(mtod(m, char *) + sizeof(struct in_addr), &ip_srcrt.nop, + OPTSIZ); + q = (struct in_addr *)(mtod(m, char *) + sizeof(struct in_addr) + OPTSIZ); #undef OPTSIZ /* @@ -1780,13 +1796,13 @@ ip_stripoptions(struct mbuf *m, struct m { int i; struct ip *ip = mtod(m, struct ip *); - caddr_t opts; + void *opts; int olen; 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); - bcopy(opts + olen, opts, (unsigned)i); + memmove(opts, (char *)opts + olen, (unsigned)i); m->m_len -= olen; if (m->m_flags & M_PKTHDR) m->m_pkthdr.len -= olen; @@ -1821,7 +1837,6 @@ void ip_forward(struct mbuf *m, int srcrt) { struct ip *ip = mtod(m, struct ip *); - struct sockaddr_in *sin; struct rtentry *rt; int error, type = 0, code = 0, destmtu = 0; struct mbuf *mcopy; @@ -1854,24 +1869,25 @@ ip_forward(struct mbuf *m, int srcrt) return; } - sin = satosin(&ipforward_rt.ro_dst); - if ((rt = ipforward_rt.ro_rt) == 0 || - !in_hosteq(ip->ip_dst, sin->sin_addr)) { - if (ipforward_rt.ro_rt) { - RTFREE(ipforward_rt.ro_rt); - ipforward_rt.ro_rt = 0; - } + if (!in_hosteq(ip->ip_dst, + satocsin(rtcache_getdst(&ipforward_rt))->sin_addr)) + rtcache_free(&ipforward_rt); + 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(struct sockaddr_in); + sin->sin_len = sizeof(*sin); sin->sin_addr = ip->ip_dst; - rtalloc(&ipforward_rt); - if (ipforward_rt.ro_rt == 0) { + 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; } + rt = ipforward_rt.ro_rt; /* * Save at most 68 bytes of the packet in case @@ -1917,7 +1933,7 @@ 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)), (struct ip_moptions *)NULL, (struct socket *)NULL); @@ -1960,7 +1976,7 @@ ip_forward(struct mbuf *m, int srcrt) type = ICMP_UNREACH; code = ICMP_UNREACH_NEEDFRAG; #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; #else /* @@ -1969,7 +1985,7 @@ ip_forward(struct mbuf *m, int srcrt) * tunnel MTU = if MTU - sizeof(IP) - ESP/AH hdrsiz * XXX quickhack!!! */ - if (ipforward_rt.ro_rt) { + if (ipforward_rt.ro_rt != NULL) { struct secpolicy *sp; int ipsecerror; size_t ipsechdr; @@ -2044,13 +2060,13 @@ ip_savecontrol(struct inpcb *inp, struct struct timeval tv; microtime(&tv); - *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv), + *mp = sbcreatecontrol((void *) &tv, sizeof(tv), SCM_TIMESTAMP, SOL_SOCKET); if (*mp) mp = &(*mp)->m_next; } 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); if (*mp) mp = &(*mp)->m_next; @@ -2064,14 +2080,14 @@ ip_savecontrol(struct inpcb *inp, struct */ /* options were tossed already */ 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); if (*mp) mp = &(*mp)->m_next; } /* ip_srcroute doesn't do what we want here, need to fix */ 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); if (*mp) mp = &(*mp)->m_next; @@ -2085,7 +2101,7 @@ ip_savecontrol(struct inpcb *inp, struct sdl.sdl_index = m->m_pkthdr.rcvif ? m->m_pkthdr.rcvif->if_index : 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); if (*mp) mp = &(*mp)->m_next; @@ -2093,6 +2109,31 @@ 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 * range of the new value and tweaks timers if it changes. */ @@ -2193,11 +2234,11 @@ SYSCTL_SETUP(sysctl_net_inet_ip_setup, " IPCTL_DEFMTU, CTL_EOL); #endif /* IPCTL_DEFMTU */ sysctl_createv(clog, 0, NULL, NULL, - CTLFLAG_PERMANENT|CTLFLAG_READONLY1, + CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT, "forwsrcrt", SYSCTL_DESCR("Enable forwarding of source-routed " "datagrams"), - NULL, 0, &ip_forwsrcrt, 0, + sysctl_net_inet_ip_forwsrcrt, 0, &ip_forwsrcrt, 0, CTL_NET, PF_INET, IPPROTO_IP, IPCTL_FORWSRCRT, CTL_EOL); sysctl_createv(clog, 0, NULL, NULL,