diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2012-07-01 02:12:43 +0000 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2012-07-01 02:12:43 +0000 |
commit | 13ea39a34766fcbecd96ab94bcdf798b08e9bb60 (patch) | |
tree | 1e1463b03838a6f36868a4dafc7e652358a51857 /pfinet/ethernet.c | |
parent | 1f8d504f631531c199d7c6154a0dc442d80ea4a7 (diff) | |
parent | 7e15f3d69a83a34ac62cbbee944a0bfbfa92724e (diff) |
Merge branch 'master' into xkb
Conflicts:
config.make.in
configure.in
Diffstat (limited to 'pfinet/ethernet.c')
-rw-r--r-- | pfinet/ethernet.c | 67 |
1 files changed, 54 insertions, 13 deletions
diff --git a/pfinet/ethernet.c b/pfinet/ethernet.c index dab5c56f..0fd76706 100644 --- a/pfinet/ethernet.c +++ b/pfinet/ethernet.c @@ -20,6 +20,8 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. */ +/* Do not include glue-include/linux/errno.h */ +#define _HACK_ERRNO_H #include "pfinet.h" #include <device/device.h> @@ -27,6 +29,7 @@ #include <netinet/in.h> #include <string.h> #include <error.h> +#include <fcntl.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> @@ -80,6 +83,18 @@ static short ether_filter[] = }; static int ether_filter_len = sizeof (ether_filter) / sizeof (short); +/* The BPF instruction allows IP and ARP packets */ +static struct bpf_insn bpf_ether_filter[] = +{ + {NETF_IN|NETF_BPF, /* Header. */ 0, 0, 0}, + {40, 0, 0, 12}, + {21, 1, 0, 2054}, + {21, 0, 1, 2048}, + {6, 0, 0, 1500}, + {6, 0, 0, 0}, +}; +static int bpf_ether_filter_len = sizeof (bpf_ether_filter) / sizeof (short); + static struct port_bucket *etherport_bucket; @@ -166,20 +181,46 @@ ethernet_open (struct device *dev) mach_port_set_qlimit (mach_task_self (), edev->readptname, MACH_PORT_QLIMIT_MAX); - err = get_privileged_ports (0, &master_device); - if (err) - error (2, err, "cannot get device master port"); - - err = device_open (master_device, D_WRITE | D_READ, dev->name, &edev->ether_port); - mach_port_deallocate (mach_task_self (), master_device); - if (err) - error (2, err, "%s", dev->name); + master_device = file_name_lookup (dev->name, O_READ | O_WRITE, 0); + if (master_device != MACH_PORT_NULL) + { + /* The device name here is the path of a device file. */ + err = device_open (master_device, D_WRITE | D_READ, "eth", &edev->ether_port); + mach_port_deallocate (mach_task_self (), master_device); + if (err) + error (2, err, "device_open on %s", dev->name); + + err = device_set_filter (edev->ether_port, ports_get_right (edev->readpt), + MACH_MSG_TYPE_MAKE_SEND, 0, + bpf_ether_filter, bpf_ether_filter_len); + if (err) + error (2, err, "device_set_filter on %s", dev->name); + } + else + { + /* No, perhaps a Mach device? */ + int file_errno = errno; + err = get_privileged_ports (0, &master_device); + if (err) + { + error (0, file_errno, "file_name_lookup %s", dev->name); + error (2, err, "and cannot get device master port"); + } + err = device_open (master_device, D_WRITE | D_READ, dev->name, &edev->ether_port); + mach_port_deallocate (mach_task_self (), master_device); + if (err) + { + error (0, file_errno, "file_name_lookup %s", dev->name); + error (2, err, "device_open(%s)", dev->name); + } + + err = device_set_filter (edev->ether_port, ports_get_right (edev->readpt), + MACH_MSG_TYPE_MAKE_SEND, 0, + ether_filter, ether_filter_len); + if (err) + error (2, err, "device_set_filter on %s", dev->name); + } - err = device_set_filter (edev->ether_port, ports_get_right (edev->readpt), - MACH_MSG_TYPE_MAKE_SEND, 0, - ether_filter, ether_filter_len); - if (err) - error (2, err, "%s", dev->name); return 0; } |