Skip site navigation (1)Skip section navigation (2)
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>