summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--eth-multiplexer/Makefile2
-rw-r--r--eth-multiplexer/ethernet.c27
-rw-r--r--eth-multiplexer/ethernet.h4
-rw-r--r--eth-multiplexer/vdev.c9
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);