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.313 retrieving revision 1.330 diff -u -p -r1.313 -r1.330 --- src/sys/netinet/ip_input.c 2014/05/23 19:35:24 1.313 +++ src/sys/netinet/ip_input.c 2016/06/28 02:02:56 1.330 @@ -1,4 +1,4 @@ -/* $NetBSD: ip_input.c,v 1.313 2014/05/23 19:35:24 rmind Exp $ */ +/* $NetBSD: ip_input.c,v 1.330 2016/06/28 02:02:56 ozaki-r Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -91,8 +91,9 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.313 2014/05/23 19:35:24 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ip_input.c,v 1.330 2016/06/28 02:02:56 ozaki-r Exp $"); +#ifdef _KERNEL_OPT #include "opt_inet.h" #include "opt_compat_netbsd.h" #include "opt_gateway.h" @@ -100,9 +101,13 @@ __KERNEL_RCSID(0, "$NetBSD: ip_input.c,v #include "opt_mrouting.h" #include "opt_mbuftrace.h" #include "opt_inet_csum.h" +#endif + +#include "arp.h" #include #include +#include #include #include #include @@ -118,6 +123,7 @@ __KERNEL_RCSID(0, "$NetBSD: ip_input.c,v #include #include #include +#include #include #include @@ -210,18 +216,18 @@ int ip_do_randomid = 0; * to the loopback interface instead of the interface where the * packets for those addresses are received. */ -int ip_checkinterface = 0; +static int ip_checkinterface __read_mostly = 0; struct rttimer_queue *ip_mtudisc_timeout_q = NULL; -struct ifqueue ipintrq; - -ipid_state_t * ip_ids; -uint16_t ip_id; +pktqueue_t * ip_pktq __read_mostly; +pfil_head_t * inet_pfil_hook __read_mostly; +ipid_state_t * ip_ids __read_mostly; +percpu_t * ipstat_percpu __read_mostly; -percpu_t *ipstat_percpu; +static struct route ipforward_rt __cacheline_aligned; -pfil_head_t *inet_pfil_hook; +uint16_t ip_id; #ifdef INET_CSUM_COUNTERS #include @@ -264,6 +270,11 @@ static struct ip_srcrt { static int ip_drainwanted; +struct sockaddr_in ipaddr = { + .sin_len = sizeof(ipaddr), + .sin_family = AF_INET, +}; + static void save_rte(u_char *, struct in_addr); #ifdef MBUFTRACE @@ -271,12 +282,17 @@ struct mowner ip_rx_mowner = MOWNER_INIT struct mowner ip_tx_mowner = MOWNER_INIT("internet", "tx"); #endif +static void ipintr(void *); static void ip_input(struct mbuf *); -static void ip_forward(struct mbuf *, int); +static void ip_forward(struct mbuf *, int, struct ifnet *); static bool ip_dooptions(struct mbuf *); static struct in_ifaddr *ip_rtaddr(struct in_addr); static void sysctl_net_inet_ip_setup(struct sysctllog **); +/* XXX: Not yet enabled. */ +#define SOFTNET_LOCK() KASSERT(mutex_owned(softnet_lock)) +#define SOFTNET_UNLOCK() KASSERT(mutex_owned(softnet_lock)) + /* * IP initialization: fill in IP protocol switch table. * All protocols not implemented in kernel go to raw IP protocol handler. @@ -292,6 +308,9 @@ ip_init(void) pr = pffindproto(PF_INET, IPPROTO_RAW, SOCK_RAW); KASSERT(pr != NULL); + ip_pktq = pktq_create(IFQ_MAXLEN, ipintr, NULL); + KASSERT(ip_pktq != NULL); + for (u_int i = 0; i < IPPROTO_MAX; i++) { ip_protox[i] = pr - inetsw; } @@ -304,9 +323,7 @@ ip_init(void) ip_reass_init(); ip_ids = ip_id_init(); - ip_id = time_second & 0xfffff; - - ipintrq.ifq_maxlen = IFQ_MAXLEN; + ip_id = time_uptime & 0xfffff; ip_mtudisc_timeout_q = rt_timer_queue_create(ip_mtudisc_timeout); #ifdef GATEWAY @@ -325,54 +342,25 @@ ip_init(void) ipstat_percpu = percpu_alloc(sizeof(uint64_t) * IP_NSTATS); } -struct sockaddr_in ipaddr = { - .sin_len = sizeof(ipaddr), - .sin_family = AF_INET, -}; - -static struct route ipforward_rt; - /* - * IP software interrupt routine + * IP software interrupt routine. */ -void -ipintr(void) +static void +ipintr(void *arg __unused) { - int s; struct mbuf *m; - struct ifqueue lcl_intrq; - memset(&lcl_intrq, 0, sizeof(lcl_intrq)); + KASSERT(cpu_softintr_p()); mutex_enter(softnet_lock); - KERNEL_LOCK(1, NULL); - if (!IF_IS_EMPTY(&ipintrq)) { - s = splnet(); - - /* Take existing queue onto stack */ - lcl_intrq = ipintrq; - - /* Zero out global queue, preserving maxlen and drops */ - ipintrq.ifq_head = NULL; - ipintrq.ifq_tail = NULL; - ipintrq.ifq_len = 0; - ipintrq.ifq_maxlen = lcl_intrq.ifq_maxlen; - ipintrq.ifq_drops = lcl_intrq.ifq_drops; - - splx(s); - } - KERNEL_UNLOCK_ONE(NULL); - while (!IF_IS_EMPTY(&lcl_intrq)) { - IF_DEQUEUE(&lcl_intrq, m); - if (m == NULL) - break; + while ((m = pktq_dequeue(ip_pktq)) != NULL) { ip_input(m); } mutex_exit(softnet_lock); } /* - * Ip input routine. Checksum and byte swap header. If fragmented + * IP input routine. Checksum and byte swap header. If fragmented * try to reassemble. Process options. Pass to next level. */ static void @@ -385,17 +373,29 @@ ip_input(struct mbuf *m) int downmatch; int checkif; int srcrt = 0; + ifnet_t *ifp; + struct psref psref; + + KASSERTMSG(cpu_softintr_p(), "ip_input: not in the software " + "interrupt handler; synchronization assumptions violated"); MCLAIM(m, &ip_rx_mowner); KASSERT((m->m_flags & M_PKTHDR) != 0); + ifp = m_get_rcvif_psref(m, &psref); + if (__predict_false(ifp == NULL)) + goto bad; + /* * If no IP addresses have been set yet but the interfaces * are receiving, can't do anything with incoming packets yet. + * Note: we pre-check without locks held. */ - if (TAILQ_FIRST(&in_ifaddrhead) == 0) + if (!TAILQ_FIRST(&in_ifaddrhead)) { goto bad; + } IP_STATINC(IP_STAT_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 @@ -407,12 +407,12 @@ ip_input(struct mbuf *m) (max_linkhdr + 3) & ~3)) == NULL) { /* XXXJRT new stat, please */ IP_STATINC(IP_STAT_TOOSMALL); - return; + goto out; } } else if (__predict_false(m->m_len < sizeof (struct ip))) { if ((m = m_pullup(m, sizeof (struct ip))) == NULL) { IP_STATINC(IP_STAT_TOOSMALL); - return; + goto out; } } ip = mtod(m, struct ip *); @@ -428,7 +428,7 @@ ip_input(struct mbuf *m) if (hlen > m->m_len) { if ((m = m_pullup(m, hlen)) == NULL) { IP_STATINC(IP_STAT_BADHLEN); - return; + goto out; } ip = mtod(m, struct ip *); } @@ -445,14 +445,14 @@ ip_input(struct mbuf *m) /* 127/8 must not appear on wire - RFC1122 */ if ((ntohl(ip->ip_dst.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET || (ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) { - if ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0) { + if ((ifp->if_flags & IFF_LOOPBACK) == 0) { IP_STATINC(IP_STAT_BADADDR); goto bad; } } switch (m->m_pkthdr.csum_flags & - ((m->m_pkthdr.rcvif->if_csum_flags_rx & M_CSUM_IPv4) | + ((ifp->if_csum_flags_rx & M_CSUM_IPv4) | M_CSUM_IPv4_BAD)) { case M_CSUM_IPv4|M_CSUM_IPv4_BAD: INET_CSUM_COUNTER_INCR(&ip_hwcsum_bad); @@ -468,8 +468,8 @@ ip_input(struct mbuf *m) * Must compute it ourselves. Maybe skip checksum on * loopback interfaces. */ - if (__predict_true(!(m->m_pkthdr.rcvif->if_flags & - IFF_LOOPBACK) || ip_do_loopback_cksum)) { + if (__predict_true(!(ifp->if_flags & IFF_LOOPBACK) || + ip_do_loopback_cksum)) { INET_CSUM_COUNTER_INCR(&ip_swcsum); if (in_cksum(m, hlen) != 0) goto badcsum; @@ -519,26 +519,24 @@ ip_input(struct mbuf *m) * Note that filters must _never_ set this flag, as another filter * in the list may have previously cleared it. */ - /* - * let ipfilter look at packet on the wire, - * not the decapsulated packet. - */ #if defined(IPSEC) - if (!ipsec_indone(m)) + if (!ipsec_used || !ipsec_indone(m)) #else if (1) #endif { - struct in_addr odst; + struct in_addr odst = ip->ip_dst; + bool freed; - odst = ip->ip_dst; - if (pfil_run_hooks(inet_pfil_hook, &m, m->m_pkthdr.rcvif, - PFIL_IN) != 0) - return; - if (m == NULL) - return; + SOFTNET_LOCK(); + freed = pfil_run_hooks(inet_pfil_hook, &m, ifp, PFIL_IN) != 0; + SOFTNET_UNLOCK(); + if (freed || m == NULL) { + goto out; + } ip = mtod(m, struct ip *); hlen = ip->ip_hl << 2; + /* * XXX The setting of "srcrt" here is to prevent ip_forward() * from generating ICMP redirects for packets that have @@ -558,9 +556,14 @@ ip_input(struct mbuf *m) #ifdef ALTQ /* XXX Temporary until ALTQ is changed to use a pfil hook */ - if (altq_input != NULL && (*altq_input)(m, AF_INET) == 0) { - /* packet dropped by traffic conditioner */ - return; + if (altq_input) { + SOFTNET_LOCK(); + if ((*altq_input)(m, AF_INET) == 0) { + /* Packet dropped by traffic conditioner. */ + SOFTNET_UNLOCK(); + goto out; + } + SOFTNET_UNLOCK(); } #endif @@ -572,7 +575,7 @@ ip_input(struct mbuf *m) */ ip_nhops = 0; /* for source routed packets */ if (hlen > sizeof (struct ip) && ip_dooptions(m)) - return; + goto out; /* * Enable a consistency check between the destination address @@ -591,20 +594,21 @@ ip_input(struct mbuf *m) * we get finer grain control. */ checkif = ip_checkinterface && (ipforwarding == 0) && - (m->m_pkthdr.rcvif != NULL) && - ((m->m_pkthdr.rcvif->if_flags & IFF_LOOPBACK) == 0); + (ifp->if_flags & IFF_LOOPBACK) == 0; /* * Check our list of addresses, to see if the packet is for us. * * Traditional 4.4BSD did not consult IFF_UP at all. * The behavior here is to treat addresses on !IFF_UP interface - * as not mine. + * or IN_IFF_NOTREADY addresses as not mine. */ downmatch = 0; LIST_FOREACH(ia, &IN_IFADDR_HASH(ip->ip_dst.s_addr), ia_hash) { if (in_hosteq(ia->ia_addr.sin_addr, ip->ip_dst)) { - if (checkif && ia->ia_ifp != m->m_pkthdr.rcvif) + if (ia->ia4_flags & IN_IFF_NOTREADY) + continue; + if (checkif && ia->ia_ifp != ifp) continue; if ((ia->ia_ifp->if_flags & IFF_UP) != 0) break; @@ -614,11 +618,13 @@ ip_input(struct mbuf *m) } if (ia != NULL) goto ours; - if (m->m_pkthdr.rcvif && m->m_pkthdr.rcvif->if_flags & IFF_BROADCAST) { - IFADDR_FOREACH(ifa, m->m_pkthdr.rcvif) { + if (ifp->if_flags & IFF_BROADCAST) { + IFADDR_FOREACH(ifa, ifp) { if (ifa->ifa_addr->sa_family != AF_INET) continue; ia = ifatoia(ifa); + if (ia->ia4_flags & IN_IFF_NOTREADY) + continue; if (in_hosteq(ip->ip_dst, ia->ia_broadaddr.sin_addr) || in_hosteq(ip->ip_dst, ia->ia_netbroadcast) || /* @@ -637,7 +643,6 @@ ip_input(struct mbuf *m) } } if (IN_MULTICAST(ip->ip_dst.s_addr)) { - struct in_multi *inm; #ifdef MROUTING extern struct socket *ip_mrouter; @@ -654,19 +659,22 @@ ip_input(struct mbuf *m) * as expected when ip_mforward() is called from * ip_output().) */ - if (ip_mforward(m, m->m_pkthdr.rcvif) != 0) { + SOFTNET_LOCK(); + if (ip_mforward(m, ifp) != 0) { + SOFTNET_UNLOCK(); IP_STATINC(IP_STAT_CANTFORWARD); - m_freem(m); - return; + goto bad; } + SOFTNET_UNLOCK(); /* * The process-level routing demon needs to receive * all multicast IGMP packets, whether or not this * host belongs to their destination groups. */ - if (ip->ip_p == IPPROTO_IGMP) + if (ip->ip_p == IPPROTO_IGMP) { goto ours; + } IP_STATINC(IP_STAT_CANTFORWARD); } #endif @@ -674,11 +682,9 @@ ip_input(struct mbuf *m) * See if we belong to the destination multicast group on the * arrival interface. */ - IN_LOOKUP_MULTI(ip->ip_dst, m->m_pkthdr.rcvif, inm); - if (inm == NULL) { + if (!in_multi_group(ip->ip_dst, ifp, 0)) { IP_STATINC(IP_STAT_CANTFORWARD); - m_freem(m); - return; + goto bad; } goto ours; } @@ -690,6 +696,7 @@ ip_input(struct mbuf *m) * Not for us; forward if possible and desirable. */ if (ipforwarding == 0) { + m_put_rcvif_psref(ifp, &psref); IP_STATINC(IP_STAT_CANTFORWARD); m_freem(m); } else { @@ -700,22 +707,31 @@ ip_input(struct mbuf *m) * forwarding loop till TTL goes to 0. */ if (downmatch) { + m_put_rcvif_psref(ifp, &psref); icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, 0, 0); IP_STATINC(IP_STAT_CANTFORWARD); return; } #ifdef IPSEC /* Perform IPsec, if any. */ - if (ipsec4_input(m, IP_FORWARDING | (ip_directedbcast ? - IP_ALLOWBROADCAST : 0)) != 0) { - goto bad; + if (ipsec_used) { + SOFTNET_LOCK(); + if (ipsec4_input(m, IP_FORWARDING | + (ip_directedbcast ? IP_ALLOWBROADCAST : 0)) != 0) { + SOFTNET_UNLOCK(); + goto bad; + } + SOFTNET_UNLOCK(); } #endif - ip_forward(m, srcrt); + ip_forward(m, srcrt, ifp); + m_put_rcvif_psref(ifp, &psref); } return; ours: + m_put_rcvif_psref(ifp, &psref); + /* * If offset or IP_MF are set, must reassemble. */ @@ -745,10 +761,14 @@ ours: * Note that we do not visit this with protocols with PCB layer * code - like UDP/TCP/raw IP. */ - if ((inetsw[ip_protox[ip->ip_p]].pr_flags & PR_LASTHDR) != 0) { + if (ipsec_used && + (inetsw[ip_protox[ip->ip_p]].pr_flags & PR_LASTHDR) != 0) { + SOFTNET_LOCK(); if (ipsec4_input(m, 0) != 0) { + SOFTNET_UNLOCK(); goto bad; } + SOFTNET_UNLOCK(); } #endif @@ -760,19 +780,25 @@ ours: ia->ia_ifa.ifa_data.ifad_inbytes += ntohs(ip->ip_len); #endif IP_STATINC(IP_STAT_DELIVERED); - { - int off = hlen, nh = ip->ip_p; + const int off = hlen, nh = ip->ip_p; + + SOFTNET_LOCK(); (*inetsw[ip_protox[nh]].pr_input)(m, off, nh); + SOFTNET_UNLOCK(); return; - } bad: + m_put_rcvif_psref(ifp, &psref); m_freem(m); return; badcsum: + m_put_rcvif_psref(ifp, &psref); IP_STATINC(IP_STAT_BADSUM); m_freem(m); + return; +out: + m_put_rcvif_psref(ifp, &psref); } /* @@ -974,7 +1000,10 @@ ip_dooptions(struct mbuf *m) case IPOPT_TS_TSONLY: break; - case IPOPT_TS_TSANDADDR: + case IPOPT_TS_TSANDADDR: { + struct ifnet *rcvif; + int s; + if (ipt->ipt_ptr - 1 + sizeof(n_time) + sizeof(struct in_addr) > ipt->ipt_len) { code = (u_char *)&ipt->ipt_ptr - @@ -982,14 +1011,17 @@ ip_dooptions(struct mbuf *m) goto bad; } ipaddr.sin_addr = dst; + rcvif = m_get_rcvif(m, &s); ia = ifatoia(ifaof_ifpforaddr(sintosa(&ipaddr), - m->m_pkthdr.rcvif)); + rcvif)); + m_put_rcvif(rcvif, &s); if (ia == 0) continue; bcopy(&ia->ia_addr.sin_addr, cp0, sizeof(struct in_addr)); ipt->ipt_ptr += sizeof(struct in_addr); break; + } case IPOPT_TS_PRESPEC: if (ipt->ipt_ptr - 1 + sizeof(n_time) + @@ -1020,12 +1052,23 @@ ip_dooptions(struct mbuf *m) } } if (forward) { + struct ifnet *rcvif; + struct psref psref; + if (ip_forwsrcrt == 0) { type = ICMP_UNREACH; code = ICMP_UNREACH_SRCFAIL; goto bad; } - ip_forward(m, 1); + + rcvif = m_get_rcvif_psref(m, &psref); + if (__predict_false(rcvif == NULL)) { + type = ICMP_UNREACH; + code = ICMP_UNREACH_HOST; + goto bad; + } + ip_forward(m, 1, rcvif); + m_put_rcvif_psref(rcvif, &psref); return true; } return false; @@ -1050,7 +1093,10 @@ ip_rtaddr(struct in_addr dst) sockaddr_in_init(&u.dst4, &dst, 0); - if ((rt = rtcache_lookup(&ipforward_rt, &u.dst)) == NULL) + SOFTNET_LOCK(); + rt = rtcache_lookup(&ipforward_rt, &u.dst); + SOFTNET_UNLOCK(); + if (rt == NULL) return NULL; return ifatoia(rt->rt_ifa); @@ -1169,7 +1215,7 @@ ip_drainstub(void) * via a source route. */ static void -ip_forward(struct mbuf *m, int srcrt) +ip_forward(struct mbuf *m, int srcrt, struct ifnet *rcvif) { struct ip *ip = mtod(m, struct ip *); struct rtentry *rt; @@ -1180,6 +1226,10 @@ ip_forward(struct mbuf *m, int srcrt) struct sockaddr dst; struct sockaddr_in dst4; } u; + uint64_t *ips; + + KASSERTMSG(cpu_softintr_p(), "ip_forward: not in the software " + "interrupt handler; synchronization assumptions violated"); /* * We are now in the output path. @@ -1197,14 +1247,20 @@ ip_forward(struct mbuf *m, int srcrt) m_freem(m); return; } + + SOFTNET_LOCK(); + if (ip->ip_ttl <= IPTTLDEC) { icmp_error(m, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, dest, 0); + SOFTNET_UNLOCK(); return; } sockaddr_in_init(&u.dst4, &ip->ip_dst, 0); + if ((rt = rtcache_lookup(&ipforward_rt, &u.dst)) == NULL) { icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, dest, 0); + SOFTNET_UNLOCK(); return; } @@ -1227,7 +1283,7 @@ ip_forward(struct mbuf *m, int srcrt) * Also, don't send redirect if forwarding using a default route * or a route modified by a redirect. */ - if (rt->rt_ifp == m->m_pkthdr.rcvif && + if (rt->rt_ifp == rcvif && (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0 && !in_nullhost(satocsin(rt_getkey(rt))->sin_addr) && ipsendredirects && !srcrt) { @@ -1251,28 +1307,38 @@ ip_forward(struct mbuf *m, int srcrt) (IP_FORWARDING | (ip_directedbcast ? IP_ALLOWBROADCAST : 0)), NULL, NULL); - if (error) + if (error) { IP_STATINC(IP_STAT_CANTFORWARD); - else { - uint64_t *ips = IP_STAT_GETREF(); - ips[IP_STAT_FORWARD]++; - if (type) { - ips[IP_STAT_REDIRECTSENT]++; - IP_STAT_PUTREF(); - } else { - IP_STAT_PUTREF(); - if (mcopy) { + goto error; + } + + ips = IP_STAT_GETREF(); + ips[IP_STAT_FORWARD]++; + + if (type) { + ips[IP_STAT_REDIRECTSENT]++; + IP_STAT_PUTREF(); + goto redirect; + } + + IP_STAT_PUTREF(); + if (mcopy) { #ifdef GATEWAY - if (mcopy->m_flags & M_CANFASTFWD) - ipflow_create(&ipforward_rt, mcopy); + if (mcopy->m_flags & M_CANFASTFWD) + ipflow_create(&ipforward_rt, mcopy); #endif - m_freem(mcopy); - } - return; - } + m_freem(mcopy); } - if (mcopy == NULL) + + SOFTNET_UNLOCK(); + return; + +redirect: +error: + if (mcopy == NULL) { + SOFTNET_UNLOCK(); return; + } switch (error) { @@ -1296,7 +1362,8 @@ ip_forward(struct mbuf *m, int srcrt) if ((rt = rtcache_validate(&ipforward_rt)) != NULL) destmtu = rt->rt_ifp->if_mtu; #ifdef IPSEC - (void)ipsec4_forward(mcopy, &destmtu); + if (ipsec_used) + (void)ipsec4_forward(mcopy, &destmtu); #endif IP_STATINC(IP_STAT_CANTFRAG); break; @@ -1310,9 +1377,11 @@ ip_forward(struct mbuf *m, int srcrt) */ if (mcopy) m_freem(mcopy); + SOFTNET_UNLOCK(); return; } icmp_error(mcopy, type, code, dest, destmtu); + SOFTNET_UNLOCK(); } void @@ -1320,7 +1389,13 @@ ip_savecontrol(struct inpcb *inp, struct struct mbuf *m) { struct socket *so = inp->inp_socket; + ifnet_t *ifp; int inpflags = inp->inp_flags; + struct psref psref; + + ifp = m_get_rcvif_psref(m, &psref); + if (__predict_false(ifp == NULL)) + return; /* XXX should report error? */ if (so->so_options & SO_TIMESTAMP #ifdef SO_OTIMESTAMP @@ -1352,7 +1427,7 @@ ip_savecontrol(struct inpcb *inp, struct if (inpflags & INP_RECVPKTINFO) { struct in_pktinfo ipi; ipi.ipi_addr = ip->ip_src; - ipi.ipi_ifindex = m->m_pkthdr.rcvif->if_index; + ipi.ipi_ifindex = ifp->if_index; *mp = sbcreatecontrol((void *) &ipi, sizeof(ipi), IP_RECVPKTINFO, IPPROTO_IP); if (*mp) @@ -1361,7 +1436,7 @@ ip_savecontrol(struct inpcb *inp, struct if (inpflags & INP_PKTINFO) { struct in_pktinfo ipi; ipi.ipi_addr = ip->ip_dst; - ipi.ipi_ifindex = m->m_pkthdr.rcvif->if_index; + ipi.ipi_ifindex = ifp->if_index; *mp = sbcreatecontrol((void *) &ipi, sizeof(ipi), IP_PKTINFO, IPPROTO_IP); if (*mp) @@ -1370,8 +1445,8 @@ ip_savecontrol(struct inpcb *inp, struct if (inpflags & INP_RECVIF) { struct sockaddr_dl sdl; - sockaddr_dl_init(&sdl, sizeof(sdl), m->m_pkthdr.rcvif ? - m->m_pkthdr.rcvif->if_index : 0, 0, NULL, 0, NULL, 0); + sockaddr_dl_init(&sdl, sizeof(sdl), ifp ? + ifp->if_index : 0, 0, NULL, 0, NULL, 0); *mp = sbcreatecontrol(&sdl, sdl.sdl_len, IP_RECVIF, IPPROTO_IP); if (*mp) mp = &(*mp)->m_next; @@ -1382,6 +1457,7 @@ ip_savecontrol(struct inpcb *inp, struct if (*mp) mp = &(*mp)->m_next; } + m_put_rcvif_psref(ifp, &psref); } /* @@ -1543,15 +1619,6 @@ sysctl_net_inet_ip_setup(struct sysctllo sysctl_net_inet_ip_pmtudto, 0, (void *)&ip_mtudisc_timeout, 0, CTL_NET, PF_INET, IPPROTO_IP, IPCTL_MTUDISCTIMEOUT, CTL_EOL); -#if NGIF > 0 - sysctl_createv(clog, 0, NULL, NULL, - CTLFLAG_PERMANENT|CTLFLAG_READWRITE, - CTLTYPE_INT, "gifttl", - SYSCTL_DESCR("Default TTL for a gif tunnel datagram"), - NULL, 0, &ip_gif_ttl, 0, - CTL_NET, PF_INET, IPPROTO_IP, - IPCTL_GIF_TTL, CTL_EOL); -#endif /* NGIF */ #ifndef IPNOPRIVPORTS sysctl_createv(clog, 0, NULL, NULL, CTLFLAG_PERMANENT|CTLFLAG_READWRITE, @@ -1608,6 +1675,16 @@ sysctl_net_inet_ip_setup(struct sysctllo sysctl_net_inet_ip_stats, 0, NULL, 0, CTL_NET, PF_INET, IPPROTO_IP, IPCTL_STATS, CTL_EOL); +#if NARP + sysctl_createv(clog, 0, NULL, NULL, + CTLFLAG_PERMANENT|CTLFLAG_READWRITE, + CTLTYPE_INT, "dad_count", + SYSCTL_DESCR("Number of Duplicate Address Detection " + "probes to send"), + NULL, 0, &ip_dad_count, 0, + CTL_NET, PF_INET, IPPROTO_IP, + IPCTL_DAD_COUNT, CTL_EOL); +#endif /* anonportalgo RFC6056 subtree */ const struct sysctlnode *portalgo_node;