Author: kevans
Date: Wed Apr 17 17:18:43 2019
New Revision: 346324
URL: https://svnweb.freebsd.org/changeset/base/346324

Log:
  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.
  
  Reviewed by:  bz, rgrimes
  Differential Revision:        https://reviews.freebsd.org/D19587

Modified:
  head/sys/net/ethernet.h
  head/sys/net/ieee_oui.h
  head/sys/net/if_bridge.c
  head/sys/net/if_ethersubr.c
  head/sys/net/if_vxlan.c

Modified: head/sys/net/ethernet.h
==============================================================================
--- head/sys/net/ethernet.h     Wed Apr 17 17:00:16 2019        (r346323)
+++ head/sys/net/ethernet.h     Wed Apr 17 17:18:43 2019        (r346324)
@@ -422,7 +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_fakeaddr(struct ether_addr *hwaddr);
+void   ether_gen_addr(struct ifnet *ifp, struct ether_addr *hwaddr);
 
 #ifdef _SYS_EVENTHANDLER_H_
 /* new ethernet interface attached event */

Modified: head/sys/net/ieee_oui.h
==============================================================================
--- head/sys/net/ieee_oui.h     Wed Apr 17 17:00:16 2019        (r346323)
+++ head/sys/net/ieee_oui.h     Wed Apr 17 17:18:43 2019        (r346324)
@@ -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: head/sys/net/if_bridge.c
==============================================================================
--- head/sys/net/if_bridge.c    Wed Apr 17 17:00:16 2019        (r346323)
+++ head/sys/net/if_bridge.c    Wed Apr 17 17:18:43 2019        (r346324)
@@ -671,7 +671,7 @@ bridge_clone_create(struct if_clone *ifc, int unit, ca
        getcredhostid(curthread->td_ucred, &hostid);
        do {
                if (fb || hostid == 0) {
-                       ether_fakeaddr(&sc->sc_defaddr);
+                       ether_gen_addr(ifp, &sc->sc_defaddr);
                } else {
                        sc->sc_defaddr.octet[0] = 0x2;
                        sc->sc_defaddr.octet[1] = (hostid >> 24) & 0xff;

Modified: head/sys/net/if_ethersubr.c
==============================================================================
--- head/sys/net/if_ethersubr.c Wed Apr 17 17:00:16 2019        (r346323)
+++ head/sys/net/if_ethersubr.c Wed Apr 17 17:18:43 2019        (r346324)
@@ -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);
@@ -1401,19 +1406,37 @@ 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_fakeaddr(struct ether_addr *hwaddr)
+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];
 
-       /*
-        * Generate a convenient locally administered address,
-        * 'bsd' + random 24 low-order bits.  'b' is 0x62, which has the locally
-        * assigned bit set, and the broadcast/multicast bit clear.
-        */
-       arc4rand(hwaddr->octet, ETHER_ADDR_LEN, 1);
-       hwaddr->octet[0] = 'b';
-       hwaddr->octet[1] = 's';
-       hwaddr->octet[2] = 'd';
+       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: head/sys/net/if_vxlan.c
==============================================================================
--- head/sys/net/if_vxlan.c     Wed Apr 17 17:00:16 2019        (r346323)
+++ head/sys/net/if_vxlan.c     Wed Apr 17 17:18:43 2019        (r346324)
@@ -2754,7 +2754,7 @@ 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);
 
-       ether_fakeaddr(&sc->vxl_hwaddr);
+       ether_gen_addr(ifp, &sc->vxl_hwaddr);
        ether_ifattach(ifp, sc->vxl_hwaddr.octet);
 
        ifp->if_baudrate = 0;
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to