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.53.2.4 retrieving revision 1.74 diff -u -p -r1.53.2.4 -r1.74 --- src/sys/netinet/ip_input.c 1998/11/15 19:18:13 1.53.2.4 +++ src/sys/netinet/ip_input.c 1998/11/13 03:24:22 1.74 @@ -1,4 +1,4 @@ -/* $NetBSD: ip_input.c,v 1.53.2.4 1998/11/15 19:18:13 cgd Exp $ */ +/* $NetBSD: ip_input.c,v 1.74 1998/11/13 03:24:22 thorpej Exp $ */ /* * Copyright (c) 1982, 1986, 1988, 1993 @@ -72,6 +72,10 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include "opt_gateway.h" +#include "opt_pfil_hooks.h" +#include "opt_mrouting.h" + #include #include #include @@ -84,6 +88,7 @@ #include #include #include +#include #include #include @@ -101,9 +106,6 @@ #include #include -/* XXX should really put this in libkern.h */ -#define offsetof(type, member) ((size_t)(&((type *)0)->member)) - #ifndef IPFORWARDING #ifdef GATEWAY #define IPFORWARDING 1 /* forward IP packets not for us */ @@ -127,7 +129,6 @@ #define IPMTUDISCTIMEOUT (10 * 60) /* as per RFC 1191 */ #endif - /* * Note: DIRECTED_BROADCAST is handled this way so that previous * configuration using this option will Just Work. @@ -160,6 +161,12 @@ int ipqmaxlen = IFQ_MAXLEN; struct in_ifaddrhead in_ifaddr; struct in_ifaddrhashhead *in_ifaddrhashtbl; struct ifqueue ipintrq; +struct ipstat ipstat; +u_int16_t ip_id; +int ip_defttl; +struct ipqhead ipq; + +struct pool ipqent_pool; /* * We need to save the IP options in case a protocol wants to respond @@ -188,6 +195,9 @@ ip_init() register struct protosw *pr; register int i; + pool_init(&ipqent_pool, sizeof(struct ipqent), 0, 0, 0, "ipqepl", + 0, NULL, NULL, M_IPQ); + pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW); if (pr == 0) panic("ip_init"); @@ -203,10 +213,13 @@ ip_init() ipintrq.ifq_maxlen = ipqmaxlen; TAILQ_INIT(&in_ifaddr); in_ifaddrhashtbl = - hashinit(IN_IFADDR_HASH_SIZE, M_IFADDR, &in_ifaddrhash); + hashinit(IN_IFADDR_HASH_SIZE, M_IFADDR, M_WAITOK, &in_ifaddrhash); if (ip_mtudisc != 0) ip_mtudisc_timeout_q = rt_timer_queue_create(ip_mtudisc_timeout); +#ifdef GATEWAY + ipflow_init(); +#endif } struct sockaddr_in ipaddr = { sizeof(ipaddr), AF_INET }; @@ -306,9 +319,19 @@ next: m_adj(m, len - m->m_pkthdr.len); } + /* + * Assume that we can create a fast-forward IP flow entry + * based on this packet. + */ + m->m_flags |= M_CANFASTFWD; + #ifdef PFIL_HOOKS /* - * Run through list of hooks for input packets. + * Run through list of hooks for input packets. If there are any + * filters which require that additional packets in the flow are + * not fast-forwarded, they must clear the M_CANFASTFWD flag. + * Note that filters must _never_ set this flag, as another filter + * in the list may have previously cleared it. */ m0 = m; for (pfh = pfil_hook_get(PFIL_IN); pfh; pfh = pfh->pfil_link.tqe_next) @@ -478,8 +501,7 @@ found: */ if (mff || ip->ip_off) { ipstat.ips_fragments++; - MALLOC(ipqe, struct ipqent *, sizeof (struct ipqent), - M_IPQ, M_NOWAIT); + ipqe = pool_get(&ipqent_pool, PR_NOWAIT); if (ipqe == NULL) { ipstat.ips_rcvmemdrop++; goto bad; @@ -596,7 +618,7 @@ ip_reass(ipqe, fp) nq = q->ipqe_q.le_next; m_freem(q->ipqe_m); LIST_REMOVE(q, ipqe_q); - FREE(q, M_IPQ); + pool_put(&ipqent_pool, q); } insert: @@ -635,11 +657,11 @@ insert: m->m_next = 0; m_cat(m, t); nq = q->ipqe_q.le_next; - FREE(q, M_IPQ); + pool_put(&ipqent_pool, q); for (q = nq; q != NULL; q = nq) { t = q->ipqe_m; nq = q->ipqe_q.le_next; - FREE(q, M_IPQ); + pool_put(&ipqent_pool, q); m_cat(m, t); } @@ -668,7 +690,7 @@ insert: dropfrag: ipstat.ips_fragdropped++; m_freem(m); - FREE(ipqe, M_IPQ); + pool_put(&ipqent_pool, ipqe); return (0); } @@ -686,7 +708,7 @@ ip_freef(fp) p = q->ipqe_q.le_next; m_freem(q->ipqe_m); LIST_REMOVE(q, ipqe_q); - FREE(q, M_IPQ); + pool_put(&ipqent_pool, q); } LIST_REMOVE(fp, ipq_q); FREE(fp, M_FTABLE); @@ -710,6 +732,9 @@ ip_slowtimo() ip_freef(fp); } } +#ifdef GATEWAY + ipflow_slowtimo(); +#endif splx(s); } @@ -879,7 +904,7 @@ ip_dooptions(m) break; case IPOPT_TS_TSANDADDR: - if (ipt->ipt_ptr + sizeof(n_time) + + if (ipt->ipt_ptr - 1 + sizeof(n_time) + sizeof(struct in_addr) > ipt->ipt_len) goto bad; ipaddr.sin_addr = dst; @@ -893,7 +918,7 @@ ip_dooptions(m) break; case IPOPT_TS_PRESPEC: - if (ipt->ipt_ptr + sizeof(n_time) + + if (ipt->ipt_ptr - 1 + sizeof(n_time) + sizeof(struct in_addr) > ipt->ipt_len) goto bad; bcopy((caddr_t)sin, (caddr_t)&ipaddr.sin_addr, @@ -1115,8 +1140,9 @@ ip_forward(m, srcrt) dest = 0; #ifdef DIAGNOSTIC if (ipprintfs) - printf("forward: src %x dst %x ttl %x\n", - ip->ip_src.s_addr, ip->ip_dst.s_addr, ip->ip_ttl); + printf("forward: src %2.2x dst %2.2x ttl %x\n", + ntohl(ip->ip_src.s_addr), + ntohl(ip->ip_dst.s_addr), ip->ip_ttl); #endif if (m->m_flags & M_BCAST || in_canforward(ip->ip_dst) == 0) { ipstat.ips_cantforward++; @@ -1193,8 +1219,13 @@ ip_forward(m, srcrt) if (type) ipstat.ips_redirectsent++; else { - if (mcopy) + if (mcopy) { +#ifdef GATEWAY + if (mcopy->m_flags & M_CANFASTFWD) + ipflow_create(&ipforward_rt, mcopy); +#endif m_freem(mcopy); + } return; } } @@ -1303,7 +1334,8 @@ ip_sysctl(name, namelen, oldp, oldlenp, size_t newlen; { extern int subnetsarelocal; - int error; + + int error, old; /* All sysctl names at this level are terminal. */ if (namelen != 1) @@ -1349,13 +1381,50 @@ ip_sysctl(name, namelen, oldp, oldlenp, ip_mtudisc_timeout_q = NULL; } return error; + case IPCTL_ANONPORTMIN: + old = anonportmin; + error = sysctl_int(oldp, oldlenp, newp, newlen, &anonportmin); + if (anonportmin >= anonportmax || anonportmin > 65535 +#ifndef IPNOPRIVPORTS + || anonportmin < IPPORT_RESERVED +#endif + ) { + anonportmin = old; + return (EINVAL); + } + return (error); + case IPCTL_ANONPORTMAX: + old = anonportmax; + error = sysctl_int(oldp, oldlenp, newp, newlen, &anonportmax); + if (anonportmin >= anonportmax || anonportmax > 65535 +#ifndef IPNOPRIVPORTS + || anonportmax < IPPORT_RESERVED +#endif + ) { + anonportmax = old; + return (EINVAL); + } + return (error); case IPCTL_MTUDISCTIMEOUT: error = sysctl_int(oldp, oldlenp, newp, newlen, &ip_mtudisc_timeout); if (ip_mtudisc_timeout_q != NULL) rt_timer_queue_change(ip_mtudisc_timeout_q, ip_mtudisc_timeout); - return (error); + return (error); +#ifdef GATEWAY + case IPCTL_MAXFLOWS: + { + int s; + + error = sysctl_int(oldp, oldlenp, newp, newlen, + &ip_maxflows); + s = splsoftnet(); + ipflow_reap(0); + splx(s); + return (error); + } +#endif default: return (EOPNOTSUPP); }