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.130.2.14 retrieving revision 1.135 diff -u -p -r1.130.2.14 -r1.135 --- src/sys/netinet/ip_input.c 2002/10/18 02:45:17 1.130.2.14 +++ src/sys/netinet/ip_input.c 2001/06/02 16:17:09 1.135 @@ -1,9 +1,9 @@ -/* $NetBSD: ip_input.c,v 1.130.2.14 2002/10/18 02:45:17 nathanw Exp $ */ +/* $NetBSD: ip_input.c,v 1.135 2001/06/02 16:17:09 thorpej Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -15,7 +15,7 @@ * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -101,9 +101,6 @@ * @(#)ip_input.c 8.2 (Berkeley) 1/4/94 */ -#include -__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.130.2.14 2002/10/18 02:45:17 nathanw Exp $"); - #include "opt_gateway.h" #include "opt_pfil_hooks.h" #include "opt_ipsec.h" @@ -121,7 +118,11 @@ __KERNEL_RCSID(0, "$NetBSD: ip_input.c,v #include #include #include +#include #include + +#include + #include #include @@ -139,8 +140,6 @@ __KERNEL_RCSID(0, "$NetBSD: ip_input.c,v /* just for gif_ttl */ #include #include "gif.h" -#include -#include "gre.h" #ifdef MROUTING #include @@ -168,7 +167,7 @@ __KERNEL_RCSID(0, "$NetBSD: ip_input.c,v #define IPALLOWSRCRT 1 /* allow source-routed packets */ #endif #ifndef IPMTUDISC -#define IPMTUDISC 1 +#define IPMTUDISC 0 #endif #ifndef IPMTUDISCTIMEOUT #define IPMTUDISCTIMEOUT (10 * 60) /* as per RFC 1191 */ @@ -192,7 +191,7 @@ int ip_forwsrcrt = IPFORWSRCRT; int ip_directedbcast = IPDIRECTEDBCAST; int ip_allowsrcrt = IPALLOWSRCRT; int ip_mtudisc = IPMTUDISC; -int ip_mtudisc_timeout = IPMTUDISCTIMEOUT; +u_int ip_mtudisc_timeout = IPMTUDISCTIMEOUT; #ifdef DIAGNOSTIC int ipprintfs = 0; #endif @@ -201,8 +200,6 @@ struct rttimer_queue *ip_mtudisc_timeout extern struct domain inetdomain; int ipqmaxlen = IFQ_MAXLEN; -u_long in_ifaddrhash; /* size of hash table - 1 */ -int in_ifaddrentries; /* total number of addrs */ struct in_ifaddrhead in_ifaddr; struct in_ifaddrhashhead *in_ifaddrhashtbl; struct ifqueue ipintrq; @@ -227,7 +224,7 @@ ipq_lock_try() int s; /* - * Use splvm() -- we're blocking things that would cause + * Use splvm() -- we're bloking things that would cause * mbuf allocation. */ s = splvm(); @@ -320,7 +317,7 @@ ip_init() int i; pool_init(&ipqent_pool, sizeof(struct ipqent), 0, 0, 0, "ipqepl", - NULL); + 0, NULL, NULL, M_IPQ); pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW); if (pr == 0) @@ -339,7 +336,7 @@ ip_init() in_ifaddrhashtbl = hashinit(IN_IFADDR_HASH_SIZE, HASH_LIST, M_IFADDR, M_WAITOK, &in_ifaddrhash); if (ip_mtudisc != 0) - ip_mtudisc_timeout_q = + ip_mtudisc_timeout_q = rt_timer_queue_create(ip_mtudisc_timeout); #ifdef GATEWAY ipflow_init(); @@ -417,27 +414,13 @@ ip_input(struct mbuf *m) * If no IP addresses have been set yet but the interfaces * are receiving, can't do anything with incoming packets yet. */ - if (TAILQ_FIRST(&in_ifaddr) == 0) + if (in_ifaddr.tqh_first == 0) goto bad; ipstat.ips_total++; - /* - * If the IP header is not aligned, slurp it up into a new - * mbuf with space for link headers, in the event we forward - * 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 ((m = m_copyup(m, sizeof(struct ip), - (max_linkhdr + 3) & ~3)) == NULL) { - /* XXXJRT new stat, please */ - ipstat.ips_toosmall++; - return; - } - } else if (__predict_false(m->m_len < sizeof (struct ip))) { - if ((m = m_pullup(m, sizeof (struct ip))) == NULL) { - ipstat.ips_toosmall++; - return; - } + if (m->m_len < sizeof (struct ip) && + (m = m_pullup(m, sizeof (struct ip))) == 0) { + ipstat.ips_toosmall++; + return; } ip = mtod(m, struct ip *); if (ip->ip_v != IPVERSION) { @@ -476,7 +459,7 @@ ip_input(struct mbuf *m) } switch (m->m_pkthdr.csum_flags & - ((m->m_pkthdr.rcvif->if_csum_flags_rx & M_CSUM_IPv4) | + ((m->m_pkthdr.rcvif->if_csum_flags & M_CSUM_IPv4) | M_CSUM_IPv4_BAD)) { case M_CSUM_IPv4|M_CSUM_IPv4_BAD: INET_CSUM_COUNTER_INCR(&ip_hwcsum_bad); @@ -525,7 +508,7 @@ ip_input(struct mbuf *m) } #ifdef IPSEC - /* ipflow (IP fast forwarding) is not compatible with IPsec. */ + /* ipflow (IP fast fowarding) is not compatible with IPsec. */ m->m_flags &= ~M_CANFASTFWD; #else /* @@ -548,7 +531,7 @@ ip_input(struct mbuf *m) * not the decapsulated packet. */ #ifdef IPSEC - if (!ipsec_getnhist(m)) + if (!ipsec_gethist(m, NULL)) #else if (1) #endif @@ -559,7 +542,6 @@ ip_input(struct mbuf *m) if (m == NULL) return; ip = mtod(m, struct ip *); - hlen = ip->ip_hl << 2; } #endif /* PFIL_HOOKS */ @@ -572,6 +554,12 @@ ip_input(struct mbuf *m) #endif /* + * Convert fields to host representation. + */ + NTOHS(ip->ip_len); + NTOHS(ip->ip_off); + + /* * Process options and, if not destined for us, * ship it on. ip_dooptions returns 1 when an * error was detected (causing an icmp message @@ -589,7 +577,9 @@ ip_input(struct mbuf *m) * as not mine. */ downmatch = 0; - LIST_FOREACH(ia, &IN_IFADDR_HASH(ip->ip_dst.s_addr), ia_hash) { + for (ia = IN_IFADDR_HASH(ip->ip_dst.s_addr).lh_first; + ia != NULL; + ia = ia->ia_hash.le_next) { if (in_hosteq(ia->ia_addr.sin_addr, ip->ip_dst)) { if ((ia->ia_ifp->if_flags & IFF_UP) != 0) break; @@ -600,9 +590,9 @@ ip_input(struct mbuf *m) if (ia != NULL) goto ours; if (m->m_pkthdr.rcvif->if_flags & IFF_BROADCAST) { - TAILQ_FOREACH(ifa, &m->m_pkthdr.rcvif->if_addrlist, ifa_list) { - if (ifa->ifa_addr->sa_family != AF_INET) - continue; + for (ifa = m->m_pkthdr.rcvif->if_addrlist.tqh_first; + ifa != NULL; ifa = ifa->ifa_list.tqe_next) { + if (ifa->ifa_addr->sa_family != AF_INET) continue; ia = ifatoia(ifa); if (in_hosteq(ip->ip_dst, ia->ia_broadaddr.sin_addr) || in_hosteq(ip->ip_dst, ia->ia_netbroadcast) || @@ -626,7 +616,7 @@ ip_input(struct mbuf *m) #ifdef MROUTING extern struct socket *ip_mrouter; - if (M_READONLY(m)) { + if (m->m_flags & M_EXT) { if ((m = m_pullup(m, hlen)) == 0) { ipstat.ips_toosmall++; return; @@ -697,13 +687,6 @@ ip_input(struct mbuf *m) ipstat.ips_cantforward++; return; } -#ifdef IPSEC - if (ipsec4_in_reject(m, NULL)) { - ipsecstat.in_polvio++; - goto bad; - } -#endif - ip_forward(m, 0); } return; @@ -716,21 +699,13 @@ ours: * if the packet was previously fragmented, * but it's not worth the time; just let them time out.) */ - if (ip->ip_off & ~htons(IP_DF|IP_RF)) { - if (M_READONLY(m)) { - if ((m = m_pullup(m, hlen)) == NULL) { - ipstat.ips_toosmall++; - goto bad; - } - ip = mtod(m, struct ip *); - } - + if (ip->ip_off & ~(IP_DF|IP_RF)) { /* * Look for queue of fragments * of this datagram. */ IPQ_LOCK(); - LIST_FOREACH(fp, &ipq, ipq_q) + for (fp = ipq.lh_first; fp != NULL; fp = fp->ipq_q.le_next) if (ip->ip_id == fp->ipq_id && in_hosteq(ip->ip_src, fp->ipq_src) && in_hosteq(ip->ip_dst, fp->ipq_dst) && @@ -744,28 +719,27 @@ found: * set ipqe_mff if more fragments are expected, * convert offset of this to bytes. */ - ip->ip_len = htons(ntohs(ip->ip_len) - hlen); - mff = (ip->ip_off & htons(IP_MF)) != 0; + ip->ip_len -= hlen; + mff = (ip->ip_off & IP_MF) != 0; if (mff) { /* * Make sure that fragments have a data length * that's a non-zero multiple of 8 bytes. */ - if (ntohs(ip->ip_len) == 0 || - (ntohs(ip->ip_len) & 0x7) != 0) { + if (ip->ip_len == 0 || (ip->ip_len & 0x7) != 0) { ipstat.ips_badfrags++; IPQ_UNLOCK(); goto bad; } } - ip->ip_off = htons((ntohs(ip->ip_off) & IP_OFFMASK) << 3); + ip->ip_off <<= 3; /* * If datagram marked as having more fragments * or if this is not the first fragment, * attempt reassembly; if it succeeds, proceed. */ - if (mff || ip->ip_off != htons(0)) { + if (mff || ip->ip_off) { ipstat.ips_fragments++; ipqe = pool_get(&ipqent_pool, PR_NOWAIT); if (ipqe == NULL) { @@ -784,7 +758,7 @@ found: ipstat.ips_reassembled++; ip = mtod(m, struct ip *); hlen = ip->ip_hl << 2; - ip->ip_len = htons(ntohs(ip->ip_len) + hlen); + ip->ip_len += hlen; } else if (fp) ip_freef(fp); @@ -809,7 +783,7 @@ found: */ #if IFA_STATS if (ia && ip) - ia->ia_ifa.ifa_data.ifad_inbytes += ntohs(ip->ip_len); + ia->ia_ifa.ifa_data.ifad_inbytes += ip->ip_len; #endif ipstat.ips_delivered++; { @@ -877,7 +851,7 @@ ip_reass(ipqe, fp) fp->ipq_ttl = IPFRAGTTL; fp->ipq_p = ipqe->ipqe_ip->ip_p; fp->ipq_id = ipqe->ipqe_ip->ip_id; - TAILQ_INIT(&fp->ipq_fragq); + LIST_INIT(&fp->ipq_fragq); fp->ipq_src = ipqe->ipqe_ip->ip_src; fp->ipq_dst = ipqe->ipqe_ip->ip_dst; p = NULL; @@ -887,9 +861,9 @@ ip_reass(ipqe, fp) /* * Find a segment which begins after this one does. */ - for (p = NULL, q = TAILQ_FIRST(&fp->ipq_fragq); q != NULL; - p = q, q = TAILQ_NEXT(q, ipqe_q)) - if (ntohs(q->ipqe_ip->ip_off) > ntohs(ipqe->ipqe_ip->ip_off)) + for (p = NULL, q = fp->ipq_fragq.lh_first; q != NULL; + p = q, q = q->ipqe_q.le_next) + if (q->ipqe_ip->ip_off > ipqe->ipqe_ip->ip_off) break; /* @@ -898,16 +872,14 @@ ip_reass(ipqe, fp) * segment. If it provides all of our data, drop us. */ if (p != NULL) { - i = ntohs(p->ipqe_ip->ip_off) + ntohs(p->ipqe_ip->ip_len) - - ntohs(ipqe->ipqe_ip->ip_off); + i = p->ipqe_ip->ip_off + p->ipqe_ip->ip_len - + ipqe->ipqe_ip->ip_off; if (i > 0) { - if (i >= ntohs(ipqe->ipqe_ip->ip_len)) + if (i >= ipqe->ipqe_ip->ip_len) goto dropfrag; m_adj(ipqe->ipqe_m, i); - ipqe->ipqe_ip->ip_off = - htons(ntohs(ipqe->ipqe_ip->ip_off) + i); - ipqe->ipqe_ip->ip_len = - htons(ntohs(ipqe->ipqe_ip->ip_len) - i); + ipqe->ipqe_ip->ip_off += i; + ipqe->ipqe_ip->ip_len -= i; } } @@ -915,22 +887,19 @@ ip_reass(ipqe, fp) * While we overlap succeeding segments trim them or, * if they are completely covered, dequeue them. */ - for (; q != NULL && - ntohs(ipqe->ipqe_ip->ip_off) + ntohs(ipqe->ipqe_ip->ip_len) > - ntohs(q->ipqe_ip->ip_off); q = nq) { - i = (ntohs(ipqe->ipqe_ip->ip_off) + - ntohs(ipqe->ipqe_ip->ip_len)) - ntohs(q->ipqe_ip->ip_off); - if (i < ntohs(q->ipqe_ip->ip_len)) { - q->ipqe_ip->ip_len = - htons(ntohs(q->ipqe_ip->ip_len) - i); - q->ipqe_ip->ip_off = - htons(ntohs(q->ipqe_ip->ip_off) + i); + for (; q != NULL && ipqe->ipqe_ip->ip_off + ipqe->ipqe_ip->ip_len > + q->ipqe_ip->ip_off; q = nq) { + i = (ipqe->ipqe_ip->ip_off + ipqe->ipqe_ip->ip_len) - + q->ipqe_ip->ip_off; + if (i < q->ipqe_ip->ip_len) { + q->ipqe_ip->ip_len -= i; + q->ipqe_ip->ip_off += i; m_adj(q->ipqe_m, i); break; } - nq = TAILQ_NEXT(q, ipqe_q); + nq = q->ipqe_q.le_next; m_freem(q->ipqe_m); - TAILQ_REMOVE(&fp->ipq_fragq, q, ipqe_q); + LIST_REMOVE(q, ipqe_q); pool_put(&ipqent_pool, q); } @@ -940,16 +909,16 @@ insert: * check for complete reassembly. */ if (p == NULL) { - TAILQ_INSERT_HEAD(&fp->ipq_fragq, ipqe, ipqe_q); + LIST_INSERT_HEAD(&fp->ipq_fragq, ipqe, ipqe_q); } else { - TAILQ_INSERT_AFTER(&fp->ipq_fragq, p, ipqe, ipqe_q); + LIST_INSERT_AFTER(p, ipqe, ipqe_q); } next = 0; - for (p = NULL, q = TAILQ_FIRST(&fp->ipq_fragq); q != NULL; - p = q, q = TAILQ_NEXT(q, ipqe_q)) { - if (ntohs(q->ipqe_ip->ip_off) != next) + for (p = NULL, q = fp->ipq_fragq.lh_first; q != NULL; + p = q, q = q->ipqe_q.le_next) { + if (q->ipqe_ip->ip_off != next) return (0); - next += ntohs(q->ipqe_ip->ip_len); + next += q->ipqe_ip->ip_len; } if (p->ipqe_mff) return (0); @@ -958,7 +927,7 @@ insert: * Reassembly is complete. Check for a bogus message size and * concatenate fragments. */ - q = TAILQ_FIRST(&fp->ipq_fragq); + q = fp->ipq_fragq.lh_first; ip = q->ipqe_ip; if ((next + (ip->ip_hl << 2)) > IP_MAXPACKET) { ipstat.ips_toolong++; @@ -969,11 +938,11 @@ insert: t = m->m_next; m->m_next = 0; m_cat(m, t); - nq = TAILQ_NEXT(q, ipqe_q); + nq = q->ipqe_q.le_next; pool_put(&ipqent_pool, q); for (q = nq; q != NULL; q = nq) { t = q->ipqe_m; - nq = TAILQ_NEXT(q, ipqe_q); + nq = q->ipqe_q.le_next; pool_put(&ipqent_pool, q); m_cat(m, t); } @@ -984,7 +953,7 @@ insert: * dequeue and discard fragment reassembly header. * Make header visible. */ - ip->ip_len = htons(next); + ip->ip_len = next; ip->ip_src = fp->ipq_src; ip->ip_dst = fp->ipq_dst; LIST_REMOVE(fp, ipq_q); @@ -1020,10 +989,10 @@ ip_freef(fp) IPQ_LOCK_CHECK(); - for (q = TAILQ_FIRST(&fp->ipq_fragq); q != NULL; q = p) { - p = TAILQ_NEXT(q, ipqe_q); + for (q = fp->ipq_fragq.lh_first; q != NULL; q = p) { + p = q->ipqe_q.le_next; m_freem(q->ipqe_m); - TAILQ_REMOVE(&fp->ipq_fragq, q, ipqe_q); + LIST_REMOVE(q, ipqe_q); pool_put(&ipqent_pool, q); } LIST_REMOVE(fp, ipq_q); @@ -1043,8 +1012,8 @@ ip_slowtimo() int s = splsoftnet(); IPQ_LOCK(); - for (fp = LIST_FIRST(&ipq); fp != NULL; fp = nfp) { - nfp = LIST_NEXT(fp, ipq_q); + for (fp = ipq.lh_first; fp != NULL; fp = nfp) { + nfp = fp->ipq_q.le_next; if (--fp->ipq_ttl == 0) { ipstat.ips_fragtimeout++; ip_freef(fp); @@ -1058,8 +1027,8 @@ ip_slowtimo() if (ip_maxfragpackets < 0) ; else { - while (ip_nfragpackets > ip_maxfragpackets && LIST_FIRST(&ipq)) - ip_freef(LIST_FIRST(&ipq)); + while (ip_nfragpackets > ip_maxfragpackets && ipq.lh_first) + ip_freef(ipq.lh_first); } IPQ_UNLOCK(); #ifdef GATEWAY @@ -1082,9 +1051,9 @@ ip_drain() if (ipq_lock_try() == 0) return; - while (LIST_FIRST(&ipq) != NULL) { + while (ipq.lh_first != NULL) { ipstat.ips_fragdropped++; - ip_freef(LIST_FIRST(&ipq)); + ip_freef(ipq.lh_first); } IPQ_UNLOCK(); @@ -1467,11 +1436,11 @@ ip_stripoptions(m, mopt) 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_len -= olen; ip->ip_hl = sizeof (struct ip) >> 2; } -const int inetctlerrmap[PRC_NCMDS] = { +int inetctlerrmap[PRC_NCMDS] = { 0, 0, 0, 0, 0, EMSGSIZE, EHOSTDOWN, EHOSTUNREACH, EHOSTUNREACH, EHOSTUNREACH, ECONNREFUSED, ECONNREFUSED, @@ -1557,7 +1526,7 @@ ip_forward(m, srcrt) * we need to generate an ICMP message to the src. * Pullup to avoid sharing mbuf cluster between m and mcopy. */ - mcopy = m_copym(m, 0, imin(ntohs(ip->ip_len), 68), M_DONTWAIT); + mcopy = m_copym(m, 0, imin((int)ip->ip_len, 68), M_DONTWAIT); if (mcopy) mcopy = m_pullup(mcopy, ip->ip_hl << 2); @@ -1684,8 +1653,6 @@ ip_forward(m, srcrt) ro = &sp->req->sav->sah->sa_route; if (ro->ro_rt && ro->ro_rt->rt_ifp) { dummyifp.if_mtu = - ro->ro_rt->rt_rmx.rmx_mtu ? - ro->ro_rt->rt_rmx.rmx_mtu : ro->ro_rt->rt_ifp->if_mtu; dummyifp.if_mtu -= ipsechdr; destifp = &dummyifp; @@ -1700,21 +1667,9 @@ ip_forward(m, srcrt) break; case ENOBUFS: -#if 1 - /* - * a router should not generate ICMP_SOURCEQUENCH as - * required in RFC1812 Requirements for IP Version 4 Routers. - * source quench could be a big problem under DoS attacks, - * or if the underlying interface is rate-limited. - */ - if (mcopy) - m_freem(mcopy); - return; -#else type = ICMP_SOURCEQUENCH; code = 0; break; -#endif } icmp_error(mcopy, type, code, dest, destifp); } @@ -1829,7 +1784,7 @@ ip_sysctl(name, namelen, oldp, oldlenp, error = sysctl_int(oldp, oldlenp, newp, newlen, &ip_mtudisc); if (ip_mtudisc != 0 && ip_mtudisc_timeout_q == NULL) { - ip_mtudisc_timeout_q = + ip_mtudisc_timeout_q = rt_timer_queue_create(ip_mtudisc_timeout); } else if (ip_mtudisc == 0 && ip_mtudisc_timeout_q != NULL) { rt_timer_queue_destroy(ip_mtudisc_timeout_q, TRUE); @@ -1863,15 +1818,10 @@ ip_sysctl(name, namelen, oldp, oldlenp, } return (error); case IPCTL_MTUDISCTIMEOUT: - old = ip_mtudisc_timeout; error = sysctl_int(oldp, oldlenp, newp, newlen, &ip_mtudisc_timeout); - if (ip_mtudisc_timeout < 0) { - ip_mtudisc_timeout = old; - return (EINVAL); - } if (ip_mtudisc_timeout_q != NULL) - rt_timer_queue_change(ip_mtudisc_timeout_q, + rt_timer_queue_change(ip_mtudisc_timeout_q, ip_mtudisc_timeout); return (error); #ifdef GATEWAY @@ -1892,16 +1842,10 @@ ip_sysctl(name, namelen, oldp, oldlenp, &hostzeroisbroadcast)); #if NGIF > 0 case IPCTL_GIF_TTL: - return (sysctl_int(oldp, oldlenp, newp, newlen, + return(sysctl_int(oldp, oldlenp, newp, newlen, &ip_gif_ttl)); #endif -#if NGRE > 0 - case IPCTL_GRE_TTL: - return (sysctl_int(oldp, oldlenp, newp, newlen, - &ip_gre_ttl)); -#endif - #ifndef IPNOPRIVPORTS case IPCTL_LOWPORTMIN: old = lowportmin;