Index: net/if.c =================================================================== RCS file: /cvs/src/sys/net/if.c,v retrieving revision 1.538 diff -u -p -r1.538 if.c --- net/if.c 12 Jan 2018 23:47:24 -0000 1.538 +++ net/if.c 15 Jan 2018 03:47:38 -0000 @@ -1139,8 +1139,8 @@ if_isconnected(const struct ifnet *ifp0, connected = 1; #endif #if NCARP > 0 - if ((ifp0->if_type == IFT_CARP && ifp0->if_carpdev == ifp) || - (ifp->if_type == IFT_CARP && ifp->if_carpdev == ifp0)) + if ((ifp0->if_type == IFT_CARP && carp_parent(ifp0) == ifp) || + (ifp->if_type == IFT_CARP && carp_parent(ifp) == ifp0)) connected = 1; #endif Index: net/if_bridge.c =================================================================== RCS file: /cvs/src/sys/net/if_bridge.c,v retrieving revision 1.301 diff -u -p -r1.301 if_bridge.c --- net/if_bridge.c 10 Jan 2018 23:50:39 -0000 1.301 +++ net/if_bridge.c 15 Jan 2018 03:47:39 -0000 @@ -1108,7 +1108,7 @@ bridge_process(struct ifnet *ifp, struct ac = (struct arpcom *)ifl->ifp; if (bcmp(ac->ac_enaddr, eh->ether_dhost, ETHER_ADDR_LEN) == 0 #if NCARP > 0 - || (!SRPL_EMPTY_LOCKED(&ifl->ifp->if_carp) && + || (!SRPL_EMPTY_LOCKED(&ac->ac_carpifs) && !carp_ourether(ifl->ifp, eh->ether_dhost)) #endif ) { @@ -1131,7 +1131,7 @@ bridge_process(struct ifnet *ifp, struct } if (bcmp(ac->ac_enaddr, eh->ether_shost, ETHER_ADDR_LEN) == 0 #if NCARP > 0 - || (!SRPL_EMPTY_LOCKED(&ifl->ifp->if_carp) && + || (!SRPL_EMPTY_LOCKED(&ac->ac_carpifs) && !carp_ourether(ifl->ifp, eh->ether_shost)) #endif ) { Index: net/if_ethersubr.c =================================================================== RCS file: /cvs/src/sys/net/if_ethersubr.c,v retrieving revision 1.250 diff -u -p -r1.250 if_ethersubr.c --- net/if_ethersubr.c 10 Jan 2018 00:14:38 -0000 1.250 +++ net/if_ethersubr.c 15 Jan 2018 03:47:39 -0000 @@ -505,6 +505,8 @@ ether_ifattach(struct ifnet *ifp) #if NBPFILTER > 0 bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, ETHER_HDR_LEN); #endif + + SRPL_INIT(&ac->ac_carpifs); } void Index: net/if_var.h =================================================================== RCS file: /cvs/src/sys/net/if_var.h,v retrieving revision 1.89 diff -u -p -r1.89 if_var.h --- net/if_var.h 10 Jan 2018 23:50:39 -0000 1.89 +++ net/if_var.h 15 Jan 2018 03:47:39 -0000 @@ -133,12 +133,6 @@ struct ifnet { /* and the entries */ caddr_t if_mcast; /* used by multicast code */ caddr_t if_mcast6; /* used by IPv6 multicast code */ caddr_t if_pf_kif; /* pf interface abstraction */ - union { - struct srpl carp_s; /* carp if list (used by !carp ifs) */ - struct ifnet *carp_d; /* ptr to carpdev (used by carp ifs) */ - } if_carp_ptr; -#define if_carp if_carp_ptr.carp_s -#define if_carpdev if_carp_ptr.carp_d unsigned int if_index; /* [I] unique index for this if */ short if_timer; /* time 'til if_watchdog called */ unsigned short if_flags; /* [N] up/down, broadcast, etc. */ Index: net/pf.c =================================================================== RCS file: /cvs/src/sys/net/pf.c,v retrieving revision 1.1055 diff -u -p -r1.1055 pf.c --- net/pf.c 10 Jan 2018 13:57:17 -0000 1.1055 +++ net/pf.c 15 Jan 2018 03:47:39 -0000 @@ -99,6 +99,10 @@ #include #endif /* NPFSYNC > 0 */ +#if NCARP > 0 +#include +#endif /* NCARP > 0 */ + #ifdef DDB #include #include @@ -334,6 +338,19 @@ RB_GENERATE(pf_state_tree_id, pf_state, SLIST_HEAD(pf_rule_gcl, pf_rule) pf_rule_gcl = SLIST_HEAD_INITIALIZER(pf_rule_gcl); +static inline struct pfi_kif * +pf_if_kif(struct ifnet *ifp) +{ +#if NCARP > 0 + if (ifp->if_type == IFT_CARP) { + struct ifnet *ifp0 = carp_parent(ifp); + if (ifp0 != NULL) + ifp = ifp0; + } +#endif /* NCARP */ + return (struct pfi_kif *)ifp->if_pf_kif; +} + __inline int pf_addr_compare(struct pf_addr *a, struct pf_addr *b, sa_family_t af) { @@ -3059,13 +3076,7 @@ pf_match_rcvif(struct mbuf *m, struct pf if (ifp == NULL) return (0); -#if NCARP > 0 - if (ifp->if_type == IFT_CARP && ifp->if_carpdev) - kif = (struct pfi_kif *)ifp->if_carpdev->if_pf_kif; - else -#endif /* NCARP */ - kif = (struct pfi_kif *)ifp->if_pf_kif; - + kif = pf_if_kif(ifp); if_put(ifp); if (kif == NULL) { @@ -5813,7 +5824,7 @@ pf_routable(struct pf_addr *addr, sa_fam ifp = if_get(rt->rt_ifidx); if (ifp != NULL && ifp->if_type == IFT_CARP && - ifp->if_carpdev == kif->pfik_ifp) + carp_parent(ifp) == kif->pfik_ifp) ret = 1; if_put(ifp); #endif /* NCARP */ @@ -6722,12 +6733,7 @@ pf_test(sa_family_t af, int fwdir, struc if (!pf_status.running) return (PF_PASS); -#if NCARP > 0 - if (ifp->if_type == IFT_CARP && ifp->if_carpdev) - kif = (struct pfi_kif *)ifp->if_carpdev->if_pf_kif; - else -#endif /* NCARP */ - kif = (struct pfi_kif *)ifp->if_pf_kif; + kif = pf_if_kif(ifp); if (kif == NULL) { DPFPRINTF(LOG_ERR, Index: netinet/if_ether.h =================================================================== RCS file: /cvs/src/sys/netinet/if_ether.h,v retrieving revision 1.73 diff -u -p -r1.73 if_ether.h --- netinet/if_ether.h 29 Nov 2016 10:09:57 -0000 1.73 +++ netinet/if_ether.h 15 Jan 2018 03:47:39 -0000 @@ -205,6 +205,14 @@ struct arpcom { int ac_multicnt; /* length of ac_multiaddrs */ int ac_multirangecnt; /* number of mcast ranges */ + union { + /* list of carp interfaces on IFT_ETHER */ + struct srpl _carpifs; + /* the parent interface on IFT_CARP */ + struct ifnet *_carpdev; + } _ac_carp; +#define ac_carpifs _ac_carp._carpifs +#define ac_carpdev _ac_carp._carpdev }; extern int arpt_keep; /* arp resolved cache expire */ Index: netinet/ip_carp.c =================================================================== RCS file: /cvs/src/sys/netinet/ip_carp.c,v retrieving revision 1.327 diff -u -p -r1.327 ip_carp.c --- netinet/ip_carp.c 12 Jan 2018 23:47:24 -0000 1.327 +++ netinet/ip_carp.c 15 Jan 2018 03:47:40 -0000 @@ -130,7 +130,7 @@ struct srpl_rc carp_vh_rc = struct carp_softc { struct arpcom sc_ac; #define sc_if sc_ac.ac_if -#define sc_carpdev sc_ac.ac_if.if_carpdev +#define sc_carpdev sc_ac.ac_carpdev void *ah_cookie; void *lh_cookie; void *dh_cookie; @@ -266,6 +266,14 @@ struct if_clone carp_cloner = #define carp_cksum(_m, _l) ((u_int16_t)in_cksum((_m), (_l))) #define CARP_IFQ_PRIO 6 +static inline struct srpl * +carp_ifs(struct ifnet *ifp0) +{ + struct arpcom *ac0 = (struct arpcom *)ifp0; + + return (&ac0->ac_carpifs); +} + void carp_hmac_prepare(struct carp_softc *sc) { @@ -455,7 +463,7 @@ carp_proto_input_if(struct ifnet *ifp, s case IFT_CARP: break; case IFT_ETHER: - if (ismulti || !SRPL_EMPTY_LOCKED(&ifp->if_carp)) + if (ismulti || !SRPL_EMPTY_LOCKED(carp_ifs(ifp))) break; /* FALLTHROUGH */ default: @@ -602,11 +610,11 @@ carp_proto_input_c(struct ifnet *ifp, st struct srpl *cif; if (ifp->if_type == IFT_CARP) - cif = &ifp->if_carpdev->if_carp; + cif = carp_ifs(carp_parent(ifp)); else - cif = &ifp->if_carp; + cif = carp_ifs(ifp); - KERNEL_ASSERT_LOCKED(); /* touching if_carp + carp_vhosts */ + KERNEL_ASSERT_LOCKED(); /* touching ac_carpifs + carp_vhosts */ SRPL_FOREACH_LOCKED(sc, cif, sc_list) { if (af == AF_INET && ismulti != IN_MULTICAST(sc->sc_peer.s_addr)) @@ -931,9 +939,9 @@ carpdetach(void *arg) if (ifp0 == NULL) return; - KERNEL_ASSERT_LOCKED(); /* touching if_carp */ + KERNEL_ASSERT_LOCKED(); /* touching ac_carpifs */ - cif = &ifp0->if_carp; + cif = carp_ifs(ifp0); /* Restore previous input handler. */ if_ih_remove(ifp0, carp_input, NULL); @@ -991,7 +999,7 @@ carp_send_ad_all(void) struct srpl *cif; struct carp_softc *vh; - KERNEL_ASSERT_LOCKED(); /* touching if_carp */ + KERNEL_ASSERT_LOCKED(); /* touching ac_carpifs */ if (carp_send_all_recur > 0) return; @@ -1000,7 +1008,7 @@ carp_send_ad_all(void) if (ifp0->if_type != IFT_ETHER) continue; - cif = &ifp0->if_carp; + cif = carp_ifs(ifp0); SRPL_FOREACH_LOCKED(vh, cif, sc_list) { if ((vh->sc_if.if_flags & (IFF_UP|IFF_RUNNING)) == (IFF_UP|IFF_RUNNING)) { @@ -1336,15 +1344,27 @@ carp_iamatch(struct ifnet *ifp) return (match); } +struct ifnet * +carp_parent(const struct ifnet *ifp) +{ + const struct arpcom *ac; + + KASSERT(ifp->if_type == IFT_CARP); + + ac = (struct arpcom *)ifp; + + return (ac->ac_carpdev); +} + int carp_ourether(struct ifnet *ifp, u_int8_t *ena) { struct srpl *cif; struct carp_softc *vh; - KERNEL_ASSERT_LOCKED(); /* touching if_carp + carp_vhosts */ + KERNEL_ASSERT_LOCKED(); /* touching ac_carpifs + carp_vhosts */ KASSERT(ifp->if_type == IFT_ETHER); - cif = &ifp->if_carp; + cif = carp_ifs(ifp); SRPL_FOREACH_LOCKED(vh, cif, sc_list) { struct carp_vhost_entry *vhe; @@ -1393,7 +1413,7 @@ carp_input(struct ifnet *ifp0, struct mb #endif eh = mtod(m, struct ether_header *); - cif = &ifp0->if_carp; + cif = carp_ifs(ifp0); SRPL_FOREACH(sc, &sr, cif, sc_list) { if ((sc->sc_if.if_flags & (IFF_UP|IFF_RUNNING)) != @@ -1685,7 +1705,7 @@ carp_set_ifp(struct carp_softc *sc, stru int myself = 0, error = 0; KASSERT(ifp0 != sc->sc_carpdev); - KERNEL_ASSERT_LOCKED(); /* touching if_carp */ + KERNEL_ASSERT_LOCKED(); /* touching ac_carpifs */ if ((ifp0->if_flags & IFF_MULTICAST) == 0) return (EADDRNOTAVAIL); @@ -1705,7 +1725,7 @@ carp_set_ifp(struct carp_softc *sc, stru goto rm_dh; } - cif = &ifp0->if_carp; + cif = carp_ifs(ifp0); if (SRPL_EMPTY_LOCKED(cif)) { if ((error = ifpromisc(ifp0, 1))) goto rm_lh; @@ -2174,7 +2194,7 @@ carp_check_dup_vhids(struct carp_softc * struct carp_vhost_entry *vhe, *vhe0; int i; - KERNEL_ASSERT_LOCKED(); /* touching if_carp + carp_vhosts */ + KERNEL_ASSERT_LOCKED(); /* touching ac_carpifs + carp_vhosts */ SRPL_FOREACH_LOCKED(vr, cif, sc_list) { if (vr == sc) @@ -2214,7 +2234,7 @@ carp_vhids_ioctl(struct carp_softc *sc, if (sc->sc_carpdev) { struct srpl *cif; - cif = &sc->sc_carpdev->if_carp; + cif = carp_ifs(sc->sc_carpdev); if (carp_check_dup_vhids(sc, cif, carpr)) return (EINVAL); } @@ -2300,7 +2320,7 @@ carp_start(struct ifnet *ifp) bpf_mtap_ether(ifp->if_bpf, m, BPF_DIRECTION_OUT); #endif /* NBPFILTER > 0 */ - if ((ifp->if_carpdev->if_flags & (IFF_UP|IFF_RUNNING)) != + if ((sc->sc_carpdev->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) { ifp->if_oerrors++; m_freem(m); @@ -2318,11 +2338,11 @@ carp_start(struct ifnet *ifp) uint8_t *esrc; eh = mtod(m, struct ether_header *); - esrc = ((struct arpcom*)ifp->if_carpdev)->ac_enaddr; + esrc = ((struct arpcom*)sc->sc_carpdev)->ac_enaddr; memcpy(eh->ether_shost, esrc, sizeof(eh->ether_shost)); } - if (if_enqueue(ifp->if_carpdev, m)) { + if (if_enqueue(sc->sc_carpdev, m)) { ifp->if_oerrors++; continue; } @@ -2486,9 +2506,9 @@ carp_carpdev_state(void *v) if (ifp0->if_type != IFT_ETHER) return; - cif = &ifp0->if_carp; + cif = carp_ifs(ifp0); - KERNEL_ASSERT_LOCKED(); /* touching if_carp */ + KERNEL_ASSERT_LOCKED(); /* touching ac_carpifs */ SRPL_FOREACH_LOCKED(sc, cif, sc_list) { int suppressed = sc->sc_suppress; Index: netinet/ip_carp.h =================================================================== RCS file: /cvs/src/sys/netinet/ip_carp.h,v retrieving revision 1.46 diff -u -p -r1.46 ip_carp.h --- netinet/ip_carp.h 12 Jan 2018 23:47:24 -0000 1.46 +++ netinet/ip_carp.h 15 Jan 2018 03:47:40 -0000 @@ -204,5 +204,7 @@ int carp_output(struct ifnet *, struct int carp_sysctl(int *, u_int, void *, size_t *, void *, size_t); int carp_lsdrop(struct mbuf *, sa_family_t, u_int32_t *, u_int32_t *, int); +struct ifnet *carp_parent(const struct ifnet *); + #endif /* _KERNEL */ #endif /* _NETINET_IP_CARP_H_ */