Index: net/if_bridge.c =================================================================== RCS file: /cvs/src/sys/net/if_bridge.c,v retrieving revision 1.261 diff -u -p -r1.261 if_bridge.c --- net/if_bridge.c 9 Sep 2015 12:50:08 -0000 1.261 +++ net/if_bridge.c 10 Sep 2015 11:05:12 -0000 @@ -1277,24 +1277,17 @@ bridge_input(struct ifnet *ifp, struct m return (NULL); } -void -bridge_process(struct mbuf *m) +static inline void +_bridge_process(struct ifnet *ifp, struct mbuf *m) { struct bridge_softc *sc; struct bridge_iflist *ifl; struct bridge_iflist *srcifl; struct ether_header *eh; - struct ifnet *ifp; struct arpcom *ac; struct mbuf_list ml = MBUF_LIST_INITIALIZER(); struct mbuf *mc; - ifp = if_get(m->m_pkthdr.ph_ifidx); - if (ifp == NULL) { - m_freem(m); - return; - } - ifl = (struct bridge_iflist *)ifp->if_bridgeport; if (ifl == NULL) goto reenqueue; @@ -1421,6 +1414,22 @@ reenqueue: m->m_flags |= M_PROTO1; ml_enqueue(&ml, m); if_input(ifp, &ml); +} + +void +bridge_process(struct mbuf *m) +{ + struct ifnet *ifp; + + ifp = if_get(m->m_pkthdr.ph_ifidx); + if (ifp == NULL) { + m_freem(m); + return; + } + + _bridge_process(ifp, m); + + if_put(ifp); } /* Index: net/if_tun.c =================================================================== RCS file: /cvs/src/sys/net/if_tun.c,v retrieving revision 1.154 diff -u -p -r1.154 if_tun.c --- net/if_tun.c 9 Sep 2015 20:18:03 -0000 1.154 +++ net/if_tun.c 10 Sep 2015 11:05:12 -0000 @@ -734,6 +734,7 @@ tunread(dev_t dev, struct uio *uio, int TUNDEBUG(("%s: read\n", ifp->if_xname)); if ((tp->tun_flags & TUN_READY) != TUN_READY) { TUNDEBUG(("%s: not ready %#x\n", ifp->if_xname, tp->tun_flags)); + if_put(ifp); return (EHOSTDOWN); } Index: net/if_var.h =================================================================== RCS file: /cvs/src/sys/net/if_var.h,v retrieving revision 1.35 diff -u -p -r1.35 if_var.h --- net/if_var.h 9 Sep 2015 16:01:10 -0000 1.35 +++ net/if_var.h 10 Sep 2015 11:05:13 -0000 @@ -148,7 +148,7 @@ struct ifnet { /* and the entries */ } if_carp_ptr; #define if_carp if_carp_ptr.carp_s #define if_carpdev if_carp_ptr.carp_d - u_short if_index; /* numeric abbreviation for this if */ + unsigned int if_index; /* numeric abbreviation for this if */ short if_timer; /* time 'til if_watchdog called */ short if_flags; /* up/down, broadcast, etc. */ int if_xflags; /* extra softnet flags */ @@ -233,7 +233,7 @@ struct ifaddr { */ struct ifmaddr { struct sockaddr *ifma_addr; /* Protocol address */ - unsigned short ifma_ifidx; /* Index of the interface */ + unsigned int ifma_ifidx; /* Index of the interface */ unsigned int ifma_refcnt; /* Count of references */ TAILQ_ENTRY(ifmaddr) ifma_list; /* Per-interface list */ }; Index: net/if_vlan.c =================================================================== RCS file: /cvs/src/sys/net/if_vlan.c,v retrieving revision 1.135 diff -u -p -r1.135 if_vlan.c --- net/if_vlan.c 20 Jul 2015 22:16:41 -0000 1.135 +++ net/if_vlan.c 10 Sep 2015 11:05:13 -0000 @@ -172,6 +172,24 @@ vlan_ifdetach(void *ptr) vlan_clone_destroy(&ifv->ifv_if); } +static inline int +vlan_mplstunnel(int ifidx) +{ +#if NMPW > 0 + struct ifnet *ifp; + int rv = 0; + + ifp = if_get(ifidx); + if (ifp != NULL) { + rv = ifp->if_type == IFT_MPLSTUNNEL; + if_put(ifp); + } + return (rv); +#else + return (0); +#endif +} + void vlan_start(struct ifnet *ifp) { @@ -206,21 +224,18 @@ vlan_start(struct ifnet *ifp) if (prio <= 1) prio = !prio; -#if NMPW > 0 - struct ifnet *ifpn = if_get(m->m_pkthdr.ph_ifidx); /* * If this packet came from a pseudowire it means it already * has all tags it needs, so just output it. */ - if (ifpn && ifpn->if_type == IFT_MPLSTUNNEL) { + if (vlan_mplstunnel(m->m_pkthdr.ph_ifidx)) { /* NOTHING */ - } else -#endif /* NMPW */ + /* * If the underlying interface cannot do VLAN tag insertion * itself, create an encapsulation header. */ - if ((p->if_capabilities & IFCAP_VLAN_HWTAGGING) && + } else if ((p->if_capabilities & IFCAP_VLAN_HWTAGGING) && (ifv->ifv_type == ETHERTYPE_VLAN)) { m->m_pkthdr.ether_vtag = ifv->ifv_tag + (prio << EVL_PRIO_BITS); Index: net/route.c =================================================================== RCS file: /cvs/src/sys/net/route.c,v retrieving revision 1.230 diff -u -p -r1.230 route.c --- net/route.c 4 Sep 2015 08:43:39 -0000 1.230 +++ net/route.c 10 Sep 2015 11:05:13 -0000 @@ -684,8 +684,10 @@ ifa_ifwithroute(int flags, struct sockad if (ifp == NULL) ifp = ifunit(sdl->sdl_data); - if (ifp != NULL) + if (ifp != NULL) { ifa = ifaof_ifpforaddr(dst, ifp); + if_put(ifp); + } } else { ifa = ifa_ifwithnet(gateway, rtableid); } @@ -764,6 +766,8 @@ rt_getifa(struct rt_addrinfo *info, u_in info->rti_ifa = ifa_ifwithroute(info->rti_flags, sa, sa, rtid); } + + if_put(ifp); if (info->rti_ifa == NULL) return (ENETUNREACH); Index: netinet/if_ether.c =================================================================== RCS file: /cvs/src/sys/netinet/if_ether.c,v retrieving revision 1.164 diff -u -p -r1.164 if_ether.c --- netinet/if_ether.c 9 Sep 2015 15:59:19 -0000 1.164 +++ netinet/if_ether.c 10 Sep 2015 11:05:14 -0000 @@ -109,7 +109,6 @@ int la_hold_total; /* revarp state */ struct in_addr revarp_myip, revarp_srvip; int revarp_finished; -int revarp_in_progress; struct ifnet *revarp_ifp; #endif /* NFSCLIENT */ @@ -545,8 +544,10 @@ in_arpinput(struct mbuf *m) unsigned int len; ifp = if_get(m->m_pkthdr.ph_ifidx); - if (ifp == NULL) - goto out; + if (ifp == NULL) { + m_freem(m); + return; + } ac = (struct arpcom *)ifp; ea = mtod(m, struct ether_arp *); @@ -724,6 +725,7 @@ in_arpinput(struct mbuf *m) reply: if (op != ARPOP_REQUEST) { out: + if_put(ifp); m_freem(m); return; } @@ -759,6 +761,7 @@ out: sa.sa_family = pseudo_AF_HDRCMPLT; sa.sa_len = sizeof(sa); (*ifp->if_output)(ifp, m, &sa, NULL); + if_put(ifp); return; } @@ -901,9 +904,6 @@ out: void in_revarpinput(struct mbuf *m) { -#ifdef NFSCLIENT - struct ifnet *ifp; -#endif /* NFSCLIENT */ struct ether_arp *ar; int op; @@ -921,14 +921,13 @@ in_revarpinput(struct mbuf *m) goto out; } #ifdef NFSCLIENT - if (!revarp_in_progress) + if (revarp_ifp == NULL) goto out; - ifp = if_get(m->m_pkthdr.ph_ifidx); - if (ifp != revarp_ifp) /* !same interface */ + if (revarp_ifp->if_index != m->m_pkthdr.ph_ifidx) /* !same interface */ goto out; if (revarp_finished) goto wake; - if (memcmp(ar->arp_tha, ((struct arpcom *)ifp)->ac_enaddr, + if (memcmp(ar->arp_tha, ((struct arpcom *)revarp_ifp)->ac_enaddr, sizeof(ar->arp_tha))) goto out; memcpy(&revarp_srvip, ar->arp_spa, sizeof(revarp_srvip)); @@ -994,15 +993,15 @@ revarpwhoarewe(struct ifnet *ifp, struct if (revarp_finished) return EIO; - revarp_ifp = ifp; - revarp_in_progress = 1; + revarp_ifp = if_ref(ifp); while (count--) { revarprequest(ifp); result = tsleep((caddr_t)&revarp_myip, PSOCK, "revarp", hz/2); if (result != EWOULDBLOCK) break; } - revarp_in_progress = 0; + if_put(revarp_ifp); + revarp_ifp = NULL; if (!revarp_finished) return ENETUNREACH; Index: netinet/igmp.c =================================================================== RCS file: /cvs/src/sys/netinet/igmp.c,v retrieving revision 1.50 diff -u -p -r1.50 igmp.c --- netinet/igmp.c 28 Aug 2015 00:03:54 -0000 1.50 +++ netinet/igmp.c 10 Sep 2015 11:05:14 -0000 @@ -107,6 +107,7 @@ void igmp_checktimer(struct ifnet *); void igmp_sendpkt(struct in_multi *, int, in_addr_t); int rti_fill(struct in_multi *); struct router_info * rti_find(struct ifnet *); +void igmp_input_if(struct ifnet *, struct mbuf *, int); void igmp_init(void) @@ -183,7 +184,7 @@ rti_find(struct ifnet *ifp) M_MRTABLE, M_NOWAIT); if (rti == NULL) return (NULL); - rti->rti_ifp = ifp; + rti->rti_ifp = if_ref(ifp); rti->rti_type = IGMP_v2_ROUTER; rti->rti_next = rti_head; rti_head = rti; @@ -197,6 +198,7 @@ rti_delete(struct ifnet *ifp) for (rti = rti_head; rti != 0; rti = rti->rti_next) { if (rti->rti_ifp == ifp) { + if_put(ifp); *prti = rti->rti_next; free(rti, M_MRTABLE, sizeof(*rti)); break; @@ -210,15 +212,6 @@ igmp_input(struct mbuf *m, ...) { int iphlen; struct ifnet *ifp; - struct ip *ip = mtod(m, struct ip *); - struct igmp *igmp; - int igmplen; - int minlen; - struct ifmaddr *ifma; - struct in_multi *inm; - struct router_info *rti; - struct in_ifaddr *ia; - int timer; va_list ap; va_start(ap, m); @@ -227,13 +220,30 @@ igmp_input(struct mbuf *m, ...) ++igmpstat.igps_rcv_total; - igmplen = ntohs(ip->ip_len) - iphlen; - ifp = if_get(m->m_pkthdr.ph_ifidx); if (ifp == NULL) { m_freem(m); return; } + + igmp_input_if(ifp, m, iphlen); + if_put(ifp); +} + +void +igmp_input_if(struct ifnet *ifp, struct mbuf *m, int iphlen) +{ + struct ip *ip = mtod(m, struct ip *); + struct igmp *igmp; + int igmplen; + int minlen; + struct ifmaddr *ifma; + struct in_multi *inm; + struct router_info *rti; + struct in_ifaddr *ia; + int timer; + + igmplen = ntohs(ip->ip_len) - iphlen; /* * Validate lengths Index: netinet/ip_carp.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_carp.c,v retrieving revision 1.264 diff -u -p -r1.264 ip_carp.c --- netinet/ip_carp.c 2 Jul 2015 09:40:03 -0000 1.264 +++ netinet/ip_carp.c 10 Sep 2015 11:05:14 -0000 @@ -195,8 +195,9 @@ void carp_hmac_generate(struct carp_vhos int carp_hmac_verify(struct carp_vhost_entry *, u_int32_t *, unsigned char *); int carp_input(struct ifnet *ifp, struct mbuf *); -void carp_proto_input_c(struct mbuf *, struct carp_header *, int, - sa_family_t); +void carp_proto_input_c(struct ifnet *ifp, struct mbuf *, + struct carp_header *, int, sa_family_t); +void carp_proto_input_if(struct ifnet *, struct mbuf *, int); void carpattach(int); void carpdetach(struct carp_softc *); int carp_prepare_ad(struct mbuf *, struct carp_vhost_entry *, @@ -390,19 +391,11 @@ carp_hmac_verify(struct carp_vhost_entry return (1); } -/* - * process input packet. - * we have rearranged checks order compared to the rfc, - * but it seems more efficient this way or not possible otherwise. - */ void carp_proto_input(struct mbuf *m, ...) { - struct ip *ip = mtod(m, struct ip *); struct ifnet *ifp; - struct carp_softc *sc = NULL; - struct carp_header *ch; - int iplen, len, hlen, ismulti; + int hlen; va_list ap; va_start(ap, m); @@ -415,6 +408,23 @@ carp_proto_input(struct mbuf *m, ...) return; } + carp_proto_input_if(ifp, m, hlen); + if_put(ifp); +} + +/* + * process input packet. + * we have rearranged checks order compared to the rfc, + * but it seems more efficient this way or not possible otherwise. + */ +void +carp_proto_input_if(struct ifnet *ifp, struct mbuf *m, int hlen) +{ + struct ip *ip = mtod(m, struct ip *); + struct carp_softc *sc = NULL; + struct carp_header *ch; + int iplen, len, ismulti; + carpstats.carps_ipackets++; if (!carp_opts[CARPCTL_ALLOW]) { @@ -476,19 +486,18 @@ carp_proto_input(struct mbuf *m, ...) } m->m_data -= iplen; - carp_proto_input_c(m, ch, ismulti, AF_INET); + carp_proto_input_c(ifp, m, ch, ismulti, AF_INET); } #ifdef INET6 +int carp6_proto_input_if(struct ifnet *, struct mbuf *, int *); + int carp6_proto_input(struct mbuf **mp, int *offp, int proto) { struct mbuf *m = *mp; struct ifnet *ifp; - struct carp_softc *sc = NULL; - struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); - struct carp_header *ch; - u_int len; + int rv; ifp = if_get(m->m_pkthdr.ph_ifidx); if (ifp == NULL) { @@ -496,6 +505,20 @@ carp6_proto_input(struct mbuf **mp, int return (IPPROTO_DONE); } + rv = carp6_proto_input_if(ifp, m, offp); + if_put(ifp); + + return (rv); +} + +int +carp6_proto_input_if(struct ifnet *ifp, struct mbuf *m, int *offp) +{ + struct carp_softc *sc = NULL; + struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); + struct carp_header *ch; + u_int len; + carpstats.carps_ipackets6++; if (!carp_opts[CARPCTL_ALLOW]) { @@ -541,24 +564,20 @@ carp6_proto_input(struct mbuf **mp, int } m->m_data -= *offp; - carp_proto_input_c(m, ch, 1, AF_INET6); + carp_proto_input_c(ifp, m, ch, 1, AF_INET6); return (IPPROTO_DONE); } #endif /* INET6 */ void -carp_proto_input_c(struct mbuf *m, struct carp_header *ch, int ismulti, - sa_family_t af) +carp_proto_input_c(struct ifnet *ifp, struct mbuf *m, struct carp_header *ch, + int ismulti, sa_family_t af) { - struct ifnet *ifp; struct carp_softc *sc; struct carp_vhost_entry *vhe; struct timeval sc_tv, ch_tv; struct carp_if *cif; - ifp = if_get(m->m_pkthdr.ph_ifidx); - KASSERT(ifp != NULL); - if (ifp->if_type == IFT_CARP) cif = (struct carp_if *)ifp->if_carpdev->if_carp; else @@ -1474,7 +1493,7 @@ carp_lsdrop(struct mbuf *m, sa_family_t { struct ifnet *ifp; struct carp_softc *sc; - int match; + int match = 1; u_int32_t fold; ifp = if_get(m->m_pkthdr.ph_ifidx); @@ -1482,13 +1501,13 @@ carp_lsdrop(struct mbuf *m, sa_family_t sc = ifp->if_softc; if (sc->sc_balancing < CARP_BAL_IP) - return (0); + goto done; /* * Never drop carp advertisements. * XXX Bad idea to pass all broadcast / multicast traffic? */ if (m->m_flags & (M_BCAST|M_MCAST)) - return (0); + goto done; fold = src[0] ^ dst[0]; #ifdef INET6 @@ -1499,9 +1518,12 @@ carp_lsdrop(struct mbuf *m, sa_family_t } #endif if (sc->sc_lscount == 0) /* just to be safe */ - return (1); - match = (1 << (ntohl(fold) % sc->sc_lscount)) & sc->sc_lsmask; + match = 0; + else + match = (1 << (ntohl(fold) % sc->sc_lscount)) & sc->sc_lsmask; +done: + if_put(ifp); return (!match); } Index: netinet/ip_icmp.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_icmp.c,v retrieving revision 1.138 diff -u -p -r1.138 ip_icmp.c --- netinet/ip_icmp.c 1 Sep 2015 21:24:04 -0000 1.138 +++ netinet/ip_icmp.c 10 Sep 2015 11:05:14 -0000 @@ -128,6 +128,7 @@ int *icmpctl_vars[ICMPCTL_MAXID] = ICMPC void icmp_mtudisc_timeout(struct rtentry *, struct rttimer *); int icmp_ratelimit(const struct in_addr *, const int, const int); void icmp_redirect_timeout(struct rtentry *, struct rttimer *); +void icmp_input_if(struct ifnet *, struct mbuf *, int); void icmp_init(void) @@ -306,22 +307,33 @@ void icmp_input(struct mbuf *m, ...) { struct ifnet *ifp; - struct icmp *icp; - struct ip *ip = mtod(m, struct ip *); - struct sockaddr_in sin; - int icmplen, i, code, hlen; - struct in_ifaddr *ia; - void *(*ctlfunc)(int, struct sockaddr *, u_int, void *); + int hlen; va_list ap; - struct mbuf *opts; va_start(ap, m); hlen = va_arg(ap, int); va_end(ap); ifp = if_get(m->m_pkthdr.ph_ifidx); - if (ifp == NULL) - goto freeit; + if (ifp == NULL) { + m_freem(m); + return; + } + + icmp_input_if(ifp, m, hlen); + if_put(ifp); +} + +void +icmp_input_if(struct ifnet *ifp, struct mbuf *m, int hlen) +{ + struct icmp *icp; + struct ip *ip = mtod(m, struct ip *); + struct sockaddr_in sin; + int icmplen, i, code; + struct in_ifaddr *ia; + void *(*ctlfunc)(int, struct sockaddr *, u_int, void *); + struct mbuf *opts; /* * Locate icmp structure in mbuf, and check Index: netinet/ip_input.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_input.c,v retrieving revision 1.253 diff -u -p -r1.253 ip_input.c --- netinet/ip_input.c 19 Aug 2015 15:30:25 -0000 1.253 +++ netinet/ip_input.c 10 Sep 2015 11:05:15 -0000 @@ -233,7 +233,7 @@ ipv4_input(struct mbuf *m) if (m->m_len < sizeof (struct ip) && (m = m_pullup(m, sizeof (struct ip))) == NULL) { ipstat.ips_toosmall++; - return; + goto out; } ip = mtod(m, struct ip *); if (ip->ip_v != IPVERSION) { @@ -248,7 +248,7 @@ ipv4_input(struct mbuf *m) if (hlen > m->m_len) { if ((m = m_pullup(m, hlen)) == NULL) { ipstat.ips_badhlen++; - return; + goto out; } ip = mtod(m, struct ip *); } @@ -318,7 +318,7 @@ ipv4_input(struct mbuf *m) if (pf_test(AF_INET, PF_IN, ifp, &m) != PF_PASS) goto bad; if (m == NULL) - return; + goto out; ip = mtod(m, struct ip *); hlen = ip->ip_hl << 2; @@ -332,12 +332,12 @@ ipv4_input(struct mbuf *m) * to be sent and the original packet to be freed). */ if (hlen > sizeof (struct ip) && ip_dooptions(m, ifp)) { - return; + goto out; } if (in_ouraddr(m, ifp, ip->ip_dst)) { ip_ours(m); - return; + goto out; } if (IN_MULTICAST(ip->ip_dst.s_addr)) { @@ -355,7 +355,7 @@ ipv4_input(struct mbuf *m) if (m->m_flags & M_EXT) { if ((m = m_pullup(m, hlen)) == NULL) { ipstat.ips_toosmall++; - return; + goto out; } ip = mtod(m, struct ip *); } @@ -383,7 +383,7 @@ ipv4_input(struct mbuf *m) */ if (ip->ip_p == IPPROTO_IGMP) { ip_ours(m); - return; + goto out; } ipstat.ips_forward++; } @@ -400,13 +400,13 @@ ipv4_input(struct mbuf *m) goto bad; } ip_ours(m); - return; + goto out; } if (ip->ip_dst.s_addr == INADDR_BROADCAST || ip->ip_dst.s_addr == INADDR_ANY) { ip_ours(m); - return; + goto out; } #if NCARP > 0 @@ -451,9 +451,12 @@ ipv4_input(struct mbuf *m) #endif /* IPSEC */ ip_forward(m, ifp, pfrdr); + if_put(ifp); return; bad: m_freem(m); +out: + if_put(ifp); } /*