summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--eth-multiplexer/Makefile8
-rw-r--r--eth-multiplexer/bpf_impl.c866
-rw-r--r--eth-multiplexer/bpf_impl.h156
-rw-r--r--eth-multiplexer/device_impl.c3
-rw-r--r--eth-multiplexer/vdev.c14
-rw-r--r--eth-multiplexer/vdev.h5
6 files changed, 18 insertions, 1034 deletions
diff --git a/eth-multiplexer/Makefile b/eth-multiplexer/Makefile
index 72027ea8..5e44227b 100644
--- a/eth-multiplexer/Makefile
+++ b/eth-multiplexer/Makefile
@@ -20,12 +20,14 @@ makemode := server
target = eth-multiplexer
#CFLAGS += -DDEBUG
-SRCS = ethernet.c vdev.c multiplexer.c bpf_impl.c queue.c dev_stat.c netfs_impl.c notify_impl.c device_impl.c demuxer.c
+SRCS = ethernet.c vdev.c multiplexer.c queue.c dev_stat.c netfs_impl.c notify_impl.c device_impl.c demuxer.c
MIGSTUBS = ourdeviceServer.o notifyServer.o
OBJS = $(SRCS:.c=.o) $(MIGSTUBS)
-LCLHDRS = bpf_impl.h ethernet.h queue.h util.h vdev.h netfs_impl.h
+LCLHDRS = ethernet.h queue.h util.h vdev.h netfs_impl.h
DIST_FILES = ourdevice.defs notify.defs
-HURDLIBS=ports fshelp shouldbeinlibc netfs
+HURDLIBS=ports fshelp shouldbeinlibc netfs bpf
+
+CFLAGS += -I../libbpf
include ../Makeconf
diff --git a/eth-multiplexer/bpf_impl.c b/eth-multiplexer/bpf_impl.c
deleted file mode 100644
index 55c2a87e..00000000
--- a/eth-multiplexer/bpf_impl.c
+++ /dev/null
@@ -1,866 +0,0 @@
- /*
- * 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"
-
-/*
- * 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
-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 (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
-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
-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
-bpf_hash (int n, unsigned int *keys)
-{
- register unsigned int hval = 0;
-
- while (n--) {
- hval += *keys++;
- }
- return (hval % NET_HASH_SIZE);
-}
-
-
-int
-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[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 (struct vether_device *ifp, 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(&ifp->if_rcv_port_list,
- (net_rcv_port_t)hp,
- net_rcv_port_t, input);
- if (((net_rcv_port_t)hp)->filter[0] & NETF_OUT)
- queue_remove(&ifp->if_snd_port_list,
- (net_rcv_port_t)hp,
- net_rcv_port_t, output);
- 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->input);
- 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.
- */
-io_return_t
-net_set_filter(struct vether_device *ifp, 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 = 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,
- (if_port_list == &ifp->if_rcv_port_list)
- ? &infp->input : &infp->output)
- {
- if (infp->rcv_port == MACH_PORT_NULL) {
- if (match != 0
- && infp->priority == priority
- && my_infp == 0
- && (infp->filter_end - infp->filter) == filter_count
- && 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 (ifp,
- (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(&ifp->if_rcv_port_list, infp,
- net_rcv_port_t, input);
- if (infp->filter[0] & NETF_OUT)
- queue_remove(&ifp->if_snd_port_list, infp,
- net_rcv_port_t, output);
-
- ENQUEUE_DEAD(dead_infp, infp, input);
- }
- }
- FILTER_ITERATE_END
- }
-
- in = (filter[0] & NETF_IN) != 0;
- out = (filter[0] & NETF_OUT) != 0;
-
- if (in)
- check_filter_list(&ifp->if_rcv_port_list);
- if (out)
- check_filter_list(&ifp->if_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(&ifp->if_rcv_port_list, infp, net_rcv_port_t, input)
- if (priority > infp->priority)
- break;
-
- queue_enter(&ifp->if_rcv_port_list, my_infp, net_rcv_port_t, input);
- }
-
- if (out) {
- queue_iterate(&ifp->if_snd_port_list, infp, net_rcv_port_t, output)
- if (priority > infp->priority)
- break;
-
- queue_enter(&ifp->if_snd_port_list, my_infp, net_rcv_port_t, output);
- }
- }
-
- 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[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);
-}
-
-void
-destroy_filters (struct vether_device *ifp)
-{
-}
-
-void
-remove_dead_filter (struct vether_device *ifp, 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,
- (if_port_list == &ifp->if_rcv_port_list)
- ? &infp->input : &infp->output) {
- 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 (ifp,
- (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(&ifp->if_rcv_port_list, infp,
- net_rcv_port_t, input);
- if (infp->filter[0] & NETF_OUT)
- queue_remove(&ifp->if_snd_port_list, infp,
- net_rcv_port_t, output);
-
- ENQUEUE_DEAD(dead_infp, infp, input);
- }
- }
- FILTER_ITERATE_END
-
- if (dead_infp != 0)
- net_free_dead_infp(dead_infp);
- if (dead_entp != 0)
- net_free_dead_entp(dead_entp);
-}
diff --git a/eth-multiplexer/bpf_impl.h b/eth-multiplexer/bpf_impl.h
deleted file mode 100644
index 82db1b8d..00000000
--- a/eth-multiplexer/bpf_impl.h
+++ /dev/null
@@ -1,156 +0,0 @@
- /*
- * 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 <device/bpf.h>
-
-#include "queue.h"
-#include "vdev.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 input; /* list of input open_descriptors */
- queue_chain_t output; /* list of output open_descriptors */
- 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 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);
-io_return_t net_set_filter(struct vether_device *ifp, mach_port_t rcv_port,
- int priority, filter_t *filter, unsigned int filter_count);
-
-int bpf_validate(bpf_insn_t f, int bytes, bpf_insn_t *match);
-int bpf_eq (bpf_insn_t f1, bpf_insn_t f2, int bytes);
-unsigned int bpf_hash (int n, unsigned int *keys);
-int bpf_match (net_hash_header_t hash, int n_keys, unsigned int *keys,
- net_hash_entry_t **hash_headpp, net_hash_entry_t *entpp);
-
-int hash_ent_remove (struct vether_device *ifp, 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 (struct vether_device *ifp,
- queue_head_t *if_port_list, mach_port_t dead_port);
-void destroy_filters (struct vether_device *ifp);
-
-#endif /* _DEVICE_BPF_H_ */
diff --git a/eth-multiplexer/device_impl.c b/eth-multiplexer/device_impl.c
index f9c8fc34..953fca70 100644
--- a/eth-multiplexer/device_impl.c
+++ b/eth-multiplexer/device_impl.c
@@ -276,7 +276,8 @@ ds_device_set_filter (device_t device, mach_port_t receive_port,
goto out;
if (tmp != MACH_PORT_NULL)
mach_port_deallocate (mach_task_self (), tmp);
- err = net_set_filter (vdev, receive_port, priority, filter, filterlen);
+ err = net_set_filter (&vdev->port_list, receive_port,
+ priority, filter, filterlen);
out:
ports_port_deref (vdev);
return err;
diff --git a/eth-multiplexer/vdev.c b/eth-multiplexer/vdev.c
index 5e525b31..29e2b4b1 100644
--- a/eth-multiplexer/vdev.c
+++ b/eth-multiplexer/vdev.c
@@ -112,8 +112,10 @@ remove_dead_port_from_dev (mach_port_t dead_port)
mutex_lock (&dev_list_lock);
for (vdev = dev_head; vdev; vdev = vdev->next)
{
- remove_dead_filter (vdev, &vdev->if_rcv_port_list, dead_port);
- remove_dead_filter (vdev, &vdev->if_snd_port_list, dead_port);
+ remove_dead_filter (&vdev->port_list,
+ &vdev->port_list.if_rcv_port_list, dead_port);
+ remove_dead_filter (&vdev->port_list,
+ &vdev->port_list.if_snd_port_list, dead_port);
}
mutex_unlock (&dev_list_lock);
return 0;
@@ -145,8 +147,8 @@ add_vdev (char *name, int size,
vdev->if_address[1] = 0x54;
*(int *)(vdev->if_address + 2) = random ();
- queue_init (&vdev->if_rcv_port_list);
- queue_init (&vdev->if_snd_port_list);
+ queue_init (&vdev->port_list.if_rcv_port_list);
+ queue_init (&vdev->port_list.if_snd_port_list);
mutex_lock (&dev_list_lock);
vdev->next = dev_head;
@@ -177,7 +179,7 @@ destroy_vdev (void *port)
/* TODO Delete all filters in the interface,
* there shouldn't be any filters left */
- destroy_filters (vdev);
+ destroy_filters (&vdev->port_list);
}
/* Test if there are devices existing in the list */
@@ -265,7 +267,7 @@ deliver_msg(struct net_rcv_msg *msg, struct vether_device *vdev)
msg->msg_hdr.msgh_kind = MACH_MSGH_KIND_NORMAL;
msg->msg_hdr.msgh_id = NET_RCV_MSG_ID;
- if_port_list = &vdev->if_rcv_port_list;
+ if_port_list = &vdev->port_list.if_rcv_port_list;
FILTER_ITERATE (if_port_list, infp, nextfp, &infp->input)
{
mach_port_t dest;
diff --git a/eth-multiplexer/vdev.h b/eth-multiplexer/vdev.h
index b8bab019..c8696785 100644
--- a/eth-multiplexer/vdev.h
+++ b/eth-multiplexer/vdev.h
@@ -28,6 +28,8 @@
#include <hurd/ports.h>
#include <device/net_status.h>
+#include <bpf_impl.h>
+
#include "queue.h"
#include "util.h"
@@ -52,8 +54,7 @@ struct vether_device
struct vether_device *next;
struct vether_device **pprev;
- queue_head_t if_rcv_port_list; /* input filter list */
- queue_head_t if_snd_port_list; /* output filter list */
+ if_filter_list_t port_list;
};
typedef int (*dev_act_func) (struct vether_device *);