Date: Sat, 27 Apr 2019 04:39:43 +0000 (UTC) From: Kyle Evans <kevans@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r346783 - in stable: 11/sys/conf 11/sys/net 12/sys/conf 12/sys/net Message-ID: <201904270439.x3R4dhar073837@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kevans Date: Sat Apr 27 04:39:41 2019 New Revision: 346783 URL: https://svnweb.freebsd.org/changeset/base/346783 Log: MFC r345139, r345151, r346324, r346328: ether_gen_addr KPI if_bridge and if_vxlan conversion to this deterministic MAC address KPI has been MFC as well. This is potentially error prone as the generated address range for these has decreased, but I've deemed this acceptable for stable branches due to collisions for thees interfaces being easily remedied. I have no intention of switching anything else to this KPI in any stable branches. r345139: ether: centralize fake hwaddr generation We currently have two places with identical fake hwaddr generation -- if_vxlan and if_bridge. Lift it into if_ethersubr for reuse in other interfaces that may also need a fake addr. r345151: ether_fakeaddr: Use 'b' 's' 'd' for the prefix This has the advantage of being obvious to sniff out the designated prefix by eye and it has all the right bits set. Comment stolen from ffec. I've removed bryanv@'s pending question of using the FreeBSD OUI range -- no one has followed up on this with a definitive action, and there's no particular reason to shoot for it and the administrative overhead that comes with deciding exactly how to use it. r346324: net: adjust randomized address bits Give devices that need a MAC a 16-bit allocation out of the FreeBSD Foundation OUI range. Change the name ether_fakeaddr to ether_gen_addr now that we're dealing real MAC addresses with a real OUI rather than random locally-administered addresses. r346328: Compile sha1.c when ether support is included sha1 is used by ether_gen_addr after r346324. Perhaps in an ideal world we could detect that the kernel's been compiled without sha1_* bits included and silently fallback to arc4random instead because these platforms/kernel configs are far and few between. It's fairly lightweight, though, so just include it for now. Modified: stable/12/sys/conf/files stable/12/sys/net/ethernet.h stable/12/sys/net/ieee_oui.h stable/12/sys/net/if_bridge.c stable/12/sys/net/if_ethersubr.c stable/12/sys/net/if_vxlan.c Directory Properties: stable/12/ (props changed) Changes in other areas also in this revision: Modified: stable/11/sys/conf/files stable/11/sys/net/ethernet.h stable/11/sys/net/ieee_oui.h stable/11/sys/net/if_bridge.c stable/11/sys/net/if_ethersubr.c stable/11/sys/net/if_vxlan.c Directory Properties: stable/11/ (props changed) Modified: stable/12/sys/conf/files ============================================================================== --- stable/12/sys/conf/files Sat Apr 27 04:16:15 2019 (r346782) +++ stable/12/sys/conf/files Sat Apr 27 04:39:41 2019 (r346783) @@ -678,8 +678,8 @@ crypto/rijndael/rijndael-alg-fst.c optional crypto | e crypto/rijndael/rijndael-api-fst.c optional ekcd | geom_bde | random !random_loadable crypto/rijndael/rijndael-api.c optional crypto | ipsec | ipsec_support | \ wlan_ccmp -crypto/sha1.c optional carp | crypto | ipsec | \ - ipsec_support | netgraph_mppc_encryption | sctp +crypto/sha1.c optional carp | crypto | ether | ipsec | \ + ipsec_support | netgraph_mppc_encryption | sctp crypto/sha2/sha256c.c optional crypto | ekcd | geom_bde | ipsec | \ ipsec_support | random !random_loadable | sctp | zfs crypto/sha2/sha512c.c optional crypto | geom_bde | ipsec | \ Modified: stable/12/sys/net/ethernet.h ============================================================================== --- stable/12/sys/net/ethernet.h Sat Apr 27 04:16:15 2019 (r346782) +++ stable/12/sys/net/ethernet.h Sat Apr 27 04:39:41 2019 (r346783) @@ -422,6 +422,7 @@ void ether_vlan_mtap(struct bpf_if *, struct mbuf *, struct mbuf *ether_vlanencap(struct mbuf *, uint16_t); bool ether_8021q_frame(struct mbuf **mp, struct ifnet *ife, struct ifnet *p, uint16_t vid, uint8_t pcp); +void ether_gen_addr(struct ifnet *ifp, struct ether_addr *hwaddr); #ifdef _SYS_EVENTHANDLER_H_ /* new ethernet interface attached event */ Modified: stable/12/sys/net/ieee_oui.h ============================================================================== --- stable/12/sys/net/ieee_oui.h Sat Apr 27 04:16:15 2019 (r346782) +++ stable/12/sys/net/ieee_oui.h Sat Apr 27 04:39:41 2019 (r346783) @@ -67,3 +67,14 @@ /* Allocate 20 bits to bhyve */ #define OUI_FREEBSD_BHYVE_LOW OUI_FREEBSD(0x000001) #define OUI_FREEBSD_BHYVE_HIGH OUI_FREEBSD(0x0fffff) + +/* + * Allocate 16 bits for a pool to give to various interfaces that need a + * generated address, but don't quite need to slice off a whole section of + * the OUI (e.g. cloned interfaces, one-off NICs of various vendors). + * + * ether_gen_addr should be used to generate an address from this pool. + */ +#define OUI_FREEBSD_GENERATED_MASK 0x10ffff +#define OUI_FREEBSD_GENERATED_LOW OUI_FREEBSD(0x100000) +#define OUI_FREEBSD_GENERATED_HIGH OUI_FREEBSD(OU_FREEBSD_GENERATED_MASK) Modified: stable/12/sys/net/if_bridge.c ============================================================================== --- stable/12/sys/net/if_bridge.c Sat Apr 27 04:16:15 2019 (r346782) +++ stable/12/sys/net/if_bridge.c Sat Apr 27 04:39:41 2019 (r346783) @@ -226,7 +226,7 @@ struct bridge_softc { struct bstp_state sc_stp; /* STP state */ uint32_t sc_brtexceeded; /* # of cache drops */ struct ifnet *sc_ifaddr; /* member mac copied from */ - u_char sc_defaddr[6]; /* Default MAC address */ + struct ether_addr sc_defaddr; /* Default MAC address */ }; VNET_DEFINE_STATIC(struct mtx, bridge_list_mtx); @@ -671,16 +671,14 @@ bridge_clone_create(struct if_clone *ifc, int unit, ca getcredhostid(curthread->td_ucred, &hostid); do { if (fb || hostid == 0) { - arc4rand(sc->sc_defaddr, ETHER_ADDR_LEN, 1); - sc->sc_defaddr[0] &= ~1;/* clear multicast bit */ - sc->sc_defaddr[0] |= 2; /* set the LAA bit */ + ether_gen_addr(ifp, &sc->sc_defaddr); } else { - sc->sc_defaddr[0] = 0x2; - sc->sc_defaddr[1] = (hostid >> 24) & 0xff; - sc->sc_defaddr[2] = (hostid >> 16) & 0xff; - sc->sc_defaddr[3] = (hostid >> 8 ) & 0xff; - sc->sc_defaddr[4] = hostid & 0xff; - sc->sc_defaddr[5] = ifp->if_dunit & 0xff; + sc->sc_defaddr.octet[0] = 0x2; + sc->sc_defaddr.octet[1] = (hostid >> 24) & 0xff; + sc->sc_defaddr.octet[2] = (hostid >> 16) & 0xff; + sc->sc_defaddr.octet[3] = (hostid >> 8 ) & 0xff; + sc->sc_defaddr.octet[4] = hostid & 0xff; + sc->sc_defaddr.octet[5] = ifp->if_dunit & 0xff; } fb = 1; @@ -688,7 +686,7 @@ bridge_clone_create(struct if_clone *ifc, int unit, ca BRIDGE_LIST_LOCK(); LIST_FOREACH(sc2, &V_bridge_list, sc_list) { bifp = sc2->sc_ifp; - if (memcmp(sc->sc_defaddr, + if (memcmp(sc->sc_defaddr.octet, IF_LLADDR(bifp), ETHER_ADDR_LEN) == 0) { retry = 1; break; @@ -698,7 +696,7 @@ bridge_clone_create(struct if_clone *ifc, int unit, ca } while (retry == 1); bstp_attach(&sc->sc_stp, &bridge_ops); - ether_ifattach(ifp, sc->sc_defaddr); + ether_ifattach(ifp, sc->sc_defaddr.octet); /* Now undo some of the damage... */ ifp->if_baudrate = 0; ifp->if_type = IFT_BRIDGE; @@ -1019,7 +1017,7 @@ bridge_delete_member(struct bridge_softc *sc, struct b */ if (V_bridge_inherit_mac && sc->sc_ifaddr == ifs) { if (LIST_EMPTY(&sc->sc_iflist)) { - bcopy(sc->sc_defaddr, + bcopy(&sc->sc_defaddr, IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN); sc->sc_ifaddr = NULL; } else { @@ -1190,7 +1188,7 @@ bridge_ioctl_add(struct bridge_softc *sc, void *arg) * the default randomly generated one. */ if (V_bridge_inherit_mac && LIST_EMPTY(&sc->sc_iflist) && - !memcmp(IF_LLADDR(sc->sc_ifp), sc->sc_defaddr, ETHER_ADDR_LEN)) { + !memcmp(IF_LLADDR(sc->sc_ifp), sc->sc_defaddr.octet, ETHER_ADDR_LEN)) { bcopy(IF_LLADDR(ifs), IF_LLADDR(sc->sc_ifp), ETHER_ADDR_LEN); sc->sc_ifaddr = ifs; EVENTHANDLER_INVOKE(iflladdr_event, sc->sc_ifp); Modified: stable/12/sys/net/if_ethersubr.c ============================================================================== --- stable/12/sys/net/if_ethersubr.c Sat Apr 27 04:16:15 2019 (r346782) +++ stable/12/sys/net/if_ethersubr.c Sat Apr 27 04:39:41 2019 (r346783) @@ -42,11 +42,13 @@ #include <sys/systm.h> #include <sys/bus.h> #include <sys/eventhandler.h> +#include <sys/jail.h> #include <sys/kernel.h> #include <sys/lock.h> #include <sys/malloc.h> #include <sys/module.h> #include <sys/mbuf.h> +#include <sys/proc.h> #include <sys/priv.h> #include <sys/random.h> #include <sys/socket.h> @@ -54,6 +56,7 @@ #include <sys/sysctl.h> #include <sys/uuid.h> +#include <net/ieee_oui.h> #include <net/if.h> #include <net/if_var.h> #include <net/if_arp.h> @@ -85,6 +88,8 @@ #endif #include <security/mac/mac_framework.h> +#include <crypto/sha1.h> + #ifdef CTASSERT CTASSERT(sizeof (struct ether_header) == ETHER_ADDR_LEN * 2 + 2); CTASSERT(sizeof (struct ether_addr) == ETHER_ADDR_LEN); @@ -1366,6 +1371,39 @@ ether_8021q_frame(struct mbuf **mp, struct ifnet *ife, } } return (true); +} + +/* + * Allocate an address from the FreeBSD Foundation OUI. This uses a + * cryptographic hash function on the containing jail's UUID and the interface + * name to attempt to provide a unique but stable address. Pseudo-interfaces + * which require a MAC address should use this function to allocate + * non-locally-administered addresses. + */ +void +ether_gen_addr(struct ifnet *ifp, struct ether_addr *hwaddr) +{ +#define ETHER_GEN_ADDR_BUFSIZ HOSTUUIDLEN + IFNAMSIZ + 2 + SHA1_CTX ctx; + char buf[ETHER_GEN_ADDR_BUFSIZ]; + char uuid[HOSTUUIDLEN + 1]; + uint64_t addr; + int i, sz; + char digest[SHA1_RESULTLEN]; + + getcredhostuuid(curthread->td_ucred, uuid, sizeof(uuid)); + sz = snprintf(buf, ETHER_GEN_ADDR_BUFSIZ, "%s-%s", uuid, ifp->if_xname); + SHA1Init(&ctx); + SHA1Update(&ctx, buf, sz); + SHA1Final(digest, &ctx); + + addr = ((digest[0] << 16) | (digest[1] << 8) | digest[2]) & + OUI_FREEBSD_GENERATED_MASK; + addr = OUI_FREEBSD(addr); + for (i = 0; i < ETHER_ADDR_LEN; ++i) { + hwaddr->octet[i] = addr >> ((ETHER_ADDR_LEN - i - 1) * 8) & + 0xFF; + } } DECLARE_MODULE(ether, ether_mod, SI_SUB_INIT_IF, SI_ORDER_ANY); Modified: stable/12/sys/net/if_vxlan.c ============================================================================== --- stable/12/sys/net/if_vxlan.c Sat Apr 27 04:16:15 2019 (r346782) +++ stable/12/sys/net/if_vxlan.c Sat Apr 27 04:39:41 2019 (r346783) @@ -177,7 +177,7 @@ struct vxlan_softc { struct sysctl_oid *vxl_sysctl_node; struct sysctl_ctx_list vxl_sysctl_ctx; struct callout vxl_callout; - uint8_t vxl_hwaddr[ETHER_ADDR_LEN]; + struct ether_addr vxl_hwaddr; int vxl_mc_ifindex; struct ifnet *vxl_mc_ifp; struct ifmedia vxl_media; @@ -345,7 +345,6 @@ static int vxlan_clone_create(struct if_clone *, int, static void vxlan_clone_destroy(struct ifnet *); static uint32_t vxlan_mac_hash(struct vxlan_softc *, const uint8_t *); -static void vxlan_fakeaddr(struct vxlan_softc *); static int vxlan_media_change(struct ifnet *); static void vxlan_media_status(struct ifnet *, struct ifmediareq *); @@ -2755,8 +2754,8 @@ vxlan_clone_create(struct if_clone *ifc, int unit, cad ifmedia_add(&sc->vxl_media, IFM_ETHER | IFM_AUTO, 0, NULL); ifmedia_set(&sc->vxl_media, IFM_ETHER | IFM_AUTO); - vxlan_fakeaddr(sc); - ether_ifattach(ifp, sc->vxl_hwaddr); + ether_gen_addr(ifp, &sc->vxl_hwaddr); + ether_ifattach(ifp, sc->vxl_hwaddr.octet); ifp->if_baudrate = 0; ifp->if_hdrlen = 0; @@ -2825,20 +2824,6 @@ do { \ #undef mix return (c); -} - -static void -vxlan_fakeaddr(struct vxlan_softc *sc) -{ - - /* - * Generate a non-multicast, locally administered address. - * - * BMV: Should we use the FreeBSD OUI range instead? - */ - arc4rand(sc->vxl_hwaddr, ETHER_ADDR_LEN, 1); - sc->vxl_hwaddr[0] &= ~1; - sc->vxl_hwaddr[0] |= 2; } static int
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201904270439.x3R4dhar073837>