/* * 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 #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_ */