summaryrefslogtreecommitdiff
path: root/eth-filter.multi-thread
diff options
context:
space:
mode:
authorroot <root@(null).(none)>2009-05-03 17:20:00 +0200
committerroot <root@(null).(none)>2009-05-03 17:20:00 +0200
commite0faf22f31c48fb27b43c1825897d26e58feafc4 (patch)
tree65a09372b31e08a3a865bd0a88cd2718bafcd643 /eth-filter.multi-thread
This is my initial working version.
There is a bug in boot in this version: subhurd sometimes cannot boot.
Diffstat (limited to 'eth-filter.multi-thread')
-rw-r--r--eth-filter.multi-thread/CVS/Entries11
-rw-r--r--eth-filter.multi-thread/CVS/Repository1
-rw-r--r--eth-filter.multi-thread/CVS/Root1
-rw-r--r--eth-filter.multi-thread/CVS/Tag1
-rw-r--r--eth-filter.multi-thread/ChangeLog105
-rw-r--r--eth-filter.multi-thread/Makefile35
-rw-r--r--eth-filter.multi-thread/Makefile~35
-rw-r--r--eth-filter.multi-thread/README39
-rw-r--r--eth-filter.multi-thread/bpf_impl.c872
-rw-r--r--eth-filter.multi-thread/bpf_impl.d83
-rw-r--r--eth-filter.multi-thread/bpf_impl.h158
-rw-r--r--eth-filter.multi-thread/bpf_impl.obin0 -> 32876 bytes
-rw-r--r--eth-filter.multi-thread/device.defs1
-rw-r--r--eth-filter.multi-thread/device_reply.defs1
-rw-r--r--eth-filter.multi-thread/device_reply.udefs.d5
-rw-r--r--eth-filter.multi-thread/device_replyUser.c374
-rw-r--r--eth-filter.multi-thread/device_replyUser.d47
-rw-r--r--eth-filter.multi-thread/device_replyUser.obin0 -> 8584 bytes
-rw-r--r--eth-filter.multi-thread/device_reply_U.h133
-rwxr-xr-xeth-filter.multi-thread/eth-filterbin0 -> 119982 bytes
-rw-r--r--eth-filter.multi-thread/eth-filter.prof_d1
-rw-r--r--eth-filter.multi-thread/filter.c878
-rw-r--r--eth-filter.multi-thread/filter.c~878
-rw-r--r--eth-filter.multi-thread/filter.d97
-rw-r--r--eth-filter.multi-thread/filter.h57
-rw-r--r--eth-filter.multi-thread/filter.h~60
-rw-r--r--eth-filter.multi-thread/filter.obin0 -> 55668 bytes
-rw-r--r--eth-filter.multi-thread/msg_queue.c224
-rw-r--r--eth-filter.multi-thread/msg_queue.c~224
-rw-r--r--eth-filter.multi-thread/msg_queue.d87
-rw-r--r--eth-filter.multi-thread/msg_queue.h69
-rw-r--r--eth-filter.multi-thread/msg_queue.h~69
-rw-r--r--eth-filter.multi-thread/msg_queue.obin0 -> 20044 bytes
-rw-r--r--eth-filter.multi-thread/notify.defs1
-rw-r--r--eth-filter.multi-thread/notify.sdefs.d3
-rw-r--r--eth-filter.multi-thread/notifyServer.c353
-rw-r--r--eth-filter.multi-thread/notifyServer.d28
-rw-r--r--eth-filter.multi-thread/notifyServer.obin0 -> 10840 bytes
-rw-r--r--eth-filter.multi-thread/notify_S.h124
-rw-r--r--eth-filter.multi-thread/ourdevice.defs383
-rw-r--r--eth-filter.multi-thread/ourdevice.sdefs.d1
-rw-r--r--eth-filter.multi-thread/ourdeviceServer.c1179
-rw-r--r--eth-filter.multi-thread/ourdeviceServer.d45
-rw-r--r--eth-filter.multi-thread/ourdeviceServer.obin0 -> 25180 bytes
-rw-r--r--eth-filter.multi-thread/ourdevice_S.h354
-rw-r--r--eth-filter.multi-thread/pcap_filter.c77
-rw-r--r--eth-filter.multi-thread/pcap_filter.d38
-rw-r--r--eth-filter.multi-thread/pcap_filter.obin0 -> 6900 bytes
-rw-r--r--eth-filter.multi-thread/queue.c131
-rw-r--r--eth-filter.multi-thread/queue.d1
-rw-r--r--eth-filter.multi-thread/queue.h329
-rw-r--r--eth-filter.multi-thread/queue.obin0 -> 4048 bytes
-rw-r--r--eth-filter.multi-thread/tmp.patch207
-rw-r--r--eth-filter.multi-thread/tmp.patch~49
-rw-r--r--eth-filter.multi-thread/util.h73
-rw-r--r--eth-filter.multi-thread/util.h~73
56 files changed, 7995 insertions, 0 deletions
diff --git a/eth-filter.multi-thread/CVS/Entries b/eth-filter.multi-thread/CVS/Entries
new file mode 100644
index 00000000..3ee05b29
--- /dev/null
+++ b/eth-filter.multi-thread/CVS/Entries
@@ -0,0 +1,11 @@
+/ChangeLog/1.1.2.8/Fri Aug 22 17:07:59 2008//Tzhengda-soc2008-virt-branch
+/Makefile/1.1.2.1/Wed Aug 13 13:29:31 2008//Tzhengda-soc2008-virt-branch
+/README/1.1.2.3/Fri Aug 22 17:07:59 2008//Tzhengda-soc2008-virt-branch
+/bpf_impl.c/1.1.2.1/Wed Aug 13 13:29:31 2008//Tzhengda-soc2008-virt-branch
+/bpf_impl.h/1.1.2.1/Wed Aug 13 13:29:31 2008//Tzhengda-soc2008-virt-branch
+/filter.c/1.1.2.8/Fri Aug 22 17:07:59 2008//Tzhengda-soc2008-virt-branch
+/pcap_filter.c/1.1.2.1/Wed Aug 13 13:29:31 2008//Tzhengda-soc2008-virt-branch
+/queue.c/1.1.2.1/Wed Aug 13 13:29:32 2008//Tzhengda-soc2008-virt-branch
+/queue.h/1.1.2.1/Wed Aug 13 13:29:32 2008//Tzhengda-soc2008-virt-branch
+/util.h/1.1.2.1/Wed Aug 13 13:29:32 2008//Tzhengda-soc2008-virt-branch
+D
diff --git a/eth-filter.multi-thread/CVS/Repository b/eth-filter.multi-thread/CVS/Repository
new file mode 100644
index 00000000..343b4f89
--- /dev/null
+++ b/eth-filter.multi-thread/CVS/Repository
@@ -0,0 +1 @@
+hurd/eth-filter
diff --git a/eth-filter.multi-thread/CVS/Root b/eth-filter.multi-thread/CVS/Root
new file mode 100644
index 00000000..a10aa66d
--- /dev/null
+++ b/eth-filter.multi-thread/CVS/Root
@@ -0,0 +1 @@
+:ext:zhengda@cvs.savannah.gnu.org:/sources/hurd
diff --git a/eth-filter.multi-thread/CVS/Tag b/eth-filter.multi-thread/CVS/Tag
new file mode 100644
index 00000000..7e454c6d
--- /dev/null
+++ b/eth-filter.multi-thread/CVS/Tag
@@ -0,0 +1 @@
+Tzhengda-soc2008-virt-branch
diff --git a/eth-filter.multi-thread/ChangeLog b/eth-filter.multi-thread/ChangeLog
new file mode 100644
index 00000000..cd920067
--- /dev/null
+++ b/eth-filter.multi-thread/ChangeLog
@@ -0,0 +1,105 @@
+2008-08-22 Zheng Da <zhengda1936@gmail.com>
+
+ * README: Update.
+
+ * filter.c (proxy_info): Removed.
+ (proxy_pfinetpi_ht): Removed.
+ (proxy_devicepi_ht): Removed.
+ (create_proxy): Removed.
+ (destroy_proxy): Removed.
+ (proxy_device): New structure.
+ (proxy_user): New structure.
+ (proxy): New structure.
+ (create_proxy_user): New function.
+ (create_proxy_device): New function.
+ (clean_proxy_user): New function.
+ (clean_proxy_device): New function.
+ (ethernet_demuxer): Get the data from proxy object instead of from
+ proxy_info.
+ (do_mach_notify_dead_name): Likewise.
+ (ds_device_write): Likewise.
+ (ds_device_write_inband): Likewise.
+ (ds_device_read): Likewise.
+ (ds_device_read_inband): Likewise.
+ (ds_device_map): Likewise.
+ (ds_device_set_status): Likewise.
+ (ds_device_get_status): Likewise.
+ (ds_device_set_filter): Likewise. Create the proxy_device object.
+ (do_mach_notify_no_senders): Use ports_do_mach_notify_no_senders().
+ (ds_device_open): Create proxy_user and proxy objects.
+ (main): Add the cleaning routine when creating the port class.
+
+2008-08-20 Zheng Da <zhengda1936@gmail.com>
+
+ * README: Update.
+
+ * filter.c (options): Update.
+
+2008-08-20 Zheng Da <zhengda1936@gmail.com>
+
+ * filter.c (destroy_proxy): Test p_deliverport_hashloc before removing
+ it from proxy_deliverport_ht, and reverse the order of calling
+ ports_destroy_right and ports_port_deref.
+ (ds_device_open): Test device_file and replace "eth" with the variable
+ name.
+
+2008-08-20 Zheng Da <zhengda1936@gmail.com>
+
+ * filter.c (device_file): Change the name of a variable.
+ (ds_device_open): Use device_file directly.
+
+2008-08-19 Zheng Da <zhengda1936@gmail.com>
+
+ * filter.c (ds_device_open): Generate the device file name, and use it
+ to open the device.
+
+2008-08-18 Zheng Da <zhengda1936@gmail.com>
+
+ * README: New file.
+
+
+2008-08-17 Zheng Da <zhengda1936@gmail.com>
+
+ * filter.c (device_name): Remove its default value.
+ (options): Remove the option '-M'.
+ (create_proxy): Get the port directly from port_right field in port_info.
+ (ds_device_open): Remove the code of checking the device name,
+ and open the device from the device file.
+ (parse_opt): Remove the code of handling the option '-M'.
+ (main): Remove the code of getting the master device port.
+
+
+2008-08-14 Zheng Da <zhengda1936@gmail.com>
+
+ * filter.c (pfinet_portclass, device_portclass, other_portclass):
+ New variables.
+ (create_proxy): Use pfinet_portclass and device_portclass to create the
+ port.
+ (destroy_proxy): Dereference the port before destroying it.
+ (trivfs_goaway): Test the number of ports in pfinet_portclass and destroy
+ the master_device.
+ (main): Create pfinet_portclass, device_portclass, other_portclass.
+ (print_msg): Deleted.
+ (deliver_msg): Remove debuging print.
+
+ * ChangeLog: New file.
+
+
+2008-08-13 Zheng Da <zhengda1936@gmail.com>
+
+ * bpf_impl.c: New file.
+
+ * Makefile: New file.
+
+ * queue.c: New file.
+
+ * util.h: New file.
+
+ * bpf_impl.h: New file.
+
+ * filter.c: New file.
+
+ * pcap_filter.c: New file.
+
+ * queue.h: New file.
+
diff --git a/eth-filter.multi-thread/Makefile b/eth-filter.multi-thread/Makefile
new file mode 100644
index 00000000..c9abe3fd
--- /dev/null
+++ b/eth-filter.multi-thread/Makefile
@@ -0,0 +1,35 @@
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 2008 Free Software Foundation, Inc.
+# This file is part of the GNU Hurd.
+#
+# The GNU Hurd is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# The GNU Hurd is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with the GNU Hurd; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+dir := eth-filter
+makemode := server
+
+SRCS = bpf_impl.c filter.c queue.c pcap_filter.c msg_queue.c
+LCLHDRS = bpf_impl.h queue.h util.h filter.h msg_queue.h
+DIST_FILES = ourdevice.defs notify.defs device_reply.defs
+HURDLIBS = threads ports trivfs fshelp ihash shouldbeinlibc
+target = eth-filter
+MIGSTUBS = ourdeviceServer.o notifyServer.o device_replyUser.o
+OBJS = $(SRCS:.c=.o) $(MIGSTUBS)
+
+include ../Makeconf
+
+CFLAGS += -I../pfinet/linux-src/include -I../pfinet/glue-include
+LDFLAGS += -lpcap
+
+ourdevice.defs: device.defs
+ $(CPP) $(CPPFLAGS) -x c $< | sed -e '/out[ ]*device[ ]*:[ ]*device_t/s/device_t/mach_port_send_t/' > $@
diff --git a/eth-filter.multi-thread/Makefile~ b/eth-filter.multi-thread/Makefile~
new file mode 100644
index 00000000..53578306
--- /dev/null
+++ b/eth-filter.multi-thread/Makefile~
@@ -0,0 +1,35 @@
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 2008 Free Software Foundation, Inc.
+# This file is part of the GNU Hurd.
+#
+# The GNU Hurd is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# The GNU Hurd is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with the GNU Hurd; see the file COPYING. If not, write to
+# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+dir := eth-filter
+makemode := server
+
+SRCS = bpf_impl.c filter.c queue.c pcap_filter.c #msg_queue.c
+LCLHDRS = bpf_impl.h queue.h util.h #filter.h msg_queue.h
+DIST_FILES = ourdevice.defs notify.defs #device_reply.defs
+HURDLIBS = threads ports trivfs fshelp ihash shouldbeinlibc
+target = eth-filter
+MIGSTUBS = ourdeviceServer.o notifyServer.o #device_replyUser.o
+OBJS = $(SRCS:.c=.o) $(MIGSTUBS)
+
+include ../Makeconf
+
+CFLAGS += -I../pfinet/linux-src/include -I../pfinet/glue-include
+LDFLAGS += -lpcap
+
+ourdevice.defs: device.defs
+ $(CPP) $(CPPFLAGS) -x c $< | sed -e '/out[ ]*device[ ]*:[ ]*device_t/s/device_t/mach_port_send_t/' > $@
diff --git a/eth-filter.multi-thread/README b/eth-filter.multi-thread/README
new file mode 100644
index 00000000..2ef16eda
--- /dev/null
+++ b/eth-filter.multi-thread/README
@@ -0,0 +1,39 @@
+[Introduce]
+
+eth-filter is a filter translator that runs on the network device. The goal of eth-filter is to allow the user to setup the policy to control the traffic to the network. For example, it can block the invalid packet or the packet with the wrong destination address. It can work with eth-multiplexer to control and reduce the traffic between eth-multiplexer and pfinet, and can also work alone, running directly on the real network device.
+
+
+[Usage]
+
+Usage: eth-filter [OPTION...]
+Hurd filter translator.
+
+ -i, --interface=DEVICE Network interface to use
+ -s, --send-filter=string The filter rule which applies to the outgoing
+ packet
+ -r, --receive-filter=string The filter rule which applies to the ingoing
+ packet
+ -S, --send-ip-range=IP range A range of IP to create the send filter
+ -R, --receive-ip-range=IP range
+ A range of IP to create the receive filter
+ -?, --help Give this help list
+ --usage Give a short usage message
+ -V, --version Print program version
+
+Mandatory or optional arguments to long options are also mandatory or optional
+for any corresponding short options.
+
+
+The '-i' option specifies the network interface the translator sits on. eth-filter can only connect to one network interface and the '-i' option should be only used once. DEVICE is a device file created by devnode translator.
+The '-s' and '-r' options give the user a full control to specify the filter rules which applies to the outgoing packet and the incoming packet, respectively. The expression of the rule is the same as the one in TCPDUMP.
+The '-S' and '-R' options specify a range of IP that the user wants to filter. They are used to create the sending filter and the receiving filter, respectively. The generated rule is "arp or (ip and src net addr/prefixlen)" or "arp or (ip and dst net addr/prefixlen)". If prefixlen is 32, it can be omitted.
+NOTE: '-s' and '-S' cannot be used together. One will replace the other if they are both used. So are '-r' and '-R' options.
+An example: settrans -acfg /servers/feth0 /hurd/eth-filter -i /dev/eth0 -S 192.168.8.0/24 -R 192.168.8.0/24
+
+[Internal]
+
+eth-filter works as a proxy, forwarding the packet between the user program and the network interface. In order to forward packets, eth-filter runs as a client to the network device. It opens the device and writes the packet to the network device as pfinet does. It calls device_set_filter() to set the filter rule and give its own port to the device so it can receive packets from the device. The rule passed to the network device is from the user program that connects to eth-filter.
+eth-filter works as a RPC server to communicate with the user program and implements the server side functions in device.defs. It gets the packet in the server side function ds_device_write and gets the port to deliver packets to the user program in ds_device_set_filter.
+Three structures are used for one pair of the user program and the device: proxy_user, proxy_device, proxy. When the ds_device_open() is called, a proxy_user and proxy objectis created. A proxy_device object is created when the ds_device_set_filter() is called. The proxy_user and proxy_device extend port_info structure. When a packet is received from the user program or from the device, we have to retrieve the proxy object to get the corresponding information. This process is very similar as pflocal. When a user program exits, we need to destroy its proxy_user object and proxy object, and meanwhile, the proxy_device object related to the proxy object is also destroyed.
+Two filters exist in eth-filter, one for outgoing packets and the other for incoming packets. These are BPF filters, which are ported from GNU Mach. These BPF filters only decide whether the packet should be forwarded, and they cannot decide the destination of the packet. The BPF instructions are generated by libpcap from the filter rules given by '-s' and '-r' or '-S' and '-R' options.
+
diff --git a/eth-filter.multi-thread/bpf_impl.c b/eth-filter.multi-thread/bpf_impl.c
new file mode 100644
index 00000000..e9202a5f
--- /dev/null
+++ b/eth-filter.multi-thread/bpf_impl.c
@@ -0,0 +1,872 @@
+ /*
+ * Mach Operating System
+ * Copyright (c) 1993-1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * Author: David B. Golub, Carnegie Mellon University
+ * Date: 3/98
+ *
+ * Network IO.
+ *
+ * Packet filter code taken from vaxif/enet.c written
+ * CMU and Stanford.
+ */
+
+/* the code copied from device/net_io.c in Mach */
+
+#include <arpa/inet.h>
+#include <string.h>
+
+#include <mach.h>
+#include <hurd.h>
+
+#include "bpf_impl.h"
+#include "queue.h"
+#include "util.h"
+
+queue_head_t rcv_port_list; /* input filter list */
+queue_head_t snd_port_list; /* output filter list */
+
+/*
+ * Execute the filter program starting at pc on the packet p
+ * wirelen is the length of the original packet
+ * buflen is the amount of data present
+ *
+ * @p: packet data.
+ * @wirelen: data_count (in bytes)
+ * @hlen: header len (in bytes)
+ */
+
+int
+mach_bpf_do_filter(net_rcv_port_t infp, char *p, unsigned int wirelen,
+ char *header, unsigned int hlen, net_hash_entry_t **hash_headpp,
+ net_hash_entry_t *entpp)
+{
+ register bpf_insn_t pc, pc_end;
+ register unsigned int buflen;
+
+ register unsigned long A, X;
+ register int k;
+ unsigned int mem[BPF_MEMWORDS];
+
+ /* Generic pointer to either HEADER or P according to the specified offset. */
+ char *data = NULL;
+
+ pc = ((bpf_insn_t) infp->filter) + 1;
+ /* filter[0].code is (NETF_BPF | flags) */
+ pc_end = (bpf_insn_t)infp->filter_end;
+ buflen = NET_RCV_MAX;
+ *entpp = 0; /* default */
+
+ A = 0;
+ X = 0;
+ for (; pc < pc_end; ++pc) {
+ switch (pc->code) {
+
+ default:
+ abort();
+ case BPF_RET|BPF_K:
+ if (infp->rcv_port == MACH_PORT_NULL &&
+ *entpp == 0) {
+ return 0;
+ }
+ return ((u_int)pc->k <= wirelen) ?
+ pc->k : wirelen;
+
+ case BPF_RET|BPF_A:
+ if (infp->rcv_port == MACH_PORT_NULL &&
+ *entpp == 0) {
+ return 0;
+ }
+ return ((u_int)A <= wirelen) ?
+ A : wirelen;
+
+ case BPF_RET|BPF_MATCH_IMM:
+ if (mach_bpf_match ((net_hash_header_t)infp, pc->jt, mem,
+ hash_headpp, entpp)) {
+ return ((u_int)pc->k <= wirelen) ?
+ pc->k : wirelen;
+ }
+ return 0;
+
+ case BPF_LD|BPF_W|BPF_ABS:
+ k = pc->k;
+
+load_word:
+ if ((u_int)k + sizeof(long) <= hlen)
+ data = header;
+ else if ((u_int)k + sizeof(long) <= buflen) {
+ k -= hlen;
+ data = p;
+ } else
+ return 0;
+
+#ifdef BPF_ALIGN
+ if (((int)(data + k) & 3) != 0)
+ A = EXTRACT_LONG(&data[k]);
+ else
+#endif
+ A = ntohl(*(long *)(data + k));
+ continue;
+
+ case BPF_LD|BPF_H|BPF_ABS:
+ k = pc->k;
+
+load_half:
+ if ((u_int)k + sizeof(short) <= hlen)
+ data = header;
+ else if ((u_int)k + sizeof(short) <= buflen) {
+ k -= hlen;
+ data = p;
+ } else
+ return 0;
+
+ A = EXTRACT_SHORT(&data[k]);
+ continue;
+
+ case BPF_LD|BPF_B|BPF_ABS:
+ k = pc->k;
+
+load_byte:
+ if ((u_int)k < hlen)
+ data = header;
+ else if ((u_int)k < buflen) {
+ data = p;
+ k -= hlen;
+ } else
+ return 0;
+
+ A = data[k];
+ continue;
+
+ case BPF_LD|BPF_W|BPF_LEN:
+ A = wirelen;
+ continue;
+
+ case BPF_LDX|BPF_W|BPF_LEN:
+ X = wirelen;
+ continue;
+
+ case BPF_LD|BPF_W|BPF_IND:
+ k = X + pc->k;
+ goto load_word;
+
+ case BPF_LD|BPF_H|BPF_IND:
+ k = X + pc->k;
+ goto load_half;
+
+ case BPF_LD|BPF_B|BPF_IND:
+ k = X + pc->k;
+ goto load_byte;
+
+ case BPF_LDX|BPF_MSH|BPF_B:
+ k = pc->k;
+ if (k < hlen)
+ data = header;
+ else if (k < buflen) {
+ data = p;
+ k -= hlen;
+ } else
+ return 0;
+
+ X = (data[k] & 0xf) << 2;
+ continue;
+
+ case BPF_LD|BPF_IMM:
+ A = pc->k;
+ continue;
+
+ case BPF_LDX|BPF_IMM:
+ X = pc->k;
+ continue;
+
+ case BPF_LD|BPF_MEM:
+ A = mem[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM:
+ X = mem[pc->k];
+ continue;
+
+ case BPF_ST:
+ mem[pc->k] = A;
+ continue;
+
+ case BPF_STX:
+ mem[pc->k] = X;
+ continue;
+
+ case BPF_JMP|BPF_JA:
+ pc += pc->k;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_K:
+ pc += (A > pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_K:
+ pc += (A >= pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_K:
+ pc += (A == pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_K:
+ pc += (A & pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_X:
+ pc += (A > X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_X:
+ pc += (A >= X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_X:
+ pc += (A == X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_X:
+ pc += (A & X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_X:
+ A += X;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_X:
+ A -= X;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_X:
+ A *= X;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_X:
+ if (X == 0)
+ return 0;
+ A /= X;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_X:
+ A &= X;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_X:
+ A |= X;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_X:
+ A <<= X;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_X:
+ A >>= X;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_K:
+ A += pc->k;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_K:
+ A -= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_K:
+ A *= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_K:
+ A /= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_K:
+ A &= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_K:
+ A |= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_K:
+ A <<= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_K:
+ A >>= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_NEG:
+ A = -A;
+ continue;
+
+ case BPF_MISC|BPF_TAX:
+ X = A;
+ continue;
+
+ case BPF_MISC|BPF_TXA:
+ A = X;
+ continue;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Return 1 if the 'f' is a valid filter program without a MATCH
+ * instruction. Return 2 if it is a valid filter program with a MATCH
+ * instruction. Otherwise, return 0.
+ * The constraints are that each jump be forward and to a valid
+ * code. The code must terminate with either an accept or reject.
+ * 'valid' is an array for use by the routine (it must be at least
+ * 'len' bytes long).
+ *
+ * The kernel needs to be able to verify an application's filter code.
+ * Otherwise, a bogus program could easily crash the system.
+ */
+int
+mach_bpf_validate(bpf_insn_t f, int bytes, bpf_insn_t *match)
+{
+ register int i, j, len;
+ register bpf_insn_t p;
+
+ len = BPF_BYTES2LEN(bytes);
+
+ /*
+ * f[0].code is already checked to be (NETF_BPF | flags).
+ * So skip f[0].
+ */
+
+ for (i = 1; i < len; ++i) {
+ /*
+ * Check that that jumps are forward, and within
+ * the code block.
+ */
+ p = &f[i];
+ if (BPF_CLASS(p->code) == BPF_JMP) {
+ register int from = i + 1;
+
+ if (BPF_OP(p->code) == BPF_JA) {
+ if (from + p->k >= len)
+ return 0;
+ }
+ else if (from + p->jt >= len || from + p->jf >= len)
+ return 0;
+ }
+ /*
+ * Check that memory operations use valid addresses.
+ */
+ if ((BPF_CLASS(p->code) == BPF_ST ||
+ (BPF_CLASS(p->code) == BPF_LD &&
+ (p->code & 0xe0) == BPF_MEM)) &&
+ (p->k >= BPF_MEMWORDS || p->k < 0)) {
+ return 0;
+ }
+ /*
+ * Check for constant division by 0.
+ */
+ if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0) {
+ return 0;
+ }
+ /*
+ * Check for match instruction.
+ * Only one match instruction per filter is allowed.
+ */
+ if (p->code == (BPF_RET|BPF_MATCH_IMM)) {
+ if (*match != 0 ||
+ p->jt == 0 ||
+ p->jt > N_NET_HASH_KEYS)
+ return 0;
+ i += p->jt; /* skip keys */
+ if (i + 1 > len)
+ return 0;
+
+ for (j = 1; j <= p->jt; j++) {
+ if (p[j].code != (BPF_MISC|BPF_KEY))
+ return 0;
+ }
+
+ *match = p;
+ }
+ }
+ if (BPF_CLASS(f[len - 1].code) == BPF_RET)
+ return ((*match == 0) ? 1 : 2);
+ else
+ return 0;
+}
+
+int
+mach_bpf_eq (bpf_insn_t f1, bpf_insn_t f2, int bytes)
+{
+ register int count;
+
+ count = BPF_BYTES2LEN(bytes);
+ for (; count--; f1++, f2++) {
+ if (!BPF_INSN_EQ(f1, f2)) {
+ if ( f1->code == (BPF_MISC|BPF_KEY) &&
+ f2->code == (BPF_MISC|BPF_KEY) )
+ continue;
+ return FALSE;
+ }
+ };
+ return TRUE;
+}
+
+unsigned int
+mach_bpf_hash (int n, unsigned int *keys)
+{
+ register unsigned int hval = 0;
+
+ while (n--) {
+ hval += *keys++;
+ }
+ return (hval % NET_HASH_SIZE);
+}
+
+
+int
+mach_bpf_match (net_hash_header_t hash, int n_keys, unsigned int *keys,
+ net_hash_entry_t **hash_headpp, net_hash_entry_t *entpp)
+{
+ register net_hash_entry_t head, entp;
+ register int i;
+
+ if (n_keys != hash->n_keys)
+ return FALSE;
+
+ *hash_headpp = &hash->table[mach_bpf_hash(n_keys, keys)];
+ head = **hash_headpp;
+
+ if (head == 0)
+ return FALSE;
+
+ HASH_ITERATE (head, entp)
+ {
+ for (i = 0; i < n_keys; i++) {
+ if (keys[i] != entp->keys[i])
+ break;
+ }
+ if (i == n_keys) {
+ *entpp = entp;
+ return TRUE;
+ }
+ }
+ HASH_ITERATE_END (head, entp)
+ return FALSE;
+}
+
+/*
+ * Removes a hash entry (ENTP) from its queue (HEAD).
+ * If the reference count of filter (HP) becomes zero and not USED,
+ * HP is removed from the corresponding port lists and is freed.
+ */
+
+int
+hash_ent_remove (net_hash_header_t hp, int used,
+ net_hash_entry_t *head, net_hash_entry_t entp, queue_entry_t *dead_p)
+{
+ hp->ref_count--;
+
+ if (*head == entp) {
+ if (queue_empty((queue_t) entp)) {
+ *head = 0;
+ ENQUEUE_DEAD(*dead_p, entp, chain);
+ if (hp->ref_count == 0 && !used) {
+ if (((net_rcv_port_t)hp)->filter[0] & NETF_IN)
+ queue_remove(&rcv_port_list,
+ (net_rcv_port_t)hp,
+ net_rcv_port_t, chain);
+ if (((net_rcv_port_t)hp)->filter[0] & NETF_OUT)
+ queue_remove(&snd_port_list,
+ (net_rcv_port_t)hp,
+ net_rcv_port_t, chain);
+ hp->n_keys = 0;
+ return TRUE;
+ }
+ return FALSE;
+ } else {
+ *head = (net_hash_entry_t)queue_next((queue_t) entp);
+ }
+ }
+
+ remqueue((queue_t)*head, (queue_entry_t)entp);
+ ENQUEUE_DEAD(*dead_p, entp, chain);
+ return FALSE;
+}
+
+/*
+ * net_free_dead_infp (dead_infp)
+ * queue_entry_t dead_infp; list of dead net_rcv_port_t.
+ *
+ * Deallocates dead net_rcv_port_t.
+ * No locks should be held when called.
+ */
+void
+net_free_dead_infp (queue_entry_t dead_infp)
+{
+ register net_rcv_port_t infp, nextfp;
+
+ for (infp = (net_rcv_port_t) dead_infp; infp != 0; infp = nextfp) {
+ nextfp = (net_rcv_port_t) queue_next(&infp->chain);
+ mach_port_deallocate(mach_task_self(), infp->rcv_port);
+ free(infp);
+ debug ("a dead infp is freed\n");
+ }
+}
+
+/*
+ * net_free_dead_entp (dead_entp)
+ * queue_entry_t dead_entp; list of dead net_hash_entry_t.
+ *
+ * Deallocates dead net_hash_entry_t.
+ * No locks should be held when called.
+ */
+void
+net_free_dead_entp (queue_entry_t dead_entp)
+{
+ register net_hash_entry_t entp, nextentp;
+
+ for (entp = (net_hash_entry_t)dead_entp; entp != 0; entp = nextentp) {
+ nextentp = (net_hash_entry_t) queue_next(&entp->chain);
+
+ mach_port_deallocate(mach_task_self(), entp->rcv_port);
+ free(entp);
+ debug ("a dead entp is freed\n");
+ }
+}
+
+/*
+ * Set a filter for a network interface.
+ *
+ * We are given a naked send right for the rcv_port.
+ * If we are successful, we must consume that right.
+ */
+error_t
+net_set_filter (mach_port_t rcv_port, int priority,
+ filter_t *filter, unsigned int filter_count)
+{
+ int filter_bytes;
+ bpf_insn_t match;
+ register net_rcv_port_t infp, my_infp;
+ net_rcv_port_t nextfp;
+ net_hash_header_t hhp;
+ register net_hash_entry_t entp, hash_entp=NULL;
+ net_hash_entry_t *head, nextentp;
+ queue_entry_t dead_infp, dead_entp;
+ int i;
+ int ret, is_new_infp;
+ io_return_t rval;
+ boolean_t in, out;
+
+ /* Check the filter syntax. */
+
+ debug ("filter_count: %d, filter[0]: %d\n", filter_count, filter[0]);
+
+ filter_bytes = CSPF_BYTES (filter_count);
+ match = (bpf_insn_t) 0;
+
+ if (filter_count == 0) {
+ return (D_INVALID_OPERATION);
+ } else if (!((filter[0] & NETF_IN) || (filter[0] & NETF_OUT))) {
+ return (D_INVALID_OPERATION); /* NETF_IN or NETF_OUT required */
+ } else if ((filter[0] & NETF_TYPE_MASK) == NETF_BPF) {
+ ret = mach_bpf_validate((bpf_insn_t)filter, filter_bytes, &match);
+ if (!ret)
+ return (D_INVALID_OPERATION);
+ } else {
+ return (D_INVALID_OPERATION);
+ }
+ debug ("net_set_filter: check over\n");
+
+ rval = D_SUCCESS; /* default return value */
+ dead_infp = dead_entp = 0;
+
+ if (match == (bpf_insn_t) 0) {
+ /*
+ * If there is no match instruction, we allocate
+ * a normal packet filter structure.
+ */
+ my_infp = (net_rcv_port_t) calloc(1, sizeof(struct net_rcv_port));
+ my_infp->rcv_port = rcv_port;
+ is_new_infp = TRUE;
+ } else {
+ /*
+ * If there is a match instruction, we assume there will be
+ * multiple sessions with a common substructure and allocate
+ * a hash table to deal with them.
+ */
+ my_infp = 0;
+ hash_entp = (net_hash_entry_t) calloc(1, sizeof(struct net_hash_entry));
+ is_new_infp = FALSE;
+ }
+
+ /*
+ * Look for an existing filter on the same reply port.
+ * Look for filters with dead ports (for GC).
+ * Look for a filter with the same code except KEY insns.
+ */
+ void check_filter_list(queue_head_t *if_port_list)
+ {
+ FILTER_ITERATE(if_port_list, infp, nextfp, &infp->chain) {
+ if (infp->rcv_port == MACH_PORT_NULL) {
+ if (match != 0
+ && infp->priority == priority
+ && my_infp == 0
+ && (infp->filter_end - infp->filter) == filter_count
+ && mach_bpf_eq((bpf_insn_t)infp->filter,
+ (bpf_insn_t)filter, filter_bytes)) {
+ my_infp = infp;
+ }
+
+ for (i = 0; i < NET_HASH_SIZE; i++) {
+ head = &((net_hash_header_t) infp)->table[i];
+ if (*head == 0)
+ continue;
+
+ /*
+ * Check each hash entry to make sure the
+ * destination port is still valid. Remove
+ * any invalid entries.
+ */
+ entp = *head;
+ do {
+ nextentp = (net_hash_entry_t) entp->he_next;
+
+ /* checked without
+ ip_lock(entp->rcv_port) */
+ if (entp->rcv_port == rcv_port) {
+ ret = hash_ent_remove ((net_hash_header_t)infp,
+ (my_infp == infp),
+ head,
+ entp,
+ &dead_entp);
+ if (ret)
+ goto hash_loop_end;
+ }
+
+ entp = nextentp;
+ /* While test checks head since hash_ent_remove
+ * might modify it.
+ */
+ } while (*head != 0 && entp != *head);
+ }
+
+hash_loop_end:
+ ;
+ } else if (infp->rcv_port == rcv_port) {
+ /* Remove the old filter from lists */
+ if (infp->filter[0] & NETF_IN)
+ queue_remove(&rcv_port_list, infp,
+ net_rcv_port_t, chain);
+ if (infp->filter[0] & NETF_OUT)
+ queue_remove(&snd_port_list, infp,
+ net_rcv_port_t, chain);
+
+ ENQUEUE_DEAD(dead_infp, infp, chain);
+ }
+ }
+ FILTER_ITERATE_END
+ }
+
+ in = (filter[0] & NETF_IN) != 0;
+ out = (filter[0] & NETF_OUT) != 0;
+
+ if (in)
+ check_filter_list(&rcv_port_list);
+ if (out)
+ check_filter_list(&snd_port_list);
+
+ if (my_infp == 0) {
+ /* Allocate a dummy infp */
+ for (i = 0; i < N_NET_HASH; i++) {
+ if (filter_hash_header[i].n_keys == 0)
+ break;
+ }
+ if (i == N_NET_HASH) {
+
+ mach_port_deallocate(mach_task_self() , rcv_port);
+ if (match != 0)
+ free(hash_entp);
+
+ rval = D_NO_MEMORY;
+ goto clean_and_return;
+ }
+
+ hhp = &filter_hash_header[i];
+ hhp->n_keys = match->jt;
+
+ hhp->ref_count = 0;
+ for (i = 0; i < NET_HASH_SIZE; i++)
+ hhp->table[i] = 0;
+
+ my_infp = (net_rcv_port_t)hhp;
+ my_infp->rcv_port = MACH_PORT_NULL; /* indication of dummy */
+ is_new_infp = TRUE;
+ }
+
+ if (is_new_infp) {
+ my_infp->priority = priority;
+ my_infp->rcv_count = 0;
+
+ /* Copy filter program. */
+ memcpy (my_infp->filter, filter, filter_bytes);
+ my_infp->filter_end =
+ (filter_t *)((char *)my_infp->filter + filter_bytes);
+
+ /* Insert my_infp according to priority */
+ if (in) {
+ queue_iterate(&rcv_port_list, infp, net_rcv_port_t, chain)
+ if (priority > infp->priority)
+ break;
+
+ queue_enter(&rcv_port_list, my_infp, net_rcv_port_t, chain);
+ }
+
+ if (out) {
+ queue_iterate(&snd_port_list, infp, net_rcv_port_t, chain)
+ if (priority > infp->priority)
+ break;
+
+ queue_enter(&snd_port_list, my_infp, net_rcv_port_t, chain);
+ }
+ }
+
+ if (match != 0) {
+ /* Insert to hash list */
+ net_hash_entry_t *p;
+
+ hash_entp->rcv_port = rcv_port;
+ for (i = 0; i < match->jt; i++) /* match->jt is n_keys */
+ hash_entp->keys[i] = match[i+1].k;
+ p = &((net_hash_header_t)my_infp)->
+ table[mach_bpf_hash(match->jt, hash_entp->keys)];
+
+ /* Not checking for the same key values */
+ if (*p == 0) {
+ queue_init ((queue_t) hash_entp);
+ *p = hash_entp;
+ } else {
+ enqueue_tail((queue_t)*p, (queue_entry_t)hash_entp);
+ }
+
+ ((net_hash_header_t)my_infp)->ref_count++;
+ }
+
+clean_and_return:
+ /* No locks are held at this point. */
+
+ if (dead_infp != 0)
+ net_free_dead_infp(dead_infp);
+ if (dead_entp != 0)
+ net_free_dead_entp(dead_entp);
+
+ return (rval);
+}
+
+/* Remove the filter in if_port_list whose port for delivering is dead_port. */
+void
+remove_dead_filter (queue_head_t *if_port_list, mach_port_t dead_port)
+{
+ net_rcv_port_t infp;
+ net_rcv_port_t nextfp;
+ net_hash_entry_t *head, nextentp;
+ queue_entry_t dead_infp, dead_entp;
+ net_hash_entry_t entp = NULL;
+ int i, ret;
+
+ dead_infp = dead_entp = 0;
+ FILTER_ITERATE (if_port_list, infp, nextfp, &infp->chain) {
+ if (infp->rcv_port == MACH_PORT_NULL) {
+ for (i = 0; i < NET_HASH_SIZE; i++) {
+ head = &((net_hash_header_t) infp)->table[i];
+ if (*head == 0)
+ continue;
+
+ /*
+ * Check each hash entry to make sure the
+ * destination port is still valid. Remove
+ * any invalid entries.
+ */
+ entp = *head;
+ do {
+ nextentp = (net_hash_entry_t) entp->he_next;
+
+ /* checked without
+ ip_lock(entp->rcv_port) */
+ if (entp->rcv_port == dead_port) {
+ ret = hash_ent_remove ((net_hash_header_t) infp,
+ 0,
+ head,
+ entp,
+ &dead_entp);
+ if (ret)
+ goto hash_loop_end;
+ }
+
+ entp = nextentp;
+ /* While test checks head since hash_ent_remove
+ * might modify it.
+ */
+ } while (*head != 0 && entp != *head);
+ }
+
+hash_loop_end:
+ ;
+ } else if (infp->rcv_port == dead_port) {
+ /* Remove the old filter from lists */
+ if (infp->filter[0] & NETF_IN)
+ queue_remove(&rcv_port_list, infp,
+ net_rcv_port_t, chain);
+ if (infp->filter[0] & NETF_OUT)
+ queue_remove(&snd_port_list, infp,
+ net_rcv_port_t, chain);
+
+ ENQUEUE_DEAD(dead_infp, infp, chain);
+ }
+ }
+ FILTER_ITERATE_END
+
+ if (dead_infp != 0)
+ net_free_dead_infp(dead_infp);
+ if (dead_entp != 0)
+ net_free_dead_entp(dead_entp);
+}
+
+/* Remove all filters whose port for delivering is dead_port. */
+void
+remove_dead_filter_from_all (mach_port_t dead_port)
+{
+ remove_dead_filter (&snd_port_list, dead_port);
+ remove_dead_filter (&rcv_port_list, dead_port);
+}
+
+void
+bpf_init()
+{
+ queue_init (&rcv_port_list);
+ queue_init (&snd_port_list);
+}
diff --git a/eth-filter.multi-thread/bpf_impl.d b/eth-filter.multi-thread/bpf_impl.d
new file mode 100644
index 00000000..04557600
--- /dev/null
+++ b/eth-filter.multi-thread/bpf_impl.d
@@ -0,0 +1,83 @@
+bpf_impl.o bpf_impl_pic.o bpf_impl_p.o bpf_impl.d: bpf_impl.c /usr/include/arpa/inet.h /usr/include/features.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
+ /usr/include/gnu/stubs-pthread.h /usr/include/netinet/in.h \
+ /usr/include/stdint.h /usr/include/bits/wchar.h \
+ /usr/include/sys/socket.h /usr/include/sys/uio.h \
+ /usr/include/sys/types.h /usr/include/bits/types.h \
+ /usr/include/bits/typesizes.h /usr/include/time.h \
+ /usr/lib/gcc/i486-gnu/4.2.4/include/stddef.h /usr/include/endian.h \
+ /usr/include/bits/endian.h /usr/include/sys/select.h \
+ /usr/include/bits/select.h /usr/include/bits/sigset.h \
+ /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
+ /usr/include/bits/pthreadtypes.h /usr/include/pthread/pthreadtypes.h \
+ /usr/include/xlocale.h /usr/include/bits/pthread.h \
+ /usr/include/bits/thread-attr.h /usr/include/sched.h \
+ /usr/include/bits/sched.h /usr/include/bits/mutex-attr.h \
+ /usr/include/bits/mutex.h /usr/include/bits/spin-lock.h \
+ /usr/include/bits/condition-attr.h /usr/include/bits/condition.h \
+ /usr/include/bits/rwlock-attr.h /usr/include/bits/rwlock.h \
+ /usr/include/bits/barrier-attr.h /usr/include/bits/barrier.h \
+ /usr/include/bits/thread-specific.h /usr/include/bits/once.h \
+ /usr/include/bits/uio.h /usr/include/bits/socket.h \
+ /usr/lib/gcc/i486-gnu/4.2.4/include/limits.h \
+ /usr/lib/gcc/i486-gnu/4.2.4/include/syslimits.h /usr/include/limits.h \
+ /usr/include/bits/posix1_lim.h /usr/include/bits/local_lim.h \
+ /usr/include/bits/posix2_lim.h /usr/include/bits/xopen_lim.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sockaddr.h \
+ /usr/include/bits/in.h /usr/include/bits/byteswap.h \
+ /usr/include/string.h /usr/include/bits/string.h \
+ /usr/include/bits/string2.h /usr/include/stdlib.h /usr/include/mach.h \
+ /usr/local/include/mach/mach_types.h \
+ /usr/local/include/mach/host_info.h /usr/local/include/mach/machine.h \
+ /usr/local/include/mach/machine/vm_types.h \
+ /usr/local/include/mach/boolean.h \
+ /usr/local/include/mach/machine/boolean.h \
+ /usr/local/include/mach/memory_object.h /usr/local/include/mach/port.h \
+ /usr/local/include/mach/pc_sample.h \
+ /usr/local/include/mach/processor_info.h \
+ /usr/local/include/mach/task_info.h \
+ /usr/local/include/mach/time_value.h \
+ /usr/local/include/mach/task_special_ports.h \
+ /usr/local/include/mach/thread_info.h /usr/local/include/mach/policy.h \
+ /usr/local/include/mach/thread_special_ports.h \
+ /usr/local/include/mach/thread_status.h \
+ /usr/local/include/mach/machine/thread_status.h \
+ /usr/local/include/mach/machine/fp_reg.h \
+ /usr/local/include/mach/vm_attributes.h \
+ /usr/local/include/mach/vm_inherit.h /usr/local/include/mach/vm_prot.h \
+ /usr/local/include/mach/vm_statistics.h \
+ /usr/local/include/mach/std_types.h \
+ /usr/local/include/mach/kern_return.h \
+ /usr/local/include/mach/machine/kern_return.h /usr/include/mach_init.h \
+ /usr/include/mach/mach_traps.h /usr/local/include/mach/message.h \
+ /usr/include/mach/mach_interface.h /usr/include/mach/mach_port.h \
+ /usr/include/mach/mach_host.h /usr/include/mach-shortcuts.h \
+ /usr/include/stdio.h /usr/include/hurd.h \
+ /usr/local/include/mach/mig_errors.h ../hurd/hurd_types.h \
+ /usr/include/errno.h /usr/include/bits/errno.h /usr/include/hurd/auth.h \
+ /usr/local/include/device/device_types.h \
+ /usr/local/include/device/net_status.h /usr/local/include/device/bpf.h \
+ /usr/include/sys/stat.h /usr/include/bits/stat.h \
+ /usr/include/sys/statfs.h /usr/include/bits/statfs.h \
+ /usr/include/sys/resource.h /usr/include/bits/resource.h \
+ /usr/include/sys/utsname.h /usr/include/bits/utsname.h \
+ /usr/include/hurd/process.h /usr/include/hurd/fs.h \
+ /usr/include/hurd/io.h /usr/include/hurd/port.h \
+ /usr/include/hurd/userlink.h /usr/include/hurd/signal.h \
+ /usr/include/signal.h /usr/include/bits/signum.h \
+ /usr/include/bits/siginfo.h /usr/include/bits/sigaction.h \
+ /usr/include/bits/sigcontext.h /usr/include/bits/sigstack.h \
+ /usr/include/sys/ucontext.h /usr/include/bits/sigthread.h \
+ /usr/include/hurd/msg.h ../include/cthreads.h \
+ ../include/../libthreads/cthreads.h /usr/include/bits/waitflags.h \
+ /usr/include/bits/waitstatus.h /usr/include/alloca.h \
+ /usr/local/include/mach/machine/vm_param.h /usr/include/machine-sp.h \
+ /usr/include/spin-lock.h /usr/include/lock-intern.h \
+ /usr/include/machine-lock.h /usr/include/setjmp.h \
+ /usr/include/bits/setjmp.h /usr/include/hurd/threadvar.h \
+ /usr/lib/gcc/i486-gnu/4.2.4/include/stdarg.h bpf_impl.h queue.h util.h \
+ /usr/include/libio.h /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/include/bits/stdio-lock.h /usr/include/bits/libc-lock.h \
+ /usr/include/bits/sys_errlist.h /usr/include/bits/stdio.h \
+ ../pfinet/linux-src/include/linux/if_ether.h /usr/include/netinet/ip.h
diff --git a/eth-filter.multi-thread/bpf_impl.h b/eth-filter.multi-thread/bpf_impl.h
new file mode 100644
index 00000000..de61df12
--- /dev/null
+++ b/eth-filter.multi-thread/bpf_impl.h
@@ -0,0 +1,158 @@
+ /*
+ * Mach Operating System
+ * Copyright (c) 1993-1989 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * Author: David B. Golub, Carnegie Mellon University
+ * Date: 3/98
+ *
+ * Network IO.
+ *
+ * Packet filter code taken from vaxif/enet.c written
+ * CMU and Stanford.
+ */
+
+/* the code copied from device/net_io.c in Mach */
+
+#ifndef BPF_IMPL_H
+#define BPF_IMPL_H
+
+#include <mach.h>
+#include <hurd.h>
+#include <device/bpf.h>
+
+#include "queue.h"
+
+typedef unsigned short filter_t;
+typedef filter_t *filter_array_t;
+
+#define NET_MAX_FILTER 128 /* was 64, bpf programs are big */
+
+#define NET_HASH_SIZE 256
+#define N_NET_HASH 4
+#define N_NET_HASH_KEYS 4
+
+#ifndef BPF_ALIGN
+#define EXTRACT_SHORT(p) ((u_short)ntohs(*(u_short *)p))
+#define EXTRACT_LONG(p) (ntohl(*(u_long *)p))
+#else
+#define EXTRACT_SHORT(p)\
+ ((u_short)\
+ ((u_short)*((u_char *)p+0)<<8|\
+ (u_short)*((u_char *)p+1)<<0))
+#define EXTRACT_LONG(p)\
+ ((u_long)*((u_char *)p+0)<<24|\
+ (u_long)*((u_char *)p+1)<<16|\
+ (u_long)*((u_char *)p+2)<<8|\
+ (u_long)*((u_char *)p+3)<<0)
+#endif
+
+#define HASH_ITERATE(head, elt) (elt) = (net_hash_entry_t) (head); do {
+#define HASH_ITERATE_END(head, elt) \
+ (elt) = (net_hash_entry_t) queue_next((queue_entry_t) (elt)); \
+} while ((elt) != (head));
+
+#define FILTER_ITERATE(if_port_list, fp, nextfp, chain) \
+ for ((fp) = (net_rcv_port_t) queue_first(if_port_list); \
+ !queue_end(if_port_list, (queue_entry_t)(fp)); \
+ (fp) = (nextfp)) { \
+ (nextfp) = (net_rcv_port_t) queue_next(chain);
+#define FILTER_ITERATE_END }
+
+/* entry_p must be net_rcv_port_t or net_hash_entry_t */
+#define ENQUEUE_DEAD(dead, entry_p, chain) { \
+ queue_next(&(entry_p)->chain) = (queue_entry_t) (dead); \
+ (dead) = (queue_entry_t)(entry_p); \
+}
+
+#define CSPF_BYTES(n) ((n) * sizeof (filter_t))
+
+/*
+ * Receive port for net, with packet filter.
+ * This data structure by itself represents a packet
+ * filter for a single session.
+ */
+struct net_rcv_port {
+ queue_chain_t chain;
+ mach_port_t rcv_port; /* port to send packet to */
+ int rcv_count; /* number of packets received */
+ int priority; /* priority for filter */
+ filter_t *filter_end; /* pointer to end of filter */
+ filter_t filter[NET_MAX_FILTER];
+ /* filter operations */
+};
+typedef struct net_rcv_port *net_rcv_port_t;
+
+/*
+ * A single hash entry.
+ */
+struct net_hash_entry {
+ queue_chain_t chain; /* list of entries with same hval */
+#define he_next chain.next
+#define he_prev chain.prev
+ mach_port_t rcv_port; /* destination port */
+ unsigned int keys[N_NET_HASH_KEYS];
+};
+typedef struct net_hash_entry *net_hash_entry_t;
+
+/*
+ * This structure represents a packet filter with multiple sessions.
+ *
+ * For example, all application level TCP sessions might be
+ * represented by one of these structures. It looks like a
+ * net_rcv_port struct so that both types can live on the
+ * same packet filter queues.
+ */
+struct net_hash_header {
+ struct net_rcv_port rcv;
+ int n_keys; /* zero if not used */
+ int ref_count; /* reference count */
+ net_hash_entry_t table[NET_HASH_SIZE];
+} filter_hash_header[N_NET_HASH];
+
+typedef struct net_hash_header *net_hash_header_t;
+
+int mach_bpf_do_filter(net_rcv_port_t infp, char *p, unsigned int wirelen,
+ char *header, unsigned int hlen, net_hash_entry_t **hash_headpp,
+ net_hash_entry_t *entpp);
+int mach_bpf_validate(bpf_insn_t f, int bytes, bpf_insn_t *match);
+int mach_bpf_eq (bpf_insn_t f1, bpf_insn_t f2, int bytes);
+unsigned int mach_bpf_hash (int n, unsigned int *keys);
+int mach_bpf_match (net_hash_header_t hash, int n_keys, unsigned int *keys,
+ net_hash_entry_t **hash_headpp, net_hash_entry_t *entpp);
+
+error_t net_set_filter(mach_port_t rcv_port, int priority,
+ filter_t *filter, unsigned int filter_count);
+int hash_ent_remove (net_hash_header_t hp, int used, net_hash_entry_t *head,
+ net_hash_entry_t entp, queue_entry_t *dead_p);
+void net_free_dead_infp (queue_entry_t dead_infp);
+void net_free_dead_entp (queue_entry_t dead_entp);
+void remove_dead_filter (queue_head_t *if_port_list, mach_port_t dead_port);
+void remove_dead_filter_from_all (mach_port_t dead_port);
+void bpf_init();
+
+extern queue_head_t rcv_port_list; /* input filter list */
+extern queue_head_t snd_port_list; /* output filter list */
+
+#endif /* _DEVICE_BPF_H_ */
diff --git a/eth-filter.multi-thread/bpf_impl.o b/eth-filter.multi-thread/bpf_impl.o
new file mode 100644
index 00000000..aaf3181a
--- /dev/null
+++ b/eth-filter.multi-thread/bpf_impl.o
Binary files differ
diff --git a/eth-filter.multi-thread/device.defs b/eth-filter.multi-thread/device.defs
new file mode 100644
index 00000000..70472689
--- /dev/null
+++ b/eth-filter.multi-thread/device.defs
@@ -0,0 +1 @@
+#include <device/device.defs>
diff --git a/eth-filter.multi-thread/device_reply.defs b/eth-filter.multi-thread/device_reply.defs
new file mode 100644
index 00000000..69930311
--- /dev/null
+++ b/eth-filter.multi-thread/device_reply.defs
@@ -0,0 +1 @@
+#include <device/device_reply.defs>
diff --git a/eth-filter.multi-thread/device_reply.udefs.d b/eth-filter.multi-thread/device_reply.udefs.d
new file mode 100644
index 00000000..5c71bec5
--- /dev/null
+++ b/eth-filter.multi-thread/device_reply.udefs.d
@@ -0,0 +1,5 @@
+device_replyUser.c device_reply_U.h: device_reply.defs \
+ /usr/local/include/device/device_reply.defs \
+ /usr/local/include/mach/std_types.defs \
+ /usr/local/include/mach/machine/machine_types.defs \
+ /usr/local/include/device/device_types.defs
diff --git a/eth-filter.multi-thread/device_replyUser.c b/eth-filter.multi-thread/device_replyUser.c
new file mode 100644
index 00000000..5735b1be
--- /dev/null
+++ b/eth-filter.multi-thread/device_replyUser.c
@@ -0,0 +1,374 @@
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#include "device_reply_U.h"
+#define EXPORT_BOOLEAN
+#include <mach/boolean.h>
+#include <mach/kern_return.h>
+#include <mach/message.h>
+#include <mach/notify.h>
+#include <mach/mach_types.h>
+#include <mach/mig_errors.h>
+#include <mach/mig_support.h>
+#include <mach/msg_type.h>
+/* LINTLIBRARY */
+
+#ifndef mig_internal
+#define mig_internal static
+#endif
+
+#ifndef mig_external
+#define mig_external
+#endif
+
+#ifndef TypeCheck
+#define TypeCheck 1
+#endif
+
+#ifndef UseExternRCSId
+#define UseExternRCSId 1
+#endif
+
+#define BAD_TYPECHECK(type, check) ({\
+ union { mach_msg_type_t t; unsigned32_t w; } _t, _c;\
+ _t.t = *(type); _c.t = *(check); _t.w != _c.w; })
+#define msgh_request_port msgh_remote_port
+#define msgh_reply_port msgh_local_port
+
+#include <mach/std_types.h>
+#include <device/device_types.h>
+#include <device/net_status.h>
+
+/* SimpleRoutine device_open_reply */
+mig_external kern_return_t ds_device_open_reply
+(
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_portPoly,
+ kern_return_t return_code,
+ mach_port_t device_port
+)
+{
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t return_codeType;
+ kern_return_t return_code;
+ mach_msg_type_t device_portType;
+ mach_port_t device_port;
+ } Request;
+
+ union {
+ Request In;
+ } Mess;
+
+ register Request *InP = &Mess.In;
+
+
+ auto const mach_msg_type_t return_codeType = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ auto const mach_msg_type_t device_portType = {
+ /* msgt_name = */ 20,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ InP->return_codeType = return_codeType;
+
+ InP->return_code = return_code;
+
+ InP->device_portType = device_portType;
+
+ InP->device_port = device_port;
+
+ InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX|
+ MACH_MSGH_BITS(reply_portPoly, 0);
+ /* msgh_size passed as argument */
+ InP->Head.msgh_request_port = reply_port;
+ InP->Head.msgh_reply_port = MACH_PORT_NULL;
+ InP->Head.msgh_seqno = 0;
+ InP->Head.msgh_id = 2900;
+
+ return __mach_msg(&InP->Head, MACH_SEND_MSG|MACH_MSG_OPTION_NONE, 40, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+}
+
+/* SimpleRoutine device_write_reply */
+mig_external kern_return_t ds_device_write_reply
+(
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_portPoly,
+ kern_return_t return_code,
+ int bytes_written
+)
+{
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t return_codeType;
+ kern_return_t return_code;
+ mach_msg_type_t bytes_writtenType;
+ int bytes_written;
+ } Request;
+
+ union {
+ Request In;
+ } Mess;
+
+ register Request *InP = &Mess.In;
+
+
+ auto const mach_msg_type_t return_codeType = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ auto const mach_msg_type_t bytes_writtenType = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ InP->return_codeType = return_codeType;
+
+ InP->return_code = return_code;
+
+ InP->bytes_writtenType = bytes_writtenType;
+
+ InP->bytes_written = bytes_written;
+
+ InP->Head.msgh_bits =
+ MACH_MSGH_BITS(reply_portPoly, 0);
+ /* msgh_size passed as argument */
+ InP->Head.msgh_request_port = reply_port;
+ InP->Head.msgh_reply_port = MACH_PORT_NULL;
+ InP->Head.msgh_seqno = 0;
+ InP->Head.msgh_id = 2902;
+
+ return __mach_msg(&InP->Head, MACH_SEND_MSG|MACH_MSG_OPTION_NONE, 40, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+}
+
+/* SimpleRoutine device_write_reply_inband */
+mig_external kern_return_t ds_device_write_reply_inband
+(
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_portPoly,
+ kern_return_t return_code,
+ int bytes_written
+)
+{
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t return_codeType;
+ kern_return_t return_code;
+ mach_msg_type_t bytes_writtenType;
+ int bytes_written;
+ } Request;
+
+ union {
+ Request In;
+ } Mess;
+
+ register Request *InP = &Mess.In;
+
+
+ auto const mach_msg_type_t return_codeType = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ auto const mach_msg_type_t bytes_writtenType = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ InP->return_codeType = return_codeType;
+
+ InP->return_code = return_code;
+
+ InP->bytes_writtenType = bytes_writtenType;
+
+ InP->bytes_written = bytes_written;
+
+ InP->Head.msgh_bits =
+ MACH_MSGH_BITS(reply_portPoly, 0);
+ /* msgh_size passed as argument */
+ InP->Head.msgh_request_port = reply_port;
+ InP->Head.msgh_reply_port = MACH_PORT_NULL;
+ InP->Head.msgh_seqno = 0;
+ InP->Head.msgh_id = 2903;
+
+ return __mach_msg(&InP->Head, MACH_SEND_MSG|MACH_MSG_OPTION_NONE, 40, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+}
+
+/* SimpleRoutine device_read_reply */
+mig_external kern_return_t ds_device_read_reply
+(
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_portPoly,
+ kern_return_t return_code,
+ io_buf_ptr_t data,
+ mach_msg_type_number_t dataCnt
+)
+{
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t return_codeType;
+ kern_return_t return_code;
+ mach_msg_type_long_t dataType;
+ io_buf_ptr_t data;
+ } Request;
+
+ union {
+ Request In;
+ } Mess;
+
+ register Request *InP = &Mess.In;
+
+
+ auto const mach_msg_type_t return_codeType = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ auto const mach_msg_type_long_t dataType = {
+ {
+ /* msgt_name = */ 0,
+ /* msgt_size = */ 0,
+ /* msgt_number = */ 0,
+ /* msgt_inline = */ FALSE,
+ /* msgt_longform = */ TRUE,
+ /* msgt_deallocate = */ TRUE,
+ /* msgt_unused = */ 0
+ },
+ /* msgtl_name = */ 9,
+ /* msgtl_size = */ 8,
+ /* msgtl_number = */ 0,
+ };
+
+ InP->return_codeType = return_codeType;
+
+ InP->return_code = return_code;
+
+ InP->dataType = dataType;
+
+ InP->data = data;
+
+ InP->dataType.msgtl_number = dataCnt;
+
+ InP->Head.msgh_bits = MACH_MSGH_BITS_COMPLEX|
+ MACH_MSGH_BITS(reply_portPoly, 0);
+ /* msgh_size passed as argument */
+ InP->Head.msgh_request_port = reply_port;
+ InP->Head.msgh_reply_port = MACH_PORT_NULL;
+ InP->Head.msgh_seqno = 0;
+ InP->Head.msgh_id = 2904;
+
+ return __mach_msg(&InP->Head, MACH_SEND_MSG|MACH_MSG_OPTION_NONE, 48, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+}
+
+/* SimpleRoutine device_read_reply_inband */
+mig_external kern_return_t ds_device_read_reply_inband
+(
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_portPoly,
+ kern_return_t return_code,
+ io_buf_ptr_inband_t data,
+ mach_msg_type_number_t dataCnt
+)
+{
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t return_codeType;
+ kern_return_t return_code;
+ mach_msg_type_t dataType;
+ char data[128];
+ } Request;
+
+ union {
+ Request In;
+ } Mess;
+
+ register Request *InP = &Mess.In;
+
+ unsigned int msgh_size;
+
+ auto const mach_msg_type_t return_codeType = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ auto const mach_msg_type_t dataType = {
+ /* msgt_name = */ 8,
+ /* msgt_size = */ 8,
+ /* msgt_number = */ 128,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ InP->return_codeType = return_codeType;
+
+ InP->return_code = return_code;
+
+ InP->dataType = dataType;
+
+ if (dataCnt > 128) {
+ return MIG_ARRAY_TOO_LARGE;
+ }
+ else {
+ memcpy(InP->data, data, dataCnt);
+ }
+
+ InP->dataType.msgt_number = dataCnt;
+
+ msgh_size = 36 + ((dataCnt + 3) & ~3);
+ InP->Head.msgh_bits =
+ MACH_MSGH_BITS(reply_portPoly, 0);
+ /* msgh_size passed as argument */
+ InP->Head.msgh_request_port = reply_port;
+ InP->Head.msgh_reply_port = MACH_PORT_NULL;
+ InP->Head.msgh_seqno = 0;
+ InP->Head.msgh_id = 2905;
+
+ return __mach_msg(&InP->Head, MACH_SEND_MSG|MACH_MSG_OPTION_NONE, msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+}
diff --git a/eth-filter.multi-thread/device_replyUser.d b/eth-filter.multi-thread/device_replyUser.d
new file mode 100644
index 00000000..dfa7dd5e
--- /dev/null
+++ b/eth-filter.multi-thread/device_replyUser.d
@@ -0,0 +1,47 @@
+device_replyUser.o device_replyUser_pic.o device_replyUser_p.o device_replyUser.d: device_replyUser.c device_reply_U.h \
+ /usr/local/include/mach/kern_return.h \
+ /usr/local/include/mach/machine/kern_return.h \
+ /usr/local/include/mach/port.h /usr/local/include/mach/boolean.h \
+ /usr/local/include/mach/machine/boolean.h \
+ /usr/local/include/mach/machine/vm_types.h \
+ /usr/local/include/mach/message.h /usr/local/include/mach/std_types.h \
+ /usr/local/include/device/device_types.h \
+ /usr/local/include/device/net_status.h /usr/local/include/device/bpf.h \
+ /usr/include/sys/types.h /usr/include/features.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
+ /usr/include/gnu/stubs-pthread.h /usr/include/bits/types.h \
+ /usr/include/bits/typesizes.h /usr/include/time.h \
+ /usr/lib/gcc/i486-gnu/4.2.4/include/stddef.h /usr/include/endian.h \
+ /usr/include/bits/endian.h /usr/include/sys/select.h \
+ /usr/include/bits/select.h /usr/include/bits/sigset.h \
+ /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
+ /usr/include/bits/pthreadtypes.h /usr/include/pthread/pthreadtypes.h \
+ /usr/include/xlocale.h /usr/include/bits/pthread.h \
+ /usr/include/bits/thread-attr.h /usr/include/sched.h \
+ /usr/include/bits/sched.h /usr/include/bits/mutex-attr.h \
+ /usr/include/bits/mutex.h /usr/include/bits/spin-lock.h \
+ /usr/include/bits/condition-attr.h /usr/include/bits/condition.h \
+ /usr/include/bits/rwlock-attr.h /usr/include/bits/rwlock.h \
+ /usr/include/bits/barrier-attr.h /usr/include/bits/barrier.h \
+ /usr/include/bits/thread-specific.h /usr/include/bits/once.h \
+ /usr/local/include/mach/notify.h /usr/local/include/mach/mach_types.h \
+ /usr/local/include/mach/host_info.h /usr/local/include/mach/machine.h \
+ /usr/local/include/mach/memory_object.h \
+ /usr/local/include/mach/pc_sample.h \
+ /usr/local/include/mach/processor_info.h \
+ /usr/local/include/mach/task_info.h \
+ /usr/local/include/mach/time_value.h \
+ /usr/local/include/mach/task_special_ports.h \
+ /usr/local/include/mach/thread_info.h /usr/local/include/mach/policy.h \
+ /usr/local/include/mach/thread_special_ports.h \
+ /usr/local/include/mach/thread_status.h \
+ /usr/local/include/mach/machine/thread_status.h \
+ /usr/local/include/mach/machine/fp_reg.h \
+ /usr/local/include/mach/vm_attributes.h \
+ /usr/local/include/mach/vm_inherit.h /usr/local/include/mach/vm_prot.h \
+ /usr/local/include/mach/vm_statistics.h \
+ /usr/local/include/mach/mig_errors.h /usr/include/mach/mig_support.h \
+ /usr/include/string.h /usr/include/bits/string.h \
+ /usr/include/bits/string2.h /usr/include/stdlib.h \
+ /usr/local/include/mach/msg_type.h
diff --git a/eth-filter.multi-thread/device_replyUser.o b/eth-filter.multi-thread/device_replyUser.o
new file mode 100644
index 00000000..19e59cbb
--- /dev/null
+++ b/eth-filter.multi-thread/device_replyUser.o
Binary files differ
diff --git a/eth-filter.multi-thread/device_reply_U.h b/eth-filter.multi-thread/device_reply_U.h
new file mode 100644
index 00000000..d70cd5b3
--- /dev/null
+++ b/eth-filter.multi-thread/device_reply_U.h
@@ -0,0 +1,133 @@
+#ifndef _device_reply_user_
+#define _device_reply_user_
+
+/* Module device_reply */
+
+#include <mach/kern_return.h>
+#include <mach/port.h>
+#include <mach/message.h>
+
+#include <mach/std_types.h>
+#include <device/device_types.h>
+#include <device/net_status.h>
+
+/* SimpleRoutine device_open_reply */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif
+kern_return_t ds_device_open_reply
+#if defined(LINTLIBRARY)
+ (reply_port, reply_portPoly, return_code, device_port)
+ mach_port_t reply_port;
+ mach_msg_type_name_t reply_portPoly;
+ kern_return_t return_code;
+ mach_port_t device_port;
+{ return ds_device_open_reply(reply_port, reply_portPoly, return_code, device_port); }
+#else
+(
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_portPoly,
+ kern_return_t return_code,
+ mach_port_t device_port
+);
+#endif
+
+/* SimpleRoutine device_write_reply */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif
+kern_return_t ds_device_write_reply
+#if defined(LINTLIBRARY)
+ (reply_port, reply_portPoly, return_code, bytes_written)
+ mach_port_t reply_port;
+ mach_msg_type_name_t reply_portPoly;
+ kern_return_t return_code;
+ int bytes_written;
+{ return ds_device_write_reply(reply_port, reply_portPoly, return_code, bytes_written); }
+#else
+(
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_portPoly,
+ kern_return_t return_code,
+ int bytes_written
+);
+#endif
+
+/* SimpleRoutine device_write_reply_inband */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif
+kern_return_t ds_device_write_reply_inband
+#if defined(LINTLIBRARY)
+ (reply_port, reply_portPoly, return_code, bytes_written)
+ mach_port_t reply_port;
+ mach_msg_type_name_t reply_portPoly;
+ kern_return_t return_code;
+ int bytes_written;
+{ return ds_device_write_reply_inband(reply_port, reply_portPoly, return_code, bytes_written); }
+#else
+(
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_portPoly,
+ kern_return_t return_code,
+ int bytes_written
+);
+#endif
+
+/* SimpleRoutine device_read_reply */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif
+kern_return_t ds_device_read_reply
+#if defined(LINTLIBRARY)
+ (reply_port, reply_portPoly, return_code, data, dataCnt)
+ mach_port_t reply_port;
+ mach_msg_type_name_t reply_portPoly;
+ kern_return_t return_code;
+ io_buf_ptr_t data;
+ mach_msg_type_number_t dataCnt;
+{ return ds_device_read_reply(reply_port, reply_portPoly, return_code, data, dataCnt); }
+#else
+(
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_portPoly,
+ kern_return_t return_code,
+ io_buf_ptr_t data,
+ mach_msg_type_number_t dataCnt
+);
+#endif
+
+/* SimpleRoutine device_read_reply_inband */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif
+kern_return_t ds_device_read_reply_inband
+#if defined(LINTLIBRARY)
+ (reply_port, reply_portPoly, return_code, data, dataCnt)
+ mach_port_t reply_port;
+ mach_msg_type_name_t reply_portPoly;
+ kern_return_t return_code;
+ io_buf_ptr_inband_t data;
+ mach_msg_type_number_t dataCnt;
+{ return ds_device_read_reply_inband(reply_port, reply_portPoly, return_code, data, dataCnt); }
+#else
+(
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_portPoly,
+ kern_return_t return_code,
+ io_buf_ptr_inband_t data,
+ mach_msg_type_number_t dataCnt
+);
+#endif
+
+#endif /* not defined(_device_reply_user_) */
diff --git a/eth-filter.multi-thread/eth-filter b/eth-filter.multi-thread/eth-filter
new file mode 100755
index 00000000..160153fe
--- /dev/null
+++ b/eth-filter.multi-thread/eth-filter
Binary files differ
diff --git a/eth-filter.multi-thread/eth-filter.prof_d b/eth-filter.multi-thread/eth-filter.prof_d
new file mode 100644
index 00000000..eb1c5518
--- /dev/null
+++ b/eth-filter.multi-thread/eth-filter.prof_d
@@ -0,0 +1 @@
+eth-filter.prof: bpf_impl_p.o filter_p.o queue_p.o pcap_filter_p.o msg_queue_p.o ourdeviceServer_p.o notifyServer_p.o device_replyUser_p.o ../libthreads/libthreads_p.a ../libports/libports_p.a ../libtrivfs/libtrivfs_p.a ../libfshelp/libfshelp_p.a ../libihash/libihash_p.a ../libshouldbeinlibc/libshouldbeinlibc_p.a
diff --git a/eth-filter.multi-thread/filter.c b/eth-filter.multi-thread/filter.c
new file mode 100644
index 00000000..36fe2fa0
--- /dev/null
+++ b/eth-filter.multi-thread/filter.c
@@ -0,0 +1,878 @@
+/*
+ Copyright (C) 2008 Free Software Foundation, Inc.
+ Written by Zheng Da.
+
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ The GNU Hurd is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the GNU Hurd; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * This program is a filter translator which sits on the top of the network
+ * interface.
+ * It provides two filters: for outgoing packets and for incoming packets.
+ * Only one pfinet server are allowed to run on the top of the translator.
+ */
+
+#include <argp.h>
+#include <errno.h>
+#include <error.h>
+#include <stddef.h>
+#include <unistd.h>
+
+#include <hurd.h>
+#include <mach.h>
+#include <cthreads.h>
+#include <device/device.h>
+#include <hurd/trivfs.h>
+#include <hurd/ports.h>
+#include <hurd/ihash.h>
+
+#include "ourdevice_S.h"
+#include "notify_S.h"
+#include "device_reply_U.h"
+#include "bpf_impl.h"
+#include "util.h"
+#include "filter.h"
+#include "msg_queue.h"
+
+#ifdef DEBUG
+
+FILE *logfile;
+
+#endif
+
+static struct hurd_ihash proxy_deliverport_ht
+= HURD_IHASH_INITIALIZER (offsetof (struct proxy, p_deliverport_hashloc));
+
+/* The name of the network interface that the filter translator sits on. */
+static char *device_file;
+const char *argp_program_version = "eth-filter 0.1";
+const char *argp_program_bug_address = "<bug-hurd@gnu.org>";
+static const char doc[] = "Hurd filter translator.";
+static const struct argp_option options[] =
+{
+ {"interface", 'i', "DEVICE", 0,
+ "Network interface to use", 2},
+ {"send-filter", 's', "string", 0,
+ "The filter rule which applies to the outgoing packet", 4},
+ {"receive-filter", 'r', "string", 0,
+ "The filter rule which applies to the ingoing packet", 5},
+ {"send-ip-range", 'S', "IP range", 0,
+ "A range of IP to create the send filter", 6},
+ {"receive-ip-range", 'R', "IP range", 0,
+ "A range of IP to create the receive filter", 7},
+ {0}
+};
+
+/* A filter allows every packet to be sent and be received. */
+static struct bpf_insn default_snd_filter[] =
+{
+ {NETF_OUT|NETF_BPF, 0, 0, 0},
+ {6, 0, 0, 1500}
+};
+static struct bpf_insn default_rcv_filter[] =
+{
+ {NETF_IN|NETF_BPF, 0, 0, 0},
+ {6, 0, 0, 1500}
+};
+static struct bpf_insn *snd_filter = NULL;
+static int snd_filter_length;
+static struct bpf_insn *rcv_filter = NULL;
+static int rcv_filter_length;
+
+static cthread_t send_thread;
+static int send_thread_running = 1;
+
+/* Port bucket we service requests on. */
+struct port_bucket *port_bucket;
+
+struct port_class *user_portclass;
+struct port_class *device_portclass;
+struct port_class *other_portclass;
+
+/* Trivfs hooks. */
+int trivfs_fstype = FSTYPE_MISC;
+int trivfs_fsid = 0;
+int trivfs_support_read = 0;
+int trivfs_support_write = 0;
+int trivfs_support_exec = 0;
+int trivfs_allow_open = 0;
+
+struct port_class *trivfs_protid_portclasses[1];
+struct port_class *trivfs_cntl_portclasses[1];
+int trivfs_protid_nportclasses = 1;
+int trivfs_cntl_nportclasses = 1;
+
+/* For getting the notification of ports from the kernel. */
+struct port_info *notify_pi;
+
+/* Write the data from the client to the device. */
+int
+filter_device_write (struct filter_msg *msg)
+{
+ error_t err = 0;
+ int ret_count = 0;
+ int has_filter = 0;
+ net_hash_entry_t entp, *hash_headp;
+ net_rcv_port_t infp, nextfp;
+ int bytes_written;
+ struct filter_write_msg *write_msg = (struct filter_write_msg *) msg;
+
+ /* The packet can be sent as long as it passes one filter,
+ * even thought there is usually only one filter in the list. */
+ FILTER_ITERATE (&snd_port_list, infp, nextfp, &infp->chain)
+ {
+ has_filter = 1;
+ ret_count = mach_bpf_do_filter (infp,
+ write_msg->data + sizeof (struct ethhdr),
+ write_msg->datalen - sizeof (struct ethhdr),
+ write_msg->data, sizeof (struct ethhdr),
+ &hash_headp, &entp);
+ if (ret_count)
+ break;
+ }
+ FILTER_ITERATE_END
+
+ if (ret_count || !has_filter)
+ err = device_write (msg->proxy->device_port, write_msg->mode,
+ write_msg->recnum, write_msg->data,
+ write_msg->datalen, &bytes_written);
+ ds_device_write_reply (write_msg->reply_port, write_msg->reply_type,
+ err, bytes_written);
+ return 0;
+}
+
+/* Deliver the data from the device to the client. */
+int
+filter_deliver (struct filter_msg *msg)
+{
+ deliver_msg (((struct filter_deliver_msg *)msg)->net_msg,
+ &rcv_port_list, msg->proxy->deliver_port);
+ return 0;
+}
+
+error_t
+create_proxy_user (struct proxy *proxy, mach_port_t *port)
+{
+ error_t err;
+ struct proxy_user *user;
+
+ err = ports_create_port (user_portclass, port_bucket, sizeof (*user), &user);
+ if (err)
+ return err;
+ user->proxy = proxy;
+
+ *port = ports_get_right (user);
+ ports_port_deref (user);
+ return 0;
+}
+
+error_t
+create_proxy_device (struct proxy *proxy, mach_port_t *port)
+{
+ error_t err;
+ struct proxy_device *device;
+
+ err = ports_create_port (device_portclass, port_bucket, sizeof (*device), &device);
+ if (err)
+ return err;
+ device->proxy = proxy;
+ proxy->device = device;
+
+ *port = ports_get_right (device);
+ ports_port_deref (device);
+ return 0;
+}
+
+void
+clean_proxy_user (void *p)
+{
+ struct proxy_user *user = p;
+ struct proxy *proxy = user->proxy;
+
+ if (proxy->p_deliverport_hashloc)
+ hurd_ihash_locp_remove (&proxy_deliverport_ht, proxy->p_deliverport_hashloc);
+
+ if (proxy->deliver_port != MACH_PORT_NULL)
+ mach_port_deallocate (mach_task_self (), proxy->deliver_port);
+ if (proxy->device_port != MACH_PORT_NULL)
+ mach_port_deallocate (mach_task_self (), proxy->device_port);
+
+ if (proxy->device)
+ ports_destroy_right (proxy->device);
+
+ free (proxy);
+}
+
+void
+clean_proxy_device (void *p)
+{
+ struct proxy_device *device = p;
+ if (device->proxy)
+ device->proxy->device = NULL;
+}
+
+static int
+filter_demuxer (mach_msg_header_t *inp,
+ mach_msg_header_t *outp)
+{
+ extern int device_server (mach_msg_header_t *, mach_msg_header_t *);
+ extern int notify_server (mach_msg_header_t *, mach_msg_header_t *);
+ extern int ethernet_demuxer (mach_msg_header_t *, mach_msg_header_t *);
+ return device_server (inp, outp) || notify_server (inp, outp)
+ || ethernet_demuxer (inp, outp) || trivfs_demuxer (inp, outp);
+}
+
+int
+ethernet_demuxer (mach_msg_header_t *inp,
+ mach_msg_header_t *outp)
+{
+ struct net_rcv_msg *msg = (struct net_rcv_msg *) inp;
+ struct proxy_device *device;
+ struct proxy *proxy;
+
+ if (inp->msgh_id != NET_RCV_MSG_ID)
+ return 0;
+
+ device = ports_lookup_port (port_bucket, inp->msgh_local_port,
+ device_portclass);
+ if (device == NULL)
+ return 0;
+
+ proxy = device->proxy;
+ ports_port_deref (device);
+
+ if (proxy && proxy->deliver_port != MACH_PORT_NULL)
+ queue_deliver (msg, proxy);
+// deliver_msg (msg, &rcv_port_list, proxy->deliver_port);
+
+ return 1;
+}
+
+/* Implementation of notify interface */
+kern_return_t
+do_mach_notify_port_deleted (mach_port_t notify,
+ mach_port_t name)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+do_mach_notify_msg_accepted (mach_port_t notify,
+ mach_port_t name)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+do_mach_notify_port_destroyed (mach_port_t notify,
+ mach_port_t port)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+do_mach_notify_no_senders (mach_port_t notify,
+ mach_port_mscount_t mscount)
+{
+ debug ("do_mach_notify_no_senders is called\n");
+ return ports_do_mach_notify_no_senders (notify, mscount);
+}
+
+kern_return_t
+do_mach_notify_send_once (mach_port_t notify)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+do_mach_notify_dead_name (mach_port_t notify,
+ mach_port_t name)
+{
+ struct proxy *proxy;
+
+ debug ("do_mach_notify_dead_name is called\n");
+ mach_port_deallocate (mach_task_self (), name);
+ proxy = hurd_ihash_find (&proxy_deliverport_ht, name);
+ if (proxy)
+ {
+ proxy->deliver_port = MACH_PORT_NULL;
+ return 0;
+ }
+ return EINVAL;
+}
+
+/* Implementation of device interface */
+kern_return_t
+ds_xxx_device_set_status (device_t device, dev_flavor_t flavor,
+ dev_status_t status, size_t statu_cnt)
+{
+ return D_INVALID_OPERATION;
+}
+
+kern_return_t
+ds_xxx_device_get_status (device_t device, dev_flavor_t flavor,
+ dev_status_t status, size_t *statuscnt)
+{
+ return D_INVALID_OPERATION;
+}
+
+kern_return_t
+ds_xxx_device_set_filter (device_t device, mach_port_t rec,
+ int pri, filter_array_t filt, size_t len)
+{
+ return D_INVALID_OPERATION;
+}
+
+kern_return_t
+ds_device_open (mach_port_t master_port, mach_port_t reply_port,
+ mach_msg_type_name_t reply_portPoly,
+ dev_mode_t mode, dev_name_t name, mach_port_t *device,
+ mach_msg_type_name_t *devicetype)
+{
+ kern_return_t err;
+ mach_port_t master_device;
+ mach_port_t user_port;
+ struct proxy *proxy;
+
+ if (device_file == NULL)
+ return D_NO_SUCH_DEVICE;
+
+ master_device = file_name_lookup (device_file, 0, 0);
+ if (master_device == MACH_PORT_NULL)
+ return errno;
+
+ proxy = (struct proxy *)calloc (1, sizeof (*proxy));
+ if (proxy == NULL)
+ {
+ mach_port_deallocate (mach_task_self (), master_device);
+ return D_NO_MEMORY;
+ }
+
+ err = device_open (master_device, mode, name, &proxy->device_port);
+ mach_port_deallocate (mach_task_self (), master_device);
+ if (err != KERN_SUCCESS)
+ {
+ free (proxy);
+ return err;
+ }
+
+ err = create_proxy_user (proxy, &user_port);
+ if (err)
+ {
+ mach_port_deallocate (mach_task_self (), master_device);
+ free (proxy);
+ return err;
+ }
+
+ *device = user_port;
+ *devicetype = MACH_MSG_TYPE_MAKE_SEND;
+
+ return 0;
+}
+
+kern_return_t
+ds_device_close (device_t device)
+{
+ return 0;
+}
+
+kern_return_t
+ds_device_write (device_t device, mach_port_t reply_port,
+ mach_msg_type_name_t reply_type, dev_mode_t mode,
+ recnum_t recnum, io_buf_ptr_t data, size_t datalen,
+ int *bytes_written)
+{
+ kern_return_t err = 0;
+ struct proxy_user *user;
+ struct proxy *proxy;
+ int ret_count = 0;
+ int has_filter = 0;
+ net_hash_entry_t entp, *hash_headp;
+ net_rcv_port_t infp, nextfp;
+
+ user = ports_lookup_port (port_bucket, device, user_portclass);
+ if (user == NULL)
+ return D_INVALID_OPERATION;
+ proxy = user->proxy;
+
+ /* The packet can be sent as long as it passes one filter,
+ * even thought there is usually only one filter in the list. */
+ FILTER_ITERATE (&snd_port_list, infp, nextfp, &infp->chain)
+ {
+ has_filter = 1;
+ ret_count = mach_bpf_do_filter (infp,
+ data + sizeof (struct ethhdr),
+ datalen - sizeof (struct ethhdr),
+ data, sizeof (struct ethhdr),
+ &hash_headp, &entp);
+ if (ret_count)
+ break;
+ }
+ FILTER_ITERATE_END
+
+ if (ret_count || !has_filter)
+ err = device_write (proxy->device_port, mode, recnum, data,
+ datalen, bytes_written);
+ ports_port_deref (user);
+ return err;
+}
+
+kern_return_t
+ds_device_write_inband (device_t device, mach_port_t reply_port,
+ mach_msg_type_name_t reply_type, dev_mode_t mode,
+ recnum_t recnum, io_buf_ptr_inband_t data,
+ size_t datalen, int *bytes_written)
+{
+ kern_return_t ret;
+ struct proxy_user *user;
+ struct proxy *proxy;
+
+ user = ports_lookup_port (port_bucket, device, user_portclass);
+ if (user == NULL)
+ return D_INVALID_OPERATION;
+ proxy = user->proxy;
+ ports_port_deref (user);
+
+ ret = device_write_inband (proxy->device_port, mode, recnum, data,
+ datalen, bytes_written);
+ return ret;
+}
+
+kern_return_t
+ds_device_read (device_t device, mach_port_t reply_port,
+ mach_msg_type_name_t reply_type, dev_mode_t mode,
+ recnum_t recnum, int bytes_wanted,
+ io_buf_ptr_t *data, size_t *datalen)
+{
+ kern_return_t ret;
+ struct proxy_user *user;
+ struct proxy *proxy;
+
+ user = ports_lookup_port (port_bucket, device, user_portclass);
+ if (user == NULL)
+ return D_INVALID_OPERATION;
+ proxy = user->proxy;
+ ports_port_deref (user);
+
+ ret = device_read (proxy->device_port, mode, recnum,
+ bytes_wanted, data, datalen);
+ return ret;
+}
+
+kern_return_t
+ds_device_read_inband (device_t device, mach_port_t reply_port,
+ mach_msg_type_name_t reply_type, dev_mode_t mode,
+ recnum_t recnum, int bytes_wanted,
+ io_buf_ptr_inband_t data, size_t *datalen)
+{
+ kern_return_t ret;
+ struct proxy_user *user;
+ struct proxy *proxy;
+
+ user = ports_lookup_port (port_bucket, device, user_portclass);
+ if (user == NULL)
+ return D_INVALID_OPERATION;
+ proxy = user->proxy;
+ ports_port_deref (user);
+
+ ret = device_read_inband (proxy->device_port, mode, recnum,
+ bytes_wanted, data, datalen);
+ return ret;
+}
+
+kern_return_t
+ds_device_map (device_t device, vm_prot_t prot, vm_offset_t offset,
+ vm_size_t size, memory_object_t *pager, int unmap)
+{
+ kern_return_t ret;
+ struct proxy_user *user;
+ struct proxy *proxy;
+
+ user = ports_lookup_port (port_bucket, device, user_portclass);
+ if (user == NULL)
+ return D_INVALID_OPERATION;
+ proxy = user->proxy;
+ ports_port_deref (user);
+
+ ret = device_map (proxy->device_port, prot, offset,
+ size, pager, unmap);
+ return ret;
+}
+
+kern_return_t
+ds_device_set_status (device_t device, dev_flavor_t flavor,
+ dev_status_t status, size_t statuslen)
+{
+ kern_return_t ret;
+ struct proxy_user *user;
+ struct proxy *proxy;
+
+ user = ports_lookup_port (port_bucket, device, user_portclass);
+ if (user == NULL)
+ return D_INVALID_OPERATION;
+ proxy = user->proxy;
+ ports_port_deref (user);
+
+ ret = device_set_status (proxy->device_port, flavor,
+ status, statuslen);
+ return ret;
+}
+
+kern_return_t
+ds_device_get_status (device_t device, dev_flavor_t flavor,
+ dev_status_t status, size_t *statuslen)
+{
+ kern_return_t ret;
+ struct proxy_user *user;
+ struct proxy *proxy;
+
+ user = ports_lookup_port (port_bucket, device, user_portclass);
+ if (user == NULL)
+ return D_INVALID_OPERATION;
+ proxy = user->proxy;
+ ports_port_deref (user);
+
+ ret = device_get_status (proxy->device_port, flavor, status, statuslen);
+ return ret;
+}
+
+kern_return_t
+ds_device_set_filter (device_t device, mach_port_t receive_port,
+ int priority, filter_array_t filter, size_t filterlen)
+{
+ mach_port_t tmp;
+ kern_return_t err;
+ mach_port_t device_receive_port;
+ struct proxy_user *user;
+ struct proxy *proxy;
+
+ user = ports_lookup_port (port_bucket, device, user_portclass);
+ if (user == NULL)
+ return D_INVALID_OPERATION;
+ proxy = user->proxy;
+ ports_port_deref (user);
+
+ if (proxy->device == NULL)
+ {
+ error_t err;
+ err = create_proxy_device (proxy, &device_receive_port);
+ if (err)
+ return err;
+ }
+ else
+ device_receive_port = ports_get_right (proxy->device);
+
+ /* Set the filter from pfinet into the interface,
+ * but the packet will be delivered to the translator,
+ * so the translator has the chance to filter some packets. */
+ err = device_set_filter (proxy->device_port,
+ device_receive_port,
+ MACH_MSG_TYPE_MAKE_SEND, priority,
+ filter, filterlen);
+ if (err)
+ return err;
+
+ proxy->deliver_port = receive_port;
+ hurd_ihash_add (&proxy_deliverport_ht, receive_port, proxy);
+
+ err = mach_port_request_notification (mach_task_self (), receive_port,
+ MACH_NOTIFY_DEAD_NAME, 0,
+ ports_get_right (notify_pi),
+ MACH_MSG_TYPE_MAKE_SEND_ONCE, &tmp);
+ if (tmp != MACH_PORT_NULL)
+ mach_port_deallocate (mach_task_self (), tmp);
+
+ return err;
+}
+
+void
+trivfs_modify_stat (struct trivfs_protid *cred, io_statbuf_t *stat)
+{
+}
+
+error_t
+trivfs_goaway (struct trivfs_control *fsys, int flags)
+{
+ int count;
+
+ /* Stop new requests. */
+ ports_inhibit_class_rpcs (trivfs_cntl_portclasses[0]);
+ ports_inhibit_class_rpcs (trivfs_protid_portclasses[0]);
+
+ count = ports_count_class (user_portclass);
+ debug ("the number of ports alive: %d\n", count);
+
+ if (count && !(flags & FSYS_GOAWAY_FORCE))
+ {
+ /* We won't go away, so start things going again... */
+ ports_enable_class (trivfs_protid_portclasses[0]);
+ ports_resume_class_rpcs (trivfs_cntl_portclasses[0]);
+ ports_resume_class_rpcs (trivfs_protid_portclasses[0]);
+ return EBUSY;
+ }
+
+ queue_flush ();
+ send_thread_running = 0;
+// cthread_join (send_thread);
+
+#ifdef DEBUG
+ fclose (logfile);
+#endif
+ debug ("the translator is gone away\n");
+ exit (0);
+}
+
+/* Convert the network address input by the user into
+ * a form that is accepted by libpcap. */
+int
+correct_net_addr (char *orig, char *result, int result_len)
+{
+ char *ptr;
+ int netmask_len;
+ int remain_bits;
+ int remain_bytes;
+ char netmask;
+ char addr[4];
+ char buf[INET_ADDRSTRLEN];
+ int i;
+
+ ptr = strstr (orig, "/");
+ if (ptr == NULL)
+ {
+ strncpy (result, orig, result_len);
+ return 0;
+ }
+
+ *ptr = 0;
+ ptr++;
+ netmask_len = atoi (ptr);
+ if (inet_pton (AF_INET, orig, addr) < 0)
+ {
+ perror ("inet_pton");
+ return -1;
+ }
+ remain_bits = netmask_len % 8;
+ netmask = ~0;
+ netmask >>= 8 - remain_bits;
+ netmask <<= 8 - remain_bits;
+ remain_bytes = netmask_len / 8;
+ addr[remain_bytes] &= netmask;
+ for (i=remain_bytes+1 ; i < 4 ; i++)
+ addr[i] = 0;
+
+ snprintf (result, result_len, "%s/%s",
+ inet_ntop (AF_INET, addr, buf, INET_ADDRSTRLEN), ptr);
+ return 0;
+}
+
+static error_t
+parse_opt (int opt, char *arg, struct argp_state *state)
+{
+ struct bpf_insn *trans_filter_program (char *str, int send,
+ int *filter_len);
+ char buf[1024];
+ char addr[INET_ADDRSTRLEN+4];
+
+ switch (opt)
+ {
+ case 'i':
+ device_file = arg;
+ break;
+ case 's':
+ if (snd_filter)
+ free (snd_filter);
+ snd_filter = trans_filter_program (arg, 1, &snd_filter_length);
+ break;
+ case 'r':
+ if (rcv_filter)
+ free (rcv_filter);
+ rcv_filter = trans_filter_program (arg, 0, &rcv_filter_length);
+ break;
+ case 'S':
+ if (correct_net_addr (arg, addr, INET_ADDRSTRLEN+4) < 0)
+ return 0;
+ snprintf (buf, sizeof (buf), "arp or (ip and src net %s)", addr);
+ if (snd_filter)
+ free (snd_filter);
+ snd_filter = trans_filter_program (buf, 1, &snd_filter_length);
+ break;
+ case 'R':
+ if (correct_net_addr (arg, addr, INET_ADDRSTRLEN+4) < 0)
+ return 0;
+ snprintf (buf, sizeof (buf), "arp or (ip and dst net %s)", addr);
+ if (rcv_filter)
+ free (rcv_filter);
+ rcv_filter = trans_filter_program (buf, 0, &rcv_filter_length);
+ break;
+ case ARGP_KEY_ERROR:
+ case ARGP_KEY_SUCCESS:
+ case ARGP_KEY_INIT:
+ break;
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+ return 0;
+}
+
+void *send_thread_func (void *arg)
+{
+ struct filter_msg *msg;
+
+ while (send_thread_running)
+ {
+ msg = dequeue_msg ();
+ if (msg == NULL)
+ {
+// queue_empty_wait ();
+ continue;
+ }
+ msg->forward (msg);
+ msg->destroy (msg);
+ free (msg);
+ }
+ return NULL;
+}
+
+int
+main (int argc, char *argv[])
+{
+ error_t err;
+ mach_port_t bootstrap;
+ struct trivfs_control *fsys;
+ const struct argp argp = { options, parse_opt, 0, doc };
+
+#ifdef DEBUG
+ logfile = fopen ("/root/filter.log", "a+");
+ if (logfile == NULL)
+ error (1, errno, "fopen");
+#endif
+
+ port_bucket = ports_create_bucket ();
+ user_portclass = ports_create_class (clean_proxy_user, 0);
+ device_portclass = ports_create_class (clean_proxy_device, 0);
+ other_portclass = ports_create_class (0, 0);
+ trivfs_cntl_portclasses[0] = ports_create_class (trivfs_clean_cntl, 0);
+ trivfs_protid_portclasses[0] = ports_create_class (trivfs_clean_protid, 0);
+
+ argp_parse (&argp, argc, argv, 0, 0, 0);
+
+ /* Prepare the filter. */
+ if (snd_filter == NULL)
+ {
+ snd_filter = default_snd_filter;
+ snd_filter_length = sizeof (default_snd_filter) / sizeof (short);
+ }
+ if (rcv_filter == NULL)
+ {
+ rcv_filter = default_rcv_filter;
+ rcv_filter_length = sizeof (default_rcv_filter) / sizeof (short);
+ }
+
+ task_get_bootstrap_port (mach_task_self (), &bootstrap);
+ if (bootstrap == MACH_PORT_NULL)
+ error (1, 0, "must be started as a translator");
+
+ err = ports_create_port (other_portclass, port_bucket,
+ sizeof (struct port_info), &notify_pi);
+ if (err)
+ error (1, err, "ports_create_port for notification");
+
+ /* Reply to our parent. */
+ err = trivfs_startup (bootstrap, 0,
+ trivfs_cntl_portclasses[0], port_bucket,
+ trivfs_protid_portclasses[0], port_bucket, &fsys);
+ mach_port_deallocate (mach_task_self (), bootstrap);
+ if (err)
+ error (1, err, "Contacting parent");
+
+ /* Initialize the bpf, and set the filter for outgoing packets.
+ * MACH_PORT_DEAD is used because we don't need a receiving port. */
+ bpf_init ();
+ err = net_set_filter (MACH_PORT_DEAD, 0, (filter_t *) snd_filter,
+ snd_filter_length);
+ if (err)
+ error (1, err, "set the sending filter");
+ /* Set the filter translator's own rule. */
+ err = net_set_filter (MACH_PORT_DEAD, 0, (filter_t *) rcv_filter,
+ rcv_filter_length);
+ if (err)
+ error (1, err, "set the receiving filter");
+
+ cthread_init ();
+ send_thread = cthread_fork (send_thread_func, NULL);
+ /* TODO if the main thread exits,
+ * does the created thread exit if cthread_detach is called */
+ cthread_detach (send_thread);
+
+ /* Launch. */
+ do
+ {
+ ports_manage_port_operations_one_thread (port_bucket,
+ filter_demuxer, 0);
+ } while (trivfs_goaway (fsys, 0));
+ return 0;
+}
+
+int
+deliver_msg (struct net_rcv_msg *msg, queue_head_t *port_list,
+ mach_port_t dest)
+{
+ static int count = 0;
+ mach_msg_return_t err;
+ net_rcv_port_t infp, nextfp;
+
+ msg->msg_hdr.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0);
+ msg->msg_hdr.msgh_local_port = MACH_PORT_NULL;
+ msg->msg_hdr.msgh_kind = MACH_MSGH_KIND_NORMAL;
+
+ /* Deliver the packet to the right pfinet,
+ * actually there should be only one filter in the list. */
+ FILTER_ITERATE (port_list, infp, nextfp, &infp->chain)
+ {
+ net_hash_entry_t entp, *hash_headp;
+ int ret_count;
+
+ entp = (net_hash_entry_t) 0;
+ ret_count = mach_bpf_do_filter (infp,
+ msg->packet + sizeof (struct packet_header),
+ msg->net_rcv_msg_packet_count,
+ msg->header,
+ sizeof (struct ethhdr),
+ &hash_headp, &entp);
+
+ if (ret_count)
+ {
+ msg->msg_hdr.msgh_remote_port = dest;
+ debug ("before delivering the packet to port %d, count: %d\n",
+ dest, ++count);
+ err = mach_msg ((mach_msg_header_t *)msg,
+ MACH_SEND_MSG|MACH_SEND_TIMEOUT,
+ msg->msg_hdr.msgh_size, 0, MACH_PORT_NULL,
+ /*MACH_MSG_TIMEOUT_NONE*/500, MACH_PORT_NULL);
+ if (err != MACH_MSG_SUCCESS)
+ {
+ mach_port_deallocate(mach_task_self (),
+ ((mach_msg_header_t *)msg)->msgh_remote_port);
+ error (0, err, "mach_msg");
+ return -1;
+ }
+ debug ("after delivering the packet\n");
+ }
+ }
+ FILTER_ITERATE_END
+
+ return 0;
+}
diff --git a/eth-filter.multi-thread/filter.c~ b/eth-filter.multi-thread/filter.c~
new file mode 100644
index 00000000..0746f5a4
--- /dev/null
+++ b/eth-filter.multi-thread/filter.c~
@@ -0,0 +1,878 @@
+/*
+ Copyright (C) 2008 Free Software Foundation, Inc.
+ Written by Zheng Da.
+
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ The GNU Hurd is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the GNU Hurd; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * This program is a filter translator which sits on the top of the network
+ * interface.
+ * It provides two filters: for outgoing packets and for incoming packets.
+ * Only one pfinet server are allowed to run on the top of the translator.
+ */
+
+#include <argp.h>
+#include <errno.h>
+#include <error.h>
+#include <stddef.h>
+#include <unistd.h>
+
+#include <hurd.h>
+#include <mach.h>
+#include <cthreads.h>
+#include <device/device.h>
+#include <hurd/trivfs.h>
+#include <hurd/ports.h>
+#include <hurd/ihash.h>
+
+#include "ourdevice_S.h"
+#include "notify_S.h"
+#include "device_reply_U.h"
+#include "bpf_impl.h"
+#include "util.h"
+#include "filter.h"
+#include "msg_queue.h"
+
+#ifdef DEBUG
+
+FILE *logfile;
+
+#endif
+
+static struct hurd_ihash proxy_deliverport_ht
+= HURD_IHASH_INITIALIZER (offsetof (struct proxy, p_deliverport_hashloc));
+
+/* The name of the network interface that the filter translator sits on. */
+static char *device_file;
+const char *argp_program_version = "eth-filter 0.1";
+const char *argp_program_bug_address = "<bug-hurd@gnu.org>";
+static const char doc[] = "Hurd filter translator.";
+static const struct argp_option options[] =
+{
+ {"interface", 'i', "DEVICE", 0,
+ "Network interface to use", 2},
+ {"send-filter", 's', "string", 0,
+ "The filter rule which applies to the outgoing packet", 4},
+ {"receive-filter", 'r', "string", 0,
+ "The filter rule which applies to the ingoing packet", 5},
+ {"send-ip-range", 'S', "IP range", 0,
+ "A range of IP to create the send filter", 6},
+ {"receive-ip-range", 'R', "IP range", 0,
+ "A range of IP to create the receive filter", 7},
+ {0}
+};
+
+/* A filter allows every packet to be sent and be received. */
+static struct bpf_insn default_snd_filter[] =
+{
+ {NETF_OUT|NETF_BPF, 0, 0, 0},
+ {6, 0, 0, 1500}
+};
+static struct bpf_insn default_rcv_filter[] =
+{
+ {NETF_IN|NETF_BPF, 0, 0, 0},
+ {6, 0, 0, 1500}
+};
+static struct bpf_insn *snd_filter = NULL;
+static int snd_filter_length;
+static struct bpf_insn *rcv_filter = NULL;
+static int rcv_filter_length;
+
+static cthread_t send_thread;
+static int send_thread_running = 1;
+
+/* Port bucket we service requests on. */
+struct port_bucket *port_bucket;
+
+struct port_class *user_portclass;
+struct port_class *device_portclass;
+struct port_class *other_portclass;
+
+/* Trivfs hooks. */
+int trivfs_fstype = FSTYPE_MISC;
+int trivfs_fsid = 0;
+int trivfs_support_read = 0;
+int trivfs_support_write = 0;
+int trivfs_support_exec = 0;
+int trivfs_allow_open = 0;
+
+struct port_class *trivfs_protid_portclasses[1];
+struct port_class *trivfs_cntl_portclasses[1];
+int trivfs_protid_nportclasses = 1;
+int trivfs_cntl_nportclasses = 1;
+
+/* For getting the notification of ports from the kernel. */
+struct port_info *notify_pi;
+
+/* Write the data from the client to the device. */
+int
+filter_device_write (struct filter_msg *msg)
+{
+ error_t err = 0;
+ int ret_count = 0;
+ int has_filter = 0;
+ net_hash_entry_t entp, *hash_headp;
+ net_rcv_port_t infp, nextfp;
+ int bytes_written;
+ struct filter_write_msg *write_msg = (struct filter_write_msg *) msg;
+
+ /* The packet can be sent as long as it passes one filter,
+ * even thought there is usually only one filter in the list. */
+ FILTER_ITERATE (&snd_port_list, infp, nextfp, &infp->chain)
+ {
+ has_filter = 1;
+ ret_count = mach_bpf_do_filter (infp,
+ write_msg->data + sizeof (struct ethhdr),
+ write_msg->datalen - sizeof (struct ethhdr),
+ write_msg->data, sizeof (struct ethhdr),
+ &hash_headp, &entp);
+ if (ret_count)
+ break;
+ }
+ FILTER_ITERATE_END
+
+ if (ret_count || !has_filter)
+ err = device_write (msg->proxy->device_port, write_msg->mode,
+ write_msg->recnum, write_msg->data,
+ write_msg->datalen, &bytes_written);
+ ds_device_write_reply (write_msg->reply_port, write_msg->reply_type,
+ err, bytes_written);
+ return 0;
+}
+
+/* Deliver the data from the device to the client. */
+int
+filter_deliver (struct filter_msg *msg)
+{
+ deliver_msg (((struct filter_deliver_msg *)msg)->net_msg,
+ &rcv_port_list, msg->proxy->deliver_port);
+ return 0;
+}
+
+error_t
+create_proxy_user (struct proxy *proxy, mach_port_t *port)
+{
+ error_t err;
+ struct proxy_user *user;
+
+ err = ports_create_port (user_portclass, port_bucket, sizeof (*user), &user);
+ if (err)
+ return err;
+ user->proxy = proxy;
+
+ *port = ports_get_right (user);
+ ports_port_deref (user);
+ return 0;
+}
+
+error_t
+create_proxy_device (struct proxy *proxy, mach_port_t *port)
+{
+ error_t err;
+ struct proxy_device *device;
+
+ err = ports_create_port (device_portclass, port_bucket, sizeof (*device), &device);
+ if (err)
+ return err;
+ device->proxy = proxy;
+ proxy->device = device;
+
+ *port = ports_get_right (device);
+ ports_port_deref (device);
+ return 0;
+}
+
+void
+clean_proxy_user (void *p)
+{
+ struct proxy_user *user = p;
+ struct proxy *proxy = user->proxy;
+
+ if (proxy->p_deliverport_hashloc)
+ hurd_ihash_locp_remove (&proxy_deliverport_ht, proxy->p_deliverport_hashloc);
+
+ if (proxy->deliver_port != MACH_PORT_NULL)
+ mach_port_deallocate (mach_task_self (), proxy->deliver_port);
+ if (proxy->device_port != MACH_PORT_NULL)
+ mach_port_deallocate (mach_task_self (), proxy->device_port);
+
+ if (proxy->device)
+ ports_destroy_right (proxy->device);
+
+ free (proxy);
+}
+
+void
+clean_proxy_device (void *p)
+{
+ struct proxy_device *device = p;
+ if (device->proxy)
+ device->proxy->device = NULL;
+}
+
+static int
+filter_demuxer (mach_msg_header_t *inp,
+ mach_msg_header_t *outp)
+{
+ extern int device_server (mach_msg_header_t *, mach_msg_header_t *);
+ extern int notify_server (mach_msg_header_t *, mach_msg_header_t *);
+ extern int ethernet_demuxer (mach_msg_header_t *, mach_msg_header_t *);
+ return device_server (inp, outp) || notify_server (inp, outp)
+ || ethernet_demuxer (inp, outp) || trivfs_demuxer (inp, outp);
+}
+
+int
+ethernet_demuxer (mach_msg_header_t *inp,
+ mach_msg_header_t *outp)
+{
+ struct net_rcv_msg *msg = (struct net_rcv_msg *) inp;
+ struct proxy_device *device;
+ struct proxy *proxy;
+
+ if (inp->msgh_id != NET_RCV_MSG_ID)
+ return 0;
+
+ device = ports_lookup_port (port_bucket, inp->msgh_local_port,
+ device_portclass);
+ if (device == NULL)
+ return 0;
+
+ proxy = device->proxy;
+ ports_port_deref (device);
+
+ if (proxy && proxy->deliver_port != MACH_PORT_NULL)
+ queue_deliver (msg, proxy);
+// deliver_msg (msg, &rcv_port_list, proxy->deliver_port);
+
+ return 1;
+}
+
+/* Implementation of notify interface */
+kern_return_t
+do_mach_notify_port_deleted (mach_port_t notify,
+ mach_port_t name)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+do_mach_notify_msg_accepted (mach_port_t notify,
+ mach_port_t name)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+do_mach_notify_port_destroyed (mach_port_t notify,
+ mach_port_t port)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+do_mach_notify_no_senders (mach_port_t notify,
+ mach_port_mscount_t mscount)
+{
+ debug ("do_mach_notify_no_senders is called\n");
+ return ports_do_mach_notify_no_senders (notify, mscount);
+}
+
+kern_return_t
+do_mach_notify_send_once (mach_port_t notify)
+{
+ return EOPNOTSUPP;
+}
+
+kern_return_t
+do_mach_notify_dead_name (mach_port_t notify,
+ mach_port_t name)
+{
+ struct proxy *proxy;
+
+ debug ("do_mach_notify_dead_name is called\n");
+ mach_port_deallocate (mach_task_self (), name);
+ proxy = hurd_ihash_find (&proxy_deliverport_ht, name);
+ if (proxy)
+ {
+ proxy->deliver_port = MACH_PORT_NULL;
+ return 0;
+ }
+ return EINVAL;
+}
+
+/* Implementation of device interface */
+kern_return_t
+ds_xxx_device_set_status (device_t device, dev_flavor_t flavor,
+ dev_status_t status, size_t statu_cnt)
+{
+ return D_INVALID_OPERATION;
+}
+
+kern_return_t
+ds_xxx_device_get_status (device_t device, dev_flavor_t flavor,
+ dev_status_t status, size_t *statuscnt)
+{
+ return D_INVALID_OPERATION;
+}
+
+kern_return_t
+ds_xxx_device_set_filter (device_t device, mach_port_t rec,
+ int pri, filter_array_t filt, size_t len)
+{
+ return D_INVALID_OPERATION;
+}
+
+kern_return_t
+ds_device_open (mach_port_t master_port, mach_port_t reply_port,
+ mach_msg_type_name_t reply_portPoly,
+ dev_mode_t mode, dev_name_t name, mach_port_t *device,
+ mach_msg_type_name_t *devicetype)
+{
+ kern_return_t err;
+ mach_port_t master_device;
+ mach_port_t user_port;
+ struct proxy *proxy;
+
+ if (device_file == NULL)
+ return D_NO_SUCH_DEVICE;
+
+ master_device = file_name_lookup (device_file, 0, 0);
+ if (master_device == MACH_PORT_NULL)
+ return errno;
+
+ proxy = (struct proxy *)calloc (1, sizeof (*proxy));
+ if (proxy == NULL)
+ {
+ mach_port_deallocate (mach_task_self (), master_device);
+ return D_NO_MEMORY;
+ }
+
+ err = device_open (master_device, mode, name, &proxy->device_port);
+ mach_port_deallocate (mach_task_self (), master_device);
+ if (err != KERN_SUCCESS)
+ {
+ free (proxy);
+ return err;
+ }
+
+ err = create_proxy_user (proxy, &user_port);
+ if (err)
+ {
+ mach_port_deallocate (mach_task_self (), master_device);
+ free (proxy);
+ return err;
+ }
+
+ *device = user_port;
+ *devicetype = MACH_MSG_TYPE_MAKE_SEND;
+
+ return 0;
+}
+
+kern_return_t
+ds_device_close (device_t device)
+{
+ return 0;
+}
+
+kern_return_t
+ds_device_write (device_t device, mach_port_t reply_port,
+ mach_msg_type_name_t reply_type, dev_mode_t mode,
+ recnum_t recnum, io_buf_ptr_t data, size_t datalen,
+ int *bytes_written)
+{
+ kern_return_t err = 0;
+ struct proxy_user *user;
+ struct proxy *proxy;
+ int ret_count = 0;
+ int has_filter = 0;
+ net_hash_entry_t entp, *hash_headp;
+ net_rcv_port_t infp, nextfp;
+
+ user = ports_lookup_port (port_bucket, device, user_portclass);
+ if (user == NULL)
+ return D_INVALID_OPERATION;
+ proxy = user->proxy;
+
+ /* The packet can be sent as long as it passes one filter,
+ * even thought there is usually only one filter in the list. */
+ FILTER_ITERATE (&snd_port_list, infp, nextfp, &infp->chain)
+ {
+ has_filter = 1;
+ ret_count = mach_bpf_do_filter (infp,
+ data + sizeof (struct ethhdr),
+ datalen - sizeof (struct ethhdr),
+ data, sizeof (struct ethhdr),
+ &hash_headp, &entp);
+ if (ret_count)
+ break;
+ }
+ FILTER_ITERATE_END
+
+ if (ret_count || !has_filter)
+ err = device_write (proxy->device_port, mode, recnum, data,
+ datalen, bytes_written);
+ ports_port_deref (user);
+ return err;
+}
+
+kern_return_t
+ds_device_write_inband (device_t device, mach_port_t reply_port,
+ mach_msg_type_name_t reply_type, dev_mode_t mode,
+ recnum_t recnum, io_buf_ptr_inband_t data,
+ size_t datalen, int *bytes_written)
+{
+ kern_return_t ret;
+ struct proxy_user *user;
+ struct proxy *proxy;
+
+ user = ports_lookup_port (port_bucket, device, user_portclass);
+ if (user == NULL)
+ return D_INVALID_OPERATION;
+ proxy = user->proxy;
+ ports_port_deref (user);
+
+ ret = device_write_inband (proxy->device_port, mode, recnum, data,
+ datalen, bytes_written);
+ return ret;
+}
+
+kern_return_t
+ds_device_read (device_t device, mach_port_t reply_port,
+ mach_msg_type_name_t reply_type, dev_mode_t mode,
+ recnum_t recnum, int bytes_wanted,
+ io_buf_ptr_t *data, size_t *datalen)
+{
+ kern_return_t ret;
+ struct proxy_user *user;
+ struct proxy *proxy;
+
+ user = ports_lookup_port (port_bucket, device, user_portclass);
+ if (user == NULL)
+ return D_INVALID_OPERATION;
+ proxy = user->proxy;
+ ports_port_deref (user);
+
+ ret = device_read (proxy->device_port, mode, recnum,
+ bytes_wanted, data, datalen);
+ return ret;
+}
+
+kern_return_t
+ds_device_read_inband (device_t device, mach_port_t reply_port,
+ mach_msg_type_name_t reply_type, dev_mode_t mode,
+ recnum_t recnum, int bytes_wanted,
+ io_buf_ptr_inband_t data, size_t *datalen)
+{
+ kern_return_t ret;
+ struct proxy_user *user;
+ struct proxy *proxy;
+
+ user = ports_lookup_port (port_bucket, device, user_portclass);
+ if (user == NULL)
+ return D_INVALID_OPERATION;
+ proxy = user->proxy;
+ ports_port_deref (user);
+
+ ret = device_read_inband (proxy->device_port, mode, recnum,
+ bytes_wanted, data, datalen);
+ return ret;
+}
+
+kern_return_t
+ds_device_map (device_t device, vm_prot_t prot, vm_offset_t offset,
+ vm_size_t size, memory_object_t *pager, int unmap)
+{
+ kern_return_t ret;
+ struct proxy_user *user;
+ struct proxy *proxy;
+
+ user = ports_lookup_port (port_bucket, device, user_portclass);
+ if (user == NULL)
+ return D_INVALID_OPERATION;
+ proxy = user->proxy;
+ ports_port_deref (user);
+
+ ret = device_map (proxy->device_port, prot, offset,
+ size, pager, unmap);
+ return ret;
+}
+
+kern_return_t
+ds_device_set_status (device_t device, dev_flavor_t flavor,
+ dev_status_t status, size_t statuslen)
+{
+ kern_return_t ret;
+ struct proxy_user *user;
+ struct proxy *proxy;
+
+ user = ports_lookup_port (port_bucket, device, user_portclass);
+ if (user == NULL)
+ return D_INVALID_OPERATION;
+ proxy = user->proxy;
+ ports_port_deref (user);
+
+ ret = device_set_status (proxy->device_port, flavor,
+ status, statuslen);
+ return ret;
+}
+
+kern_return_t
+ds_device_get_status (device_t device, dev_flavor_t flavor,
+ dev_status_t status, size_t *statuslen)
+{
+ kern_return_t ret;
+ struct proxy_user *user;
+ struct proxy *proxy;
+
+ user = ports_lookup_port (port_bucket, device, user_portclass);
+ if (user == NULL)
+ return D_INVALID_OPERATION;
+ proxy = user->proxy;
+ ports_port_deref (user);
+
+ ret = device_get_status (proxy->device_port, flavor, status, statuslen);
+ return ret;
+}
+
+kern_return_t
+ds_device_set_filter (device_t device, mach_port_t receive_port,
+ int priority, filter_array_t filter, size_t filterlen)
+{
+ mach_port_t tmp;
+ kern_return_t err;
+ mach_port_t device_receive_port;
+ struct proxy_user *user;
+ struct proxy *proxy;
+
+ user = ports_lookup_port (port_bucket, device, user_portclass);
+ if (user == NULL)
+ return D_INVALID_OPERATION;
+ proxy = user->proxy;
+ ports_port_deref (user);
+
+ if (proxy->device == NULL)
+ {
+ error_t err;
+ err = create_proxy_device (proxy, &device_receive_port);
+ if (err)
+ return err;
+ }
+ else
+ device_receive_port = ports_get_right (proxy->device);
+
+ /* Set the filter from pfinet into the interface,
+ * but the packet will be delivered to the translator,
+ * so the translator has the chance to filter some packets. */
+ err = device_set_filter (proxy->device_port,
+ device_receive_port,
+ MACH_MSG_TYPE_MAKE_SEND, priority,
+ filter, filterlen);
+ if (err)
+ return err;
+
+ proxy->deliver_port = receive_port;
+ hurd_ihash_add (&proxy_deliverport_ht, receive_port, proxy);
+
+ err = mach_port_request_notification (mach_task_self (), receive_port,
+ MACH_NOTIFY_DEAD_NAME, 0,
+ ports_get_right (notify_pi),
+ MACH_MSG_TYPE_MAKE_SEND_ONCE, &tmp);
+ if (tmp != MACH_PORT_NULL)
+ mach_port_deallocate (mach_task_self (), tmp);
+
+ return err;
+}
+
+void
+trivfs_modify_stat (struct trivfs_protid *cred, io_statbuf_t *stat)
+{
+}
+
+error_t
+trivfs_goaway (struct trivfs_control *fsys, int flags)
+{
+ int count;
+
+ /* Stop new requests. */
+ ports_inhibit_class_rpcs (trivfs_cntl_portclasses[0]);
+ ports_inhibit_class_rpcs (trivfs_protid_portclasses[0]);
+
+ count = ports_count_class (user_portclass);
+ debug ("the number of ports alive: %d\n", count);
+
+ if (count && !(flags & FSYS_GOAWAY_FORCE))
+ {
+ /* We won't go away, so start things going again... */
+ ports_enable_class (trivfs_protid_portclasses[0]);
+ ports_resume_class_rpcs (trivfs_cntl_portclasses[0]);
+ ports_resume_class_rpcs (trivfs_protid_portclasses[0]);
+ return EBUSY;
+ }
+
+ queue_flush ();
+ send_thread_running = 0;
+// cthread_join (send_thread);
+
+#ifdef DEBUG
+ fclose (logfile);
+#endif
+ debug ("the translator is gone away\n");
+ exit (0);
+}
+
+/* Convert the network address input by the user into
+ * a form that is accepted by libpcap. */
+int
+correct_net_addr (char *orig, char *result, int result_len)
+{
+ char *ptr;
+ int netmask_len;
+ int remain_bits;
+ int remain_bytes;
+ char netmask;
+ char addr[4];
+ char buf[INET_ADDRSTRLEN];
+ int i;
+
+ ptr = strstr (orig, "/");
+ if (ptr == NULL)
+ {
+ strncpy (result, orig, result_len);
+ return 0;
+ }
+
+ *ptr = 0;
+ ptr++;
+ netmask_len = atoi (ptr);
+ if (inet_pton (AF_INET, orig, addr) < 0)
+ {
+ perror ("inet_pton");
+ return -1;
+ }
+ remain_bits = netmask_len % 8;
+ netmask = ~0;
+ netmask >>= 8 - remain_bits;
+ netmask <<= 8 - remain_bits;
+ remain_bytes = netmask_len / 8;
+ addr[remain_bytes] &= netmask;
+ for (i=remain_bytes+1 ; i < 4 ; i++)
+ addr[i] = 0;
+
+ snprintf (result, result_len, "%s/%s",
+ inet_ntop (AF_INET, addr, buf, INET_ADDRSTRLEN), ptr);
+ return 0;
+}
+
+static error_t
+parse_opt (int opt, char *arg, struct argp_state *state)
+{
+ struct bpf_insn *trans_filter_program (char *str, int send,
+ int *filter_len);
+ char buf[1024];
+ char addr[INET_ADDRSTRLEN+4];
+
+ switch (opt)
+ {
+ case 'i':
+ device_file = arg;
+ break;
+ case 's':
+ if (snd_filter)
+ free (snd_filter);
+ snd_filter = trans_filter_program (arg, 1, &snd_filter_length);
+ break;
+ case 'r':
+ if (rcv_filter)
+ free (rcv_filter);
+ rcv_filter = trans_filter_program (arg, 0, &rcv_filter_length);
+ break;
+ case 'S':
+ if (correct_net_addr (arg, addr, INET_ADDRSTRLEN+4) < 0)
+ return 0;
+ snprintf (buf, sizeof (buf), "arp or (ip and src net %s)", addr);
+ if (snd_filter)
+ free (snd_filter);
+ snd_filter = trans_filter_program (buf, 1, &snd_filter_length);
+ break;
+ case 'R':
+ if (correct_net_addr (arg, addr, INET_ADDRSTRLEN+4) < 0)
+ return 0;
+ snprintf (buf, sizeof (buf), "arp or (ip and dst net %s)", addr);
+ if (rcv_filter)
+ free (rcv_filter);
+ rcv_filter = trans_filter_program (buf, 0, &rcv_filter_length);
+ break;
+ case ARGP_KEY_ERROR:
+ case ARGP_KEY_SUCCESS:
+ case ARGP_KEY_INIT:
+ break;
+ default:
+ return ARGP_ERR_UNKNOWN;
+ }
+ return 0;
+}
+
+void *send_thread_func (void *arg)
+{
+ struct filter_msg *msg;
+
+ while (send_thread_running)
+ {
+ msg = dequeue_msg ();
+ if (msg == NULL)
+ {
+ queue_empty_wait ();
+ continue;
+ }
+ msg->forward (msg);
+ msg->destroy (msg);
+ free (msg);
+ }
+ return NULL;
+}
+
+int
+main (int argc, char *argv[])
+{
+ error_t err;
+ mach_port_t bootstrap;
+ struct trivfs_control *fsys;
+ const struct argp argp = { options, parse_opt, 0, doc };
+
+#ifdef DEBUG
+ logfile = fopen ("/root/filter.log", "a+");
+ if (logfile == NULL)
+ error (1, errno, "fopen");
+#endif
+
+ port_bucket = ports_create_bucket ();
+ user_portclass = ports_create_class (clean_proxy_user, 0);
+ device_portclass = ports_create_class (clean_proxy_device, 0);
+ other_portclass = ports_create_class (0, 0);
+ trivfs_cntl_portclasses[0] = ports_create_class (trivfs_clean_cntl, 0);
+ trivfs_protid_portclasses[0] = ports_create_class (trivfs_clean_protid, 0);
+
+ argp_parse (&argp, argc, argv, 0, 0, 0);
+
+ /* Prepare the filter. */
+ if (snd_filter == NULL)
+ {
+ snd_filter = default_snd_filter;
+ snd_filter_length = sizeof (default_snd_filter) / sizeof (short);
+ }
+ if (rcv_filter == NULL)
+ {
+ rcv_filter = default_rcv_filter;
+ rcv_filter_length = sizeof (default_rcv_filter) / sizeof (short);
+ }
+
+ task_get_bootstrap_port (mach_task_self (), &bootstrap);
+ if (bootstrap == MACH_PORT_NULL)
+ error (1, 0, "must be started as a translator");
+
+ err = ports_create_port (other_portclass, port_bucket,
+ sizeof (struct port_info), &notify_pi);
+ if (err)
+ error (1, err, "ports_create_port for notification");
+
+ /* Reply to our parent. */
+ err = trivfs_startup (bootstrap, 0,
+ trivfs_cntl_portclasses[0], port_bucket,
+ trivfs_protid_portclasses[0], port_bucket, &fsys);
+ mach_port_deallocate (mach_task_self (), bootstrap);
+ if (err)
+ error (1, err, "Contacting parent");
+
+ /* Initialize the bpf, and set the filter for outgoing packets.
+ * MACH_PORT_DEAD is used because we don't need a receiving port. */
+ bpf_init ();
+ err = net_set_filter (MACH_PORT_DEAD, 0, (filter_t *) snd_filter,
+ snd_filter_length);
+ if (err)
+ error (1, err, "set the sending filter");
+ /* Set the filter translator's own rule. */
+ err = net_set_filter (MACH_PORT_DEAD, 0, (filter_t *) rcv_filter,
+ rcv_filter_length);
+ if (err)
+ error (1, err, "set the receiving filter");
+
+ cthread_init ();
+ send_thread = cthread_fork (send_thread_func, NULL);
+ /* TODO if the main thread exits,
+ * does the created thread exit if cthread_detach is called */
+ cthread_detach (send_thread);
+
+ /* Launch. */
+ do
+ {
+ ports_manage_port_operations_one_thread (port_bucket,
+ filter_demuxer, 0);
+ } while (trivfs_goaway (fsys, 0));
+ return 0;
+}
+
+int
+deliver_msg (struct net_rcv_msg *msg, queue_head_t *port_list,
+ mach_port_t dest)
+{
+ static int count = 0;
+ mach_msg_return_t err;
+ net_rcv_port_t infp, nextfp;
+
+ msg->msg_hdr.msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND, 0);
+ msg->msg_hdr.msgh_local_port = MACH_PORT_NULL;
+ msg->msg_hdr.msgh_kind = MACH_MSGH_KIND_NORMAL;
+
+ /* Deliver the packet to the right pfinet,
+ * actually there should be only one filter in the list. */
+ FILTER_ITERATE (port_list, infp, nextfp, &infp->chain)
+ {
+ net_hash_entry_t entp, *hash_headp;
+ int ret_count;
+
+ entp = (net_hash_entry_t) 0;
+ ret_count = mach_bpf_do_filter (infp,
+ msg->packet + sizeof (struct packet_header),
+ msg->net_rcv_msg_packet_count,
+ msg->header,
+ sizeof (struct ethhdr),
+ &hash_headp, &entp);
+
+ if (ret_count)
+ {
+ msg->msg_hdr.msgh_remote_port = dest;
+ debug ("before delivering the packet to port %d, count: %d\n",
+ dest, ++count);
+ err = mach_msg ((mach_msg_header_t *)msg,
+ MACH_SEND_MSG|MACH_SEND_TIMEOUT,
+ msg->msg_hdr.msgh_size, 0, MACH_PORT_NULL,
+ /*MACH_MSG_TIMEOUT_NONE*/500, MACH_PORT_NULL);
+ if (err != MACH_MSG_SUCCESS)
+ {
+ mach_port_deallocate(mach_task_self (),
+ ((mach_msg_header_t *)msg)->msgh_remote_port);
+ error (0, err, "mach_msg");
+ return -1;
+ }
+ debug ("after delivering the packet\n");
+ }
+ }
+ FILTER_ITERATE_END
+
+ return 0;
+}
diff --git a/eth-filter.multi-thread/filter.d b/eth-filter.multi-thread/filter.d
new file mode 100644
index 00000000..c62ef276
--- /dev/null
+++ b/eth-filter.multi-thread/filter.d
@@ -0,0 +1,97 @@
+filter.o filter_pic.o filter_p.o filter.d: filter.c /usr/include/argp.h /usr/include/stdio.h \
+ /usr/include/features.h /usr/include/sys/cdefs.h \
+ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
+ /usr/include/gnu/stubs-32.h /usr/include/gnu/stubs-pthread.h \
+ /usr/lib/gcc/i486-gnu/4.2.4/include/stddef.h /usr/include/bits/types.h \
+ /usr/include/bits/typesizes.h /usr/include/libio.h \
+ /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/i486-gnu/4.2.4/include/stdarg.h \
+ /usr/include/bits/stdio-lock.h /usr/include/bits/libc-lock.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/ctype.h /usr/include/endian.h \
+ /usr/include/bits/endian.h /usr/include/xlocale.h /usr/include/getopt.h \
+ /usr/lib/gcc/i486-gnu/4.2.4/include/limits.h \
+ /usr/lib/gcc/i486-gnu/4.2.4/include/syslimits.h /usr/include/limits.h \
+ /usr/include/bits/posix1_lim.h /usr/include/bits/local_lim.h \
+ /usr/include/bits/posix2_lim.h /usr/include/bits/xopen_lim.h \
+ /usr/include/errno.h /usr/include/bits/errno.h /usr/include/error.h \
+ /usr/include/unistd.h /usr/include/bits/posix_opt.h \
+ /usr/include/bits/environments.h /usr/include/bits/confname.h \
+ /usr/include/hurd.h /usr/include/mach.h \
+ /usr/local/include/mach/mach_types.h \
+ /usr/local/include/mach/host_info.h /usr/local/include/mach/machine.h \
+ /usr/local/include/mach/machine/vm_types.h \
+ /usr/local/include/mach/boolean.h \
+ /usr/local/include/mach/machine/boolean.h \
+ /usr/local/include/mach/memory_object.h /usr/local/include/mach/port.h \
+ /usr/local/include/mach/pc_sample.h \
+ /usr/local/include/mach/processor_info.h \
+ /usr/local/include/mach/task_info.h \
+ /usr/local/include/mach/time_value.h \
+ /usr/local/include/mach/task_special_ports.h \
+ /usr/local/include/mach/thread_info.h /usr/local/include/mach/policy.h \
+ /usr/local/include/mach/thread_special_ports.h \
+ /usr/local/include/mach/thread_status.h \
+ /usr/local/include/mach/machine/thread_status.h \
+ /usr/local/include/mach/machine/fp_reg.h \
+ /usr/local/include/mach/vm_attributes.h \
+ /usr/local/include/mach/vm_inherit.h /usr/local/include/mach/vm_prot.h \
+ /usr/local/include/mach/vm_statistics.h \
+ /usr/local/include/mach/std_types.h \
+ /usr/local/include/mach/kern_return.h \
+ /usr/local/include/mach/machine/kern_return.h /usr/include/mach_init.h \
+ /usr/include/mach/mach_traps.h /usr/local/include/mach/message.h \
+ /usr/include/mach/mach_interface.h /usr/include/mach/mach_port.h \
+ /usr/include/mach/mach_host.h /usr/include/mach-shortcuts.h \
+ /usr/local/include/mach/mig_errors.h ../hurd/hurd_types.h \
+ /usr/include/sys/types.h /usr/include/time.h /usr/include/sys/select.h \
+ /usr/include/bits/select.h /usr/include/bits/sigset.h \
+ /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
+ /usr/include/bits/pthreadtypes.h /usr/include/pthread/pthreadtypes.h \
+ /usr/include/bits/pthread.h /usr/include/bits/thread-attr.h \
+ /usr/include/sched.h /usr/include/bits/sched.h \
+ /usr/include/bits/mutex-attr.h /usr/include/bits/mutex.h \
+ /usr/include/bits/spin-lock.h /usr/include/bits/condition-attr.h \
+ /usr/include/bits/condition.h /usr/include/bits/rwlock-attr.h \
+ /usr/include/bits/rwlock.h /usr/include/bits/barrier-attr.h \
+ /usr/include/bits/barrier.h /usr/include/bits/thread-specific.h \
+ /usr/include/bits/once.h /usr/include/hurd/auth.h \
+ /usr/local/include/device/device_types.h \
+ /usr/local/include/device/net_status.h /usr/local/include/device/bpf.h \
+ /usr/include/sys/stat.h /usr/include/bits/stat.h \
+ /usr/include/sys/statfs.h /usr/include/bits/statfs.h \
+ /usr/include/sys/resource.h /usr/include/bits/resource.h \
+ /usr/include/sys/utsname.h /usr/include/bits/utsname.h \
+ /usr/include/hurd/process.h /usr/include/hurd/fs.h \
+ /usr/include/hurd/io.h /usr/include/hurd/port.h \
+ /usr/include/hurd/userlink.h /usr/include/hurd/signal.h \
+ /usr/include/signal.h /usr/include/bits/signum.h \
+ /usr/include/bits/siginfo.h /usr/include/bits/sigaction.h \
+ /usr/include/bits/sigcontext.h /usr/include/bits/sigstack.h \
+ /usr/include/sys/ucontext.h /usr/include/bits/sigthread.h \
+ /usr/include/hurd/msg.h ../include/cthreads.h \
+ ../include/../libthreads/cthreads.h /usr/include/stdlib.h \
+ /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
+ /usr/include/alloca.h /usr/local/include/mach/machine/vm_param.h \
+ /usr/include/machine-sp.h /usr/include/spin-lock.h \
+ /usr/include/lock-intern.h /usr/include/machine-lock.h \
+ /usr/include/setjmp.h /usr/include/bits/setjmp.h \
+ /usr/include/hurd/threadvar.h /usr/include/device/device.h \
+ ../hurd/trivfs.h ../hurd/../libtrivfs/trivfs.h /usr/include/mach/mach.h \
+ ../hurd/ports.h ../hurd/../libports/ports.h ../hurd/ihash.h \
+ ../hurd/../libihash/ihash.h /usr/include/stdint.h \
+ /usr/include/bits/wchar.h /usr/local/include/mach/notify.h \
+ ../hurd/iohelp.h ../hurd/../libiohelp/iohelp.h ../hurd/shared.h \
+ ../include/idvec.h ../include/../libshouldbeinlibc/idvec.h \
+ /usr/include/string.h /usr/include/bits/string.h \
+ /usr/include/bits/string2.h ../hurd/trivfs_fs_S.h \
+ ../hurd/../libtrivfs/trivfs_fs_S.h ../hurd/trivfs_io_S.h \
+ ../hurd/../libtrivfs/trivfs_io_S.h ../hurd/trivfs_fsys_S.h \
+ ../hurd/../libtrivfs/trivfs_fsys_S.h ourdevice_S.h notify_S.h \
+ device_reply_U.h bpf_impl.h queue.h util.h \
+ ../pfinet/linux-src/include/linux/if_ether.h /usr/include/sys/socket.h \
+ /usr/include/sys/uio.h /usr/include/bits/uio.h \
+ /usr/include/bits/socket.h /usr/include/bits/sockaddr.h \
+ /usr/include/arpa/inet.h /usr/include/netinet/in.h \
+ /usr/include/bits/in.h /usr/include/bits/byteswap.h \
+ /usr/include/netinet/ip.h filter.h msg_queue.h
diff --git a/eth-filter.multi-thread/filter.h b/eth-filter.multi-thread/filter.h
new file mode 100644
index 00000000..e1c4c8bf
--- /dev/null
+++ b/eth-filter.multi-thread/filter.h
@@ -0,0 +1,57 @@
+/*
+ Copyright (C) 2008 Free Software Foundation, Inc.
+ Written by Zheng Da.
+
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ The GNU Hurd is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the GNU Hurd; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef FILTER_H
+#define FILTER_H
+
+#include <hurd.h>
+#include <mach.h>
+#include <hurd/ports.h>
+
+#include "bpf_impl.h"
+
+struct filter_msg;
+
+struct proxy_user
+{
+ struct port_info pi;
+ struct proxy *proxy;
+};
+
+struct proxy_device
+{
+ struct port_info pi;
+ struct proxy *proxy;
+};
+
+struct proxy
+{
+ struct proxy_device *device;
+ mach_port_t deliver_port;
+ hurd_ihash_locp_t p_deliverport_hashloc;
+ mach_port_t device_port;
+};
+
+int deliver_msg (struct net_rcv_msg *msg, queue_head_t *port_list,
+ mach_port_t dest);
+int filter_device_write (struct filter_msg *msg);
+int filter_deliver (struct filter_msg *msg);
+
+#endif
diff --git a/eth-filter.multi-thread/filter.h~ b/eth-filter.multi-thread/filter.h~
new file mode 100644
index 00000000..e5ec7e7c
--- /dev/null
+++ b/eth-filter.multi-thread/filter.h~
@@ -0,0 +1,60 @@
+/*
+ Copyright (C) 2008 Free Software Foundation, Inc.
+ Written by Zheng Da.
+
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ The GNU Hurd is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the GNU Hurd; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef FILTER_H
+#define FILTER_H
+
+#include <hurd.h>
+#include <mach.h>
+#include <hurd/ports.h>
+
+#include "bpf_impl.h"
+
+struct filter_msg;
+
+struct proxy_user
+{
+ struct port_info pi;
+ struct proxy *proxy;
+};
+
+struct proxy_device
+{
+ struct port_info pi;
+ struct proxy *proxy;
+};
+
+struct proxy
+{
+ struct proxy_device *device;
+ mach_port_t deliver_port;
+ hurd_ihash_locp_t p_deliverport_hashloc;
+ mach_port_t device_port;
+};
+
+extern struct mutex condition_mutex;
+extern struct condition condition_cond;
+
+int deliver_msg (struct net_rcv_msg *msg, queue_head_t *port_list,
+ mach_port_t dest);
+int filter_device_write (struct filter_msg *msg);
+int filter_deliver (struct filter_msg *msg);
+
+#endif
diff --git a/eth-filter.multi-thread/filter.o b/eth-filter.multi-thread/filter.o
new file mode 100644
index 00000000..de893389
--- /dev/null
+++ b/eth-filter.multi-thread/filter.o
Binary files differ
diff --git a/eth-filter.multi-thread/msg_queue.c b/eth-filter.multi-thread/msg_queue.c
new file mode 100644
index 00000000..c9e62e02
--- /dev/null
+++ b/eth-filter.multi-thread/msg_queue.c
@@ -0,0 +1,224 @@
+/*
+ Copyright (C) 2008 Free Software Foundation, Inc.
+ Written by Zheng Da.
+
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ The GNU Hurd is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the GNU Hurd; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "msg_queue.h"
+#include "filter.h"
+#include "util.h"
+
+static struct filter_msg *queue_head;
+static struct filter_msg *queue_tail;
+static int queue_len = 0;
+
+static struct mutex queuelock = MUTEX_INITIALIZER;
+static struct mutex condition_mutex = MUTEX_INITIALIZER;
+static struct condition condition_cond = CONDITION_INITIALIZER;
+
+void
+queue_msg (struct filter_msg *msg)
+{
+ msg->next = NULL;
+ // TODO what kind of lock do I need?
+ mutex_lock (&queuelock);
+ if (queue_head == NULL)
+ {
+ assert (queue_tail == NULL);
+ assert (queue_len == 0);
+ /* When the queue is empty. */
+ queue_head = msg;
+ queue_tail = msg;
+ }
+ else
+ {
+ queue_tail->next = msg;
+ queue_tail = msg;
+ }
+ queue_len++;
+ debug ("queue a message, queue length: %d.\n", queue_len);
+ mutex_unlock (&queuelock);
+// queue_wakeup ();
+}
+
+struct filter_msg *
+dequeue_msg ()
+{
+ struct filter_msg *msg;
+
+ mutex_lock (&queuelock);
+ if (queue_head == NULL)
+ {
+ assert (queue_tail == NULL);
+ assert (queue_len == 0);
+ msg = NULL;
+ }
+ else
+ {
+ msg = queue_head;
+ queue_head = msg->next;
+ if (queue_head == NULL)
+ queue_tail = NULL;
+ queue_len--;
+ }
+ debug ("dequeue a message, the queue length: %d.\n", queue_len);
+ mutex_unlock (&queuelock);
+
+ return msg;
+}
+
+/* It can be called when the translator exits. */
+void
+queue_flush ()
+{
+ struct filter_msg *msg;
+ struct filter_msg *tmp;
+
+ mutex_lock (&queuelock);
+ msg = queue_head;
+ queue_head = queue_tail = NULL;
+ queue_len = 0;
+ mutex_unlock (&queuelock);
+
+ while (msg)
+ {
+ tmp = msg;
+ msg = msg->next;
+ if (tmp->destroy)
+ tmp->destroy (tmp);
+ free (tmp);
+ }
+}
+
+void
+filter_write_destroy (struct filter_msg *msg)
+{
+ struct filter_write_msg *write_msg = (struct filter_write_msg *) msg;
+
+ free (write_msg->data);
+}
+
+void filter_deliver_destroy (struct filter_msg *msg)
+{
+ struct filter_deliver_msg *deliver_msg = (struct filter_deliver_msg *) msg;
+
+ free (deliver_msg->net_msg);
+}
+
+kern_return_t
+queue_write (char *data, size_t datalen, mach_port_t reply_port,
+ mach_msg_type_name_t reply_type, dev_mode_t mode,
+ recnum_t recnum, struct proxy *proxy)
+{
+ /* Make a copy of the data */
+ char *new_data;
+ struct filter_msg *msg;
+ struct filter_write_msg *write_msg;
+
+ if (queue_len >= MAX_QUEUE)
+ return D_NO_MEMORY;
+
+ new_data = (char *) malloc (datalen);
+ if (new_data == NULL)
+ return D_NO_MEMORY;
+
+ memcpy (new_data, data, datalen);
+
+ write_msg = (struct filter_write_msg *) malloc (sizeof (*write_msg));
+ if (write_msg == NULL)
+ {
+ free (new_data);
+ return D_NO_MEMORY;
+ }
+ msg = (struct filter_msg *) write_msg;
+
+ msg->proxy = proxy;
+ msg->forward = filter_device_write;
+ msg->destroy = filter_write_destroy;
+
+ write_msg->data = new_data;
+ write_msg->datalen = datalen;
+ write_msg->reply_port = reply_port;
+ write_msg->reply_type = reply_type;
+ write_msg->mode = mode;
+ write_msg->recnum = recnum;
+
+ queue_msg (msg);
+ return D_SUCCESS;
+}
+
+int
+queue_deliver (struct net_rcv_msg *msg, struct proxy *proxy)
+{
+ struct net_rcv_msg *msg_copy;
+ struct filter_deliver_msg *deliver_msg;
+
+ if (queue_len >= MAX_QUEUE)
+ return D_NO_MEMORY;
+
+ /* Make a copy of the data */
+ msg_copy = (struct net_rcv_msg *) malloc (sizeof (*msg_copy));
+ if (msg_copy == NULL)
+ return D_NO_MEMORY;
+
+ deliver_msg = (struct filter_deliver_msg *) malloc (sizeof (*deliver_msg));
+ if (deliver_msg == NULL)
+ {
+ free (msg_copy);
+ return D_NO_MEMORY;
+ }
+
+ *msg_copy = *msg;
+
+ deliver_msg->msg.proxy = proxy;
+ deliver_msg->msg.forward = filter_deliver;
+ deliver_msg->msg.destroy = filter_deliver_destroy;
+
+ deliver_msg->net_msg = msg_copy;
+
+ queue_msg ((struct filter_msg *)deliver_msg);
+ return D_SUCCESS;
+}
+
+void
+queue_empty_wait ()
+{
+ mutex_lock (&condition_mutex);
+// debug ("queue length is %d\n", queue_len);
+ while (queue_head == NULL)
+ {
+ debug ("thread waits for a signal.\n");
+ condition_wait (&condition_cond, &condition_mutex);
+ }
+ mutex_unlock (&condition_mutex);
+}
+
+void
+queue_wakeup ()
+{
+ if (queue_head)
+ {
+ debug ("wake up a thread.\n");
+ condition_signal (&condition_cond);
+ }
+}
+
diff --git a/eth-filter.multi-thread/msg_queue.c~ b/eth-filter.multi-thread/msg_queue.c~
new file mode 100644
index 00000000..9e5a6766
--- /dev/null
+++ b/eth-filter.multi-thread/msg_queue.c~
@@ -0,0 +1,224 @@
+/*
+ Copyright (C) 2008 Free Software Foundation, Inc.
+ Written by Zheng Da.
+
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ The GNU Hurd is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the GNU Hurd; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "msg_queue.h"
+#include "filter.h"
+#include "util.h"
+
+static struct filter_msg *queue_head;
+static struct filter_msg *queue_tail;
+static int queue_len = 0;
+
+static struct mutex queuelock = MUTEX_INITIALIZER;
+static struct mutex condition_mutex = MUTEX_INITIALIZER;
+static struct condition condition_cond = CONDITION_INITIALIZER;
+
+void
+queue_msg (struct filter_msg *msg)
+{
+ msg->next = NULL;
+ // TODO what kind of lock do I need?
+ mutex_lock (&queuelock);
+ if (queue_head == NULL)
+ {
+ assert (queue_tail == NULL);
+ assert (queue_len == 0);
+ /* When the queue is empty. */
+ queue_head = msg;
+ queue_tail = msg;
+ }
+ else
+ {
+ queue_tail->next = msg;
+ queue_tail = msg;
+ }
+ queue_len++;
+ debug ("queue a message, queue length: %d.\n", queue_len);
+ mutex_unlock (&queuelock);
+ queue_wakeup ();
+}
+
+struct filter_msg *
+dequeue_msg ()
+{
+ struct filter_msg *msg;
+
+ mutex_lock (&queuelock);
+ if (queue_head == NULL)
+ {
+ assert (queue_tail == NULL);
+ assert (queue_len == 0);
+ msg = NULL;
+ }
+ else
+ {
+ msg = queue_head;
+ queue_head = msg->next;
+ if (queue_head == NULL)
+ queue_tail = NULL;
+ queue_len--;
+ }
+ debug ("dequeue a message, the queue length: %d.\n", queue_len);
+ mutex_unlock (&queuelock);
+
+ return msg;
+}
+
+/* It can be called when the translator exits. */
+void
+queue_flush ()
+{
+ struct filter_msg *msg;
+ struct filter_msg *tmp;
+
+ mutex_lock (&queuelock);
+ msg = queue_head;
+ queue_head = queue_tail = NULL;
+ queue_len = 0;
+ mutex_unlock (&queuelock);
+
+ while (msg)
+ {
+ tmp = msg;
+ msg = msg->next;
+ if (tmp->destroy)
+ tmp->destroy (tmp);
+ free (tmp);
+ }
+}
+
+void
+filter_write_destroy (struct filter_msg *msg)
+{
+ struct filter_write_msg *write_msg = (struct filter_write_msg *) msg;
+
+ free (write_msg->data);
+}
+
+void filter_deliver_destroy (struct filter_msg *msg)
+{
+ struct filter_deliver_msg *deliver_msg = (struct filter_deliver_msg *) msg;
+
+ free (deliver_msg->net_msg);
+}
+
+kern_return_t
+queue_write (char *data, size_t datalen, mach_port_t reply_port,
+ mach_msg_type_name_t reply_type, dev_mode_t mode,
+ recnum_t recnum, struct proxy *proxy)
+{
+ /* Make a copy of the data */
+ char *new_data;
+ struct filter_msg *msg;
+ struct filter_write_msg *write_msg;
+
+ if (queue_len >= MAX_QUEUE)
+ return D_NO_MEMORY;
+
+ new_data = (char *) malloc (datalen);
+ if (new_data == NULL)
+ return D_NO_MEMORY;
+
+ memcpy (new_data, data, datalen);
+
+ write_msg = (struct filter_write_msg *) malloc (sizeof (*write_msg));
+ if (write_msg == NULL)
+ {
+ free (new_data);
+ return D_NO_MEMORY;
+ }
+ msg = (struct filter_msg *) write_msg;
+
+ msg->proxy = proxy;
+ msg->forward = filter_device_write;
+ msg->destroy = filter_write_destroy;
+
+ write_msg->data = new_data;
+ write_msg->datalen = datalen;
+ write_msg->reply_port = reply_port;
+ write_msg->reply_type = reply_type;
+ write_msg->mode = mode;
+ write_msg->recnum = recnum;
+
+ queue_msg (msg);
+ return D_SUCCESS;
+}
+
+int
+queue_deliver (struct net_rcv_msg *msg, struct proxy *proxy)
+{
+ struct net_rcv_msg *msg_copy;
+ struct filter_deliver_msg *deliver_msg;
+
+ if (queue_len >= MAX_QUEUE)
+ return D_NO_MEMORY;
+
+ /* Make a copy of the data */
+ msg_copy = (struct net_rcv_msg *) malloc (sizeof (*msg_copy));
+ if (msg_copy == NULL)
+ return D_NO_MEMORY;
+
+ deliver_msg = (struct filter_deliver_msg *) malloc (sizeof (*deliver_msg));
+ if (deliver_msg == NULL)
+ {
+ free (msg_copy);
+ return D_NO_MEMORY;
+ }
+
+ *msg_copy = *msg;
+
+ deliver_msg->msg.proxy = proxy;
+ deliver_msg->msg.forward = filter_deliver;
+ deliver_msg->msg.destroy = filter_deliver_destroy;
+
+ deliver_msg->net_msg = msg_copy;
+
+ queue_msg ((struct filter_msg *)deliver_msg);
+ return D_SUCCESS;
+}
+
+void
+queue_empty_wait ()
+{
+ mutex_lock (&condition_mutex);
+// debug ("queue length is %d\n", queue_len);
+ while (queue_head == NULL)
+ {
+ debug ("thread waits for a signal.\n");
+ condition_wait (&condition_cond, &condition_mutex);
+ }
+ mutex_unlock (&condition_mutex);
+}
+
+void
+queue_wakeup ()
+{
+ if (queue_head)
+ {
+ debug ("wake up a thread.\n");
+ condition_signal (&condition_cond);
+ }
+}
+
diff --git a/eth-filter.multi-thread/msg_queue.d b/eth-filter.multi-thread/msg_queue.d
new file mode 100644
index 00000000..5da1f176
--- /dev/null
+++ b/eth-filter.multi-thread/msg_queue.d
@@ -0,0 +1,87 @@
+msg_queue.o msg_queue_pic.o msg_queue_p.o msg_queue.d: msg_queue.c /usr/include/stdio.h /usr/include/features.h \
+ /usr/include/sys/cdefs.h /usr/include/bits/wordsize.h \
+ /usr/include/gnu/stubs.h /usr/include/gnu/stubs-32.h \
+ /usr/include/gnu/stubs-pthread.h \
+ /usr/lib/gcc/i486-gnu/4.2.4/include/stddef.h /usr/include/bits/types.h \
+ /usr/include/bits/typesizes.h /usr/include/libio.h \
+ /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/i486-gnu/4.2.4/include/stdarg.h \
+ /usr/include/bits/stdio-lock.h /usr/include/bits/libc-lock.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/stdlib.h \
+ /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
+ /usr/include/endian.h /usr/include/bits/endian.h /usr/include/xlocale.h \
+ /usr/include/sys/types.h /usr/include/time.h /usr/include/sys/select.h \
+ /usr/include/bits/select.h /usr/include/bits/sigset.h \
+ /usr/include/bits/time.h /usr/include/sys/sysmacros.h \
+ /usr/include/bits/pthreadtypes.h /usr/include/pthread/pthreadtypes.h \
+ /usr/include/bits/pthread.h /usr/include/bits/thread-attr.h \
+ /usr/include/sched.h /usr/include/bits/sched.h \
+ /usr/include/bits/mutex-attr.h /usr/include/bits/mutex.h \
+ /usr/include/bits/spin-lock.h /usr/include/bits/condition-attr.h \
+ /usr/include/bits/condition.h /usr/include/bits/rwlock-attr.h \
+ /usr/include/bits/rwlock.h /usr/include/bits/barrier-attr.h \
+ /usr/include/bits/barrier.h /usr/include/bits/thread-specific.h \
+ /usr/include/bits/once.h /usr/include/alloca.h /usr/include/string.h \
+ /usr/include/bits/string.h /usr/include/bits/string2.h \
+ /usr/include/assert.h msg_queue.h /usr/include/hurd.h \
+ /usr/include/mach.h /usr/local/include/mach/mach_types.h \
+ /usr/local/include/mach/host_info.h /usr/local/include/mach/machine.h \
+ /usr/local/include/mach/machine/vm_types.h \
+ /usr/local/include/mach/boolean.h \
+ /usr/local/include/mach/machine/boolean.h \
+ /usr/local/include/mach/memory_object.h /usr/local/include/mach/port.h \
+ /usr/local/include/mach/pc_sample.h \
+ /usr/local/include/mach/processor_info.h \
+ /usr/local/include/mach/task_info.h \
+ /usr/local/include/mach/time_value.h \
+ /usr/local/include/mach/task_special_ports.h \
+ /usr/local/include/mach/thread_info.h /usr/local/include/mach/policy.h \
+ /usr/local/include/mach/thread_special_ports.h \
+ /usr/local/include/mach/thread_status.h \
+ /usr/local/include/mach/machine/thread_status.h \
+ /usr/local/include/mach/machine/fp_reg.h \
+ /usr/local/include/mach/vm_attributes.h \
+ /usr/local/include/mach/vm_inherit.h /usr/local/include/mach/vm_prot.h \
+ /usr/local/include/mach/vm_statistics.h \
+ /usr/local/include/mach/std_types.h \
+ /usr/local/include/mach/kern_return.h \
+ /usr/local/include/mach/machine/kern_return.h /usr/include/mach_init.h \
+ /usr/include/mach/mach_traps.h /usr/local/include/mach/message.h \
+ /usr/include/mach/mach_interface.h /usr/include/mach/mach_port.h \
+ /usr/include/mach/mach_host.h /usr/include/mach-shortcuts.h \
+ /usr/local/include/mach/mig_errors.h ../hurd/hurd_types.h \
+ /usr/include/errno.h /usr/include/bits/errno.h /usr/include/hurd/auth.h \
+ /usr/local/include/device/device_types.h \
+ /usr/local/include/device/net_status.h /usr/local/include/device/bpf.h \
+ /usr/include/sys/stat.h /usr/include/bits/stat.h \
+ /usr/include/sys/statfs.h /usr/include/bits/statfs.h \
+ /usr/include/sys/resource.h /usr/include/bits/resource.h \
+ /usr/include/sys/utsname.h /usr/include/bits/utsname.h \
+ /usr/include/hurd/process.h /usr/include/hurd/fs.h \
+ /usr/include/hurd/io.h /usr/include/hurd/port.h \
+ /usr/include/hurd/userlink.h /usr/include/hurd/signal.h \
+ /usr/include/signal.h /usr/include/bits/signum.h \
+ /usr/include/bits/siginfo.h /usr/include/bits/sigaction.h \
+ /usr/include/bits/sigcontext.h /usr/include/bits/sigstack.h \
+ /usr/include/sys/ucontext.h /usr/include/bits/sigthread.h \
+ /usr/include/hurd/msg.h ../include/cthreads.h \
+ ../include/../libthreads/cthreads.h \
+ /usr/local/include/mach/machine/vm_param.h /usr/include/machine-sp.h \
+ /usr/include/spin-lock.h /usr/include/lock-intern.h \
+ /usr/include/machine-lock.h /usr/include/setjmp.h \
+ /usr/include/bits/setjmp.h /usr/include/hurd/threadvar.h filter.h \
+ ../hurd/ports.h ../hurd/../libports/ports.h ../hurd/ihash.h \
+ ../hurd/../libihash/ihash.h \
+ /usr/lib/gcc/i486-gnu/4.2.4/include/limits.h \
+ /usr/lib/gcc/i486-gnu/4.2.4/include/syslimits.h /usr/include/limits.h \
+ /usr/include/bits/posix1_lim.h /usr/include/bits/local_lim.h \
+ /usr/include/bits/posix2_lim.h /usr/include/bits/xopen_lim.h \
+ /usr/include/stdint.h /usr/include/bits/wchar.h \
+ /usr/local/include/mach/notify.h bpf_impl.h queue.h util.h \
+ ../pfinet/linux-src/include/linux/if_ether.h /usr/include/sys/socket.h \
+ /usr/include/sys/uio.h /usr/include/bits/uio.h \
+ /usr/include/bits/socket.h /usr/include/bits/sockaddr.h \
+ /usr/include/arpa/inet.h /usr/include/netinet/in.h \
+ /usr/include/bits/in.h /usr/include/bits/byteswap.h \
+ /usr/include/netinet/ip.h
diff --git a/eth-filter.multi-thread/msg_queue.h b/eth-filter.multi-thread/msg_queue.h
new file mode 100644
index 00000000..bc7800fb
--- /dev/null
+++ b/eth-filter.multi-thread/msg_queue.h
@@ -0,0 +1,69 @@
+/*
+ Copyright (C) 2008 Free Software Foundation, Inc.
+ Written by Zheng Da.
+
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ The GNU Hurd is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the GNU Hurd; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef MSG_QUEUE_H
+#define MSG_QUEUE_H
+
+#include <hurd.h>
+#include <mach.h>
+
+#define MAX_QUEUE 1000
+
+struct proxy;
+
+struct filter_msg
+{
+ struct proxy *proxy;
+ struct filter_msg *next;
+
+ int (*forward) (struct filter_msg *);
+ void (*destroy) (struct filter_msg *);
+};
+
+struct filter_write_msg
+{
+ struct filter_msg msg;
+
+ char *data;
+ size_t datalen;
+ dev_mode_t mode;
+ recnum_t recnum;
+ mach_port_t reply_port;
+ mach_msg_type_name_t reply_type;
+};
+
+struct filter_deliver_msg
+{
+ struct filter_msg msg;
+
+ struct net_rcv_msg *net_msg;
+};
+
+void queue_msg (struct filter_msg *msg);
+struct filter_msg * dequeue_msg ();
+void queue_flush ();
+kern_return_t queue_write (char *data, size_t datalen, mach_port_t reply_port,
+ mach_msg_type_name_t reply_type, dev_mode_t mode,
+ recnum_t recnum, struct proxy *proxy);
+int queue_deliver (struct net_rcv_msg *msg, struct proxy *proxy);
+void queue_wakeup ();
+void queue_empty_wait ();
+
+#endif
diff --git a/eth-filter.multi-thread/msg_queue.h~ b/eth-filter.multi-thread/msg_queue.h~
new file mode 100644
index 00000000..448b7475
--- /dev/null
+++ b/eth-filter.multi-thread/msg_queue.h~
@@ -0,0 +1,69 @@
+/*
+ Copyright (C) 2008 Free Software Foundation, Inc.
+ Written by Zheng Da.
+
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ The GNU Hurd is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the GNU Hurd; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef MSG_QUEUE_H
+#define MSG_QUEUE_H
+
+#include <hurd.h>
+#include <mach.h>
+
+//#define MAX_QUEUE 1000
+
+struct proxy;
+
+struct filter_msg
+{
+ struct proxy *proxy;
+ struct filter_msg *next;
+
+ int (*forward) (struct filter_msg *);
+ void (*destroy) (struct filter_msg *);
+};
+
+struct filter_write_msg
+{
+ struct filter_msg msg;
+
+ char *data;
+ size_t datalen;
+ dev_mode_t mode;
+ recnum_t recnum;
+ mach_port_t reply_port;
+ mach_msg_type_name_t reply_type;
+};
+
+struct filter_deliver_msg
+{
+ struct filter_msg msg;
+
+ struct net_rcv_msg *net_msg;
+};
+
+void queue_msg (struct filter_msg *msg);
+struct filter_msg * dequeue_msg ();
+void queue_flush ();
+kern_return_t queue_write (char *data, size_t datalen, mach_port_t reply_port,
+ mach_msg_type_name_t reply_type, dev_mode_t mode,
+ recnum_t recnum, struct proxy *proxy);
+int queue_deliver (struct net_rcv_msg *msg, struct proxy *proxy);
+void queue_wakeup ();
+void queue_empty_wait ();
+
+#endif
diff --git a/eth-filter.multi-thread/msg_queue.o b/eth-filter.multi-thread/msg_queue.o
new file mode 100644
index 00000000..db8ea579
--- /dev/null
+++ b/eth-filter.multi-thread/msg_queue.o
Binary files differ
diff --git a/eth-filter.multi-thread/notify.defs b/eth-filter.multi-thread/notify.defs
new file mode 100644
index 00000000..2014be5c
--- /dev/null
+++ b/eth-filter.multi-thread/notify.defs
@@ -0,0 +1 @@
+#include <mach/notify.defs>
diff --git a/eth-filter.multi-thread/notify.sdefs.d b/eth-filter.multi-thread/notify.sdefs.d
new file mode 100644
index 00000000..6f5ca2e4
--- /dev/null
+++ b/eth-filter.multi-thread/notify.sdefs.d
@@ -0,0 +1,3 @@
+notifyServer.c notify_S.h: notify.defs /usr/local/include/mach/notify.defs \
+ /usr/local/include/mach/std_types.defs \
+ /usr/local/include/mach/machine/machine_types.defs
diff --git a/eth-filter.multi-thread/notifyServer.c b/eth-filter.multi-thread/notifyServer.c
new file mode 100644
index 00000000..7965461a
--- /dev/null
+++ b/eth-filter.multi-thread/notifyServer.c
@@ -0,0 +1,353 @@
+/* Module notify */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#define EXPORT_BOOLEAN
+#include <mach/boolean.h>
+#include <mach/kern_return.h>
+#include <mach/message.h>
+#include <mach/mig_errors.h>
+#include <mach/mig_support.h>
+
+#ifndef mig_internal
+#define mig_internal static
+#endif
+
+#ifndef mig_external
+#define mig_external
+#endif
+
+#ifndef TypeCheck
+#define TypeCheck 1
+#endif
+
+#ifndef UseExternRCSId
+#define UseExternRCSId 1
+#endif
+
+#define BAD_TYPECHECK(type, check) ({\
+ union { mach_msg_type_t t; unsigned32_t w; } _t, _c;\
+ _t.t = *(type); _c.t = *(check); _t.w != _c.w; })
+#define msgh_request_port msgh_local_port
+#define MACH_MSGH_BITS_REQUEST(bits) MACH_MSGH_BITS_LOCAL(bits)
+#define msgh_reply_port msgh_remote_port
+#define MACH_MSGH_BITS_REPLY(bits) MACH_MSGH_BITS_REMOTE(bits)
+
+#include <mach/std_types.h>
+
+/* SimpleRoutine mach_notify_port_deleted */
+mig_internal void _Xmach_notify_port_deleted
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
+{
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t nameType;
+ mach_port_t name;
+ } Request;
+
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t RetCodeType;
+ kern_return_t RetCode;
+ } Reply;
+
+ register Request *In0P = (Request *) InHeadP;
+ register Reply *OutP = (Reply *) OutHeadP;
+ mig_external kern_return_t do_mach_notify_port_deleted
+ (mach_port_t notify, mach_port_t name);
+
+ auto const mach_msg_type_t nameCheck = {
+ /* msgt_name = */ 15,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+#if TypeCheck
+ if ((In0P->Head.msgh_size != 32) ||
+ (In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->nameType, &nameCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+ OutP->RetCode = do_mach_notify_port_deleted(In0P->Head.msgh_request_port, In0P->name);
+}
+
+/* SimpleRoutine mach_notify_msg_accepted */
+mig_internal void _Xmach_notify_msg_accepted
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
+{
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t nameType;
+ mach_port_t name;
+ } Request;
+
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t RetCodeType;
+ kern_return_t RetCode;
+ } Reply;
+
+ register Request *In0P = (Request *) InHeadP;
+ register Reply *OutP = (Reply *) OutHeadP;
+ mig_external kern_return_t do_mach_notify_msg_accepted
+ (mach_port_t notify, mach_port_t name);
+
+ auto const mach_msg_type_t nameCheck = {
+ /* msgt_name = */ 15,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+#if TypeCheck
+ if ((In0P->Head.msgh_size != 32) ||
+ (In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->nameType, &nameCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+ OutP->RetCode = do_mach_notify_msg_accepted(In0P->Head.msgh_request_port, In0P->name);
+}
+
+/* SimpleRoutine mach_notify_port_destroyed */
+mig_internal void _Xmach_notify_port_destroyed
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
+{
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t rightsType;
+ mach_port_t rights;
+ } Request;
+
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t RetCodeType;
+ kern_return_t RetCode;
+ } Reply;
+
+ register Request *In0P = (Request *) InHeadP;
+ register Reply *OutP = (Reply *) OutHeadP;
+ mig_external kern_return_t do_mach_notify_port_destroyed
+ (mach_port_t notify, mach_port_t rights);
+
+ auto const mach_msg_type_t rightsCheck = {
+ /* msgt_name = */ 16,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+#if TypeCheck
+ if ((In0P->Head.msgh_size != 32) ||
+ !(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->rightsType, &rightsCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+ OutP->RetCode = do_mach_notify_port_destroyed(In0P->Head.msgh_request_port, In0P->rights);
+}
+
+/* SimpleRoutine mach_notify_no_senders */
+mig_internal void _Xmach_notify_no_senders
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
+{
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t mscountType;
+ mach_port_mscount_t mscount;
+ } Request;
+
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t RetCodeType;
+ kern_return_t RetCode;
+ } Reply;
+
+ register Request *In0P = (Request *) InHeadP;
+ register Reply *OutP = (Reply *) OutHeadP;
+ mig_external kern_return_t do_mach_notify_no_senders
+ (mach_port_t notify, mach_port_mscount_t mscount);
+
+ auto const mach_msg_type_t mscountCheck = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+#if TypeCheck
+ if ((In0P->Head.msgh_size != 32) ||
+ (In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->mscountType, &mscountCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+ OutP->RetCode = do_mach_notify_no_senders(In0P->Head.msgh_request_port, In0P->mscount);
+}
+
+/* SimpleRoutine mach_notify_send_once */
+mig_internal void _Xmach_notify_send_once
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
+{
+ typedef struct {
+ mach_msg_header_t Head;
+ } Request;
+
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t RetCodeType;
+ kern_return_t RetCode;
+ } Reply;
+
+ register Request *In0P = (Request *) InHeadP;
+ register Reply *OutP = (Reply *) OutHeadP;
+ mig_external kern_return_t do_mach_notify_send_once
+ (mach_port_t notify);
+
+#if TypeCheck
+ if ((In0P->Head.msgh_size != 24) ||
+ (In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+ OutP->RetCode = do_mach_notify_send_once(In0P->Head.msgh_request_port);
+}
+
+/* SimpleRoutine mach_notify_dead_name */
+mig_internal void _Xmach_notify_dead_name
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
+{
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t nameType;
+ mach_port_t name;
+ } Request;
+
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t RetCodeType;
+ kern_return_t RetCode;
+ } Reply;
+
+ register Request *In0P = (Request *) InHeadP;
+ register Reply *OutP = (Reply *) OutHeadP;
+ mig_external kern_return_t do_mach_notify_dead_name
+ (mach_port_t notify, mach_port_t name);
+
+ auto const mach_msg_type_t nameCheck = {
+ /* msgt_name = */ 15,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+#if TypeCheck
+ if ((In0P->Head.msgh_size != 32) ||
+ (In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->nameType, &nameCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+ OutP->RetCode = do_mach_notify_dead_name(In0P->Head.msgh_request_port, In0P->name);
+}
+
+static mig_routine_t notify_server_routines[] = {
+ 0,
+ _Xmach_notify_port_deleted,
+ _Xmach_notify_msg_accepted,
+ 0,
+ 0,
+ _Xmach_notify_port_destroyed,
+ _Xmach_notify_no_senders,
+ _Xmach_notify_send_once,
+ _Xmach_notify_dead_name,
+};
+
+mig_external boolean_t notify_server
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
+{
+ register mach_msg_header_t *InP = InHeadP;
+ register mig_reply_header_t *OutP = (mig_reply_header_t *) OutHeadP;
+
+ auto const mach_msg_type_t RetCodeType = {
+ /* msgt_name = */ MACH_MSG_TYPE_INTEGER_32,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ register mig_routine_t routine;
+
+ OutP->Head.msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REPLY(InP->msgh_bits), 0);
+ OutP->Head.msgh_size = sizeof *OutP;
+ OutP->Head.msgh_remote_port = InP->msgh_reply_port;
+ OutP->Head.msgh_local_port = MACH_PORT_NULL;
+ OutP->Head.msgh_seqno = 0;
+ OutP->Head.msgh_id = InP->msgh_id + 100;
+
+ OutP->RetCodeType = RetCodeType;
+
+ if ((InP->msgh_id > 72) || (InP->msgh_id < 64) ||
+ ((routine = notify_server_routines[InP->msgh_id - 64]) == 0)) {
+ OutP->RetCode = MIG_BAD_ID;
+ return FALSE;
+ }
+ (*routine) (InP, &OutP->Head);
+ return TRUE;
+}
+
+mig_external mig_routine_t notify_server_routine
+ (const mach_msg_header_t *InHeadP)
+{
+ register int msgh_id;
+
+ msgh_id = InHeadP->msgh_id - 64;
+
+ if ((msgh_id > 8) || (msgh_id < 0))
+ return 0;
+
+ return notify_server_routines[msgh_id];
+}
+
diff --git a/eth-filter.multi-thread/notifyServer.d b/eth-filter.multi-thread/notifyServer.d
new file mode 100644
index 00000000..9c024c0d
--- /dev/null
+++ b/eth-filter.multi-thread/notifyServer.d
@@ -0,0 +1,28 @@
+notifyServer.o notifyServer_pic.o notifyServer_p.o notifyServer.d: notifyServer.c /usr/local/include/mach/boolean.h \
+ /usr/local/include/mach/machine/boolean.h \
+ /usr/local/include/mach/kern_return.h \
+ /usr/local/include/mach/machine/kern_return.h \
+ /usr/local/include/mach/message.h /usr/local/include/mach/port.h \
+ /usr/local/include/mach/machine/vm_types.h \
+ /usr/local/include/mach/mig_errors.h /usr/include/mach/mig_support.h \
+ /usr/local/include/mach/std_types.h /usr/include/sys/types.h \
+ /usr/include/features.h /usr/include/sys/cdefs.h \
+ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
+ /usr/include/gnu/stubs-32.h /usr/include/gnu/stubs-pthread.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/time.h /usr/lib/gcc/i486-gnu/4.2.4/include/stddef.h \
+ /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/pthread/pthreadtypes.h /usr/include/xlocale.h \
+ /usr/include/bits/pthread.h /usr/include/bits/thread-attr.h \
+ /usr/include/sched.h /usr/include/bits/sched.h \
+ /usr/include/bits/mutex-attr.h /usr/include/bits/mutex.h \
+ /usr/include/bits/spin-lock.h /usr/include/bits/condition-attr.h \
+ /usr/include/bits/condition.h /usr/include/bits/rwlock-attr.h \
+ /usr/include/bits/rwlock.h /usr/include/bits/barrier-attr.h \
+ /usr/include/bits/barrier.h /usr/include/bits/thread-specific.h \
+ /usr/include/bits/once.h /usr/include/string.h \
+ /usr/include/bits/string.h /usr/include/bits/string2.h \
+ /usr/include/stdlib.h
diff --git a/eth-filter.multi-thread/notifyServer.o b/eth-filter.multi-thread/notifyServer.o
new file mode 100644
index 00000000..7de1ecfb
--- /dev/null
+++ b/eth-filter.multi-thread/notifyServer.o
Binary files differ
diff --git a/eth-filter.multi-thread/notify_S.h b/eth-filter.multi-thread/notify_S.h
new file mode 100644
index 00000000..ac3f4659
--- /dev/null
+++ b/eth-filter.multi-thread/notify_S.h
@@ -0,0 +1,124 @@
+#ifndef _notify_server_
+#define _notify_server_
+
+/* Module notify */
+
+#include <mach/kern_return.h>
+#include <mach/port.h>
+#include <mach/message.h>
+
+#include <mach/std_types.h>
+
+/* SimpleRoutine mach_notify_port_deleted */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif
+kern_return_t do_mach_notify_port_deleted
+#if defined(LINTLIBRARY)
+ (notify, name)
+ mach_port_t notify;
+ mach_port_t name;
+{ return do_mach_notify_port_deleted(notify, name); }
+#else
+(
+ mach_port_t notify,
+ mach_port_t name
+);
+#endif
+
+/* SimpleRoutine mach_notify_msg_accepted */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif
+kern_return_t do_mach_notify_msg_accepted
+#if defined(LINTLIBRARY)
+ (notify, name)
+ mach_port_t notify;
+ mach_port_t name;
+{ return do_mach_notify_msg_accepted(notify, name); }
+#else
+(
+ mach_port_t notify,
+ mach_port_t name
+);
+#endif
+
+/* SimpleRoutine mach_notify_port_destroyed */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif
+kern_return_t do_mach_notify_port_destroyed
+#if defined(LINTLIBRARY)
+ (notify, rights)
+ mach_port_t notify;
+ mach_port_t rights;
+{ return do_mach_notify_port_destroyed(notify, rights); }
+#else
+(
+ mach_port_t notify,
+ mach_port_t rights
+);
+#endif
+
+/* SimpleRoutine mach_notify_no_senders */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif
+kern_return_t do_mach_notify_no_senders
+#if defined(LINTLIBRARY)
+ (notify, mscount)
+ mach_port_t notify;
+ mach_port_mscount_t mscount;
+{ return do_mach_notify_no_senders(notify, mscount); }
+#else
+(
+ mach_port_t notify,
+ mach_port_mscount_t mscount
+);
+#endif
+
+/* SimpleRoutine mach_notify_send_once */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif
+kern_return_t do_mach_notify_send_once
+#if defined(LINTLIBRARY)
+ (notify)
+ mach_port_t notify;
+{ return do_mach_notify_send_once(notify); }
+#else
+(
+ mach_port_t notify
+);
+#endif
+
+/* SimpleRoutine mach_notify_dead_name */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif
+kern_return_t do_mach_notify_dead_name
+#if defined(LINTLIBRARY)
+ (notify, name)
+ mach_port_t notify;
+ mach_port_t name;
+{ return do_mach_notify_dead_name(notify, name); }
+#else
+(
+ mach_port_t notify,
+ mach_port_t name
+);
+#endif
+
+#endif /* not defined(_notify_server_) */
diff --git a/eth-filter.multi-thread/ourdevice.defs b/eth-filter.multi-thread/ourdevice.defs
new file mode 100644
index 00000000..1b8ac442
--- /dev/null
+++ b/eth-filter.multi-thread/ourdevice.defs
@@ -0,0 +1,383 @@
+# 1 "device.defs"
+# 1 "<built-in>"
+# 1 "<command-line>"
+# 1 "device.defs"
+# 1 "/usr/local/include/device/device.defs" 1 3
+# 39 "/usr/local/include/device/device.defs" 3
+subsystem
+
+
+
+ device 2800;
+
+# 1 "/usr/local/include/mach/std_types.defs" 1 3
+# 33 "/usr/local/include/mach/std_types.defs" 3
+type char = MACH_MSG_TYPE_CHAR;
+type short = MACH_MSG_TYPE_INTEGER_16;
+type int = MACH_MSG_TYPE_INTEGER_32;
+type int32 = MACH_MSG_TYPE_INTEGER_32;
+type int64 = MACH_MSG_TYPE_INTEGER_64;
+type boolean_t = MACH_MSG_TYPE_BOOLEAN;
+type unsigned = MACH_MSG_TYPE_INTEGER_32;
+type unsigned32 = MACH_MSG_TYPE_INTEGER_32;
+type unsigned64 = MACH_MSG_TYPE_INTEGER_64;
+
+
+# 1 "/usr/local/include/mach/machine/machine_types.defs" 1 3
+# 50 "/usr/local/include/mach/machine/machine_types.defs" 3
+type natural_t = unsigned32;
+# 59 "/usr/local/include/mach/machine/machine_types.defs" 3
+type integer_t = int32;
+# 45 "/usr/local/include/mach/std_types.defs" 2 3
+
+type kern_return_t = int;
+
+type pointer_t = ^array[] of MACH_MSG_TYPE_BYTE
+ ctype: vm_offset_t;
+
+
+type mach_port_t = MACH_MSG_TYPE_COPY_SEND;
+type mach_port_array_t = array[] of mach_port_t;
+
+type mach_port_name_t = MACH_MSG_TYPE_PORT_NAME
+ ctype: mach_port_t;
+type mach_port_name_array_t = array[] of mach_port_name_t
+ ctype: mach_port_array_t;
+
+type mach_port_right_t = natural_t;
+
+type mach_port_type_t = natural_t;
+type mach_port_type_array_t = array[] of mach_port_type_t;
+
+type mach_port_urefs_t = natural_t;
+type mach_port_delta_t = integer_t;
+type mach_port_seqno_t = natural_t;
+type mach_port_mscount_t = unsigned;
+type mach_port_msgcount_t = unsigned;
+type mach_port_rights_t = unsigned;
+type mach_msg_id_t = integer_t;
+type mach_msg_type_name_t = unsigned;
+type mach_msg_type_number_t = natural_t;
+
+type mach_port_move_receive_t = MACH_MSG_TYPE_MOVE_RECEIVE
+ ctype: mach_port_t;
+type mach_port_copy_send_t = MACH_MSG_TYPE_COPY_SEND
+ ctype: mach_port_t;
+type mach_port_make_send_t = MACH_MSG_TYPE_MAKE_SEND
+ ctype: mach_port_t;
+type mach_port_move_send_t = MACH_MSG_TYPE_MOVE_SEND
+ ctype: mach_port_t;
+type mach_port_make_send_once_t = MACH_MSG_TYPE_MAKE_SEND_ONCE
+ ctype: mach_port_t;
+type mach_port_move_send_once_t = MACH_MSG_TYPE_MOVE_SEND_ONCE
+ ctype: mach_port_t;
+
+type mach_port_receive_t = MACH_MSG_TYPE_PORT_RECEIVE
+ ctype: mach_port_t;
+type mach_port_send_t = MACH_MSG_TYPE_PORT_SEND
+ ctype: mach_port_t;
+type mach_port_send_once_t = MACH_MSG_TYPE_PORT_SEND_ONCE
+ ctype: mach_port_t;
+
+type mach_port_poly_t = polymorphic
+ ctype: mach_port_t;
+
+import <mach/std_types.h>;
+# 46 "/usr/local/include/device/device.defs" 2 3
+# 1 "/usr/local/include/mach/mach_types.defs" 1 3
+# 61 "/usr/local/include/mach/mach_types.defs" 3
+type mach_port_status_t = struct[9] of integer_t;
+
+type old_mach_port_status_t = struct[8] of integer_t;
+
+type task_t = mach_port_t
+ ctype: mach_port_t
+
+
+
+
+
+ ;
+# 85 "/usr/local/include/mach/mach_types.defs" 3
+type thread_t = mach_port_t
+ ctype: mach_port_t
+
+
+
+
+
+ ;
+
+type thread_state_t = array[*:1024] of natural_t;
+
+type task_array_t = ^array[] of task_t;
+type thread_array_t = ^array[] of thread_t;
+
+type vm_task_t = mach_port_t
+ ctype: mach_port_t
+
+
+
+
+ ;
+
+type ipc_space_t = mach_port_t
+ ctype: mach_port_t
+
+
+
+
+ ;
+
+type vm_address_t = natural_t;
+type vm_offset_t = natural_t;
+type vm_size_t = natural_t;
+type vm_prot_t = int;
+type vm_inherit_t = int;
+type vm_statistics_data_t = struct[13] of integer_t;
+type vm_machine_attribute_t = int;
+type vm_machine_attribute_val_t = int;
+
+type thread_info_t = array[*:1024] of natural_t;
+type thread_basic_info_data_t = struct[11] of integer_t;
+type thread_sched_info_data_t = struct[7] of integer_t;
+
+type task_info_t = array[*:1024] of natural_t;
+type task_basic_info_data_t = struct[8] of integer_t;
+type task_events_info = struct[7] of natural_t;
+type task_thread_times_info_data_t = struct[4] of integer_t;
+
+
+type memory_object_t = mach_port_t
+ ctype: mach_port_t
+
+
+
+ ;
+
+type memory_object_control_t = mach_port_t
+ ctype: mach_port_t
+
+
+
+ ;
+
+type memory_object_name_t = mach_port_t
+ ctype: mach_port_t
+
+
+
+
+ ;
+
+type memory_object_copy_strategy_t = int;
+type memory_object_return_t = int;
+
+type machine_info_data_t = struct[5] of integer_t;
+type machine_slot_data_t = struct[8] of integer_t;
+
+type host_t = mach_port_t
+ ctype: mach_port_t
+
+
+
+
+ ;
+
+type host_priv_t = mach_port_t
+ ctype: mach_port_t
+
+
+
+ ;
+
+type host_info_t = array[*:1024] of natural_t;
+type host_basic_info_data_t = struct[5] of integer_t;
+type host_sched_info_data_t = struct[2] of integer_t;
+type host_load_info_data_t = struct[6] of integer_t;
+
+
+type processor_t = mach_port_t
+ ctype: mach_port_t
+
+
+
+
+ ;
+
+type processor_array_t = ^array[] of processor_t;
+type processor_info_t = array[*:1024] of natural_t;
+type processor_basic_info_data_t = struct[5] of integer_t;
+
+
+type processor_set_t = mach_port_t
+ ctype: mach_port_t
+
+
+
+
+
+ ;
+
+type processor_set_array_t = ^array[] of processor_set_t;
+
+type processor_set_name_t = mach_port_t
+ ctype: mach_port_t
+
+
+
+
+
+ ;
+
+type processor_set_name_array_t = ^array[] of processor_set_name_t;
+
+type processor_set_info_t = array[*:1024] of natural_t;
+type processor_set_basic_info_data_t = struct[5] of integer_t;
+type processor_set_sched_info_data_t = struct[2] of integer_t;
+
+
+type kernel_version_t = (MACH_MSG_TYPE_STRING, 512*8);
+
+type kernel_boot_info_t = (MACH_MSG_TYPE_STRING, 4096*8);
+
+type time_value_t = struct[2] of integer_t;
+
+type emulation_vector_t = ^array[] of vm_offset_t;
+
+type xxx_emulation_vector_t = array[*:1024] of vm_offset_t
+ ctype: emulation_vector_t;
+
+
+type rpc_signature_info_t = array[*:1024] of int;
+# 250 "/usr/local/include/mach/mach_types.defs" 3
+import <mach/mach_types.h>;
+# 47 "/usr/local/include/device/device.defs" 2 3
+# 1 "/usr/local/include/device/device_types.defs" 1 3
+# 42 "/usr/local/include/device/device_types.defs" 3
+type recnum_t = unsigned32;
+type dev_mode_t = unsigned32;
+type dev_flavor_t = unsigned32;
+type dev_name_t = (MACH_MSG_TYPE_STRING_C, 8*128);
+type dev_status_t = array[*:1024] of int;
+type io_buf_ptr_t = ^array[] of MACH_MSG_TYPE_INTEGER_8;
+type io_buf_ptr_inband_t= array[*:128] of char;
+type filter_t = short;
+type filter_array_t = array[*:128] of filter_t;
+
+type device_t = mach_port_t
+ ctype: mach_port_t
+
+
+
+
+
+ ;
+
+import <device/device_types.h>;
+import <device/net_status.h>;
+# 48 "/usr/local/include/device/device.defs" 2 3
+
+serverprefix ds_;
+
+type reply_port_t = MACH_MSG_TYPE_MAKE_SEND_ONCE | polymorphic
+ ctype: mach_port_t;
+
+routine device_open(
+ master_port : mach_port_t;
+ sreplyport reply_port : reply_port_t;
+ mode : dev_mode_t;
+ name : dev_name_t;
+ out device : mach_port_send_t
+ );
+
+routine device_close(
+ device : device_t
+ );
+
+routine device_write(
+ device : device_t;
+ sreplyport reply_port : reply_port_t;
+ in mode : dev_mode_t;
+ in recnum : recnum_t;
+ in data : io_buf_ptr_t;
+ out bytes_written : int
+ );
+
+routine device_write_inband(
+ device : device_t;
+ sreplyport reply_port : reply_port_t;
+ in mode : dev_mode_t;
+ in recnum : recnum_t;
+ in data : io_buf_ptr_inband_t;
+ out bytes_written : int
+ );
+
+routine device_read(
+ device : device_t;
+ sreplyport reply_port : reply_port_t;
+ in mode : dev_mode_t;
+ in recnum : recnum_t;
+ in bytes_wanted : int;
+ out data : io_buf_ptr_t
+ );
+
+routine device_read_inband(
+ device : device_t;
+ sreplyport reply_port : reply_port_t;
+ in mode : dev_mode_t;
+ in recnum : recnum_t;
+ in bytes_wanted : int;
+ out data : io_buf_ptr_inband_t
+ );
+
+
+routine xxx_device_set_status(
+ device : device_t;
+ in flavor : dev_flavor_t;
+ in status : dev_status_t, IsLong
+ );
+
+
+routine xxx_device_get_status(
+ device : device_t;
+ in flavor : dev_flavor_t;
+ out status : dev_status_t, IsLong
+ );
+
+
+routine xxx_device_set_filter(
+ device : device_t;
+ in receive_port : mach_port_send_t;
+ in priority : int;
+ in filter : filter_array_t, IsLong
+ );
+
+routine device_map(
+ device : device_t;
+ in prot : vm_prot_t;
+ in offset : vm_offset_t;
+ in size : vm_size_t;
+ out pager : memory_object_t;
+ in unmap : int
+ );
+
+routine device_set_status(
+ device : device_t;
+ in flavor : dev_flavor_t;
+ in status : dev_status_t
+ );
+
+routine device_get_status(
+ device : device_t;
+ in flavor : dev_flavor_t;
+ out status : dev_status_t, CountInOut
+ );
+
+routine device_set_filter(
+ device : device_t;
+ in receive_port : mach_port_send_t;
+ in priority : int;
+ in filter : filter_array_t
+ );
+# 1 "device.defs" 2
diff --git a/eth-filter.multi-thread/ourdevice.sdefs.d b/eth-filter.multi-thread/ourdevice.sdefs.d
new file mode 100644
index 00000000..95384eeb
--- /dev/null
+++ b/eth-filter.multi-thread/ourdevice.sdefs.d
@@ -0,0 +1 @@
+ourdeviceServer.c ourdevice_S.h: ourdevice.defs
diff --git a/eth-filter.multi-thread/ourdeviceServer.c b/eth-filter.multi-thread/ourdeviceServer.c
new file mode 100644
index 00000000..3db5fd8d
--- /dev/null
+++ b/eth-filter.multi-thread/ourdeviceServer.c
@@ -0,0 +1,1179 @@
+/* Module device */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE 1
+#endif
+
+#define EXPORT_BOOLEAN
+#include <mach/boolean.h>
+#include <mach/kern_return.h>
+#include <mach/message.h>
+#include <mach/mig_errors.h>
+#include <mach/mig_support.h>
+
+#ifndef mig_internal
+#define mig_internal static
+#endif
+
+#ifndef mig_external
+#define mig_external
+#endif
+
+#ifndef TypeCheck
+#define TypeCheck 1
+#endif
+
+#ifndef UseExternRCSId
+#define UseExternRCSId 1
+#endif
+
+#define BAD_TYPECHECK(type, check) ({\
+ union { mach_msg_type_t t; unsigned32_t w; } _t, _c;\
+ _t.t = *(type); _c.t = *(check); _t.w != _c.w; })
+#define msgh_request_port msgh_local_port
+#define MACH_MSGH_BITS_REQUEST(bits) MACH_MSGH_BITS_LOCAL(bits)
+#define msgh_reply_port msgh_remote_port
+#define MACH_MSGH_BITS_REPLY(bits) MACH_MSGH_BITS_REMOTE(bits)
+
+#include <mach/std_types.h>
+#include <mach/mach_types.h>
+#include <device/device_types.h>
+#include <device/net_status.h>
+
+/* Routine device_open */
+mig_internal void _Xdevice_open
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
+{
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t modeType;
+ dev_mode_t mode;
+ mach_msg_type_long_t nameType;
+ dev_name_t name;
+ } Request;
+
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t RetCodeType;
+ kern_return_t RetCode;
+ mach_msg_type_t deviceType;
+ mach_port_t device;
+ } Reply;
+
+ register Request *In0P = (Request *) InHeadP;
+ register Reply *OutP = (Reply *) OutHeadP;
+ mig_external kern_return_t ds_device_open
+ (mach_port_t master_port, mach_port_t reply_port, mach_msg_type_name_t reply_portPoly, dev_mode_t mode, dev_name_t name, mach_port_t *device, mach_msg_type_name_t *devicePoly);
+
+ boolean_t msgh_simple;
+ auto const mach_msg_type_t modeCheck = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ auto const mach_msg_type_t deviceType = {
+ /* msgt_name = */ -1,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ mach_msg_type_name_t devicePoly;
+
+#if TypeCheck
+ if ((In0P->Head.msgh_size != 172) ||
+ (In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->modeType, &modeCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if ((In0P->nameType.msgtl_header.msgt_inline != TRUE) ||
+ (In0P->nameType.msgtl_header.msgt_longform != TRUE) ||
+ (In0P->nameType.msgtl_name != 12) ||
+ (In0P->nameType.msgtl_number != 1) ||
+ (In0P->nameType.msgtl_size != 1024))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+ OutP->RetCode = ds_device_open(In0P->Head.msgh_request_port, In0P->Head.msgh_reply_port, MACH_MSGH_BITS_REPLY(In0P->Head.msgh_bits), In0P->mode, In0P->name, &OutP->device, &devicePoly);
+ if (OutP->RetCode != KERN_SUCCESS)
+ return;
+
+ msgh_simple = TRUE;
+ OutP->Head.msgh_size = 40;
+
+ OutP->deviceType = deviceType;
+
+ if (MACH_MSG_TYPE_PORT_ANY(devicePoly))
+ msgh_simple = FALSE;
+
+ OutP->deviceType.msgt_name = devicePoly;
+
+ if (!msgh_simple)
+ OutP->Head.msgh_bits |= MACH_MSGH_BITS_COMPLEX;
+}
+
+/* Routine device_close */
+mig_internal void _Xdevice_close
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
+{
+ typedef struct {
+ mach_msg_header_t Head;
+ } Request;
+
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t RetCodeType;
+ kern_return_t RetCode;
+ } Reply;
+
+ register Request *In0P = (Request *) InHeadP;
+ register Reply *OutP = (Reply *) OutHeadP;
+ mig_external kern_return_t ds_device_close
+ (mach_port_t device);
+
+#if TypeCheck
+ if ((In0P->Head.msgh_size != 24) ||
+ (In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+ OutP->RetCode = ds_device_close(In0P->Head.msgh_request_port);
+}
+
+/* Routine device_write */
+mig_internal void _Xdevice_write
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
+{
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t modeType;
+ dev_mode_t mode;
+ mach_msg_type_t recnumType;
+ recnum_t recnum;
+ mach_msg_type_long_t dataType;
+ io_buf_ptr_t data;
+ } Request;
+
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t RetCodeType;
+ kern_return_t RetCode;
+ mach_msg_type_t bytes_writtenType;
+ int bytes_written;
+ } Reply;
+
+ register Request *In0P = (Request *) InHeadP;
+ register Reply *OutP = (Reply *) OutHeadP;
+ mig_external kern_return_t ds_device_write
+ (mach_port_t device, mach_port_t reply_port, mach_msg_type_name_t reply_portPoly, dev_mode_t mode, recnum_t recnum, io_buf_ptr_t data, mach_msg_type_number_t dataCnt, int *bytes_written);
+
+ auto const mach_msg_type_t modeCheck = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ auto const mach_msg_type_t recnumCheck = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ auto const mach_msg_type_t bytes_writtenType = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+#if TypeCheck
+ if ((In0P->Head.msgh_size != 56) ||
+ !(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->modeType, &modeCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->recnumType, &recnumCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if ((In0P->dataType.msgtl_header.msgt_inline != FALSE) ||
+ (In0P->dataType.msgtl_header.msgt_longform != TRUE) ||
+ (In0P->dataType.msgtl_name != 9) ||
+ (In0P->dataType.msgtl_size != 8))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+ OutP->RetCode = ds_device_write(In0P->Head.msgh_request_port, In0P->Head.msgh_reply_port, MACH_MSGH_BITS_REPLY(In0P->Head.msgh_bits), In0P->mode, In0P->recnum, In0P->data, In0P->dataType.msgtl_number, &OutP->bytes_written);
+ if (OutP->RetCode != KERN_SUCCESS)
+ return;
+
+ OutP->Head.msgh_size = 40;
+
+ OutP->bytes_writtenType = bytes_writtenType;
+}
+
+/* Routine device_write_inband */
+mig_internal void _Xdevice_write_inband
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
+{
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t modeType;
+ dev_mode_t mode;
+ mach_msg_type_t recnumType;
+ recnum_t recnum;
+ mach_msg_type_t dataType;
+ char data[128];
+ } Request;
+
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t RetCodeType;
+ kern_return_t RetCode;
+ mach_msg_type_t bytes_writtenType;
+ int bytes_written;
+ } Reply;
+
+ register Request *In0P = (Request *) InHeadP;
+ register Reply *OutP = (Reply *) OutHeadP;
+ mig_external kern_return_t ds_device_write_inband
+ (mach_port_t device, mach_port_t reply_port, mach_msg_type_name_t reply_portPoly, dev_mode_t mode, recnum_t recnum, io_buf_ptr_inband_t data, mach_msg_type_number_t dataCnt, int *bytes_written);
+
+ unsigned int msgh_size;
+
+ auto const mach_msg_type_t modeCheck = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ auto const mach_msg_type_t recnumCheck = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ auto const mach_msg_type_t bytes_writtenType = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+#if TypeCheck
+ msgh_size = In0P->Head.msgh_size;
+ if ((msgh_size < 44) ||
+ (In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->modeType, &modeCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->recnumType, &recnumCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if ((In0P->dataType.msgt_inline != TRUE) ||
+ (In0P->dataType.msgt_longform != FALSE) ||
+ (In0P->dataType.msgt_name != 8) ||
+ (In0P->dataType.msgt_size != 8))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (msgh_size != 44 + ((In0P->dataType.msgt_number + 3) & ~3))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+ OutP->RetCode = ds_device_write_inband(In0P->Head.msgh_request_port, In0P->Head.msgh_reply_port, MACH_MSGH_BITS_REPLY(In0P->Head.msgh_bits), In0P->mode, In0P->recnum, In0P->data, In0P->dataType.msgt_number, &OutP->bytes_written);
+ if (OutP->RetCode != KERN_SUCCESS)
+ return;
+
+ OutP->Head.msgh_size = 40;
+
+ OutP->bytes_writtenType = bytes_writtenType;
+}
+
+/* Routine device_read */
+mig_internal void _Xdevice_read
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
+{
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t modeType;
+ dev_mode_t mode;
+ mach_msg_type_t recnumType;
+ recnum_t recnum;
+ mach_msg_type_t bytes_wantedType;
+ int bytes_wanted;
+ } Request;
+
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t RetCodeType;
+ kern_return_t RetCode;
+ mach_msg_type_long_t dataType;
+ io_buf_ptr_t data;
+ } Reply;
+
+ register Request *In0P = (Request *) InHeadP;
+ register Reply *OutP = (Reply *) OutHeadP;
+ mig_external kern_return_t ds_device_read
+ (mach_port_t device, mach_port_t reply_port, mach_msg_type_name_t reply_portPoly, dev_mode_t mode, recnum_t recnum, int bytes_wanted, io_buf_ptr_t *data, mach_msg_type_number_t *dataCnt);
+
+ auto const mach_msg_type_t modeCheck = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ auto const mach_msg_type_t recnumCheck = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ auto const mach_msg_type_t bytes_wantedCheck = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ auto const mach_msg_type_long_t dataType = {
+ {
+ /* msgt_name = */ 0,
+ /* msgt_size = */ 0,
+ /* msgt_number = */ 0,
+ /* msgt_inline = */ FALSE,
+ /* msgt_longform = */ TRUE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ },
+ /* msgtl_name = */ 9,
+ /* msgtl_size = */ 8,
+ /* msgtl_number = */ 0,
+ };
+
+ mach_msg_type_number_t dataCnt;
+
+#if TypeCheck
+ if ((In0P->Head.msgh_size != 48) ||
+ (In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->modeType, &modeCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->recnumType, &recnumCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->bytes_wantedType, &bytes_wantedCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+ OutP->RetCode = ds_device_read(In0P->Head.msgh_request_port, In0P->Head.msgh_reply_port, MACH_MSGH_BITS_REPLY(In0P->Head.msgh_bits), In0P->mode, In0P->recnum, In0P->bytes_wanted, &OutP->data, &dataCnt);
+ if (OutP->RetCode != KERN_SUCCESS)
+ return;
+
+ OutP->Head.msgh_bits |= MACH_MSGH_BITS_COMPLEX;
+ OutP->Head.msgh_size = 48;
+
+ OutP->dataType = dataType;
+
+ OutP->dataType.msgtl_number = dataCnt;
+}
+
+/* Routine device_read_inband */
+mig_internal void _Xdevice_read_inband
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
+{
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t modeType;
+ dev_mode_t mode;
+ mach_msg_type_t recnumType;
+ recnum_t recnum;
+ mach_msg_type_t bytes_wantedType;
+ int bytes_wanted;
+ } Request;
+
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t RetCodeType;
+ kern_return_t RetCode;
+ mach_msg_type_t dataType;
+ char data[128];
+ } Reply;
+
+ register Request *In0P = (Request *) InHeadP;
+ register Reply *OutP = (Reply *) OutHeadP;
+ mig_external kern_return_t ds_device_read_inband
+ (mach_port_t device, mach_port_t reply_port, mach_msg_type_name_t reply_portPoly, dev_mode_t mode, recnum_t recnum, int bytes_wanted, io_buf_ptr_inband_t data, mach_msg_type_number_t *dataCnt);
+
+ auto const mach_msg_type_t modeCheck = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ auto const mach_msg_type_t recnumCheck = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ auto const mach_msg_type_t bytes_wantedCheck = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ auto const mach_msg_type_t dataType = {
+ /* msgt_name = */ 8,
+ /* msgt_size = */ 8,
+ /* msgt_number = */ 128,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ mach_msg_type_number_t dataCnt;
+
+#if TypeCheck
+ if ((In0P->Head.msgh_size != 48) ||
+ (In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->modeType, &modeCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->recnumType, &recnumCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->bytes_wantedType, &bytes_wantedCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+ dataCnt = 128;
+
+ OutP->RetCode = ds_device_read_inband(In0P->Head.msgh_request_port, In0P->Head.msgh_reply_port, MACH_MSGH_BITS_REPLY(In0P->Head.msgh_bits), In0P->mode, In0P->recnum, In0P->bytes_wanted, OutP->data, &dataCnt);
+ if (OutP->RetCode != KERN_SUCCESS)
+ return;
+
+ OutP->dataType = dataType;
+
+ OutP->dataType.msgt_number = dataCnt;
+ OutP->Head.msgh_size = 36 + ((dataCnt + 3) & ~3);
+}
+
+/* Routine xxx_device_set_status */
+mig_internal void _Xxxx_device_set_status
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
+{
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t flavorType;
+ dev_flavor_t flavor;
+ mach_msg_type_long_t statusType;
+ int status[1024];
+ } Request;
+
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t RetCodeType;
+ kern_return_t RetCode;
+ } Reply;
+
+ register Request *In0P = (Request *) InHeadP;
+ register Reply *OutP = (Reply *) OutHeadP;
+ mig_external kern_return_t ds_xxx_device_set_status
+ (mach_port_t device, dev_flavor_t flavor, dev_status_t status, mach_msg_type_number_t statusCnt);
+
+ unsigned int msgh_size;
+
+ auto const mach_msg_type_t flavorCheck = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+#if TypeCheck
+ msgh_size = In0P->Head.msgh_size;
+ if ((msgh_size < 44) ||
+ (In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->flavorType, &flavorCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if ((In0P->statusType.msgtl_header.msgt_inline != TRUE) ||
+ (In0P->statusType.msgtl_header.msgt_longform != TRUE) ||
+ (In0P->statusType.msgtl_name != 2) ||
+ (In0P->statusType.msgtl_size != 32))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (msgh_size != 44 + (4 * In0P->statusType.msgtl_number))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+ OutP->RetCode = ds_xxx_device_set_status(In0P->Head.msgh_request_port, In0P->flavor, In0P->status, In0P->statusType.msgtl_number);
+}
+
+/* Routine xxx_device_get_status */
+mig_internal void _Xxxx_device_get_status
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
+{
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t flavorType;
+ dev_flavor_t flavor;
+ } Request;
+
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t RetCodeType;
+ kern_return_t RetCode;
+ mach_msg_type_long_t statusType;
+ int status[1024];
+ } Reply;
+
+ register Request *In0P = (Request *) InHeadP;
+ register Reply *OutP = (Reply *) OutHeadP;
+ mig_external kern_return_t ds_xxx_device_get_status
+ (mach_port_t device, dev_flavor_t flavor, dev_status_t status, mach_msg_type_number_t *statusCnt);
+
+ auto const mach_msg_type_t flavorCheck = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ auto const mach_msg_type_long_t statusType = {
+ {
+ /* msgt_name = */ 0,
+ /* msgt_size = */ 0,
+ /* msgt_number = */ 0,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ TRUE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ },
+ /* msgtl_name = */ 2,
+ /* msgtl_size = */ 32,
+ /* msgtl_number = */ 1024,
+ };
+
+ mach_msg_type_number_t statusCnt;
+
+#if TypeCheck
+ if ((In0P->Head.msgh_size != 32) ||
+ (In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->flavorType, &flavorCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+ statusCnt = 1024;
+
+ OutP->RetCode = ds_xxx_device_get_status(In0P->Head.msgh_request_port, In0P->flavor, OutP->status, &statusCnt);
+ if (OutP->RetCode != KERN_SUCCESS)
+ return;
+
+ OutP->statusType = statusType;
+
+ OutP->statusType.msgtl_number = statusCnt;
+ OutP->Head.msgh_size = 44 + (4 * statusCnt);
+}
+
+/* Routine xxx_device_set_filter */
+mig_internal void _Xxxx_device_set_filter
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
+{
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t receive_portType;
+ mach_port_t receive_port;
+ mach_msg_type_t priorityType;
+ int priority;
+ mach_msg_type_long_t filterType;
+ filter_t filter[128];
+ } Request;
+
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t RetCodeType;
+ kern_return_t RetCode;
+ } Reply;
+
+ register Request *In0P = (Request *) InHeadP;
+ register Reply *OutP = (Reply *) OutHeadP;
+ mig_external kern_return_t ds_xxx_device_set_filter
+ (mach_port_t device, mach_port_t receive_port, int priority, filter_array_t filter, mach_msg_type_number_t filterCnt);
+
+ unsigned int msgh_size;
+
+ auto const mach_msg_type_t receive_portCheck = {
+ /* msgt_name = */ 17,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ auto const mach_msg_type_t priorityCheck = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+#if TypeCheck
+ msgh_size = In0P->Head.msgh_size;
+ if ((msgh_size < 52) ||
+ !(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->receive_portType, &receive_portCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->priorityType, &priorityCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if ((In0P->filterType.msgtl_header.msgt_inline != TRUE) ||
+ (In0P->filterType.msgtl_header.msgt_longform != TRUE) ||
+ (In0P->filterType.msgtl_name != 1) ||
+ (In0P->filterType.msgtl_size != 16))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (msgh_size != 52 + ((2 * In0P->filterType.msgtl_number + 3) & ~3))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+ OutP->RetCode = ds_xxx_device_set_filter(In0P->Head.msgh_request_port, In0P->receive_port, In0P->priority, In0P->filter, In0P->filterType.msgtl_number);
+}
+
+/* Routine device_map */
+mig_internal void _Xdevice_map
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
+{
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t protType;
+ vm_prot_t prot;
+ mach_msg_type_t offsetType;
+ vm_offset_t offset;
+ mach_msg_type_t sizeType;
+ vm_size_t size;
+ mach_msg_type_t unmapType;
+ int unmap;
+ } Request;
+
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t RetCodeType;
+ kern_return_t RetCode;
+ mach_msg_type_t pagerType;
+ mach_port_t pager;
+ } Reply;
+
+ register Request *In0P = (Request *) InHeadP;
+ register Reply *OutP = (Reply *) OutHeadP;
+ mig_external kern_return_t ds_device_map
+ (mach_port_t device, vm_prot_t prot, vm_offset_t offset, vm_size_t size, mach_port_t *pager, int unmap);
+
+ auto const mach_msg_type_t protCheck = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ auto const mach_msg_type_t offsetCheck = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ auto const mach_msg_type_t sizeCheck = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ auto const mach_msg_type_t unmapCheck = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ auto const mach_msg_type_t pagerType = {
+ /* msgt_name = */ 19,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+#if TypeCheck
+ if ((In0P->Head.msgh_size != 56) ||
+ (In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->protType, &protCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->offsetType, &offsetCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->sizeType, &sizeCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->unmapType, &unmapCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+ OutP->RetCode = ds_device_map(In0P->Head.msgh_request_port, In0P->prot, In0P->offset, In0P->size, &OutP->pager, In0P->unmap);
+ if (OutP->RetCode != KERN_SUCCESS)
+ return;
+
+ OutP->Head.msgh_bits |= MACH_MSGH_BITS_COMPLEX;
+ OutP->Head.msgh_size = 40;
+
+ OutP->pagerType = pagerType;
+}
+
+/* Routine device_set_status */
+mig_internal void _Xdevice_set_status
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
+{
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t flavorType;
+ dev_flavor_t flavor;
+ mach_msg_type_t statusType;
+ int status[1024];
+ } Request;
+
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t RetCodeType;
+ kern_return_t RetCode;
+ } Reply;
+
+ register Request *In0P = (Request *) InHeadP;
+ register Reply *OutP = (Reply *) OutHeadP;
+ mig_external kern_return_t ds_device_set_status
+ (mach_port_t device, dev_flavor_t flavor, dev_status_t status, mach_msg_type_number_t statusCnt);
+
+ unsigned int msgh_size;
+
+ auto const mach_msg_type_t flavorCheck = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+#if TypeCheck
+ msgh_size = In0P->Head.msgh_size;
+ if ((msgh_size < 36) ||
+ (In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->flavorType, &flavorCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if ((In0P->statusType.msgt_inline != TRUE) ||
+ (In0P->statusType.msgt_longform != FALSE) ||
+ (In0P->statusType.msgt_name != 2) ||
+ (In0P->statusType.msgt_size != 32))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (msgh_size != 36 + (4 * In0P->statusType.msgt_number))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+ OutP->RetCode = ds_device_set_status(In0P->Head.msgh_request_port, In0P->flavor, In0P->status, In0P->statusType.msgt_number);
+}
+
+/* Routine device_get_status */
+mig_internal void _Xdevice_get_status
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
+{
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t flavorType;
+ dev_flavor_t flavor;
+ mach_msg_type_t statusCntType;
+ mach_msg_type_number_t statusCnt;
+ } Request;
+
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t RetCodeType;
+ kern_return_t RetCode;
+ mach_msg_type_t statusType;
+ int status[1024];
+ } Reply;
+
+ register Request *In0P = (Request *) InHeadP;
+ register Reply *OutP = (Reply *) OutHeadP;
+ mig_external kern_return_t ds_device_get_status
+ (mach_port_t device, dev_flavor_t flavor, dev_status_t status, mach_msg_type_number_t *statusCnt);
+
+ auto const mach_msg_type_t flavorCheck = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ auto const mach_msg_type_t statusCntCheck = {
+ /* msgt_name = */ MACH_MSG_TYPE_INTEGER_32,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ auto const mach_msg_type_t statusType = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1024,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ mach_msg_type_number_t statusCnt;
+
+#if TypeCheck
+ if ((In0P->Head.msgh_size != 40) ||
+ (In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->flavorType, &flavorCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->statusCntType, &statusCntCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+ statusCnt = 1024;
+ if (In0P->statusCnt < statusCnt)
+ statusCnt = In0P->statusCnt;
+
+ OutP->RetCode = ds_device_get_status(In0P->Head.msgh_request_port, In0P->flavor, OutP->status, &statusCnt);
+ if (OutP->RetCode != KERN_SUCCESS)
+ return;
+
+ OutP->statusType = statusType;
+
+ OutP->statusType.msgt_number = statusCnt;
+ OutP->Head.msgh_size = 36 + (4 * statusCnt);
+}
+
+/* Routine device_set_filter */
+mig_internal void _Xdevice_set_filter
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
+{
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t receive_portType;
+ mach_port_t receive_port;
+ mach_msg_type_t priorityType;
+ int priority;
+ mach_msg_type_t filterType;
+ filter_t filter[128];
+ } Request;
+
+ typedef struct {
+ mach_msg_header_t Head;
+ mach_msg_type_t RetCodeType;
+ kern_return_t RetCode;
+ } Reply;
+
+ register Request *In0P = (Request *) InHeadP;
+ register Reply *OutP = (Reply *) OutHeadP;
+ mig_external kern_return_t ds_device_set_filter
+ (mach_port_t device, mach_port_t receive_port, int priority, filter_array_t filter, mach_msg_type_number_t filterCnt);
+
+ unsigned int msgh_size;
+
+ auto const mach_msg_type_t receive_portCheck = {
+ /* msgt_name = */ 17,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ auto const mach_msg_type_t priorityCheck = {
+ /* msgt_name = */ 2,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+#if TypeCheck
+ msgh_size = In0P->Head.msgh_size;
+ if ((msgh_size < 44) ||
+ !(In0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->receive_portType, &receive_portCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (BAD_TYPECHECK(&In0P->priorityType, &priorityCheck))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if ((In0P->filterType.msgt_inline != TRUE) ||
+ (In0P->filterType.msgt_longform != FALSE) ||
+ (In0P->filterType.msgt_name != 1) ||
+ (In0P->filterType.msgt_size != 16))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+#if TypeCheck
+ if (msgh_size != 44 + ((2 * In0P->filterType.msgt_number + 3) & ~3))
+ { OutP->RetCode = MIG_BAD_ARGUMENTS; return; }
+#endif /* TypeCheck */
+
+ OutP->RetCode = ds_device_set_filter(In0P->Head.msgh_request_port, In0P->receive_port, In0P->priority, In0P->filter, In0P->filterType.msgt_number);
+}
+
+static mig_routine_t device_server_routines[] = {
+ _Xdevice_open,
+ _Xdevice_close,
+ _Xdevice_write,
+ _Xdevice_write_inband,
+ _Xdevice_read,
+ _Xdevice_read_inband,
+ _Xxxx_device_set_status,
+ _Xxxx_device_get_status,
+ _Xxxx_device_set_filter,
+ _Xdevice_map,
+ _Xdevice_set_status,
+ _Xdevice_get_status,
+ _Xdevice_set_filter,
+};
+
+mig_external boolean_t device_server
+ (mach_msg_header_t *InHeadP, mach_msg_header_t *OutHeadP)
+{
+ register mach_msg_header_t *InP = InHeadP;
+ register mig_reply_header_t *OutP = (mig_reply_header_t *) OutHeadP;
+
+ auto const mach_msg_type_t RetCodeType = {
+ /* msgt_name = */ MACH_MSG_TYPE_INTEGER_32,
+ /* msgt_size = */ 32,
+ /* msgt_number = */ 1,
+ /* msgt_inline = */ TRUE,
+ /* msgt_longform = */ FALSE,
+ /* msgt_deallocate = */ FALSE,
+ /* msgt_unused = */ 0
+ };
+
+ register mig_routine_t routine;
+
+ OutP->Head.msgh_bits = MACH_MSGH_BITS(MACH_MSGH_BITS_REPLY(InP->msgh_bits), 0);
+ OutP->Head.msgh_size = sizeof *OutP;
+ OutP->Head.msgh_remote_port = InP->msgh_reply_port;
+ OutP->Head.msgh_local_port = MACH_PORT_NULL;
+ OutP->Head.msgh_seqno = 0;
+ OutP->Head.msgh_id = InP->msgh_id + 100;
+
+ OutP->RetCodeType = RetCodeType;
+
+ if ((InP->msgh_id > 2812) || (InP->msgh_id < 2800) ||
+ ((routine = device_server_routines[InP->msgh_id - 2800]) == 0)) {
+ OutP->RetCode = MIG_BAD_ID;
+ return FALSE;
+ }
+ (*routine) (InP, &OutP->Head);
+ return TRUE;
+}
+
+mig_external mig_routine_t device_server_routine
+ (const mach_msg_header_t *InHeadP)
+{
+ register int msgh_id;
+
+ msgh_id = InHeadP->msgh_id - 2800;
+
+ if ((msgh_id > 12) || (msgh_id < 0))
+ return 0;
+
+ return device_server_routines[msgh_id];
+}
+
diff --git a/eth-filter.multi-thread/ourdeviceServer.d b/eth-filter.multi-thread/ourdeviceServer.d
new file mode 100644
index 00000000..6a1d17f7
--- /dev/null
+++ b/eth-filter.multi-thread/ourdeviceServer.d
@@ -0,0 +1,45 @@
+ourdeviceServer.o ourdeviceServer_pic.o ourdeviceServer_p.o ourdeviceServer.d: ourdeviceServer.c /usr/local/include/mach/boolean.h \
+ /usr/local/include/mach/machine/boolean.h \
+ /usr/local/include/mach/kern_return.h \
+ /usr/local/include/mach/machine/kern_return.h \
+ /usr/local/include/mach/message.h /usr/local/include/mach/port.h \
+ /usr/local/include/mach/machine/vm_types.h \
+ /usr/local/include/mach/mig_errors.h /usr/include/mach/mig_support.h \
+ /usr/local/include/mach/std_types.h /usr/include/sys/types.h \
+ /usr/include/features.h /usr/include/sys/cdefs.h \
+ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
+ /usr/include/gnu/stubs-32.h /usr/include/gnu/stubs-pthread.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/time.h /usr/lib/gcc/i486-gnu/4.2.4/include/stddef.h \
+ /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/pthread/pthreadtypes.h /usr/include/xlocale.h \
+ /usr/include/bits/pthread.h /usr/include/bits/thread-attr.h \
+ /usr/include/sched.h /usr/include/bits/sched.h \
+ /usr/include/bits/mutex-attr.h /usr/include/bits/mutex.h \
+ /usr/include/bits/spin-lock.h /usr/include/bits/condition-attr.h \
+ /usr/include/bits/condition.h /usr/include/bits/rwlock-attr.h \
+ /usr/include/bits/rwlock.h /usr/include/bits/barrier-attr.h \
+ /usr/include/bits/barrier.h /usr/include/bits/thread-specific.h \
+ /usr/include/bits/once.h /usr/include/string.h \
+ /usr/include/bits/string.h /usr/include/bits/string2.h \
+ /usr/include/stdlib.h /usr/local/include/mach/mach_types.h \
+ /usr/local/include/mach/host_info.h /usr/local/include/mach/machine.h \
+ /usr/local/include/mach/memory_object.h \
+ /usr/local/include/mach/pc_sample.h \
+ /usr/local/include/mach/processor_info.h \
+ /usr/local/include/mach/task_info.h \
+ /usr/local/include/mach/time_value.h \
+ /usr/local/include/mach/task_special_ports.h \
+ /usr/local/include/mach/thread_info.h /usr/local/include/mach/policy.h \
+ /usr/local/include/mach/thread_special_ports.h \
+ /usr/local/include/mach/thread_status.h \
+ /usr/local/include/mach/machine/thread_status.h \
+ /usr/local/include/mach/machine/fp_reg.h \
+ /usr/local/include/mach/vm_attributes.h \
+ /usr/local/include/mach/vm_inherit.h /usr/local/include/mach/vm_prot.h \
+ /usr/local/include/mach/vm_statistics.h \
+ /usr/local/include/device/device_types.h \
+ /usr/local/include/device/net_status.h /usr/local/include/device/bpf.h
diff --git a/eth-filter.multi-thread/ourdeviceServer.o b/eth-filter.multi-thread/ourdeviceServer.o
new file mode 100644
index 00000000..d67d79bd
--- /dev/null
+++ b/eth-filter.multi-thread/ourdeviceServer.o
Binary files differ
diff --git a/eth-filter.multi-thread/ourdevice_S.h b/eth-filter.multi-thread/ourdevice_S.h
new file mode 100644
index 00000000..c899ae3e
--- /dev/null
+++ b/eth-filter.multi-thread/ourdevice_S.h
@@ -0,0 +1,354 @@
+#ifndef _device_server_
+#define _device_server_
+
+/* Module device */
+
+#include <mach/kern_return.h>
+#include <mach/port.h>
+#include <mach/message.h>
+
+#include <mach/std_types.h>
+#include <mach/mach_types.h>
+#include <device/device_types.h>
+#include <device/net_status.h>
+
+/* Routine device_open */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif
+kern_return_t ds_device_open
+#if defined(LINTLIBRARY)
+ (master_port, reply_port, reply_portPoly, mode, name, device, devicePoly)
+ mach_port_t master_port;
+ mach_port_t reply_port;
+ mach_msg_type_name_t reply_portPoly;
+ dev_mode_t mode;
+ dev_name_t name;
+ mach_port_t *device;
+ mach_msg_type_name_t *devicePoly;
+{ return ds_device_open(master_port, reply_port, reply_portPoly, mode, name, device, devicePoly); }
+#else
+(
+ mach_port_t master_port,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_portPoly,
+ dev_mode_t mode,
+ dev_name_t name,
+ mach_port_t *device,
+ mach_msg_type_name_t *devicePoly
+);
+#endif
+
+/* Routine device_close */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif
+kern_return_t ds_device_close
+#if defined(LINTLIBRARY)
+ (device)
+ mach_port_t device;
+{ return ds_device_close(device); }
+#else
+(
+ mach_port_t device
+);
+#endif
+
+/* Routine device_write */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif
+kern_return_t ds_device_write
+#if defined(LINTLIBRARY)
+ (device, reply_port, reply_portPoly, mode, recnum, data, dataCnt, bytes_written)
+ mach_port_t device;
+ mach_port_t reply_port;
+ mach_msg_type_name_t reply_portPoly;
+ dev_mode_t mode;
+ recnum_t recnum;
+ io_buf_ptr_t data;
+ mach_msg_type_number_t dataCnt;
+ int *bytes_written;
+{ return ds_device_write(device, reply_port, reply_portPoly, mode, recnum, data, dataCnt, bytes_written); }
+#else
+(
+ mach_port_t device,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_portPoly,
+ dev_mode_t mode,
+ recnum_t recnum,
+ io_buf_ptr_t data,
+ mach_msg_type_number_t dataCnt,
+ int *bytes_written
+);
+#endif
+
+/* Routine device_write_inband */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif
+kern_return_t ds_device_write_inband
+#if defined(LINTLIBRARY)
+ (device, reply_port, reply_portPoly, mode, recnum, data, dataCnt, bytes_written)
+ mach_port_t device;
+ mach_port_t reply_port;
+ mach_msg_type_name_t reply_portPoly;
+ dev_mode_t mode;
+ recnum_t recnum;
+ io_buf_ptr_inband_t data;
+ mach_msg_type_number_t dataCnt;
+ int *bytes_written;
+{ return ds_device_write_inband(device, reply_port, reply_portPoly, mode, recnum, data, dataCnt, bytes_written); }
+#else
+(
+ mach_port_t device,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_portPoly,
+ dev_mode_t mode,
+ recnum_t recnum,
+ io_buf_ptr_inband_t data,
+ mach_msg_type_number_t dataCnt,
+ int *bytes_written
+);
+#endif
+
+/* Routine device_read */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif
+kern_return_t ds_device_read
+#if defined(LINTLIBRARY)
+ (device, reply_port, reply_portPoly, mode, recnum, bytes_wanted, data, dataCnt)
+ mach_port_t device;
+ mach_port_t reply_port;
+ mach_msg_type_name_t reply_portPoly;
+ dev_mode_t mode;
+ recnum_t recnum;
+ int bytes_wanted;
+ io_buf_ptr_t *data;
+ mach_msg_type_number_t *dataCnt;
+{ return ds_device_read(device, reply_port, reply_portPoly, mode, recnum, bytes_wanted, data, dataCnt); }
+#else
+(
+ mach_port_t device,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_portPoly,
+ dev_mode_t mode,
+ recnum_t recnum,
+ int bytes_wanted,
+ io_buf_ptr_t *data,
+ mach_msg_type_number_t *dataCnt
+);
+#endif
+
+/* Routine device_read_inband */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif
+kern_return_t ds_device_read_inband
+#if defined(LINTLIBRARY)
+ (device, reply_port, reply_portPoly, mode, recnum, bytes_wanted, data, dataCnt)
+ mach_port_t device;
+ mach_port_t reply_port;
+ mach_msg_type_name_t reply_portPoly;
+ dev_mode_t mode;
+ recnum_t recnum;
+ int bytes_wanted;
+ io_buf_ptr_inband_t data;
+ mach_msg_type_number_t *dataCnt;
+{ return ds_device_read_inband(device, reply_port, reply_portPoly, mode, recnum, bytes_wanted, data, dataCnt); }
+#else
+(
+ mach_port_t device,
+ mach_port_t reply_port,
+ mach_msg_type_name_t reply_portPoly,
+ dev_mode_t mode,
+ recnum_t recnum,
+ int bytes_wanted,
+ io_buf_ptr_inband_t data,
+ mach_msg_type_number_t *dataCnt
+);
+#endif
+
+/* Routine xxx_device_set_status */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif
+kern_return_t ds_xxx_device_set_status
+#if defined(LINTLIBRARY)
+ (device, flavor, status, statusCnt)
+ mach_port_t device;
+ dev_flavor_t flavor;
+ dev_status_t status;
+ mach_msg_type_number_t statusCnt;
+{ return ds_xxx_device_set_status(device, flavor, status, statusCnt); }
+#else
+(
+ mach_port_t device,
+ dev_flavor_t flavor,
+ dev_status_t status,
+ mach_msg_type_number_t statusCnt
+);
+#endif
+
+/* Routine xxx_device_get_status */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif
+kern_return_t ds_xxx_device_get_status
+#if defined(LINTLIBRARY)
+ (device, flavor, status, statusCnt)
+ mach_port_t device;
+ dev_flavor_t flavor;
+ dev_status_t status;
+ mach_msg_type_number_t *statusCnt;
+{ return ds_xxx_device_get_status(device, flavor, status, statusCnt); }
+#else
+(
+ mach_port_t device,
+ dev_flavor_t flavor,
+ dev_status_t status,
+ mach_msg_type_number_t *statusCnt
+);
+#endif
+
+/* Routine xxx_device_set_filter */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif
+kern_return_t ds_xxx_device_set_filter
+#if defined(LINTLIBRARY)
+ (device, receive_port, priority, filter, filterCnt)
+ mach_port_t device;
+ mach_port_t receive_port;
+ int priority;
+ filter_array_t filter;
+ mach_msg_type_number_t filterCnt;
+{ return ds_xxx_device_set_filter(device, receive_port, priority, filter, filterCnt); }
+#else
+(
+ mach_port_t device,
+ mach_port_t receive_port,
+ int priority,
+ filter_array_t filter,
+ mach_msg_type_number_t filterCnt
+);
+#endif
+
+/* Routine device_map */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif
+kern_return_t ds_device_map
+#if defined(LINTLIBRARY)
+ (device, prot, offset, size, pager, unmap)
+ mach_port_t device;
+ vm_prot_t prot;
+ vm_offset_t offset;
+ vm_size_t size;
+ mach_port_t *pager;
+ int unmap;
+{ return ds_device_map(device, prot, offset, size, pager, unmap); }
+#else
+(
+ mach_port_t device,
+ vm_prot_t prot,
+ vm_offset_t offset,
+ vm_size_t size,
+ mach_port_t *pager,
+ int unmap
+);
+#endif
+
+/* Routine device_set_status */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif
+kern_return_t ds_device_set_status
+#if defined(LINTLIBRARY)
+ (device, flavor, status, statusCnt)
+ mach_port_t device;
+ dev_flavor_t flavor;
+ dev_status_t status;
+ mach_msg_type_number_t statusCnt;
+{ return ds_device_set_status(device, flavor, status, statusCnt); }
+#else
+(
+ mach_port_t device,
+ dev_flavor_t flavor,
+ dev_status_t status,
+ mach_msg_type_number_t statusCnt
+);
+#endif
+
+/* Routine device_get_status */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif
+kern_return_t ds_device_get_status
+#if defined(LINTLIBRARY)
+ (device, flavor, status, statusCnt)
+ mach_port_t device;
+ dev_flavor_t flavor;
+ dev_status_t status;
+ mach_msg_type_number_t *statusCnt;
+{ return ds_device_get_status(device, flavor, status, statusCnt); }
+#else
+(
+ mach_port_t device,
+ dev_flavor_t flavor,
+ dev_status_t status,
+ mach_msg_type_number_t *statusCnt
+);
+#endif
+
+/* Routine device_set_filter */
+#ifdef mig_external
+mig_external
+#else
+extern
+#endif
+kern_return_t ds_device_set_filter
+#if defined(LINTLIBRARY)
+ (device, receive_port, priority, filter, filterCnt)
+ mach_port_t device;
+ mach_port_t receive_port;
+ int priority;
+ filter_array_t filter;
+ mach_msg_type_number_t filterCnt;
+{ return ds_device_set_filter(device, receive_port, priority, filter, filterCnt); }
+#else
+(
+ mach_port_t device,
+ mach_port_t receive_port,
+ int priority,
+ filter_array_t filter,
+ mach_msg_type_number_t filterCnt
+);
+#endif
+
+#endif /* not defined(_device_server_) */
diff --git a/eth-filter.multi-thread/pcap_filter.c b/eth-filter.multi-thread/pcap_filter.c
new file mode 100644
index 00000000..67ee9bb8
--- /dev/null
+++ b/eth-filter.multi-thread/pcap_filter.c
@@ -0,0 +1,77 @@
+/*
+ Copyright (C) 2008 Free Software Foundation, Inc.
+ Written by Zheng Da.
+
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ The GNU Hurd is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the GNU Hurd; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+/*
+ * This file translates a string into a bpf program.
+ * The BPF structures are defined in both of bpf.h and pcap-bpf.h
+ * Hopefully, there is no conflict between them.
+ * This file uses the BPF definition in pcap-bpf.h.
+ */
+
+#include <pcap.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "util.h"
+
+#define NETF_IN 0x1
+#define NETF_OUT 0x2
+#define NETF_NBPA 10
+#define NETF_BPF (1 << NETF_NBPA)
+
+/* This function translates the bpf program
+ * from the string into the instructions. */
+struct bpf_insn *trans_filter_program (char *str, int send, int *filter_len)
+{
+ struct bpf_program program;
+ struct bpf_insn *insn;
+ pcap_t *pcap;
+ int err;
+
+ debug ("Compiling the bpf program: %s.\n", str);
+ pcap = pcap_open_dead (DLT_EN10MB, 1500);
+ if (pcap == NULL)
+ return NULL;
+ err = pcap_compile (pcap, &program, str, 1, 0);
+ if (err < 0)
+ {
+ debug ("pcap_compile: %s\n", pcap_geterr (pcap));
+ pcap_close (pcap);
+ return NULL;
+ }
+
+ debug ("Finish compiling the bpf program, get %d bpf instructions.\n",
+ program.bf_len);
+ insn = (struct bpf_insn *) malloc ((program.bf_len + 1) * sizeof (*insn));
+ /* Clear the first instruction. */
+ memset (insn, 0, sizeof (*insn));
+ if (send)
+ insn->code = NETF_OUT | NETF_BPF;
+ else
+ insn->code = NETF_IN | NETF_BPF;
+ memcpy (insn + 1, program.bf_insns, program.bf_len * sizeof (*insn));
+ *filter_len = ((program.bf_len + 1) * sizeof (*insn)) / sizeof (short);
+ debug ("%d bpf instructions, the length of filters is %d words\n",
+ program.bf_len, *filter_len);
+ pcap_freecode (&program);
+ pcap_close (pcap);
+
+ return insn;
+}
diff --git a/eth-filter.multi-thread/pcap_filter.d b/eth-filter.multi-thread/pcap_filter.d
new file mode 100644
index 00000000..a6104bf4
--- /dev/null
+++ b/eth-filter.multi-thread/pcap_filter.d
@@ -0,0 +1,38 @@
+pcap_filter.o pcap_filter_pic.o pcap_filter_p.o pcap_filter.d: pcap_filter.c /usr/include/pcap.h /usr/include/sys/types.h \
+ /usr/include/features.h /usr/include/sys/cdefs.h \
+ /usr/include/bits/wordsize.h /usr/include/gnu/stubs.h \
+ /usr/include/gnu/stubs-32.h /usr/include/gnu/stubs-pthread.h \
+ /usr/include/bits/types.h /usr/include/bits/typesizes.h \
+ /usr/include/time.h /usr/lib/gcc/i486-gnu/4.2.4/include/stddef.h \
+ /usr/include/endian.h /usr/include/bits/endian.h \
+ /usr/include/sys/select.h /usr/include/bits/select.h \
+ /usr/include/bits/sigset.h /usr/include/bits/time.h \
+ /usr/include/sys/sysmacros.h /usr/include/bits/pthreadtypes.h \
+ /usr/include/pthread/pthreadtypes.h /usr/include/xlocale.h \
+ /usr/include/bits/pthread.h /usr/include/bits/thread-attr.h \
+ /usr/include/sched.h /usr/include/bits/sched.h \
+ /usr/include/bits/mutex-attr.h /usr/include/bits/mutex.h \
+ /usr/include/bits/spin-lock.h /usr/include/bits/condition-attr.h \
+ /usr/include/bits/condition.h /usr/include/bits/rwlock-attr.h \
+ /usr/include/bits/rwlock.h /usr/include/bits/barrier-attr.h \
+ /usr/include/bits/barrier.h /usr/include/bits/thread-specific.h \
+ /usr/include/bits/once.h /usr/include/sys/time.h \
+ /usr/include/pcap-bpf.h /usr/include/stdio.h /usr/include/libio.h \
+ /usr/include/_G_config.h /usr/include/wchar.h \
+ /usr/lib/gcc/i486-gnu/4.2.4/include/stdarg.h \
+ /usr/include/bits/stdio-lock.h /usr/include/bits/libc-lock.h \
+ /usr/include/bits/stdio_lim.h /usr/include/bits/sys_errlist.h \
+ /usr/include/bits/stdio.h /usr/include/stdlib.h \
+ /usr/include/bits/waitflags.h /usr/include/bits/waitstatus.h \
+ /usr/include/alloca.h /usr/include/string.h /usr/include/bits/string.h \
+ /usr/include/bits/string2.h util.h \
+ ../pfinet/linux-src/include/linux/if_ether.h /usr/include/sys/socket.h \
+ /usr/include/sys/uio.h /usr/include/bits/uio.h \
+ /usr/include/bits/socket.h /usr/lib/gcc/i486-gnu/4.2.4/include/limits.h \
+ /usr/lib/gcc/i486-gnu/4.2.4/include/syslimits.h /usr/include/limits.h \
+ /usr/include/bits/posix1_lim.h /usr/include/bits/local_lim.h \
+ /usr/include/bits/posix2_lim.h /usr/include/bits/xopen_lim.h \
+ /usr/include/bits/sockaddr.h /usr/include/arpa/inet.h \
+ /usr/include/netinet/in.h /usr/include/stdint.h \
+ /usr/include/bits/wchar.h /usr/include/bits/in.h \
+ /usr/include/bits/byteswap.h /usr/include/netinet/ip.h
diff --git a/eth-filter.multi-thread/pcap_filter.o b/eth-filter.multi-thread/pcap_filter.o
new file mode 100644
index 00000000..4eeb89bb
--- /dev/null
+++ b/eth-filter.multi-thread/pcap_filter.o
Binary files differ
diff --git a/eth-filter.multi-thread/queue.c b/eth-filter.multi-thread/queue.c
new file mode 100644
index 00000000..a43a21b0
--- /dev/null
+++ b/eth-filter.multi-thread/queue.c
@@ -0,0 +1,131 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * Routines to implement queue package.
+ */
+
+#include "queue.h"
+
+
+
+/*
+ * Insert element at head of queue.
+ */
+void enqueue_head(
+ register queue_t que,
+ register queue_entry_t elt)
+{
+ elt->next = que->next;
+ elt->prev = que;
+ elt->next->prev = elt;
+ que->next = elt;
+}
+
+/*
+ * Insert element at tail of queue.
+ */
+void enqueue_tail(
+ register queue_t que,
+ register queue_entry_t elt)
+{
+ elt->next = que;
+ elt->prev = que->prev;
+ elt->prev->next = elt;
+ que->prev = elt;
+}
+
+/*
+ * Remove and return element at head of queue.
+ */
+queue_entry_t dequeue_head(
+ register queue_t que)
+{
+ register queue_entry_t elt;
+
+ if (que->next == que)
+ return((queue_entry_t)0);
+
+ elt = que->next;
+ elt->next->prev = que;
+ que->next = elt->next;
+ return(elt);
+}
+
+/*
+ * Remove and return element at tail of queue.
+ */
+queue_entry_t dequeue_tail(
+ register queue_t que)
+{
+ register queue_entry_t elt;
+
+ if (que->prev == que)
+ return((queue_entry_t)0);
+
+ elt = que->prev;
+ elt->prev->next = que;
+ que->prev = elt->prev;
+ return(elt);
+}
+
+/*
+ * Remove arbitrary element from queue.
+ * Does not check whether element is on queue - the world
+ * will go haywire if it isn't.
+ */
+
+/*ARGSUSED*/
+void remqueue(
+ queue_t que,
+ register queue_entry_t elt)
+{
+ elt->next->prev = elt->prev;
+ elt->prev->next = elt->next;
+}
+
+/*
+ * Routines to directly imitate the VAX hardware queue
+ * package.
+ */
+void insque(
+ register struct queue_entry *entry,
+ register struct queue_entry *pred)
+{
+ entry->next = pred->next;
+ entry->prev = pred;
+ (pred->next)->prev = entry;
+ pred->next = entry;
+}
+
+struct queue_entry
+*remque(
+ register struct queue_entry *elt)
+{
+ (elt->next)->prev = elt->prev;
+ (elt->prev)->next = elt->next;
+ return(elt);
+}
+
diff --git a/eth-filter.multi-thread/queue.d b/eth-filter.multi-thread/queue.d
new file mode 100644
index 00000000..b670fa42
--- /dev/null
+++ b/eth-filter.multi-thread/queue.d
@@ -0,0 +1 @@
+queue.o queue_pic.o queue_p.o queue.d: queue.c queue.h
diff --git a/eth-filter.multi-thread/queue.h b/eth-filter.multi-thread/queue.h
new file mode 100644
index 00000000..f067f557
--- /dev/null
+++ b/eth-filter.multi-thread/queue.h
@@ -0,0 +1,329 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon rights
+ * to redistribute these changes.
+ */
+/*
+ * File: queue.h
+ * Author: Avadis Tevanian, Jr.
+ * Date: 1985
+ *
+ * Type definitions for generic queues.
+ *
+ */
+
+#ifndef _KERN_QUEUE_H_
+#define _KERN_QUEUE_H_
+
+/*
+ * Queue of abstract objects. Queue is maintained
+ * within that object.
+ *
+ * Supports fast removal from within the queue.
+ *
+ * How to declare a queue of elements of type "foo_t":
+ * In the "*foo_t" type, you must have a field of
+ * type "queue_chain_t" to hold together this queue.
+ * There may be more than one chain through a
+ * "foo_t", for use by different queues.
+ *
+ * Declare the queue as a "queue_t" type.
+ *
+ * Elements of the queue (of type "foo_t", that is)
+ * are referred to by reference, and cast to type
+ * "queue_entry_t" within this module.
+ */
+
+/*
+ * A generic doubly-linked list (queue).
+ */
+
+struct queue_entry {
+ struct queue_entry *next; /* next element */
+ struct queue_entry *prev; /* previous element */
+};
+
+typedef struct queue_entry *queue_t;
+typedef struct queue_entry queue_head_t;
+typedef struct queue_entry queue_chain_t;
+typedef struct queue_entry *queue_entry_t;
+
+/*
+ * enqueue puts "elt" on the "queue".
+ * dequeue returns the first element in the "queue".
+ * remqueue removes the specified "elt" from the specified "queue".
+ */
+
+#define enqueue(queue,elt) enqueue_tail(queue, elt)
+#define dequeue(queue) dequeue_head(queue)
+
+void enqueue_head(queue_t, queue_entry_t);
+void enqueue_tail(queue_t, queue_entry_t);
+queue_entry_t dequeue_head(queue_t);
+queue_entry_t dequeue_tail(queue_t);
+void remqueue(queue_t, queue_entry_t);
+
+/*
+ * Macro: queue_init
+ * Function:
+ * Initialize the given queue.
+ * Header:
+ * void queue_init(q)
+ * queue_t q; *MODIFIED*
+ */
+#define queue_init(q) ((q)->next = (q)->prev = q)
+
+/*
+ * Macro: queue_first
+ * Function:
+ * Returns the first entry in the queue,
+ * Header:
+ * queue_entry_t queue_first(q)
+ * queue_t q; *IN*
+ */
+#define queue_first(q) ((q)->next)
+
+/*
+ * Macro: queue_next
+ * Function:
+ * Returns the entry after an item in the queue.
+ * Header:
+ * queue_entry_t queue_next(qc)
+ * queue_t qc;
+ */
+#define queue_next(qc) ((qc)->next)
+
+/*
+ * Macro: queue_last
+ * Function:
+ * Returns the last entry in the queue.
+ * Header:
+ * queue_entry_t queue_last(q)
+ * queue_t q; *IN*
+ */
+#define queue_last(q) ((q)->prev)
+
+/*
+ * Macro: queue_prev
+ * Function:
+ * Returns the entry before an item in the queue.
+ * Header:
+ * queue_entry_t queue_prev(qc)
+ * queue_t qc;
+ */
+#define queue_prev(qc) ((qc)->prev)
+
+/*
+ * Macro: queue_end
+ * Function:
+ * Tests whether a new entry is really the end of
+ * the queue.
+ * Header:
+ * boolean_t queue_end(q, qe)
+ * queue_t q;
+ * queue_entry_t qe;
+ */
+#define queue_end(q, qe) ((q) == (qe))
+
+/*
+ * Macro: queue_empty
+ * Function:
+ * Tests whether a queue is empty.
+ * Header:
+ * boolean_t queue_empty(q)
+ * queue_t q;
+ */
+#define queue_empty(q) queue_end((q), queue_first(q))
+
+
+/*----------------------------------------------------------------*/
+/*
+ * Macros that operate on generic structures. The queue
+ * chain may be at any location within the structure, and there
+ * may be more than one chain.
+ */
+
+/*
+ * Macro: queue_enter
+ * Function:
+ * Insert a new element at the tail of the queue.
+ * Header:
+ * void queue_enter(q, elt, type, field)
+ * queue_t q;
+ * <type> elt;
+ * <type> is what's in our queue
+ * <field> is the chain field in (*<type>)
+ */
+#define queue_enter(head, elt, type, field) \
+{ \
+ register queue_entry_t prev; \
+ \
+ prev = (head)->prev; \
+ if ((head) == prev) { \
+ (head)->next = (queue_entry_t) (elt); \
+ } \
+ else { \
+ ((type)prev)->field.next = (queue_entry_t)(elt);\
+ } \
+ (elt)->field.prev = prev; \
+ (elt)->field.next = head; \
+ (head)->prev = (queue_entry_t) elt; \
+}
+
+/*
+ * Macro: queue_enter_first
+ * Function:
+ * Insert a new element at the head of the queue.
+ * Header:
+ * void queue_enter_first(q, elt, type, field)
+ * queue_t q;
+ * <type> elt;
+ * <type> is what's in our queue
+ * <field> is the chain field in (*<type>)
+ */
+#define queue_enter_first(head, elt, type, field) \
+{ \
+ register queue_entry_t next; \
+ \
+ next = (head)->next; \
+ if ((head) == next) { \
+ (head)->prev = (queue_entry_t) (elt); \
+ } \
+ else { \
+ ((type)next)->field.prev = (queue_entry_t)(elt);\
+ } \
+ (elt)->field.next = next; \
+ (elt)->field.prev = head; \
+ (head)->next = (queue_entry_t) elt; \
+}
+
+/*
+ * Macro: queue_field [internal use only]
+ * Function:
+ * Find the queue_chain_t (or queue_t) for the
+ * given element (thing) in the given queue (head)
+ */
+#define queue_field(head, thing, type, field) \
+ (((head) == (thing)) ? (head) : &((type)(thing))->field)
+
+/*
+ * Macro: queue_remove
+ * Function:
+ * Remove an arbitrary item from the queue.
+ * Header:
+ * void queue_remove(q, qe, type, field)
+ * arguments as in queue_enter
+ */
+#define queue_remove(head, elt, type, field) \
+{ \
+ register queue_entry_t next, prev; \
+ \
+ next = (elt)->field.next; \
+ prev = (elt)->field.prev; \
+ \
+ if ((head) == next) \
+ (head)->prev = prev; \
+ else \
+ ((type)next)->field.prev = prev; \
+ \
+ if ((head) == prev) \
+ (head)->next = next; \
+ else \
+ ((type)prev)->field.next = next; \
+}
+
+/*
+ * Macro: queue_remove_first
+ * Function:
+ * Remove and return the entry at the head of
+ * the queue.
+ * Header:
+ * queue_remove_first(head, entry, type, field)
+ * entry is returned by reference
+ */
+#define queue_remove_first(head, entry, type, field) \
+{ \
+ register queue_entry_t next; \
+ \
+ (entry) = (type) ((head)->next); \
+ next = (entry)->field.next; \
+ \
+ if ((head) == next) \
+ (head)->prev = (head); \
+ else \
+ ((type)(next))->field.prev = (head); \
+ (head)->next = next; \
+}
+
+/*
+ * Macro: queue_remove_last
+ * Function:
+ * Remove and return the entry at the tail of
+ * the queue.
+ * Header:
+ * queue_remove_last(head, entry, type, field)
+ * entry is returned by reference
+ */
+#define queue_remove_last(head, entry, type, field) \
+{ \
+ register queue_entry_t prev; \
+ \
+ (entry) = (type) ((head)->prev); \
+ prev = (entry)->field.prev; \
+ \
+ if ((head) == prev) \
+ (head)->next = (head); \
+ else \
+ ((type)(prev))->field.next = (head); \
+ (head)->prev = prev; \
+}
+
+/*
+ * Macro: queue_assign
+ */
+#define queue_assign(to, from, type, field) \
+{ \
+ ((type)((from)->prev))->field.next = (to); \
+ ((type)((from)->next))->field.prev = (to); \
+ *to = *from; \
+}
+
+/*
+ * Macro: queue_iterate
+ * Function:
+ * iterate over each item in the queue.
+ * Generates a 'for' loop, setting elt to
+ * each item in turn (by reference).
+ * Header:
+ * queue_iterate(q, elt, type, field)
+ * queue_t q;
+ * <type> elt;
+ * <type> is what's in our queue
+ * <field> is the chain field in (*<type>)
+ */
+#define queue_iterate(head, elt, type, field) \
+ for ((elt) = (type) queue_first(head); \
+ !queue_end((head), (queue_entry_t)(elt)); \
+ (elt) = (type) queue_next(&(elt)->field))
+
+#endif /* _KERN_QUEUE_H_ */
diff --git a/eth-filter.multi-thread/queue.o b/eth-filter.multi-thread/queue.o
new file mode 100644
index 00000000..90878697
--- /dev/null
+++ b/eth-filter.multi-thread/queue.o
Binary files differ
diff --git a/eth-filter.multi-thread/tmp.patch b/eth-filter.multi-thread/tmp.patch
new file mode 100644
index 00000000..24dd25d7
--- /dev/null
+++ b/eth-filter.multi-thread/tmp.patch
@@ -0,0 +1,207 @@
+? .Makefile.swp
+? .filter.c.swp
+? .filter.h.swp
+? .msg_queue.c.swp
+? .msg_queue.h.swp
+? bpf_impl.d
+? device.defs
+? device_reply.defs
+? filter.d
+? filter.h
+? msg_queue.c
+? msg_queue.h
+? notify.defs
+? notify.sdefs.d
+? notifyServer.c
+? notifyServer.d
+? notify_S.h
+? ourdevice.defs
+? ourdevice.sdefs.d
+? ourdeviceServer.c
+? ourdeviceServer.d
+? ourdevice_S.h
+? pcap_filter.d
+? queue.d
+? tmp.patch
+Index: Makefile
+===================================================================
+RCS file: /sources/hurd/hurd/eth-filter/Attic/Makefile,v
+retrieving revision 1.1.2.1
+diff -r1.1.2.1 Makefile
+21,23c21,23
+< SRCS = bpf_impl.c filter.c queue.c pcap_filter.c
+< LCLHDRS = bpf_impl.h queue.h util.h
+< DIST_FILES = ourdevice.defs notify.defs
+---
+> SRCS = bpf_impl.c filter.c queue.c pcap_filter.c #msg_queue.c
+> LCLHDRS = bpf_impl.h queue.h util.h #filter.h msg_queue.h
+> DIST_FILES = ourdevice.defs notify.defs #device_reply.defs
+26c26
+< MIGSTUBS = ourdeviceServer.o notifyServer.o
+---
+> MIGSTUBS = ourdeviceServer.o notifyServer.o #device_replyUser.o
+Index: filter.c
+===================================================================
+RCS file: /sources/hurd/hurd/eth-filter/Attic/filter.c,v
+retrieving revision 1.1.2.8
+diff -r1.1.2.8 filter.c
+34a35
+> #include <cthread.h>
+44,66c45,46
+<
+< struct proxy_user
+< {
+< struct port_info pi;
+< struct proxy *proxy;
+< };
+<
+< struct proxy_device
+< {
+< struct port_info pi;
+< struct proxy *proxy;
+< };
+<
+< struct proxy
+< {
+< struct proxy_device *device;
+< mach_port_t deliver_port;
+< hurd_ihash_locp_t p_deliverport_hashloc;
+< mach_port_t device_port;
+< };
+<
+< int deliver_msg (struct net_rcv_msg *msg, queue_head_t *port_list,
+< mach_port_t dest);
+---
+> //#include "filter.h"
+> //#include "msg_queue.h"
+129a110,152
+> /* Write the data from the client to the device. */
+> int
+> filter_device_write (struct filter_msg *msg)
+> {
+> int ret_count = 0;
+> int has_filter = 0;
+> net_hash_entry_t entp, *hash_headp;
+> net_rcv_port_t infp, nextfp;
+> int bytes_written;
+>
+> /* The packet can be sent as long as it passes one filter,
+> * even thought there is usually only one filter in the list. */
+> FILTER_ITERATE (&snd_port_list, infp, nextfp, &infp->chain)
+> {
+> has_filter = 1;
+> ret_count = mach_bpf_do_filter (infp,
+> data + sizeof (struct ethhdr),
+> datalen - sizeof (struct ethhdr),
+> data, sizeof (struct ethhdr),
+> &hash_headp, &entp);
+> if (ret_count)
+> break;
+> }
+> FILTER_ITERATE_END
+>
+> if (ret_count || !has_filter)
+> {
+> error_t err;
+> err = device_write (proxy->device_port, mode , recnum ,
+> data, datalen, &bytes_written);
+> }
+> ds_device_write_reply (msg->reply_port, msg->reply_type, err, bytes_written);
+> return 0;
+> }
+>
+> /* Deliver the data from the device to the client. */
+> int
+> filter_deliver (struct filter_msg *msg)
+> {
+> deliver_msg (msg, &rcv_port_list, proxy->deliver_port);
+> return 0;
+> }
+>
+213c236,237
+< device = ports_lookup_port (port_bucket, inp->msgh_local_port, device_portclass);
+---
+> device = ports_lookup_port (port_bucket, inp->msgh_local_port,
+> device_portclass);
+215a240
+>
+220c245,246
+< deliver_msg (msg, &rcv_port_list, proxy->deliver_port);
+---
+> queue_deliver (msg, proxy);
+> // deliver_msg (msg, &rcv_port_list, proxy->deliver_port);
+359,362d384
+< int ret_count = 0;
+< int has_filter = 0;
+< net_hash_entry_t entp, *hash_headp;
+< net_rcv_port_t infp, nextfp;
+369a392
+> queue_write (data, datalen, reply_port, reply_type, mode, recnum, proxy);
+372,399c395
+< /* The packet can be sent as long as it passes one filter,
+< * even thought there is usually only one filter in the list. */
+< FILTER_ITERATE (&snd_port_list, infp, nextfp, &infp->chain)
+< {
+< has_filter = 1;
+< ret_count = mach_bpf_do_filter (infp,
+< data + sizeof (struct ethhdr),
+< datalen - sizeof (struct ethhdr),
+< data, sizeof (struct ethhdr),
+< &hash_headp, &entp);
+< if (ret_count)
+< break;
+< }
+< FILTER_ITERATE_END
+<
+< if (ret_count || !has_filter)
+< {
+< error_t err;
+< print_pack (data, datalen);
+< err = device_write (proxy->device_port, mode , recnum ,
+< data, datalen, bytes_written);
+< return err;
+< }
+< else
+< {
+< *bytes_written = datalen;
+< return 0;
+< }
+---
+> return MIG_NO_REPLY;
+691a688,704
+> void *send_thread_func (void *)
+> {
+> struct filter_msg *msg;
+>
+> while (1)
+> {
+> msg = dequeue_msg ();
+> if (msg == NULL)
+> {
+> cthread_suspend (send_thread);
+> continue;
+> }
+> msg->write (msg);
+> }
+> return NULL;
+> }
+>
+750a764,768
+> send_thread = cthread_fork (send_thread_func, NULL);
+> /* TODO if the main thread exits,
+> * does the created thread exit if cthread_detach is called */
+> // cthread_detach (send_thread);
+>
+789c807,809
+< err = mach_msg ((mach_msg_header_t *)msg, MACH_SEND_MSG,
+---
+> debug ("before delivering the packet\n");
+> err = mach_msg ((mach_msg_header_t *)msg,
+> MACH_SEND_MSG,
+794,795c814
+< fprintf (stderr, "deliver msg: mach_msg: %s\n",
+< strerror (err));
+---
+> error (0, err, "mach_msg");
+797a817
+> debug ("after delivering the packet\n");
diff --git a/eth-filter.multi-thread/tmp.patch~ b/eth-filter.multi-thread/tmp.patch~
new file mode 100644
index 00000000..cca91c30
--- /dev/null
+++ b/eth-filter.multi-thread/tmp.patch~
@@ -0,0 +1,49 @@
+? bpf_impl.d
+? device.defs
+? eth-filter
+? eth-filter.prof_d
+? filter.d
+? notify.defs
+? notify.sdefs.d
+? notifyServer.c
+? notifyServer.d
+? notify_S.h
+? ourdevice.defs
+? ourdevice.sdefs.d
+? ourdeviceServer.c
+? ourdeviceServer.d
+? ourdevice_S.h
+? pcap_filter.d
+? queue.d
+? tmp.patch
+Index: filter.c
+===================================================================
+RCS file: /sources/hurd/hurd/eth-filter/Attic/filter.c,v
+retrieving revision 1.1.2.8
+diff -r1.1.2.8 filter.c
+208a209
+> mach_msg_header_t header;
+213c214,215
+< device = ports_lookup_port (port_bucket, inp->msgh_local_port, device_portclass);
+---
+> device = ports_lookup_port (port_bucket, inp->msgh_local_port,
+> device_portclass);
+215a218
+>
+218a222
+> header = msg->msg_hdr;
+220a225
+> msg->msg_hdr = header;
+789c794,796
+< err = mach_msg ((mach_msg_header_t *)msg, MACH_SEND_MSG,
+---
+> debug ("before delivering the packet\n");
+> err = mach_msg ((mach_msg_header_t *)msg,
+> MACH_SEND_MSG,
+794,795c801
+< fprintf (stderr, "deliver msg: mach_msg: %s\n",
+< strerror (err));
+---
+> error (0, err, "mach_msg");
+797a804
+> debug ("after delivering the packet\n");
diff --git a/eth-filter.multi-thread/util.h b/eth-filter.multi-thread/util.h
new file mode 100644
index 00000000..fa7189eb
--- /dev/null
+++ b/eth-filter.multi-thread/util.h
@@ -0,0 +1,73 @@
+/*
+ Copyright (C) 2008 Free Software Foundation, Inc.
+ Written by Zheng Da.
+
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ The GNU Hurd is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the GNU Hurd; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef UTIL_H
+#define UTIL_H
+
+#include <stdio.h>
+
+#include <linux/if_ether.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/ip.h>
+
+#define DEBUG
+
+#ifdef DEBUG
+
+#define debug(format, ...) do \
+{ \
+ extern FILE *logfile; \
+ char buf[1024]; \
+ snprintf (buf, 1024, "filter: %s", format); \
+ fprintf (stderr , buf, ## __VA_ARGS__); \
+ fflush (logfile); \
+} while (0)
+
+#else
+
+#define debug(format, ...) do {} while (0)
+
+#endif
+
+static inline void
+print_pack (char *packet, int len)
+{
+#ifdef DEBUG
+ struct ethhdr *ethh = (struct ethhdr *) packet;
+ struct iphdr *iph = (struct iphdr *)(ethh + 1);
+ char src_str[INET_ADDRSTRLEN];
+ char dst_str[INET_ADDRSTRLEN];
+ if (ntohs (ethh->h_proto) == ETH_P_IP
+ && len >= sizeof (struct ethhdr) + sizeof (struct iphdr))
+ {
+ debug ("pack: get a IP packet from %s to %s\n",
+ inet_ntop (AF_INET, &iph->saddr, src_str, INET_ADDRSTRLEN),
+ inet_ntop (AF_INET, &iph->daddr, dst_str, INET_ADDRSTRLEN));
+ }
+ else
+ {
+ debug ("pack: get a non-IP packet: %x\n", ntohs (ethh->h_proto));
+ }
+#endif
+}
+
+#endif
diff --git a/eth-filter.multi-thread/util.h~ b/eth-filter.multi-thread/util.h~
new file mode 100644
index 00000000..44755152
--- /dev/null
+++ b/eth-filter.multi-thread/util.h~
@@ -0,0 +1,73 @@
+/*
+ Copyright (C) 2008 Free Software Foundation, Inc.
+ Written by Zheng Da.
+
+ This file is part of the GNU Hurd.
+
+ The GNU Hurd is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ The GNU Hurd is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with the GNU Hurd; see the file COPYING. If not, write to
+ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+
+#ifndef UTIL_H
+#define UTIL_H
+
+#include <stdio.h>
+
+#include <linux/if_ether.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/ip.h>
+
+#define DEBUG
+
+#ifdef DEBUG
+
+#define debug(format, ...) do \
+{ \
+ extern FILE *logfile; \
+ char buf[1024]; \
+ snprintf (buf, 1024, "filter: %s", format); \
+ fprintf (logfile , buf, ## __VA_ARGS__); \
+ fflush (logfile); \
+} while (0)
+
+#else
+
+#define debug(format, ...) do {} while (0)
+
+#endif
+
+static inline void
+print_pack (char *packet, int len)
+{
+#ifdef DEBUG
+ struct ethhdr *ethh = (struct ethhdr *) packet;
+ struct iphdr *iph = (struct iphdr *)(ethh + 1);
+ char src_str[INET_ADDRSTRLEN];
+ char dst_str[INET_ADDRSTRLEN];
+ if (ntohs (ethh->h_proto) == ETH_P_IP
+ && len >= sizeof (struct ethhdr) + sizeof (struct iphdr))
+ {
+ debug ("pack: get a IP packet from %s to %s\n",
+ inet_ntop (AF_INET, &iph->saddr, src_str, INET_ADDRSTRLEN),
+ inet_ntop (AF_INET, &iph->daddr, dst_str, INET_ADDRSTRLEN));
+ }
+ else
+ {
+ debug ("pack: get a non-IP packet: %x\n", ntohs (ethh->h_proto));
+ }
+#endif
+}
+
+#endif