diff options
-rw-r--r-- | eth-multiplexer/Makefile | 2 | ||||
-rw-r--r-- | eth-multiplexer/ethernet.c | 27 | ||||
-rw-r--r-- | eth-multiplexer/ethernet.h | 4 | ||||
-rw-r--r-- | eth-multiplexer/vdev.c | 9 |
4 files changed, 39 insertions, 3 deletions
diff --git a/eth-multiplexer/Makefile b/eth-multiplexer/Makefile index 35110a80..07f909e7 100644 --- a/eth-multiplexer/Makefile +++ b/eth-multiplexer/Makefile @@ -26,7 +26,7 @@ MIGSFLAGS = -imacros $(srcdir)/mig-mutate.h device-MIGSFLAGS="-DMACH_PAYLOAD_TO_PORT=ports_payload_get_name" OBJS = $(SRCS:.c=.o) $(MIGSTUBS) LCLHDRS = ethernet.h util.h vdev.h netfs_impl.h -HURDLIBS=ports fshelp shouldbeinlibc netfs bpf +HURDLIBS = ports ihash fshelp shouldbeinlibc netfs bpf LDLIBS = -lpthread CFLAGS += -I$(top_srcdir)/libbpf diff --git a/eth-multiplexer/ethernet.c b/eth-multiplexer/ethernet.c index 002f30c2..1f3a57c4 100644 --- a/eth-multiplexer/ethernet.c +++ b/eth-multiplexer/ethernet.c @@ -42,6 +42,10 @@ static struct port_info *readpt; /* Port for writing message to the real network interface. */ mach_port_t ether_port; + +/* The ethernet address of the real network interface. */ +char ether_address[ETH_ALEN]; + /* Port for receiving messages from the interface. */ static mach_port_t readptname; @@ -102,6 +106,24 @@ int set_promisc (char *dev_name, mach_port_t ether_port, int is_promisc) return 0; } +static error_t +get_ethernet_address (mach_port_t port, char *address) +{ + error_t err; + int net_address[2]; + size_t count = 2; + assert (count * sizeof (int) >= ETH_ALEN); + + err = device_get_status (port, NET_ADDRESS, net_address, &count); + if (err) + return err; + + net_address[0] = ntohl (net_address[0]); + net_address[1] = ntohl (net_address[1]); + memcpy (address, net_address, ETH_ALEN); + return 0; +} + int ethernet_open (char *dev_name, device_t master_device, struct port_bucket *etherport_bucket, struct port_class *etherreadclass) @@ -132,6 +154,11 @@ int ethernet_open (char *dev_name, device_t master_device, error (2, err, "device_set_filter: %s", dev_name); set_promisc (dev_name, ether_port, 1); + + err = get_ethernet_address (ether_port, ether_address); + if (err) + error (2, err, "%s: Cannot get hardware Ethernet address", dev_name); + return 0; } diff --git a/eth-multiplexer/ethernet.h b/eth-multiplexer/ethernet.h index 8efab9b1..a2b2f5ee 100644 --- a/eth-multiplexer/ethernet.h +++ b/eth-multiplexer/ethernet.h @@ -23,10 +23,12 @@ #ifndef ETHERNET_H #define ETHERNET_H +#include <mach.h> +#include <net/if_ether.h> #include <netinet/in.h> -#include <stdlib.h> extern mach_port_t ether_port; +extern char ether_address[ETH_ALEN]; int ethernet_open (char *dev_name, device_t master_device, struct port_bucket *etherport_bucket, diff --git a/eth-multiplexer/vdev.c b/eth-multiplexer/vdev.c index e753b85f..47dc8d2d 100644 --- a/eth-multiplexer/vdev.c +++ b/eth-multiplexer/vdev.c @@ -28,10 +28,12 @@ #include <arpa/inet.h> #include <stdlib.h> #include <error.h> +#include <hurd/ihash.h> #include <pthread.h> #include "vdev.h" +#include "ethernet.h" #include "queue.h" #include "bpf_impl.h" #include "util.h" @@ -127,6 +129,7 @@ add_vdev (char *name, int size, struct port_class *class, struct port_bucket *bucket) { error_t err; + uint32_t hash; struct vether_device *vdev; if (size < sizeof (*vdev)) @@ -143,9 +146,13 @@ add_vdev (char *name, int size, vdev->if_header_format = HDR_ETHERNET; vdev->if_address_size = ETH_ALEN; vdev->if_flags = 0; + + /* Compute a pseudo-random but stable ethernet address. */ vdev->if_address[0] = 0x52; vdev->if_address[1] = 0x54; - *(int *)(vdev->if_address + 2) = random (); + hash = hurd_ihash_hash32 (ether_address, ETH_ALEN, 0); + hash = hurd_ihash_hash32 (name, strlen (name), hash); + memcpy (&vdev->if_address[2], &hash, 4); queue_init (&vdev->port_list.if_rcv_port_list); queue_init (&vdev->port_list.if_snd_port_list); |