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
This commit is contained in:
Kyle Evans 2019-04-17 17:18:43 +00:00
parent 9817bae932
commit 3c3aa8c170
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=346324
5 changed files with 47 additions and 13 deletions

View File

@ -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 */

View File

@ -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)

View File

@ -671,7 +671,7 @@ bridge_clone_create(struct if_clone *ifc, int unit, caddr_t params)
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;

View File

@ -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, struct ifnet *p,
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);

View File

@ -2754,7 +2754,7 @@ vxlan_clone_create(struct if_clone *ifc, int unit, caddr_t params)
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;