Home | History | Annotate | Line # | Download | only in common
pf.c revision 1.8.2.1
      1  1.8.2.1       jmc /*	$NetBSD: pf.c,v 1.8.2.1 2004/04/21 03:55:55 jmc Exp $	*/
      2      1.3   thorpej 
      3      1.1       cjs /*
      4      1.1       cjs  * Copyright (c) 1993-95 Mats O Jansson.  All rights reserved.
      5      1.1       cjs  * Copyright (c) 1990 The Regents of the University of California.
      6      1.1       cjs  * All rights reserved.
      7      1.1       cjs  *
      8      1.1       cjs  * This code is partly derived from rarpd.
      9      1.1       cjs  *
     10      1.1       cjs  * Redistribution and use in source and binary forms, with or without
     11      1.1       cjs  * modification, are permitted provided that the following conditions
     12      1.1       cjs  * are met:
     13      1.1       cjs  * 1. Redistributions of source code must retain the above copyright
     14      1.1       cjs  *    notice, this list of conditions and the following disclaimer.
     15      1.1       cjs  * 2. Redistributions in binary form must reproduce the above copyright
     16      1.1       cjs  *    notice, this list of conditions and the following disclaimer in the
     17      1.1       cjs  *    documentation and/or other materials provided with the distribution.
     18      1.1       cjs  * 3. All advertising materials mentioning features or use of this software
     19      1.1       cjs  *    must display the following acknowledgement:
     20      1.1       cjs  *	This product includes software developed by Mats O Jansson.
     21      1.1       cjs  * 4. The name of the author may not be used to endorse or promote products
     22      1.1       cjs  *    derived from this software without specific prior written permission.
     23      1.1       cjs  *
     24      1.1       cjs  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     25      1.1       cjs  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     26      1.1       cjs  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     27      1.1       cjs  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     28      1.1       cjs  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     29      1.1       cjs  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     30      1.1       cjs  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     31      1.1       cjs  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     32      1.1       cjs  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     33      1.1       cjs  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     34      1.1       cjs  */
     35      1.1       cjs 
     36      1.4     lukem #include <sys/cdefs.h>
     37      1.4     lukem #ifndef lint
     38  1.8.2.1       jmc __RCSID("$NetBSD: pf.c,v 1.8.2.1 2004/04/21 03:55:55 jmc Exp $");
     39      1.1       cjs #endif
     40      1.1       cjs 
     41      1.4     lukem #include "os.h"
     42      1.4     lukem 
     43      1.1       cjs #include <sys/uio.h>
     44      1.1       cjs #include <net/bpf.h>
     45      1.1       cjs 
     46      1.4     lukem #include "mopdef.h"
     47      1.4     lukem #include "pf.h"
     48      1.8  christos #include "log.h"
     49      1.1       cjs 
     50      1.1       cjs /*
     51      1.1       cjs  * Variables
     52      1.1       cjs  */
     53      1.1       cjs 
     54      1.1       cjs extern int promisc;
     55      1.1       cjs 
     56      1.1       cjs /*
     57      1.1       cjs  * Return information to device.c how to open device.
     58      1.1       cjs  * In this case the driver can handle both Ethernet type II and
     59      1.1       cjs  * IEEE 802.3 frames (SNAP) in a single pfOpen.
     60      1.1       cjs  */
     61      1.1       cjs 
     62      1.1       cjs int
     63      1.1       cjs pfTrans(interface)
     64      1.1       cjs 	char *interface;
     65      1.1       cjs {
     66      1.1       cjs 	return TRANS_ETHER+TRANS_8023+TRANS_AND;
     67      1.1       cjs }
     68      1.1       cjs 
     69      1.1       cjs /*
     70      1.1       cjs  * Open and initialize packet filter.
     71      1.1       cjs  */
     72      1.1       cjs 
     73      1.1       cjs int
     74      1.1       cjs pfInit(interface, mode, protocol, typ)
     75      1.1       cjs 	char *interface;
     76      1.1       cjs 	u_short protocol;
     77      1.1       cjs 	int typ, mode;
     78      1.1       cjs {
     79      1.1       cjs 	int	fd;
     80      1.1       cjs 	int	n = 0;
     81      1.1       cjs 	char	device[sizeof "/dev/bpf000"];
     82      1.1       cjs 	struct ifreq ifr;
     83      1.1       cjs 	u_int	dlt;
     84      1.1       cjs 	int	immediate;
     85  1.8.2.1       jmc 	u_int	bufsize;
     86      1.1       cjs 
     87      1.1       cjs 	static struct bpf_insn insns[] = {
     88      1.1       cjs 		BPF_STMT(BPF_LD | BPF_H | BPF_ABS, 12),
     89      1.1       cjs 		BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x4711, 4, 0),
     90      1.1       cjs 		BPF_STMT(BPF_LD | BPF_H | BPF_ABS, 20),
     91      1.1       cjs 		BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0x4711, 0, 3),
     92      1.1       cjs 		BPF_STMT(BPF_LD | BPF_H | BPF_ABS, 14),
     93      1.1       cjs 		BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0xaaaa, 0, 1),
     94      1.1       cjs 		BPF_STMT(BPF_RET | BPF_K, 1520),
     95      1.1       cjs 		BPF_STMT(BPF_RET | BPF_K, 0),
     96      1.1       cjs 	};
     97      1.1       cjs 	static struct bpf_program filter = {
     98      1.1       cjs 		sizeof insns / sizeof(insns[0]),
     99      1.1       cjs 		insns
    100      1.1       cjs 	};
    101      1.1       cjs 
    102      1.1       cjs   	/* Go through all the minors and find one that isn't in use. */
    103      1.1       cjs 	do {
    104      1.6    itojun 		(void) snprintf(device, sizeof(device), "/dev/bpf%d", n++);
    105      1.1       cjs 		fd = open(device, mode);
    106      1.1       cjs 	} while (fd < 0 && errno == EBUSY);
    107      1.1       cjs 
    108      1.1       cjs 	if (fd < 0) {
    109      1.8  christos       		mopLogWarn("pfInit: open %s", device);
    110      1.1       cjs 		return(-1);
    111      1.1       cjs 	}
    112      1.1       cjs 
    113      1.1       cjs 	/* Set immediate mode so packets are processed as they arrive. */
    114      1.1       cjs 	immediate = 1;
    115      1.1       cjs 	if (ioctl(fd, BIOCIMMEDIATE, &immediate) < 0) {
    116      1.8  christos       		mopLogWarn("pfInit: BIOCIMMEDIATE");
    117      1.1       cjs 		return(-1);
    118      1.1       cjs 	}
    119  1.8.2.1       jmc 	bufsize = 32768;
    120  1.8.2.1       jmc 	if (ioctl(fd, BIOCSBLEN, &bufsize) < 0) {
    121  1.8.2.1       jmc       		mopLogWarn("pfInit: BIOCSBLEN(%d)", bufsize);
    122  1.8.2.1       jmc 	}
    123      1.1       cjs 	(void) strncpy(ifr.ifr_name, interface, sizeof ifr.ifr_name);
    124      1.1       cjs 	if (ioctl(fd, BIOCSETIF, (caddr_t) & ifr) < 0) {
    125      1.8  christos       		mopLogWarn("pfInit: BIOCSETIF");
    126      1.1       cjs 		return(-1);
    127      1.1       cjs 	}
    128      1.1       cjs 	/* Check that the data link layer is an Ethernet; this code won't work
    129      1.1       cjs 	 * with anything else. */
    130      1.1       cjs 	if (ioctl(fd, BIOCGDLT, (caddr_t) & dlt) < 0) {
    131      1.8  christos       		mopLogWarn("pfInit: BIOCGDLT");
    132      1.1       cjs 		return(-1);
    133      1.1       cjs 	}
    134      1.1       cjs 	if (dlt != DLT_EN10MB) {
    135      1.8  christos       		mopLogWarnX("pfInit: %s is not ethernet", device);
    136      1.1       cjs 		return(-1);
    137      1.1       cjs 	}
    138      1.1       cjs 	if (promisc) {
    139      1.1       cjs 		/* Set promiscuous mode. */
    140      1.1       cjs 		if (ioctl(fd, BIOCPROMISC, (caddr_t)0) < 0) {
    141      1.8  christos       			mopLogWarn("pfInit: BIOCPROMISC");
    142      1.1       cjs 			return(-1);
    143      1.1       cjs 		}
    144      1.1       cjs 	}
    145      1.1       cjs 	/* Set filter program. */
    146      1.1       cjs 	insns[1].k = protocol;
    147      1.1       cjs 	insns[3].k = protocol;
    148      1.1       cjs 
    149      1.1       cjs 	if (ioctl(fd, BIOCSETF, (caddr_t) & filter) < 0) {
    150      1.8  christos       		mopLogWarn("pfInit: BIOCSETF");
    151      1.1       cjs 		return(-1);
    152      1.1       cjs 	}
    153      1.1       cjs 	return(fd);
    154      1.1       cjs }
    155      1.1       cjs 
    156      1.1       cjs /*
    157      1.1       cjs  * Add a Multicast address to the interface
    158      1.1       cjs  */
    159      1.1       cjs 
    160      1.1       cjs int
    161      1.1       cjs pfAddMulti(s, interface, addr)
    162      1.1       cjs 	int s;
    163      1.1       cjs 	char *interface, *addr;
    164      1.1       cjs {
    165      1.1       cjs 	struct ifreq ifr;
    166      1.1       cjs 	int	fd;
    167      1.1       cjs 
    168      1.7    itojun 	strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name));
    169      1.1       cjs 
    170      1.1       cjs 	ifr.ifr_addr.sa_family = AF_UNSPEC;
    171      1.4     lukem 	memmove(ifr.ifr_addr.sa_data, addr, 6);
    172      1.1       cjs 
    173      1.1       cjs 	/*
    174      1.1       cjs 	 * open a socket, temporarily, to use for SIOC* ioctls
    175      1.1       cjs 	 *
    176      1.1       cjs 	 */
    177      1.1       cjs 	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    178      1.8  christos 		mopLogWarn("pfAddMulti: socket");
    179      1.1       cjs 		return(-1);
    180      1.1       cjs 	}
    181      1.1       cjs 	if (ioctl(fd, SIOCADDMULTI, (caddr_t)&ifr) < 0) {
    182      1.8  christos 		mopLogWarn("pfAddMulti: SIOCADDMULTI");
    183      1.1       cjs 		close(fd);
    184      1.1       cjs 		return(-1);
    185      1.1       cjs 	}
    186      1.1       cjs 	close(fd);
    187      1.1       cjs 
    188      1.1       cjs 	return(0);
    189      1.1       cjs }
    190      1.1       cjs 
    191      1.1       cjs /*
    192      1.1       cjs  * Delete a Multicast address from the interface
    193      1.1       cjs  */
    194      1.1       cjs 
    195      1.1       cjs int
    196      1.1       cjs pfDelMulti(s, interface, addr)
    197      1.1       cjs 	int s;
    198      1.1       cjs 	char *interface, *addr;
    199      1.1       cjs {
    200      1.1       cjs 	struct ifreq ifr;
    201      1.1       cjs 	int	fd;
    202      1.1       cjs 
    203      1.7    itojun 	strncpy(ifr.ifr_name, interface, sizeof(ifr.ifr_name));
    204      1.1       cjs 
    205      1.1       cjs 	ifr.ifr_addr.sa_family = AF_UNSPEC;
    206      1.4     lukem 	memmove(ifr.ifr_addr.sa_data, addr, 6);
    207      1.1       cjs 
    208      1.1       cjs 	/*
    209      1.1       cjs 	 * open a socket, temporarily, to use for SIOC* ioctls
    210      1.1       cjs 	 *
    211      1.1       cjs 	 */
    212      1.1       cjs 	if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    213      1.8  christos 		mopLogWarn("pfDelMulti: socket");
    214      1.1       cjs 		return(-1);
    215      1.1       cjs 	}
    216      1.1       cjs 	if (ioctl(fd, SIOCDELMULTI, (caddr_t)&ifr) < 0) {
    217      1.8  christos 		mopLogWarn("pfAddMulti: SIOCDELMULTI");
    218      1.1       cjs 		close(fd);
    219      1.1       cjs 		return(-1);
    220      1.1       cjs 	}
    221      1.1       cjs 	close(fd);
    222      1.1       cjs 
    223      1.1       cjs 	return(0);
    224      1.1       cjs }
    225      1.1       cjs 
    226      1.1       cjs /*
    227      1.1       cjs  * read a packet
    228      1.1       cjs  */
    229      1.1       cjs 
    230      1.1       cjs int
    231      1.1       cjs pfRead(fd, buf, len)
    232      1.1       cjs 	int	fd, len;
    233      1.1       cjs 	u_char *buf;
    234      1.1       cjs {
    235      1.1       cjs 	return(read(fd, buf, len));
    236      1.1       cjs }
    237      1.1       cjs 
    238      1.1       cjs /*
    239      1.1       cjs  * write a packet
    240      1.1       cjs  */
    241      1.1       cjs 
    242      1.1       cjs int
    243      1.1       cjs pfWrite(fd, buf, len, trans)
    244      1.1       cjs 	int fd, len, trans;
    245      1.1       cjs 	u_char *buf;
    246      1.1       cjs {
    247      1.1       cjs 
    248      1.1       cjs 	struct iovec iov[2];
    249      1.1       cjs 
    250      1.1       cjs 	switch (trans) {
    251      1.1       cjs 	case TRANS_8023:
    252      1.1       cjs 		iov[0].iov_base = (caddr_t)buf;
    253      1.1       cjs 		iov[0].iov_len = 22;
    254      1.1       cjs 		iov[1].iov_base = (caddr_t)buf+22;
    255      1.1       cjs 		iov[1].iov_len = len-22;
    256      1.1       cjs 		break;
    257      1.1       cjs 	default:
    258      1.1       cjs 		iov[0].iov_base = (caddr_t)buf;
    259      1.1       cjs 		iov[0].iov_len = 14;
    260      1.1       cjs 		iov[1].iov_base = (caddr_t)buf+14;
    261      1.1       cjs 		iov[1].iov_len = len-14;
    262      1.1       cjs 		break;
    263      1.1       cjs 	}
    264      1.1       cjs 
    265      1.1       cjs 	if (writev(fd, iov, 2) == len)
    266      1.1       cjs 		return(len);
    267      1.1       cjs 
    268      1.1       cjs 	return(-1);
    269      1.1       cjs }
    270      1.1       cjs 
    271