diff options
author | pst <pst@FreeBSD.org> | 1996-08-19 21:01:37 +0000 |
---|---|---|
committer | pst <pst@FreeBSD.org> | 1996-08-19 21:01:37 +0000 |
commit | a96a62bfacccf7334e66ee6a2b30b77ecead73bb (patch) | |
tree | 41ec5baddc2ce9552e9eb67dd009e0e1b24cb5b6 | |
parent | 4aa0d21568e0328935f60c5b71e4c21e934f5922 (diff) | |
download | FreeBSD-src-a96a62bfacccf7334e66ee6a2b30b77ecead73bb.zip FreeBSD-src-a96a62bfacccf7334e66ee6a2b30b77ecead73bb.tar.gz |
Grab libpcap sources out of contrib_libpcap module
-rw-r--r-- | lib/libpcap/Makefile | 36 | ||||
-rw-r--r-- | lib/libpcap/bpf_filter.c | 550 | ||||
-rw-r--r-- | lib/libpcap/bpf_image.c | 284 | ||||
-rw-r--r-- | lib/libpcap/etherent.c | 148 | ||||
-rw-r--r-- | lib/libpcap/ethertype.h | 74 | ||||
-rw-r--r-- | lib/libpcap/gencode.c | 1764 | ||||
-rw-r--r-- | lib/libpcap/gencode.h | 173 | ||||
-rw-r--r-- | lib/libpcap/grammar.y | 266 | ||||
-rw-r--r-- | lib/libpcap/inet.c | 196 | ||||
-rw-r--r-- | lib/libpcap/nametoaddr.c | 358 | ||||
-rw-r--r-- | lib/libpcap/optimize.c | 1924 | ||||
-rw-r--r-- | lib/libpcap/pcap-bpf.c | 235 | ||||
-rw-r--r-- | lib/libpcap/pcap-dlpi.c | 506 | ||||
-rw-r--r-- | lib/libpcap/pcap-enet.c | 227 | ||||
-rw-r--r-- | lib/libpcap/pcap-int.h | 98 | ||||
-rw-r--r-- | lib/libpcap/pcap-namedb.h | 76 | ||||
-rw-r--r-- | lib/libpcap/pcap-nit.c | 240 | ||||
-rw-r--r-- | lib/libpcap/pcap-nit.h | 19 | ||||
-rw-r--r-- | lib/libpcap/pcap-pf.c | 310 | ||||
-rw-r--r-- | lib/libpcap/pcap-pf.h | 19 | ||||
-rw-r--r-- | lib/libpcap/pcap-snit.c | 293 | ||||
-rw-r--r-- | lib/libpcap/pcap-snoop.c | 195 | ||||
-rw-r--r-- | lib/libpcap/pcap.3 | 325 | ||||
-rw-r--r-- | lib/libpcap/pcap.c | 173 | ||||
-rw-r--r-- | lib/libpcap/pcap.h | 137 | ||||
-rw-r--r-- | lib/libpcap/savefile.c | 285 | ||||
-rw-r--r-- | lib/libpcap/scanner.l | 193 |
27 files changed, 23 insertions, 9081 deletions
diff --git a/lib/libpcap/Makefile b/lib/libpcap/Makefile index a3009c7..85509b1 100644 --- a/lib/libpcap/Makefile +++ b/lib/libpcap/Makefile @@ -2,30 +2,40 @@ # $Id: Makefile,v 1.7 1996/06/02 17:09:03 phk Exp $ LIB= pcap - -SRCS= \ - pcap-bpf.c \ - pcap.c inet.c gencode.c optimize.c nametoaddr.c etherent.c savefile.c \ - bpf_filter.c bpf_image.c \ +SRCS= pcap-bpf.c \ + pcap.c inet.c gencode.c optimize.c nametoaddr.c \ + etherent.c savefile.c bpf_filter.c bpf_image.c \ grammar.y scanner.l +MAN3= pcap.3 CLEANFILES+= lex.yy.c tokdefs.h grammar.c scanner.c -# CFLAGS+=-Wall -I. -I${.CURDIR} -DFDDI -Dyylval=pcap_lval -CFLAGS+=-DFDDI -I. -I${.CURDIR} -DETHER_SERVICE -MAN3= pcap.3 + +DEFS= -DHAVE_SYS_IOCCOM_H=1 -DHAVE_SYS_SOCKIO_H=1 \ + -DHAVE_ETHER_HOSTTON=1 -DHAVE_STRERROR=1 \ + -DHAVE_SOCKADDR_SA_LEN=1 -DLBL_ALIGN=1 + +CFLAGS+=-Wall -I. -I${.CURDIR} -Dyylval=pcap_lval -Dlint ${DEFS} + +# +# Magic to grab sources out of src/contrib +# +DISTDIR?=${.CURDIR}/../../contrib/libpcap +.PATH: ${DISTDIR} +.PATH: ${DISTDIR}/bpf/net +CFLAGS+=-I${DISTDIR} -I${DISTDIR}/lbl beforeinstall: - -cmp -s ${.CURDIR}/pcap.h ${DESTDIR}/usr/include/pcap.h || \ + -cmp -s ${DISTDIR}/pcap.h ${DESTDIR}/usr/include/pcap.h || \ ( $(INSTALL) -c -o ${BINOWN} -g ${BINGRP} -m 444 \ - ${.CURDIR}/pcap.h ${DESTDIR}/usr/include; ) - -cmp -s ${.CURDIR}/pcap-namedb.h ${DESTDIR}/usr/include/pcap-namedb.h || \ + ${DISTDIR}/pcap.h ${DESTDIR}/usr/include; ) + -cmp -s ${DISTDIR}/pcap-namedb.h ${DESTDIR}/usr/include/pcap-namedb.h || \ ( $(INSTALL) -c -o ${BINOWN} -g ${BINGRP} -m 444 \ - ${.CURDIR}/pcap-namedb.h ${DESTDIR}/usr/include; ) + ${DISTDIR}/pcap-namedb.h ${DESTDIR}/usr/include; ) + scanner.o: tokdefs.h tokdefs.h: grammar.c mv -f y.tab.h tokdefs.h - .include <bsd.lib.mk> diff --git a/lib/libpcap/bpf_filter.c b/lib/libpcap/bpf_filter.c deleted file mode 100644 index e755b59..0000000 --- a/lib/libpcap/bpf_filter.c +++ /dev/null @@ -1,550 +0,0 @@ -/*- - * Copyright (c) 1990, 1991, 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from the Stanford/CMU enet packet filter, - * (net/enet.c) distributed as part of 4.3BSD, and code contributed - * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence - * Berkeley Laboratory. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)bpf.c 7.5 (Berkeley) 7/15/91 - * - * static char rcsid[] = - * "$Header: /home/ncvs/src/lib/libpcap/bpf_filter.c,v 1.1.1.1 1995/01/20 04:13:02 jkh Exp $"; - */ -#if !(defined(lint) || defined(KERNEL)) -static char rcsid[] = - "@(#) $Header: /home/ncvs/src/lib/libpcap/bpf_filter.c,v 1.1.1.1 1995/01/20 04:13:02 jkh Exp $ (LBL)"; -#endif - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/time.h> -#include <net/bpf.h> - -#if defined(__alpha) -typedef int int32; -typedef u_int u_int32; -#else -typedef long int32; -typedef u_long u_int32; -#endif - -#ifdef sun -#include <netinet/in.h> -#endif - -#if defined(sparc) || defined(mips) || defined(ibm032) || defined(__alpha) -#define BPF_ALIGN -#endif - -#ifndef BPF_ALIGN -#define EXTRACT_SHORT(p) ((u_short)ntohs(*(u_short *)p)) -#define EXTRACT_LONG(p) (ntohl(*(u_int32 *)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_int32)*((u_char *)p+0)<<24|\ - (u_int32)*((u_char *)p+1)<<16|\ - (u_int32)*((u_char *)p+2)<<8|\ - (u_int32)*((u_char *)p+3)<<0) -#endif - -#ifdef KERNEL -#include <sys/mbuf.h> -#define MINDEX(m, k) \ -{ \ - register int len = m->m_len; \ - \ - while (k >= len) { \ - k -= len; \ - m = m->m_next; \ - if (m == 0) \ - return 0; \ - len = m->m_len; \ - } \ -} - -static int -m_xword(m, k, err) - register struct mbuf *m; - register int k, *err; -{ - register int len; - register u_char *cp, *np; - register struct mbuf *m0; - - len = m->m_len; - while (k >= len) { - k -= len; - m = m->m_next; - if (m == 0) - goto bad; - len = m->m_len; - } - cp = mtod(m, u_char *) + k; - if (len - k >= 4) { - *err = 0; - return EXTRACT_LONG(cp); - } - m0 = m->m_next; - if (m0 == 0 || m0->m_len + len - k < 4) - goto bad; - *err = 0; - np = mtod(m0, u_char *); - switch (len - k) { - - case 1: - return (cp[k] << 24) | (np[0] << 16) | (np[1] << 8) | np[2]; - - case 2: - return (cp[k] << 24) | (cp[k + 1] << 16) | (np[0] << 8) | - np[1]; - - default: - return (cp[k] << 24) | (cp[k + 1] << 16) | (cp[k + 2] << 8) | - np[0]; - } - bad: - *err = 1; - return 0; -} - -static int -m_xhalf(m, k, err) - register struct mbuf *m; - register int k, *err; -{ - register int len; - register u_char *cp; - register struct mbuf *m0; - - len = m->m_len; - while (k >= len) { - k -= len; - m = m->m_next; - if (m == 0) - goto bad; - len = m->m_len; - } - cp = mtod(m, u_char *) + k; - if (len - k >= 2) { - *err = 0; - return EXTRACT_SHORT(cp); - } - m0 = m->m_next; - if (m0 == 0) - goto bad; - *err = 0; - return (cp[k] << 8) | mtod(m0, u_char *)[0]; - bad: - *err = 1; - return 0; -} -#endif - -/* - * 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 - */ -u_int -bpf_filter(pc, p, wirelen, buflen) - register struct bpf_insn *pc; - register u_char *p; - u_int wirelen; - register u_int buflen; -{ - register u_int32 A, X; - register int k; - int32 mem[BPF_MEMWORDS]; - - if (pc == 0) - /* - * No filter means accept all. - */ - return (u_int)-1; -#ifdef lint - A = 0; - X = 0; -#endif - --pc; - while (1) { - ++pc; - switch (pc->code) { - - default: -#ifdef KERNEL - return 0; -#else - abort(); -#endif - case BPF_RET|BPF_K: - return (u_int)pc->k; - - case BPF_RET|BPF_A: - return (u_int)A; - - case BPF_LD|BPF_W|BPF_ABS: - k = pc->k; - if (k + sizeof(int32) > buflen) { -#ifdef KERNEL - int merr; - - if (buflen != 0) - return 0; - A = m_xword((struct mbuf *)p, k, &merr); - if (merr != 0) - return 0; - continue; -#else - return 0; -#endif - } - A = EXTRACT_LONG(&p[k]); - continue; - - case BPF_LD|BPF_H|BPF_ABS: - k = pc->k; - if (k + sizeof(short) > buflen) { -#ifdef KERNEL - int merr; - - if (buflen != 0) - return 0; - A = m_xhalf((struct mbuf *)p, k, &merr); - continue; -#else - return 0; -#endif - } - A = EXTRACT_SHORT(&p[k]); - continue; - - case BPF_LD|BPF_B|BPF_ABS: - k = pc->k; - if (k >= buflen) { -#ifdef KERNEL - register struct mbuf *m; - - if (buflen != 0) - return 0; - m = (struct mbuf *)p; - MINDEX(m, k); - A = mtod(m, u_char *)[k]; - continue; -#else - return 0; -#endif - } - A = p[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; - if (k + sizeof(int32) > buflen) { -#ifdef KERNEL - int merr; - - if (buflen != 0) - return 0; - A = m_xword((struct mbuf *)p, k, &merr); - if (merr != 0) - return 0; - continue; -#else - return 0; -#endif - } - A = EXTRACT_LONG(&p[k]); - continue; - - case BPF_LD|BPF_H|BPF_IND: - k = X + pc->k; - if (k + sizeof(short) > buflen) { -#ifdef KERNEL - int merr; - - if (buflen != 0) - return 0; - A = m_xhalf((struct mbuf *)p, k, &merr); - if (merr != 0) - return 0; - continue; -#else - return 0; -#endif - } - A = EXTRACT_SHORT(&p[k]); - continue; - - case BPF_LD|BPF_B|BPF_IND: - k = X + pc->k; - if (k >= buflen) { -#ifdef KERNEL - register struct mbuf *m; - - if (buflen != 0) - return 0; - m = (struct mbuf *)p; - MINDEX(m, k); - A = mtod(m, char *)[k]; - continue; -#else - return 0; -#endif - } - A = p[k]; - continue; - - case BPF_LDX|BPF_MSH|BPF_B: - k = pc->k; - if (k >= buflen) { -#ifdef KERNEL - register struct mbuf *m; - - if (buflen != 0) - return 0; - m = (struct mbuf *)p; - MINDEX(m, k); - X = (mtod(m, char *)[k] & 0xf) << 2; - continue; -#else - return 0; -#endif - } - X = (p[pc->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; - } - } -} - -#ifdef KERNEL -/* - * Return true if the 'fcode' is a valid filter program. - * 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(f, len) - struct bpf_insn *f; - int len; -{ - register int i; - register struct bpf_insn *p; - - for (i = 0; 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; - } - return BPF_CLASS(f[len - 1].code) == BPF_RET; -} -#endif diff --git a/lib/libpcap/bpf_image.c b/lib/libpcap/bpf_image.c deleted file mode 100644 index e86fa85..0000000 --- a/lib/libpcap/bpf_image.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Copyright (c) 1990, 1991, 1992, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that: (1) source code distributions - * retain the above copyright notice and this paragraph in its entirety, (2) - * distributions including binary code include the above copyright notice and - * this paragraph in its entirety in the documentation or other materials - * provided with the distribution, and (3) all advertising materials mentioning - * features or use of this software display the following acknowledgement: - * ``This product includes software developed by the University of California, - * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of - * the University nor the names of its contributors may be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#ifndef lint -static char rcsid[] = - "@(#) $Header: bpf_image.c,v 1.12 94/01/31 03:22:34 leres Exp $ (LBL)"; -#endif - -#include <sys/types.h> -#include <sys/time.h> - -#include <net/bpf.h> - -#include <pcap.h> -#include <stdio.h> -#include <string.h> - -char * -bpf_image(p, n) - struct bpf_insn *p; - int n; -{ - int v; - char *fmt, *op; - static char image[256]; - char operand[64]; - - v = p->k; - switch (p->code) { - - default: - op = "unimp"; - fmt = "0x%x"; - v = p->code; - break; - - case BPF_RET|BPF_K: - op = "ret"; - fmt = "#%d"; - break; - - case BPF_RET|BPF_A: - op = "ret"; - fmt = ""; - break; - - case BPF_LD|BPF_W|BPF_ABS: - op = "ld"; - fmt = "[%d]"; - break; - - case BPF_LD|BPF_H|BPF_ABS: - op = "ldh"; - fmt = "[%d]"; - break; - - case BPF_LD|BPF_B|BPF_ABS: - op = "ldb"; - fmt = "[%d]"; - break; - - case BPF_LD|BPF_W|BPF_LEN: - op = "ld"; - fmt = "#pktlen"; - break; - - case BPF_LD|BPF_W|BPF_IND: - op = "ld"; - fmt = "[x + %d]"; - break; - - case BPF_LD|BPF_H|BPF_IND: - op = "ldh"; - fmt = "[x + %d]"; - break; - - case BPF_LD|BPF_B|BPF_IND: - op = "ldb"; - fmt = "[x + %d]"; - break; - - case BPF_LD|BPF_IMM: - op = "ld"; - fmt = "#0x%x"; - break; - - case BPF_LDX|BPF_IMM: - op = "ldx"; - fmt = "#0x%x"; - break; - - case BPF_LDX|BPF_MSH|BPF_B: - op = "ldxb"; - fmt = "4*([%d]&0xf)"; - break; - - case BPF_LD|BPF_MEM: - op = "ld"; - fmt = "M[%d]"; - break; - - case BPF_LDX|BPF_MEM: - op = "ldx"; - fmt = "M[%d]"; - break; - - case BPF_ST: - op = "st"; - fmt = "M[%d]"; - break; - - case BPF_STX: - op = "stx"; - fmt = "M[%d]"; - break; - - case BPF_JMP|BPF_JA: - op = "ja"; - fmt = "%d"; - v = n + p->k; - break; - - case BPF_JMP|BPF_JGT|BPF_K: - op = "jgt"; - fmt = "#0x%x"; - break; - - case BPF_JMP|BPF_JGE|BPF_K: - op = "jge"; - fmt = "#0x%x"; - break; - - case BPF_JMP|BPF_JEQ|BPF_K: - op = "jeq"; - fmt = "#0x%x"; - break; - - case BPF_JMP|BPF_JSET|BPF_K: - op = "jset"; - fmt = "#0x%x"; - break; - - case BPF_JMP|BPF_JGT|BPF_X: - op = "jgt"; - fmt = "x"; - break; - - case BPF_JMP|BPF_JGE|BPF_X: - op = "jge"; - fmt = "x"; - break; - - case BPF_JMP|BPF_JEQ|BPF_X: - op = "jeq"; - fmt = "x"; - break; - - case BPF_JMP|BPF_JSET|BPF_X: - op = "jset"; - fmt = "x"; - break; - - case BPF_ALU|BPF_ADD|BPF_X: - op = "add"; - fmt = "x"; - break; - - case BPF_ALU|BPF_SUB|BPF_X: - op = "sub"; - fmt = "x"; - break; - - case BPF_ALU|BPF_MUL|BPF_X: - op = "mul"; - fmt = "x"; - break; - - case BPF_ALU|BPF_DIV|BPF_X: - op = "div"; - fmt = "x"; - break; - - case BPF_ALU|BPF_AND|BPF_X: - op = "and"; - fmt = "x"; - break; - - case BPF_ALU|BPF_OR|BPF_X: - op = "or"; - fmt = "x"; - break; - - case BPF_ALU|BPF_LSH|BPF_X: - op = "lsh"; - fmt = "x"; - break; - - case BPF_ALU|BPF_RSH|BPF_X: - op = "rsh"; - fmt = "x"; - break; - - case BPF_ALU|BPF_ADD|BPF_K: - op = "add"; - fmt = "#%d"; - break; - - case BPF_ALU|BPF_SUB|BPF_K: - op = "sub"; - fmt = "#%d"; - break; - - case BPF_ALU|BPF_MUL|BPF_K: - op = "mul"; - fmt = "#%d"; - break; - - case BPF_ALU|BPF_DIV|BPF_K: - op = "div"; - fmt = "#%d"; - break; - - case BPF_ALU|BPF_AND|BPF_K: - op = "and"; - fmt = "#%d"; - break; - - case BPF_ALU|BPF_OR|BPF_K: - op = "or"; - fmt = "#%d"; - break; - - case BPF_ALU|BPF_LSH|BPF_K: - op = "lsh"; - fmt = "#%d"; - break; - - case BPF_ALU|BPF_RSH|BPF_K: - op = "rsh"; - fmt = "#%d"; - break; - - case BPF_ALU|BPF_NEG: - op = "neg"; - fmt = ""; - break; - - case BPF_MISC|BPF_TAX: - op = "tax"; - fmt = ""; - break; - - case BPF_MISC|BPF_TXA: - op = "txa"; - fmt = ""; - break; - } - (void)sprintf(operand, fmt, v); - (void)sprintf(image, - (BPF_CLASS(p->code) == BPF_JMP && - BPF_OP(p->code) != BPF_JA) ? - "(%03d) %-8s %-16s jt %d\tjf %d" - : "(%03d) %-8s %s", - n, op, operand, n + 1 + p->jt, n + 1 + p->jf); - return image; -} diff --git a/lib/libpcap/etherent.c b/lib/libpcap/etherent.c deleted file mode 100644 index 7045f3d..0000000 --- a/lib/libpcap/etherent.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 1990, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that: (1) source code distributions - * retain the above copyright notice and this paragraph in its entirety, (2) - * distributions including binary code include the above copyright notice and - * this paragraph in its entirety in the documentation or other materials - * provided with the distribution, and (3) all advertising materials mentioning - * features or use of this software display the following acknowledgement: - * ``This product includes software developed by the University of California, - * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of - * the University nor the names of its contributors may be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ -#ifndef lint -static char rcsid[] = - "@(#) $Header: etherent.c,v 1.8 94/06/20 19:07:50 leres Exp $ (LBL)"; -#endif - -#include <sys/types.h> - -#include <ctype.h> -#include <pcap.h> -#include <pcap-namedb.h> -#include <stdio.h> - -#ifndef __GNUC__ -#define inline -#endif - -static inline int xdtoi(int); -static inline int skip_space(FILE *); -static inline int skip_line(FILE *); - -/* Hex digit to integer. */ -static inline int -xdtoi(c) - register int c; -{ - if (isdigit(c)) - return c - '0'; - else if (islower(c)) - return c - 'a' + 10; - else - return c - 'A' + 10; -} - -static inline int -skip_space(f) - FILE *f; -{ - int c; - - do { - c = getc(f); - } while (isspace(c) && c != '\n'); - - return c; -} - -static inline int -skip_line(f) - FILE *f; -{ - int c; - - do - c = getc(f); - while (c != '\n' && c != EOF); - - return c; -} - -struct pcap_etherent * -pcap_next_etherent(FILE *fp) -{ - register int c, d, i; - char *bp; - static struct pcap_etherent e; - static int nline = 1; - top: - while (nline) { - /* Find addr */ - c = skip_space(fp); - if (c == '\n') - continue; - /* If this is a comment, or first thing on line - cannot be ethernet address, skip the line. */ - else if (!isxdigit(c)) - c = skip_line(fp); - else { - /* must be the start of an address */ - for (i = 0; i < 6; i += 1) { - d = xdtoi(c); - c = getc(fp); - if (c != ':') { - d <<= 4; - d |= xdtoi(c); - c = getc(fp); - } - e.addr[i] = d; - if (c != ':') - break; - c = getc(fp); - } - nline = 0; - } - if (c == EOF) - return 0; - } - - /* If we started a new line, 'c' holds the char past the ether addr, - which we assume is white space. If we are continuing a line, - 'c' is garbage. In either case, we can throw it away. */ - - c = skip_space(fp); - if (c == '\n') { - nline = 1; - goto top; - } - else if (c == '#') { - (void)skip_line(fp); - nline = 1; - goto top; - } - else if (c == EOF) - return 0; - - /* Must be a name. */ - bp = e.name; - /* Use 'd' to prevent buffer overflow. */ - d = sizeof(e.name) - 1; - do { - *bp++ = c; - c = getc(fp); - } while (!isspace(c) && c != EOF && --d > 0); - *bp = '\0'; - if (c == '\n') - nline = 1; - - return &e; -} diff --git a/lib/libpcap/ethertype.h b/lib/libpcap/ethertype.h deleted file mode 100644 index 37f6920..0000000 --- a/lib/libpcap/ethertype.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that: (1) source code distributions - * retain the above copyright notice and this paragraph in its entirety, (2) - * distributions including binary code include the above copyright notice and - * this paragraph in its entirety in the documentation or other materials - * provided with the distribution, and (3) all advertising materials mentioning - * features or use of this software display the following acknowledgement: - * ``This product includes software developed by the University of California, - * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of - * the University nor the names of its contributors may be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * @(#) $Header: ethertype.h,v 1.2 94/06/14 20:03:27 leres Exp $ (LBL) - */ - -/* Map between Ethernet protocol types and names */ - -/* Add other Ethernet packet types here */ -#ifndef ETHERTYPE_SPRITE -#define ETHERTYPE_SPRITE 0x0500 -#endif -#ifndef ETHERTYPE_MOPDL -#define ETHERTYPE_MOPDL 0x6001 -#endif -#ifndef ETHERTYPE_MOPRC -#define ETHERTYPE_MOPRC 0x6002 -#endif -#ifndef ETHERTYPE_DN -#define ETHERTYPE_DN 0x6003 -#endif -#ifndef ETHERTYPE_LAT -#define ETHERTYPE_LAT 0x6004 -#endif -#ifndef ETHERTYPE_LANBRIDGE -#define ETHERTYPE_LANBRIDGE 0x8038 -#endif -#ifndef ETHERTYPE_DECDNS -#define ETHERTYPE_DECDNS 0x803c -#endif -#ifndef ETHERTYPE_DECDTS -#define ETHERTYPE_DECDTS 0x803e -#endif -#ifndef ETHERTYPE_VEXP -#define ETHERTYPE_VEXP 0x805b -#endif -#ifndef ETHERTYPE_VPROD -#define ETHERTYPE_VPROD 0x805c -#endif -#ifndef ETHERTYPE_LOOPBACK -#define ETHERTYPE_LOOPBACK 0x9000 -#endif - -#ifndef ETHERTYPE_ATALK -#define ETHERTYPE_ATALK 0x809b /* XXX */ -#endif -#ifndef ETHERTYPE_AARP -#define ETHERTYPE_AARP 0x80f3 -#endif -#ifndef ETHERTYPE_NS -#define ETHERTYPE_NS 0x0600 -#endif - -#ifndef ETHERTYPE_REVARP -#define ETHERTYPE_REVARP 0x8035 -#endif - diff --git a/lib/libpcap/gencode.c b/lib/libpcap/gencode.c deleted file mode 100644 index 3f237c1..0000000 --- a/lib/libpcap/gencode.c +++ /dev/null @@ -1,1764 +0,0 @@ -/* - * Copyright (c) 1990, 1991, 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that: (1) source code distributions - * retain the above copyright notice and this paragraph in its entirety, (2) - * distributions including binary code include the above copyright notice and - * this paragraph in its entirety in the documentation or other materials - * provided with the distribution, and (3) all advertising materials mentioning - * features or use of this software display the following acknowledgement: - * ``This product includes software developed by the University of California, - * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of - * the University nor the names of its contributors may be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ -#ifndef lint -static char rcsid[] = - "@(#) $Header: /home/ncvs/src/lib/libpcap/gencode.c,v 1.1.1.1 1995/01/20 04:13:04 jkh Exp $ (LBL)"; -#endif - -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/time.h> - -#include <net/if.h> -#include <net/bpf.h> - -#include <netinet/in.h> -#include <netinet/if_ether.h> - -#include <memory.h> -#include <pcap.h> -#include <pcap-namedb.h> -#include <setjmp.h> -#if __STDC__ -#include <stdarg.h> -#include <stdlib.h> -#else -#include <varargs.h> -#endif - -#include "gencode.h" - -#ifndef __GNUC__ -#define inline -#endif - -#ifndef ETHERTYPE_REVARP -#define ETHERTYPE_REVARP 0x8035 -#endif -#ifndef ETHERTYPE_MOPDL -#define ETHERTYPE_MOPDL 0x6001 -#endif -#ifndef ETHERTYPE_MOPRC -#define ETHERTYPE_MOPRC 0x6002 -#endif -#ifndef ETHERTYPE_DN -#define ETHERTYPE_DN 0x6003 -#endif -#ifndef ETHERTYPE_LAT -#define ETHERTYPE_LAT 0x6004 -#endif - -#define JMP(c) ((c)|BPF_JMP|BPF_K) - -static jmp_buf top_ctx; -static pcap_t *bpf_pcap; - -/* VARARGS */ -volatile void -#if __STDC__ || defined(SOLARIS) -bpf_error(char *fmt, ...) -#else -bpf_error(fmt, va_alist) - char *fmt; - va_dcl -#endif -{ - va_list ap; - -#if __STDC__ - va_start(ap, fmt); -#else - va_start(ap); -#endif - if (bpf_pcap != NULL) - (void)vsprintf(pcap_geterr(bpf_pcap), fmt, ap); - va_end(ap); - longjmp(top_ctx, 1); - /* NOTREACHED */ -} - -static void init_linktype(int); - -static int alloc_reg(void); -static void free_reg(int); - -static struct block *root; - -/* - * We divy out chunks of memory rather than call malloc each time so - * we don't have to worry about leaking memory. It's probably - * not a big deal if all this memory was wasted but it this ever - * goes into a library that would probably not be a good idea. - */ -#define NCHUNKS 16 -#define CHUNK0SIZE 1024 -struct chunk { - u_int n_left; - void *m; -}; - -static struct chunk chunks[NCHUNKS]; -static int cur_chunk; - -static void *newchunk(u_int); -static void freechunks(void); -static inline struct block *new_block(int); -static inline struct slist *new_stmt(int); -static struct block *gen_retblk(int); -static inline void syntax(void); - -static void backpatch(struct block *, struct block *); -static void merge(struct block *, struct block *); -static struct block *gen_cmp(u_int, u_int, long); -static struct block *gen_mcmp(u_int, u_int, long, u_long); -static struct block *gen_bcmp(u_int, u_int, u_char *); -static struct block *gen_uncond(int); -static inline struct block *gen_true(void); -static inline struct block *gen_false(void); -static struct block *gen_linktype(int); -static struct block *gen_hostop(u_long, u_long, int, int, u_int, u_int); -static struct block *gen_ehostop(u_char *, int); -#ifdef FDDI -static struct block *gen_fhostop(u_char *, int); -#endif -static struct block *gen_dnhostop(u_long, int, u_int); -static struct block *gen_host(u_long, u_long, int, int); -static struct block *gen_gateway(u_char *, u_long **, int, int); -static struct block *gen_ipfrag(void); -static struct block *gen_portatom(int, long); -struct block *gen_portop(int, int, int); -static struct block *gen_port(int, int, int); -static int lookup_proto(char *, int); -static struct block *gen_proto(int, int, int); -static u_long net_mask(u_long *); -static u_long net_mask(u_long *); -static struct slist *xfer_to_x(struct arth *); -static struct slist *xfer_to_a(struct arth *); -static struct block *gen_len(int, int); - -static void * -newchunk(n) - u_int n; -{ - struct chunk *cp; - int k, size; - - /* XXX Round up to nearest long. */ - n = (n + sizeof(long) - 1) & ~(sizeof(long) - 1); - - cp = &chunks[cur_chunk]; - if (n > cp->n_left) { - ++cp, k = ++cur_chunk; - if (k >= NCHUNKS) - bpf_error("out of memory"); - size = CHUNK0SIZE << k; - cp->m = (void *)malloc(size); - memset((char *)cp->m, 0, size); - cp->n_left = size; - if (n > size) - bpf_error("out of memory"); - } - cp->n_left -= n; - return (void *)((char *)cp->m + cp->n_left); -} - -static void -freechunks() -{ - int i; - - for (i = 0; i < NCHUNKS; ++i) - if (chunks[i].m) - free(chunks[i].m); -} - -/* - * A strdup whose allocations are freed after code generation is over. - */ -char * -sdup(s) - char *s; -{ - int n = strlen(s) + 1; - char *cp = newchunk(n); - strcpy(cp, s); - return (cp); -} - -static inline struct block * -new_block(code) - int code; -{ - struct block *p; - - p = (struct block *)newchunk(sizeof(*p)); - p->s.code = code; - p->head = p; - - return p; -} - -static inline struct slist * -new_stmt(code) - int code; -{ - struct slist *p; - - p = (struct slist *)newchunk(sizeof(*p)); - p->s.code = code; - - return p; -} - -static struct block * -gen_retblk(v) - int v; -{ - struct block *b = new_block(BPF_RET|BPF_K); - - b->s.k = v; - return b; -} - -static inline void -syntax() -{ - bpf_error("syntax error in filter expression"); -} - -static u_long netmask; -static int snaplen; - -int -pcap_compile(pcap_t *p, struct bpf_program *program, - char *buf, int optimize, u_long mask) -{ - extern int n_errors; - int len; - - bpf_pcap = p; - if (setjmp(top_ctx)) - return (-1); - - netmask = mask; - snaplen = pcap_snapshot(p); - - lex_init(buf ? buf : ""); - init_linktype(pcap_datalink(p)); - pcap_parse(); - - if (n_errors) - syntax(); - - if (root == NULL) - root = gen_retblk(snaplen); - - if (optimize) { - bpf_optimize(&root); - if (root == NULL || - (root->s.code == (BPF_RET|BPF_K) && root->s.k == 0)) - bpf_error("expression rejects all packets"); - } - program->bf_insns = icode_to_fcode(root, &len); - program->bf_len = len; - - freechunks(); - return (0); -} - -/* - * Backpatch the blocks in 'list' to 'target'. The 'sense' field indicates - * which of the jt and jf fields has been resolved and which is a pointer - * back to another unresolved block (or nil). At least one of the fields - * in each block is already resolved. - */ -static void -backpatch(list, target) - struct block *list, *target; -{ - struct block *next; - - while (list) { - if (!list->sense) { - next = JT(list); - JT(list) = target; - } else { - next = JF(list); - JF(list) = target; - } - list = next; - } -} - -/* - * Merge the lists in b0 and b1, using the 'sense' field to indicate - * which of jt and jf is the link. - */ -static void -merge(b0, b1) - struct block *b0, *b1; -{ - register struct block **p = &b0; - - /* Find end of list. */ - while (*p) - p = !((*p)->sense) ? &JT(*p) : &JF(*p); - - /* Concatenate the lists. */ - *p = b1; -} - -void -finish_parse(p) - struct block *p; -{ - backpatch(p, gen_retblk(snaplen)); - p->sense = !p->sense; - backpatch(p, gen_retblk(0)); - root = p->head; -} - -void -gen_and(b0, b1) - struct block *b0, *b1; -{ - backpatch(b0, b1->head); - b0->sense = !b0->sense; - b1->sense = !b1->sense; - merge(b1, b0); - b1->sense = !b1->sense; - b1->head = b0->head; -} - -void -gen_or(b0, b1) - struct block *b0, *b1; -{ - b0->sense = !b0->sense; - backpatch(b0, b1->head); - b0->sense = !b0->sense; - merge(b1, b0); - b1->head = b0->head; -} - -void -gen_not(b) - struct block *b; -{ - b->sense = !b->sense; -} - -static struct block * -gen_cmp(offset, size, v) - u_int offset, size; - long v; -{ - struct slist *s; - struct block *b; - - s = new_stmt(BPF_LD|BPF_ABS|size); - s->s.k = offset; - - b = new_block(JMP(BPF_JEQ)); - b->stmts = s; - b->s.k = v; - - return b; -} - -static struct block * -gen_mcmp(offset, size, v, mask) - u_int offset, size; - long v; - u_long mask; -{ - struct block *b = gen_cmp(offset, size, v); - struct slist *s; - - if (mask != 0xffffffff) { - s = new_stmt(BPF_ALU|BPF_AND|BPF_K); - s->s.k = mask; - b->stmts->next = s; - } - return b; -} - -static struct block * -gen_bcmp(offset, size, v) - u_int offset, size; - u_char *v; -{ - struct block *b, *tmp; - - b = NULL; - while (size >= 4) { - u_char *p = &v[size - 4]; - long w = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; - tmp = gen_cmp(offset + size - 4, BPF_W, w); - if (b != NULL) - gen_and(b, tmp); - b = tmp; - size -= 4; - } - while (size >= 2) { - u_char *p = &v[size - 2]; - long w = (p[0] << 8) | p[1]; - tmp = gen_cmp(offset + size - 2, BPF_H, w); - if (b != NULL) - gen_and(b, tmp); - b = tmp; - size -= 2; - } - if (size > 0) { - tmp = gen_cmp(offset, BPF_B, (long)v[0]); - if (b != NULL) - gen_and(b, tmp); - b = tmp; - } - return b; -} - -/* - * Various code constructs need to know the layout of the data link - * layer. These variables give the necessary offsets. off_linktype - * is set to -1 for no encapsulation, in which case, IP is assumed. - */ -static u_int off_linktype; -static u_int off_nl; -static int linktype; -#ifdef FDDI -extern int fddipad; -#endif - -static void -init_linktype(type) - int type; -{ - linktype = type; - - switch (type) { - - case DLT_EN10MB: - off_linktype = 12; - off_nl = 14; - return; - - case DLT_SLIP: - /* - * SLIP doesn't have a link level type. The 16 byte - * header is hacked into our SLIP driver. - */ - off_linktype = -1; - off_nl = 16; - return; - - case DLT_NULL: - off_linktype = 0; - off_nl = 4; - return; - - case DLT_PPP: - off_linktype = 2; - off_nl = 4; - return; - -#ifdef FDDI - case DLT_FDDI: - /* - * FDDI doesn't really have a link-level type field. - * We assume that SSAP = SNAP is being used and pick - * out the encapsulated Ethernet type. - */ - off_linktype = 19 + fddipad; - off_nl = 21 + fddipad; - return; -#endif - - case DLT_IEEE802: - off_linktype = 20; - off_nl = 22; - return; - } - bpf_error("unknown data link type 0x%x", linktype); - /* NOTREACHED */ -} - -static struct block * -gen_uncond(rsense) - int rsense; -{ - struct block *b; - struct slist *s; - - s = new_stmt(BPF_LD|BPF_IMM); - s->s.k = !rsense; - b = new_block(JMP(BPF_JEQ)); - b->stmts = s; - - return b; -} - -static inline struct block * -gen_true() -{ - return gen_uncond(1); -} - -static inline struct block * -gen_false() -{ - return gen_uncond(0); -} - -static struct block * -gen_linktype(proto) - int proto; -{ - switch (linktype) { - case DLT_SLIP: - if (proto == ETHERTYPE_IP) - return gen_true(); - else - return gen_false(); - - case DLT_PPP: - if (proto == ETHERTYPE_IP) - proto = 0x0021; /* XXX - need ppp.h defs */ - break; - - case DLT_NULL: - if (proto == ETHERTYPE_IP) { - proto = htonl(AF_INET); /* loopback & tun put */ - /* sa_family into */ - /* prepended word */ - return gen_cmp(off_linktype, BPF_W, (long)proto); - } - break; - } - return gen_cmp(off_linktype, BPF_H, (long)proto); -} - -static struct block * -gen_hostop(addr, mask, dir, proto, src_off, dst_off) - u_long addr; - u_long mask; - int dir, proto; - u_int src_off, dst_off; -{ - struct block *b0, *b1; - u_int offset; - - switch (dir) { - - case Q_SRC: - offset = src_off; - break; - - case Q_DST: - offset = dst_off; - break; - - case Q_AND: - b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off); - b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off); - gen_and(b0, b1); - return b1; - - case Q_OR: - case Q_DEFAULT: - b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off); - b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off); - gen_or(b0, b1); - return b1; - - default: - abort(); - } - b0 = gen_linktype(proto); - b1 = gen_mcmp(offset, BPF_W, (long)addr, mask); - gen_and(b0, b1); - return b1; -} - -static struct block * -gen_ehostop(eaddr, dir) - u_char *eaddr; - int dir; -{ - struct block *b0, *b1; - - switch (dir) { - case Q_SRC: - return gen_bcmp(6, 6, eaddr); - - case Q_DST: - return gen_bcmp(0, 6, eaddr); - - case Q_AND: - b0 = gen_ehostop(eaddr, Q_SRC); - b1 = gen_ehostop(eaddr, Q_DST); - gen_and(b0, b1); - return b1; - - case Q_DEFAULT: - case Q_OR: - b0 = gen_ehostop(eaddr, Q_SRC); - b1 = gen_ehostop(eaddr, Q_DST); - gen_or(b0, b1); - return b1; - } - abort(); - /* NOTREACHED */ -} - -#ifdef FDDI -/* - * Like gen_ehostop, but for DLT_FDDI - */ -static struct block * -gen_fhostop(eaddr, dir) - u_char *eaddr; - int dir; -{ - struct block *b0, *b1; - - switch (dir) { - case Q_SRC: - return gen_bcmp(6 + 1 + fddipad, 6, eaddr); - - case Q_DST: - return gen_bcmp(0 + 1 + fddipad, 6, eaddr); - - case Q_AND: - b0 = gen_fhostop(eaddr, Q_SRC); - b1 = gen_fhostop(eaddr, Q_DST); - gen_and(b0, b1); - return b1; - - case Q_DEFAULT: - case Q_OR: - b0 = gen_fhostop(eaddr, Q_SRC); - b1 = gen_fhostop(eaddr, Q_DST); - gen_or(b0, b1); - return b1; - } - abort(); - /* NOTREACHED */ -} -#endif - -/* - * This is quite tricky because there may be pad bytes in front of the - * DECNET header, and then there are two possible data packet formats that - * carry both src and dst addresses, plus 5 packet types in a format that - * carries only the src node, plus 2 types that use a different format and - * also carry just the src node. - * - * Yuck. - * - * Instead of doing those all right, we just look for data packets with - * 0 or 1 bytes of padding. If you want to look at other packets, that - * will require a lot more hacking. - * - * To add support for filtering on DECNET "areas" (network numbers) - * one would want to add a "mask" argument to this routine. That would - * make the filter even more inefficient, although one could be clever - * and not generate masking instructions if the mask is 0xFFFF. - */ -static struct block * -gen_dnhostop(addr, dir, base_off) - u_long addr; - int dir; - u_int base_off; -{ - struct block *b0, *b1, *b2, *tmp; - u_int offset_lh; /* offset if long header is received */ - u_int offset_sh; /* offset if short header is received */ - - switch (dir) { - - case Q_DST: - offset_sh = 1; /* follows flags */ - offset_lh = 7; /* flgs,darea,dsubarea,HIORD */ - break; - - case Q_SRC: - offset_sh = 3; /* follows flags, dstnode */ - offset_lh = 15; /* flgs,darea,dsubarea,did,sarea,ssub,HIORD */ - break; - - case Q_AND: - /* Inefficient because we do our Calvinball dance twice */ - b0 = gen_dnhostop(addr, Q_SRC, base_off); - b1 = gen_dnhostop(addr, Q_DST, base_off); - gen_and(b0, b1); - return b1; - - case Q_OR: - case Q_DEFAULT: - /* Inefficient because we do our Calvinball dance twice */ - b0 = gen_dnhostop(addr, Q_SRC, base_off); - b1 = gen_dnhostop(addr, Q_DST, base_off); - gen_or(b0, b1); - return b1; - - default: - abort(); - } - b0 = gen_linktype(ETHERTYPE_DN); - /* Check for pad = 1, long header case */ - tmp = gen_mcmp(base_off + 2, BPF_H, - (long)ntohs(0x0681), (long)ntohs(0x07FF)); - b1 = gen_cmp(base_off + 2 + 1 + offset_lh, BPF_H, (long)ntohs(addr)); - gen_and(tmp, b1); - /* Check for pad = 0, long header case */ - tmp = gen_mcmp(base_off + 2, BPF_B, (long)0x06, (long)0x7); - b2 = gen_cmp(base_off + 2 + offset_lh, BPF_H, (long)ntohs(addr)); - gen_and(tmp, b2); - gen_or(b2, b1); - /* Check for pad = 1, short header case */ - tmp = gen_mcmp(base_off + 2, BPF_H, - (long)ntohs(0x0281), (long)ntohs(0x07FF)); - b2 = gen_cmp(base_off + 2 + 1 + offset_sh, BPF_H, (long)ntohs(addr)); - gen_and(tmp, b2); - gen_or(b2, b1); - /* Check for pad = 0, short header case */ - tmp = gen_mcmp(base_off + 2, BPF_B, (long)0x02, (long)0x7); - b2 = gen_cmp(base_off + 2 + offset_sh, BPF_H, (long)ntohs(addr)); - gen_and(tmp, b2); - gen_or(b2, b1); - - /* Combine with test for linktype */ - gen_and(b0, b1); - return b1; -} - -static struct block * -gen_host(addr, mask, proto, dir) - u_long addr; - u_long mask; - int proto; - int dir; -{ - struct block *b0, *b1; - - switch (proto) { - - case Q_DEFAULT: - b0 = gen_host(addr, mask, Q_IP, dir); - b1 = gen_host(addr, mask, Q_ARP, dir); - gen_or(b0, b1); - b0 = gen_host(addr, mask, Q_RARP, dir); - gen_or(b1, b0); - return b0; - - case Q_IP: - return gen_hostop(addr, mask, dir, ETHERTYPE_IP, - off_nl + 12, off_nl + 16); - - case Q_RARP: - return gen_hostop(addr, mask, dir, ETHERTYPE_REVARP, - off_nl + 14, off_nl + 24); - - case Q_ARP: - return gen_hostop(addr, mask, dir, ETHERTYPE_ARP, - off_nl + 14, off_nl + 24); - - case Q_TCP: - bpf_error("'tcp' modifier applied to host"); - - case Q_UDP: - bpf_error("'udp' modifier applied to host"); - - case Q_ICMP: - bpf_error("'icmp' modifier applied to host"); - - case Q_DECNET: - return gen_dnhostop(addr, dir, off_nl); - - case Q_LAT: - bpf_error("LAT host filtering not implemented"); - - case Q_MOPDL: - bpf_error("MOPDL host filtering not implemented"); - - case Q_MOPRC: - bpf_error("MOPRC host filtering not implemented"); - - default: - abort(); - } - /* NOTREACHED */ -} - -static struct block * -gen_gateway(eaddr, alist, proto, dir) - u_char *eaddr; - u_long **alist; - int proto; - int dir; -{ - struct block *b0, *b1, *tmp; - - if (dir != 0) - bpf_error("direction applied to 'gateway'"); - - switch (proto) { - case Q_DEFAULT: - case Q_IP: - case Q_ARP: - case Q_RARP: - if (linktype == DLT_EN10MB) - b0 = gen_ehostop(eaddr, Q_OR); -#ifdef FDDI - else if (linktype == DLT_FDDI) - b0 = gen_fhostop(eaddr, Q_OR); -#endif - else - bpf_error("'gateway' supported only on ethernet or FDDI"); - - b1 = gen_host(**alist++, 0xffffffffL, proto, Q_OR); - while (*alist) { - tmp = gen_host(**alist++, 0xffffffffL, proto, Q_OR); - gen_or(b1, tmp); - b1 = tmp; - } - gen_not(b1); - gen_and(b0, b1); - return b1; - } - bpf_error("illegal modifier of 'gateway'"); - /* NOTREACHED */ -} - -struct block * -gen_proto_abbrev(proto) - int proto; -{ - struct block *b0, *b1; - - switch (proto) { - - case Q_TCP: - b0 = gen_linktype(ETHERTYPE_IP); - b1 = gen_cmp(off_nl + 9, BPF_B, (long)IPPROTO_TCP); - gen_and(b0, b1); - break; - - case Q_UDP: - b0 = gen_linktype(ETHERTYPE_IP); - b1 = gen_cmp(off_nl + 9, BPF_B, (long)IPPROTO_UDP); - gen_and(b0, b1); - break; - - case Q_ICMP: - b0 = gen_linktype(ETHERTYPE_IP); - b1 = gen_cmp(off_nl + 9, BPF_B, (long)IPPROTO_ICMP); - gen_and(b0, b1); - break; - - case Q_IP: - b1 = gen_linktype(ETHERTYPE_IP); - break; - - case Q_ARP: - b1 = gen_linktype(ETHERTYPE_ARP); - break; - - case Q_RARP: - b1 = gen_linktype(ETHERTYPE_REVARP); - break; - - case Q_LINK: - bpf_error("link layer applied in wrong context"); - - case Q_DECNET: - b1 = gen_linktype(ETHERTYPE_DN); - break; - - case Q_LAT: - b1 = gen_linktype(ETHERTYPE_LAT); - break; - - case Q_MOPDL: - b1 = gen_linktype(ETHERTYPE_MOPDL); - break; - - case Q_MOPRC: - b1 = gen_linktype(ETHERTYPE_MOPRC); - break; - - default: - abort(); - } - return b1; -} - -static struct block * -gen_ipfrag() -{ - struct slist *s; - struct block *b; - - /* not ip frag */ - s = new_stmt(BPF_LD|BPF_H|BPF_ABS); - s->s.k = off_nl + 6; - b = new_block(JMP(BPF_JSET)); - b->s.k = 0x1fff; - b->stmts = s; - gen_not(b); - - return b; -} - -static struct block * -gen_portatom(off, v) - int off; - long v; -{ - struct slist *s; - struct block *b; - - s = new_stmt(BPF_LDX|BPF_MSH|BPF_B); - s->s.k = off_nl; - - s->next = new_stmt(BPF_LD|BPF_IND|BPF_H); - s->next->s.k = off_nl + off; - - b = new_block(JMP(BPF_JEQ)); - b->stmts = s; - b->s.k = v; - - return b; -} - -struct block * -gen_portop(port, proto, dir) - int port, proto, dir; -{ - struct block *b0, *b1, *tmp; - - /* ip proto 'proto' */ - tmp = gen_cmp(off_nl + 9, BPF_B, (long)proto); - b0 = gen_ipfrag(); - gen_and(tmp, b0); - - switch (dir) { - case Q_SRC: - b1 = gen_portatom(0, (long)port); - break; - - case Q_DST: - b1 = gen_portatom(2, (long)port); - break; - - case Q_OR: - case Q_DEFAULT: - tmp = gen_portatom(0, (long)port); - b1 = gen_portatom(2, (long)port); - gen_or(tmp, b1); - break; - - case Q_AND: - tmp = gen_portatom(0, (long)port); - b1 = gen_portatom(2, (long)port); - gen_and(tmp, b1); - break; - - default: - abort(); - } - gen_and(b0, b1); - - return b1; -} - -static struct block * -gen_port(port, ip_proto, dir) - int port; - int ip_proto; - int dir; -{ - struct block *b0, *b1, *tmp; - - /* ether proto ip */ - b0 = gen_linktype(ETHERTYPE_IP); - - switch (ip_proto) { - case IPPROTO_UDP: - case IPPROTO_TCP: - b1 = gen_portop(port, ip_proto, dir); - break; - - case PROTO_UNDEF: - tmp = gen_portop(port, IPPROTO_TCP, dir); - b1 = gen_portop(port, IPPROTO_UDP, dir); - gen_or(tmp, b1); - break; - - default: - abort(); - } - gen_and(b0, b1); - return b1; -} - -static int -lookup_proto(name, proto) - char *name; - int proto; -{ - int v; - - switch (proto) { - case Q_DEFAULT: - case Q_IP: - v = pcap_nametoproto(name); - if (v == PROTO_UNDEF) - bpf_error("unknown ip proto '%s'", name); - break; - - case Q_LINK: - /* XXX should look up h/w protocol type based on linktype */ - v = pcap_nametoeproto(name); - if (v == PROTO_UNDEF) - bpf_error("unknown ether proto '%s'", name); - break; - - default: - v = PROTO_UNDEF; - break; - } - return v; -} - -static struct block * -gen_proto(v, proto, dir) - int v; - int proto; - int dir; -{ - struct block *b0, *b1; - - if (dir != Q_DEFAULT) - bpf_error("direction applied to 'proto'"); - - switch (proto) { - case Q_DEFAULT: - case Q_IP: - b0 = gen_linktype(ETHERTYPE_IP); - b1 = gen_cmp(off_nl + 9, BPF_B, (long)v); - gen_and(b0, b1); - return b1; - - case Q_ARP: - bpf_error("arp does not encapsulate another protocol"); - /* NOTREACHED */ - - case Q_RARP: - bpf_error("rarp does not encapsulate another protocol"); - /* NOTREACHED */ - - case Q_DECNET: - bpf_error("decnet encapsulation is not specifiable"); - /* NOTREACHED */ - - case Q_LAT: - bpf_error("lat does not encapsulate another protocol"); - /* NOTREACHED */ - - case Q_MOPRC: - bpf_error("moprc does not encapsulate another protocol"); - /* NOTREACHED */ - - case Q_MOPDL: - bpf_error("mopdl does not encapsulate another protocol"); - /* NOTREACHED */ - - case Q_LINK: - return gen_linktype(v); - - case Q_UDP: - bpf_error("'udp proto' is bogus"); - /* NOTREACHED */ - - case Q_TCP: - bpf_error("'tcp proto' is bogus"); - /* NOTREACHED */ - - case Q_ICMP: - bpf_error("'icmp proto' is bogus"); - /* NOTREACHED */ - - default: - abort(); - /* NOTREACHED */ - } - /* NOTREACHED */ -} - -/* - * Left justify 'addr' and return its resulting network mask. - */ -static u_long -net_mask(addr) - u_long *addr; -{ - register u_long m = 0xffffffff; - - if (*addr) - while ((*addr & 0xff000000) == 0) - *addr <<= 8, m <<= 8; - - return m; -} - -struct block * -gen_scode(name, q) - char *name; - struct qual q; -{ - int proto = q.proto; - int dir = q.dir; - u_char *eaddr; - u_long mask, addr, **alist; - struct block *b, *tmp; - int port, real_proto; - - switch (q.addr) { - - case Q_NET: - addr = pcap_nametonetaddr(name); - if (addr == 0) - bpf_error("unknown network '%s'", name); - mask = net_mask(&addr); - return gen_host(addr, mask, proto, dir); - - case Q_DEFAULT: - case Q_HOST: - if (proto == Q_LINK) { - switch (linktype) { - case DLT_EN10MB: - eaddr = pcap_ether_hostton(name); - if (eaddr == NULL) - bpf_error("unknown ether host '%s'", name); - return gen_ehostop(eaddr, dir); - -#ifdef FDDI - case DLT_FDDI: - eaddr = pcap_ether_hostton(name); - if (eaddr == NULL) - bpf_error("unknown FDDI host '%s'", name); - return gen_fhostop(eaddr, dir); -#endif - default: - bpf_error("only ethernet/FDDI supports link-level host name"); - break; - } - } else if (proto == Q_DECNET) { - unsigned short dn_addr = __pcap_nametodnaddr(name); - /* - * I don't think DECNET hosts can be multihomed, so - * there is no need to build up a list of addresses - */ - return (gen_host(dn_addr, 0, proto, dir)); - } else { - alist = pcap_nametoaddr(name); - if (alist == NULL || *alist == NULL) - bpf_error("unknown host '%s'", name); - b = gen_host(**alist++, 0xffffffffL, proto, dir); - while (*alist) { - tmp = gen_host(**alist++, 0xffffffffL, - proto, dir); - gen_or(b, tmp); - b = tmp; - } - return b; - } - - case Q_PORT: - if (proto != Q_DEFAULT && proto != Q_UDP && proto != Q_TCP) - bpf_error("illegal qualifier of 'port'"); - if (pcap_nametoport(name, &port, &real_proto) == 0) - bpf_error("unknown port '%s'", name); - if (proto == Q_UDP) { - if (real_proto == IPPROTO_TCP) - bpf_error("port '%s' is tcp", name); - else - /* override PROTO_UNDEF */ - real_proto = IPPROTO_UDP; - } - if (proto == Q_TCP) { - if (real_proto == IPPROTO_UDP) - bpf_error("port '%s' is udp", name); - else - /* override PROTO_UNDEF */ - real_proto = IPPROTO_TCP; - } - return gen_port(port, real_proto, dir); - - case Q_GATEWAY: - eaddr = pcap_ether_hostton(name); - if (eaddr == NULL) - bpf_error("unknown ether host: %s", name); - - alist = pcap_nametoaddr(name); - if (alist == NULL || *alist == NULL) - bpf_error("unknown host '%s'", name); - return gen_gateway(eaddr, alist, proto, dir); - - case Q_PROTO: - real_proto = lookup_proto(name, proto); - if (real_proto >= 0) - return gen_proto(real_proto, proto, dir); - else - bpf_error("unknown protocol: %s", name); - - case Q_UNDEF: - syntax(); - /* NOTREACHED */ - } - abort(); - /* NOTREACHED */ -} - -struct block * -gen_ncode(v, q) - u_long v; - struct qual q; -{ - u_long mask; - int proto = q.proto; - int dir = q.dir; - - switch (q.addr) { - - case Q_DEFAULT: - case Q_HOST: - case Q_NET: - if (proto == Q_DECNET) - return gen_host(v, 0, proto, dir); - else if (proto == Q_LINK) { - bpf_error("illegal link layer address"); - } else { - mask = net_mask(&v); - return gen_host(v, mask, proto, dir); - } - - case Q_PORT: - if (proto == Q_UDP) - proto = IPPROTO_UDP; - else if (proto == Q_TCP) - proto = IPPROTO_TCP; - else if (proto == Q_DEFAULT) - proto = PROTO_UNDEF; - else - bpf_error("illegal qualifier of 'port'"); - - return gen_port((int)v, proto, dir); - - case Q_GATEWAY: - bpf_error("'gateway' requires a name"); - /* NOTREACHED */ - - case Q_PROTO: - return gen_proto((int)v, proto, dir); - - case Q_UNDEF: - syntax(); - /* NOTREACHED */ - - default: - abort(); - /* NOTREACHED */ - } - /* NOTREACHED */ -} - -struct block * -gen_ecode(eaddr, q) - u_char *eaddr; - struct qual q; -{ - if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) { - if (linktype == DLT_EN10MB) - return gen_ehostop(eaddr, (int)q.dir); -#ifdef FDDI - if (linktype == DLT_FDDI) - return gen_fhostop(eaddr, (int)q.dir); -#endif - } - bpf_error("ethernet address used in non-ether expression"); - /* NOTREACHED */ -} - -void -sappend(s0, s1) - struct slist *s0, *s1; -{ - /* - * This is definitely not the best way to do this, but the - * lists will rarely get long. - */ - while (s0->next) - s0 = s0->next; - s0->next = s1; -} - -static struct slist * -xfer_to_x(a) - struct arth *a; -{ - struct slist *s; - - s = new_stmt(BPF_LDX|BPF_MEM); - s->s.k = a->regno; - return s; -} - -static struct slist * -xfer_to_a(a) - struct arth *a; -{ - struct slist *s; - - s = new_stmt(BPF_LD|BPF_MEM); - s->s.k = a->regno; - return s; -} - -struct arth * -gen_load(proto, index, size) - int proto; - struct arth *index; - int size; -{ - struct slist *s, *tmp; - struct block *b; - int regno = alloc_reg(); - - free_reg(index->regno); - switch (size) { - - default: - bpf_error("data size must be 1, 2, or 4"); - - case 1: - size = BPF_B; - break; - - case 2: - size = BPF_H; - break; - - case 4: - size = BPF_W; - break; - } - switch (proto) { - default: - bpf_error("unsupported index operation"); - - case Q_LINK: - s = xfer_to_x(index); - tmp = new_stmt(BPF_LD|BPF_IND|size); - sappend(s, tmp); - sappend(index->s, s); - break; - - case Q_IP: - case Q_ARP: - case Q_RARP: - case Q_DECNET: - case Q_LAT: - case Q_MOPRC: - case Q_MOPDL: - /* XXX Note that we assume a fixed link link header here. */ - s = xfer_to_x(index); - tmp = new_stmt(BPF_LD|BPF_IND|size); - tmp->s.k = off_nl; - sappend(s, tmp); - sappend(index->s, s); - - b = gen_proto_abbrev(proto); - if (index->b) - gen_and(index->b, b); - index->b = b; - break; - - case Q_TCP: - case Q_UDP: - case Q_ICMP: - s = new_stmt(BPF_LDX|BPF_MSH|BPF_B); - s->s.k = off_nl; - sappend(s, xfer_to_a(index)); - sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X)); - sappend(s, new_stmt(BPF_MISC|BPF_TAX)); - sappend(s, tmp = new_stmt(BPF_LD|BPF_IND|size)); - tmp->s.k = off_nl; - sappend(index->s, s); - - gen_and(gen_proto_abbrev(proto), b = gen_ipfrag()); - if (index->b) - gen_and(index->b, b); - index->b = b; - break; - } - index->regno = regno; - s = new_stmt(BPF_ST); - s->s.k = regno; - sappend(index->s, s); - - return index; -} - -struct block * -gen_relation(code, a0, a1, reversed) - int code; - struct arth *a0, *a1; - int reversed; -{ - struct slist *s0, *s1, *s2; - struct block *b, *tmp; - - s0 = xfer_to_x(a1); - s1 = xfer_to_a(a0); - s2 = new_stmt(BPF_ALU|BPF_SUB|BPF_X); - b = new_block(JMP(code)); - if (reversed) - gen_not(b); - - sappend(s1, s2); - sappend(s0, s1); - sappend(a1->s, s0); - sappend(a0->s, a1->s); - - b->stmts = a0->s; - - free_reg(a0->regno); - free_reg(a1->regno); - - /* 'and' together protocol checks */ - if (a0->b) { - if (a1->b) { - gen_and(a0->b, tmp = a1->b); - } - else - tmp = a0->b; - } else - tmp = a1->b; - - if (tmp) - gen_and(tmp, b); - - return b; -} - -struct arth * -gen_loadlen() -{ - int regno = alloc_reg(); - struct arth *a = (struct arth *)newchunk(sizeof(*a)); - struct slist *s; - - s = new_stmt(BPF_LD|BPF_LEN); - s->next = new_stmt(BPF_ST); - s->next->s.k = regno; - a->s = s; - a->regno = regno; - - return a; -} - -struct arth * -gen_loadi(val) - int val; -{ - struct arth *a; - struct slist *s; - int reg; - - a = (struct arth *)newchunk(sizeof(*a)); - - reg = alloc_reg(); - - s = new_stmt(BPF_LD|BPF_IMM); - s->s.k = val; - s->next = new_stmt(BPF_ST); - s->next->s.k = reg; - a->s = s; - a->regno = reg; - - return a; -} - -struct arth * -gen_neg(a) - struct arth *a; -{ - struct slist *s; - - s = xfer_to_a(a); - sappend(a->s, s); - s = new_stmt(BPF_ALU|BPF_NEG); - s->s.k = 0; - sappend(a->s, s); - s = new_stmt(BPF_ST); - s->s.k = a->regno; - sappend(a->s, s); - - return a; -} - -struct arth * -gen_arth(code, a0, a1) - int code; - struct arth *a0, *a1; -{ - struct slist *s0, *s1, *s2; - - s0 = xfer_to_x(a1); - s1 = xfer_to_a(a0); - s2 = new_stmt(BPF_ALU|BPF_X|code); - - sappend(s1, s2); - sappend(s0, s1); - sappend(a1->s, s0); - sappend(a0->s, a1->s); - - free_reg(a1->regno); - - s0 = new_stmt(BPF_ST); - a0->regno = s0->s.k = alloc_reg(); - sappend(a0->s, s0); - - return a0; -} - -/* - * Here we handle simple allocation of the scratch registers. - * If too many registers are alloc'd, the allocator punts. - */ -static int regused[BPF_MEMWORDS]; -static int curreg; - -/* - * Return the next free register. - */ -static int -alloc_reg() -{ - int n = BPF_MEMWORDS; - - while (--n >= 0) { - if (regused[curreg]) - curreg = (curreg + 1) % BPF_MEMWORDS; - else { - regused[curreg] = 1; - return curreg; - } - } - bpf_error("too many registers needed to evaluate expression"); - /* NOTREACHED */ -} - -/* - * Return a register to the table so it can - * be used later. - */ -static void -free_reg(n) - int n; -{ - regused[n] = 0; -} - -static struct block * -gen_len(jmp, n) - int jmp, n; -{ - struct slist *s; - struct block *b; - - s = new_stmt(BPF_LD|BPF_LEN); - s->next = new_stmt(BPF_ALU|BPF_SUB|BPF_K); - s->next->s.k = n; - b = new_block(JMP(jmp)); - b->stmts = s; - - return b; -} - -struct block * -gen_greater(n) - int n; -{ - return gen_len(BPF_JGE, n); -} - -struct block * -gen_less(n) - int n; -{ - struct block *b; - - b = gen_len(BPF_JGT, n); - gen_not(b); - - return b; -} - -struct block * -gen_byteop(op, idx, val) - int op, idx, val; -{ - struct block *b; - struct slist *s; - - switch (op) { - default: - abort(); - - case '=': - return gen_cmp((u_int)idx, BPF_B, (long)val); - - case '<': - b = gen_cmp((u_int)idx, BPF_B, (long)val); - b->s.code = JMP(BPF_JGE); - gen_not(b); - return b; - - case '>': - b = gen_cmp((u_int)idx, BPF_B, (long)val); - b->s.code = JMP(BPF_JGT); - return b; - - case '|': - s = new_stmt(BPF_ALU|BPF_OR|BPF_K); - break; - - case '&': - s = new_stmt(BPF_ALU|BPF_AND|BPF_K); - break; - } - s->s.k = val; - b = new_block(JMP(BPF_JEQ)); - b->stmts = s; - gen_not(b); - - return b; -} - -struct block * -gen_broadcast(proto) - int proto; -{ - u_long hostmask; - struct block *b0, *b1, *b2; - static u_char ebroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - - switch (proto) { - - case Q_DEFAULT: - case Q_LINK: - if (linktype == DLT_EN10MB) - return gen_ehostop(ebroadcast, Q_DST); -#ifdef FDDI - if (linktype == DLT_FDDI) - return gen_fhostop(ebroadcast, Q_DST); -#endif - bpf_error("not a broadcast link"); - break; - - case Q_IP: - b0 = gen_linktype(ETHERTYPE_IP); - hostmask = ~netmask; - b1 = gen_mcmp(off_nl + 16, BPF_W, (long)0, hostmask); - b2 = gen_mcmp(off_nl + 16, BPF_W, - (long)(~0 & hostmask), hostmask); - gen_or(b1, b2); - gen_and(b0, b2); - return b2; - } - bpf_error("only ether/ip broadcast filters supported"); -} - -struct block * -gen_multicast(proto) - int proto; -{ - register struct block *b0, *b1; - register struct slist *s; - - switch (proto) { - - case Q_DEFAULT: - case Q_LINK: - if (linktype == DLT_EN10MB) { - /* ether[0] & 1 != 0 */ - s = new_stmt(BPF_LD|BPF_B|BPF_ABS); - s->s.k = 0; - b0 = new_block(JMP(BPF_JSET)); - b0->s.k = 1; - b0->stmts = s; - return b0; - } - - if (linktype == DLT_FDDI) { - /* XXX TEST THIS: MIGHT NOT PORT PROPERLY XXX */ - /* fddi[1] & 1 != 0 */ - s = new_stmt(BPF_LD|BPF_B|BPF_ABS); - s->s.k = 1; - b0 = new_block(JMP(BPF_JSET)); - b0->s.k = 1; - b0->stmts = s; - return b0; - } - /* Link not known to support multicasts */ - break; - - case Q_IP: - b0 = gen_linktype(ETHERTYPE_IP); - b1 = gen_cmp(off_nl + 16, BPF_B, (long)224); - b1->s.code = JMP(BPF_JGE); - gen_and(b0, b1); - return b1; - } - bpf_error("only IP multicast filters supported on ethernet/FDDI"); -} - -/* - * generate command for inbound/outbound. It's here so we can - * make it link-type specific. 'dir' = 0 implies "inbound", - * = 1 implies "outbound". - */ -struct block * -gen_inbound(dir) - int dir; -{ - register struct block *b0; - - b0 = gen_relation(BPF_JEQ, - gen_load(Q_LINK, gen_loadi(0), 1), - gen_loadi(0), - dir); - return (b0); -} diff --git a/lib/libpcap/gencode.h b/lib/libpcap/gencode.h deleted file mode 100644 index 34d4c19..0000000 --- a/lib/libpcap/gencode.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (c) 1990, 1991, 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that: (1) source code distributions - * retain the above copyright notice and this paragraph in its entirety, (2) - * distributions including binary code include the above copyright notice and - * this paragraph in its entirety in the documentation or other materials - * provided with the distribution, and (3) all advertising materials mentioning - * features or use of this software display the following acknowledgement: - * ``This product includes software developed by the University of California, - * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of - * the University nor the names of its contributors may be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * @(#) $Header: /home/ncvs/src/lib/libpcap/gencode.h,v 1.1.1.1 1995/01/20 04:13:06 jkh Exp $ (LBL) - */ - -/* - * filter.h must be included before this file. - */ - -/* Address qualifers. */ - -#define Q_HOST 1 -#define Q_NET 2 -#define Q_PORT 3 -#define Q_GATEWAY 4 -#define Q_PROTO 5 - -/* Protocol qualifiers. */ - -#define Q_LINK 1 -#define Q_IP 2 -#define Q_ARP 3 -#define Q_RARP 4 -#define Q_TCP 5 -#define Q_UDP 6 -#define Q_ICMP 7 - -#define Q_DECNET 8 -#define Q_LAT 9 -#define Q_MOPRC 10 -#define Q_MOPDL 11 - -/* Directional qualifers. */ - -#define Q_SRC 1 -#define Q_DST 2 -#define Q_OR 3 -#define Q_AND 4 - -#define Q_DEFAULT 0 -#define Q_UNDEF 255 - -struct stmt { - int code; - long k; -}; - -struct slist { - struct stmt s; - struct slist *next; -}; - -/* - * A bit vector to represent definition sets. We assume TOT_REGISTERS - * is smaller than 8*sizeof(atomset). - */ -typedef u_long atomset; -#define ATOMMASK(n) (1 << (n)) -#define ATOMELEM(d, n) (d & ATOMMASK(n)) - -/* - * An unbounded set. - */ -typedef u_long *uset; - -/* - * Total number of atomic entities, including accumulator (A) and index (X). - * We treat all these guys similarly during flow analysis. - */ -#define N_ATOMS (BPF_MEMWORDS+2) - -struct edge { - int id; - int code; - uset edom; - struct block *succ; - struct block *pred; - struct edge *next; /* link list of incoming edges for a node */ -}; - -struct block { - int id; - struct slist *stmts; /* side effect stmts */ - struct stmt s; /* branch stmt */ - int mark; - int level; - int offset; - int sense; - struct edge et; - struct edge ef; - struct block *head; - struct block *link; /* link field used by optimizer */ - uset dom; - uset closure; - struct edge *in_edges; - atomset def, kill; - atomset in_use; - atomset out_use; - long oval; - long val[N_ATOMS]; -}; - -struct arth { - struct block *b; /* protocol checks */ - struct slist *s; /* stmt list */ - int regno; /* virtual register number of result */ -}; - -struct qual { - unsigned char addr; - unsigned char proto; - unsigned char dir; - unsigned char pad; -}; - -#ifndef __GNUC__ -#define volatile -#endif - -struct arth *gen_loadi(int); -struct arth *gen_load(int, struct arth *, int); -struct arth *gen_loadlen(void); -struct arth *gen_neg(struct arth *); -struct arth *gen_arth(int, struct arth *, struct arth *); - -void gen_and(struct block *, struct block *); -void gen_or(struct block *, struct block *); -void gen_not(struct block *); - -struct block *gen_scode(char *, struct qual); -struct block *gen_ecode(u_char *, struct qual); -struct block *gen_ncode(u_long, struct qual); -struct block *gen_proto_abbrev(int); -struct block *gen_relation(int, struct arth *, struct arth *, int); -struct block *gen_less(int); -struct block *gen_greater(int); -struct block *gen_byteop(int, int, int); -struct block *gen_broadcast(int); -struct block *gen_multicast(int); -struct block *gen_inbound(int); - -void bpf_optimize(struct block **); -volatile void bpf_error(char *, ...); - -void finish_parse(struct block *); -char *sdup(char *); - -struct bpf_insn *icode_to_fcode(struct block *, int *); -int pcap_parse(void); -void lex_init(char *); -void sappend(struct slist *, struct slist *); - -/* XXX */ -#define JT(b) ((b)->et.succ) -#define JF(b) ((b)->ef.succ) diff --git a/lib/libpcap/grammar.y b/lib/libpcap/grammar.y deleted file mode 100644 index 4c17bdc..0000000 --- a/lib/libpcap/grammar.y +++ /dev/null @@ -1,266 +0,0 @@ -%{ -/* - * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that: (1) source code distributions - * retain the above copyright notice and this paragraph in its entirety, (2) - * distributions including binary code include the above copyright notice and - * this paragraph in its entirety in the documentation or other materials - * provided with the distribution, and (3) all advertising materials mentioning - * features or use of this software display the following acknowledgement: - * ``This product includes software developed by the University of California, - * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of - * the University nor the names of its contributors may be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - */ -#ifndef lint -static char rcsid[] = - "@(#) $Header: /home/ncvs/src/lib/libpcap/grammar.y,v 1.1.1.1 1995/01/20 04:13:06 jkh Exp $ (LBL)"; -#endif - -#include <sys/types.h> -#include <sys/time.h> -#include <sys/socket.h> - -#include <net/if.h> -#include <net/bpf.h> - -#include <netinet/in.h> -#include <netinet/if_ether.h> - -#include <stdio.h> -#include <pcap.h> -#include <pcap-namedb.h> - -#include "gencode.h" - -#define yylval pcap_lval - -#define QSET(q, p, d, a) (q).proto = (p),\ - (q).dir = (d),\ - (q).addr = (a) - -int n_errors = 0; - -static struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF }; - -static void -yyerror(char *msg) -{ - ++n_errors; - bpf_error(msg); - /* NOTREACHED */ -} - -#ifndef YYBISON -pcap_parse() -{ - return (yyparse()); -} -#endif - -%} - -%union { - int i; - u_long h; - u_char *e; - char *s; - struct stmt *stmt; - struct arth *a; - struct { - struct qual q; - struct block *b; - } blk; - struct block *rblk; -} - -%type <blk> expr id nid pid term rterm qid -%type <blk> head -%type <i> pqual dqual aqual ndaqual -%type <a> arth narth -%type <i> byteop pname pnum relop irelop -%type <blk> and or paren not null prog -%type <rblk> other - -%token DST SRC HOST GATEWAY -%token NET PORT LESS GREATER PROTO BYTE -%token ARP RARP IP TCP UDP ICMP -%token DECNET LAT MOPRC MOPDL -%token TK_BROADCAST TK_MULTICAST -%token NUM INBOUND OUTBOUND -%token LINK -%token GEQ LEQ NEQ -%token ID EID HID -%token LSH RSH -%token LEN - -%type <s> ID -%type <e> EID -%type <h> HID -%type <i> NUM - -%left OR AND -%nonassoc '!' -%left '|' -%left '&' -%left LSH RSH -%left '+' '-' -%left '*' '/' -%nonassoc UMINUS -%% -prog: null expr -{ - finish_parse($2.b); -} - | null - ; -null: /* null */ { $$.q = qerr; } - ; -expr: term - | expr and term { gen_and($1.b, $3.b); $$ = $3; } - | expr and id { gen_and($1.b, $3.b); $$ = $3; } - | expr or term { gen_or($1.b, $3.b); $$ = $3; } - | expr or id { gen_or($1.b, $3.b); $$ = $3; } - ; -and: AND { $$ = $<blk>0; } - ; -or: OR { $$ = $<blk>0; } - ; -id: nid - | pnum { $$.b = gen_ncode((u_long)$1, - $$.q = $<blk>0.q); } - | paren pid ')' { $$ = $2; } - ; -nid: ID { $$.b = gen_scode($1, $$.q = $<blk>0.q); } - | HID { - /* Decide how to parse HID based on proto */ - $$.q = $<blk>0.q; - switch ($$.q.proto) { - case Q_DECNET: - $$.b = - gen_ncode(__pcap_atodn((char *)$1), - $$.q); - break; - default: - $$.b = - gen_ncode(__pcap_atoin((char *)$1), - $$.q); - break; - } - } - | EID { $$.b = gen_ecode($1, $$.q = $<blk>0.q); } - | not id { gen_not($2.b); $$ = $2; } - ; -not: '!' { $$ = $<blk>0; } - ; -paren: '(' { $$ = $<blk>0; } - ; -pid: nid - | qid and id { gen_and($1.b, $3.b); $$ = $3; } - | qid or id { gen_or($1.b, $3.b); $$ = $3; } - ; -qid: pnum { $$.b = gen_ncode((u_long)$1, - $$.q = $<blk>0.q); } - | pid - ; -term: rterm - | not term { gen_not($2.b); $$ = $2; } - ; -head: pqual dqual aqual { QSET($$.q, $1, $2, $3); } - | pqual dqual { QSET($$.q, $1, $2, Q_DEFAULT); } - | pqual aqual { QSET($$.q, $1, Q_DEFAULT, $2); } - | pqual PROTO { QSET($$.q, $1, Q_DEFAULT, Q_PROTO); } - | pqual ndaqual { QSET($$.q, $1, Q_DEFAULT, $2); } - ; -rterm: head id { $$ = $2; } - | paren expr ')' { $$.b = $2.b; $$.q = $1.q; } - | pname { $$.b = gen_proto_abbrev($1); $$.q = qerr; } - | arth relop arth { $$.b = gen_relation($2, $1, $3, 0); - $$.q = qerr; } - | arth irelop arth { $$.b = gen_relation($2, $1, $3, 1); - $$.q = qerr; } - | other { $$.b = $1; $$.q = qerr; } - ; -/* protocol level qualifiers */ -pqual: pname - | { $$ = Q_DEFAULT; } - ; -/* 'direction' qualifiers */ -dqual: SRC { $$ = Q_SRC; } - | DST { $$ = Q_DST; } - | SRC OR DST { $$ = Q_OR; } - | DST OR SRC { $$ = Q_OR; } - | SRC AND DST { $$ = Q_AND; } - | DST AND SRC { $$ = Q_AND; } - ; -/* address type qualifiers */ -aqual: HOST { $$ = Q_HOST; } - | NET { $$ = Q_NET; } - | PORT { $$ = Q_PORT; } - ; -/* non-directional address type qualifiers */ -ndaqual: GATEWAY { $$ = Q_GATEWAY; } - ; -pname: LINK { $$ = Q_LINK; } - | IP { $$ = Q_IP; } - | ARP { $$ = Q_ARP; } - | RARP { $$ = Q_RARP; } - | TCP { $$ = Q_TCP; } - | UDP { $$ = Q_UDP; } - | ICMP { $$ = Q_ICMP; } - | DECNET { $$ = Q_DECNET; } - | LAT { $$ = Q_LAT; } - | MOPDL { $$ = Q_MOPDL; } - | MOPRC { $$ = Q_MOPRC; } - ; -other: pqual TK_BROADCAST { $$ = gen_broadcast($1); } - | pqual TK_MULTICAST { $$ = gen_multicast($1); } - | LESS NUM { $$ = gen_less($2); } - | GREATER NUM { $$ = gen_greater($2); } - | BYTE NUM byteop NUM { $$ = gen_byteop($3, $2, $4); } - | INBOUND { $$ = gen_inbound(0); } - | OUTBOUND { $$ = gen_inbound(1); } - ; -relop: '>' { $$ = BPF_JGT; } - | GEQ { $$ = BPF_JGE; } - | '=' { $$ = BPF_JEQ; } - ; -irelop: LEQ { $$ = BPF_JGT; } - | '<' { $$ = BPF_JGE; } - | NEQ { $$ = BPF_JEQ; } - ; -arth: pnum { $$ = gen_loadi($1); } - | narth - ; -narth: pname '[' arth ']' { $$ = gen_load($1, $3, 1); } - | pname '[' arth ':' NUM ']' { $$ = gen_load($1, $3, $5); } - | arth '+' arth { $$ = gen_arth(BPF_ADD, $1, $3); } - | arth '-' arth { $$ = gen_arth(BPF_SUB, $1, $3); } - | arth '*' arth { $$ = gen_arth(BPF_MUL, $1, $3); } - | arth '/' arth { $$ = gen_arth(BPF_DIV, $1, $3); } - | arth '&' arth { $$ = gen_arth(BPF_AND, $1, $3); } - | arth '|' arth { $$ = gen_arth(BPF_OR, $1, $3); } - | arth LSH arth { $$ = gen_arth(BPF_LSH, $1, $3); } - | arth RSH arth { $$ = gen_arth(BPF_RSH, $1, $3); } - | '-' arth %prec UMINUS { $$ = gen_neg($2); } - | paren narth ')' { $$ = $2; } - | LEN { $$ = gen_loadlen(); } - ; -byteop: '&' { $$ = '&'; } - | '|' { $$ = '|'; } - | '<' { $$ = '<'; } - | '>' { $$ = '>'; } - | '=' { $$ = '='; } - ; -pnum: NUM - | paren pnum ')' { $$ = $2; } - ; -%% diff --git a/lib/libpcap/inet.c b/lib/libpcap/inet.c deleted file mode 100644 index 3092011..0000000 --- a/lib/libpcap/inet.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (c) 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the Computer Systems - * Engineering Group at Lawrence Berkeley Laboratory. - * 4. Neither the name of the University nor of the Laboratory may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char rcsid[] = - "@(#) $Header: /home/ncvs/src/lib/libpcap/inet.c,v 1.1.1.1 1995/01/20 04:13:03 jkh Exp $ (LBL)"; -#endif - -#include <sys/param.h> -#include <sys/file.h> -#include <sys/ioctl.h> -#include <sys/socket.h> -#ifdef SOLARIS -#include <sys/sockio.h> -#endif - -#include <net/if.h> -#include <netinet/in.h> - -#include <ctype.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <pcap.h> - -/* Not all systems have IFF_LOOPBACK */ -#ifdef IFF_LOOPBACK -#define ISLOOPBACK(p) ((p)->ifr_flags & IFF_LOOPBACK) -#else -#define ISLOOPBACK(p) (strcmp((p)->ifr_name, "lo0") == 0) -#endif - -/* - * Return the name of a network interface attached to the system, or NULL - * if none can be found. The interface must be configured up; the - * lowest unit number is preferred; loopback is ignored. - */ -char * -pcap_lookupdev(errbuf) - register char *errbuf; -{ - register int fd, minunit, n; - register char *cp; - register struct ifreq *ifrp, *ifend, *ifnext, *mp; - struct ifconf ifc; - struct ifreq ibuf[16], ifr; - static char device[sizeof(ifrp->ifr_name) + 1]; - - fd = socket(AF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - (void)sprintf(errbuf, "socket: %s", pcap_strerror(errno)); - return (NULL); - } - ifc.ifc_len = sizeof ibuf; - ifc.ifc_buf = (caddr_t)ibuf; - - if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 || - ifc.ifc_len < sizeof(struct ifreq)) { - (void)sprintf(errbuf, "SIOCGIFCONF: %s", pcap_strerror(errno)); - (void)close(fd); - return (NULL); - } - ifrp = ibuf; - ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len); - - mp = NULL; - minunit = 666; - for (; ifrp < ifend; ifrp = ifnext) { -#if BSD - 0 >= 199006 - n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name); - if (n < sizeof(*ifrp)) - ifnext = ifrp + 1; - else - ifnext = (struct ifreq *)((char *)ifrp + n); - if (ifrp->ifr_addr.sa_family != AF_INET) - continue; -#else - ifnext = ifrp + 1; -#endif - /* - * Need a template to preserve address info that is - * used below to locate the next entry. (Otherwise, - * SIOCGIFFLAGS stomps over it because the requests - * are returned in a union.) - */ - strncpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifr.ifr_name)); - if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) { - (void)sprintf(errbuf, "SIOCGIFFLAGS: %s", - pcap_strerror(errno)); - (void)close(fd); - return (NULL); - } - - /* Must be up and not the loopback */ - if ((ifr.ifr_flags & IFF_UP) == 0 || ISLOOPBACK(&ifr)) - continue; - - for (cp = ifrp->ifr_name; !isdigit(*cp); ++cp) - continue; - n = atoi(cp); - if (n < minunit) { - minunit = n; - mp = ifrp; - } - } - (void)close(fd); - if (mp == NULL) { - (void)strcpy(errbuf, "no suitable device found"); - return (NULL); - } - - (void)strncpy(device, mp->ifr_name, sizeof(device) - 1); - device[sizeof(device) - 1] = '\0'; - return (device); -} - -int -pcap_lookupnet(device, netp, maskp, errbuf) - register char *device; - register u_long *netp, *maskp; - register char *errbuf; -{ - register int fd; - register struct sockaddr_in *sin; - struct ifreq ifr; - - fd = socket(AF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - (void)sprintf(errbuf, "socket: %s", pcap_strerror(errno)); - return (-1); - } - (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); - if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) { - (void)sprintf(errbuf, "SIOCGIFADDR: %s: %s", - device, pcap_strerror(errno)); - (void)close(fd); - return (-1); - } - sin = (struct sockaddr_in *)&ifr.ifr_addr; - *netp = sin->sin_addr.s_addr; - if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) { - (void)sprintf(errbuf, "SIOCGIFNETMASK: %s: %s", - device, pcap_strerror(errno)); - (void)close(fd); - return (-1); - } - (void)close(fd); - *maskp = sin->sin_addr.s_addr; - if (*maskp == 0) { - if (IN_CLASSA(*netp)) - *maskp = IN_CLASSA_NET; - else if (IN_CLASSB(*netp)) - *maskp = IN_CLASSB_NET; - else if (IN_CLASSC(*netp)) - *maskp = IN_CLASSC_NET; - else { - (void)sprintf(errbuf, "inet class for 0x%lx unknown", - *netp); - return (-1); - } - } - *netp &= *maskp; - return (0); -} diff --git a/lib/libpcap/nametoaddr.c b/lib/libpcap/nametoaddr.c deleted file mode 100644 index 59e7439..0000000 --- a/lib/libpcap/nametoaddr.c +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Copyright (c) 1990, 1991, 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that: (1) source code distributions - * retain the above copyright notice and this paragraph in its entirety, (2) - * distributions including binary code include the above copyright notice and - * this paragraph in its entirety in the documentation or other materials - * provided with the distribution, and (3) all advertising materials mentioning - * features or use of this software display the following acknowledgement: - * ``This product includes software developed by the University of California, - * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of - * the University nor the names of its contributors may be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * Name to id translation routines used by the scanner. - * These functions are not time critical. - */ - -#ifndef lint -static char rcsid[] = - "@(#) $Header: /home/ncvs/src/lib/libpcap/nametoaddr.c,v 1.2 1995/05/30 05:47:21 rgrimes Exp $ (LBL)"; -#endif - -#include <sys/param.h> -#include <sys/socket.h> -#include <net/if.h> -#include <netinet/in.h> -#include <netinet/if_ether.h> -#include <arpa/inet.h> - -#include <ctype.h> -#include <errno.h> -#include <netdb.h> -#include <pcap.h> -#include <pcap-namedb.h> -#include <stdio.h> -#include <stdlib.h> - -#include "gencode.h" - -#ifndef __GNUC__ -#define inline -#endif - -#ifndef NTOHL -#define NTOHL(x) (x) = ntohl(x) -#define NTOHS(x) (x) = ntohs(x) -#endif - -static inline int xdtoi(int); - -/* - * Convert host name to internet address. - * Return 0 upon failure. - */ -u_long ** -pcap_nametoaddr(const char *name) -{ -#ifndef h_addr - static u_long *hlist[2]; -#endif - u_long **p; - struct hostent *hp; - - if ((hp = gethostbyname(name)) != NULL) { -#ifndef h_addr - hlist[0] = (u_long *)hp->h_addr; - NTOHL(hp->h_addr); - return hlist; -#else - for (p = (u_long **)hp->h_addr_list; *p; ++p) - NTOHL(**p); - return (u_long **)hp->h_addr_list; -#endif - } - else - return 0; -} - -/* - * Convert net name to internet address. - * Return 0 upon failure. - */ -u_long -pcap_nametonetaddr(const char *name) -{ - struct netent *np; - - if ((np = getnetbyname(name)) != NULL) - return np->n_net; - else - return 0; -} - -/* - * Convert a port name to its port and protocol numbers. - * We assume only TCP or UDP. - * Return 0 upon failure. - */ -int -pcap_nametoport(const char *name, int *port, int *proto) -{ - struct servent *sp; - char *other; - - sp = getservbyname(name, (char *)0); - if (sp != NULL) { - NTOHS(sp->s_port); - *port = sp->s_port; - *proto = pcap_nametoproto(sp->s_proto); - /* - * We need to check /etc/services for ambiguous entries. - * If we find the ambiguous entry, and it has the - * same port number, change the proto to PROTO_UNDEF - * so both TCP and UDP will be checked. - */ - if (*proto == IPPROTO_TCP) - other = "udp"; - else - other = "tcp"; - - sp = getservbyname(name, other); - if (sp != 0) { - NTOHS(sp->s_port); - if (*port != sp->s_port) - /* Can't handle ambiguous names that refer - to different port numbers. */ -#ifdef notdef - warning("ambiguous port %s in /etc/services", - name); -#else - ; -#endif - *proto = PROTO_UNDEF; - } - return 1; - } -#if defined(ultrix) || defined(__osf__) - /* Special hack in case NFS isn't in /etc/services */ - if (strcmp(name, "nfs") == 0) { - *port = 2049; - *proto = PROTO_UNDEF; - return 1; - } -#endif - return 0; -} - -int -pcap_nametoproto(const char *str) -{ - struct protoent *p; - - p = getprotobyname(str); - if (p != 0) - return p->p_proto; - else - return PROTO_UNDEF; -} - -#include "ethertype.h" - -struct eproto { - char *s; - u_short p; -}; - -/* Static data base of ether protocol types. */ -struct eproto eproto_db[] = { - { "pup", ETHERTYPE_PUP }, - { "xns", ETHERTYPE_NS }, - { "ip", ETHERTYPE_IP }, - { "arp", ETHERTYPE_ARP }, - { "rarp", ETHERTYPE_REVARP }, - { "sprite", ETHERTYPE_SPRITE }, - { "mopdl", ETHERTYPE_MOPDL }, - { "moprc", ETHERTYPE_MOPRC }, - { "decnet", ETHERTYPE_DN }, - { "lat", ETHERTYPE_LAT }, - { "lanbridge", ETHERTYPE_LANBRIDGE }, - { "vexp", ETHERTYPE_VEXP }, - { "vprod", ETHERTYPE_VPROD }, - { "atalk", ETHERTYPE_ATALK }, - { "atalkarp", ETHERTYPE_AARP }, - { "loopback", ETHERTYPE_LOOPBACK }, - { "decdts", ETHERTYPE_DECDTS }, - { "decdns", ETHERTYPE_DECDNS }, - { (char *)0, 0 } -}; - -int -pcap_nametoeproto(const char *s) -{ - struct eproto *p = eproto_db; - - while (p->s != 0) { - if (strcmp(p->s, s) == 0) - return p->p; - p += 1; - } - return PROTO_UNDEF; -} - -/* Hex digit to integer. */ -static inline int -xdtoi(c) - register int c; -{ - if (isdigit(c)) - return c - '0'; - else if (islower(c)) - return c - 'a' + 10; - else - return c - 'A' + 10; -} - -u_long -__pcap_atoin(const char *s) -{ - u_long addr = 0; - u_int n; - - while (1) { - n = 0; - while (*s && *s != '.') - n = n * 10 + *s++ - '0'; - addr <<= 8; - addr |= n & 0xff; - if (*s == '\0') - return addr; - ++s; - } - /* NOTREACHED */ -} - -u_long -__pcap_atodn(const char *s) -{ -#define AREASHIFT 10 -#define AREAMASK 0176000 -#define NODEMASK 01777 - - u_long addr = 0; - u_int node, area; - - if (sscanf((char *)s, "%d.%d", &area, &node) != 2) - bpf_error("malformed decnet address '%s'", s); - - addr = (area << AREASHIFT) & AREAMASK; - addr |= (node & NODEMASK); - - return(addr); -} - -/* - * Convert 's' which has the form "xx:xx:xx:xx:xx:xx" into a new - * ethernet address. Assumes 's' is well formed. - */ -u_char * -pcap_ether_aton(const char *s) -{ - register u_char *ep, *e; - register u_int d; - - e = ep = (u_char *)malloc(6); - - while (*s) { - if (*s == ':') - s += 1; - d = xdtoi(*s++); - if (isxdigit(*s)) { - d <<= 4; - d |= xdtoi(*s++); - } - *ep++ = d; - } - - return (e); -} - -#ifndef ETHER_SERVICE -/* Roll our own */ -u_char * -pcap_ether_hostton(const char *name) -{ - register struct pcap_etherent *ep; - register u_char *ap; - static FILE *fp = NULL; - static init = 0; - - if (!init) { - fp = fopen(PCAP_ETHERS_FILE, "r"); - ++init; - if (fp == NULL) - return (NULL); - } else if (fp == NULL) - return (NULL); - else - rewind(fp); - - while ((ep = pcap_next_etherent(fp)) != NULL) { - if (strcmp(ep->name, name) == 0) { - ap = (u_char *)malloc(6); - if (ap != NULL) { - memcpy(ap, ep->addr, 6); - return (ap); - } - break; - } - } - return (NULL); -} -#else -/* Use the os supplied routines */ -u_char * -pcap_ether_hostton(const char *name) -{ - register u_char *ap; - u_char a[6]; -#ifndef sgi - extern int ether_hostton(char *, struct ether_addr *); -#endif - - ap = NULL; - if (ether_hostton((char*)name, (struct ether_addr *)a) == 0) { - ap = (u_char *)malloc(6); - if (ap != NULL) - memcpy(ap, a, 6); - } - return (ap); -} -#endif - -u_short -__pcap_nametodnaddr(const char *name) -{ -#ifdef DECNETLIB - struct nodeent *getnodebyname(); - struct nodeent *nep; - unsigned short res; - - nep = getnodebyname(name); - if (nep == ((struct nodeent *)0)) - bpf_error("unknown decnet host name '%s'\n", name); - - memcpy((char *)&res, (char *)nep->n_addr, sizeof(unsigned short)); - return(res); -#else - bpf_error("decnet name support not included, '%s' cannot be translated\n", - name); -#endif -} diff --git a/lib/libpcap/optimize.c b/lib/libpcap/optimize.c deleted file mode 100644 index c198e36..0000000 --- a/lib/libpcap/optimize.c +++ /dev/null @@ -1,1924 +0,0 @@ -/* - * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that: (1) source code distributions - * retain the above copyright notice and this paragraph in its entirety, (2) - * distributions including binary code include the above copyright notice and - * this paragraph in its entirety in the documentation or other materials - * provided with the distribution, and (3) all advertising materials mentioning - * features or use of this software display the following acknowledgement: - * ``This product includes software developed by the University of California, - * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of - * the University nor the names of its contributors may be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * Optimization module for tcpdump intermediate representation. - */ -#ifndef lint -static char rcsid[] = - "@(#) $Header: /home/ncvs/src/lib/libpcap/optimize.c,v 1.1.1.1 1995/01/20 04:13:03 jkh Exp $ (LBL)"; -#endif - -#include <sys/types.h> -#include <sys/time.h> - -#include <net/bpf.h> - -#include <stdio.h> -#include <stdlib.h> -#ifdef __osf__ -#include <stdlib.h> -#include <malloc.h> -#endif -#include <memory.h> - -#include "gencode.h" - -#ifndef __GNUC__ -#define inline -#endif - -#define A_ATOM BPF_MEMWORDS -#define X_ATOM (BPF_MEMWORDS+1) - -#define NOP -1 - -/* - * This define is used to represent *both* the accumulator and - * x register in use-def computations. - * Currently, the use-def code assumes only one definition per instruction. - */ -#define AX_ATOM N_ATOMS - -/* - * A flag to indicate that further optimization is needed. - * Iterative passes are continued until a given pass yields no - * branch movement. - */ -static int done; - -/* - * A block is marked if only if its mark equals the current mark. - * Rather than traverse the code array, marking each item, 'cur_mark' is - * incremented. This automatically makes each element unmarked. - */ -static int cur_mark; -#define isMarked(p) ((p)->mark == cur_mark) -#define unMarkAll() cur_mark += 1 -#define Mark(p) ((p)->mark = cur_mark) - -static void opt_init(struct block *); -static void opt_cleanup(void); - -static void make_marks(struct block *); -static void mark_code(struct block *); - -static void intern_blocks(struct block *); - -static int eq_slist(struct slist *, struct slist *); - -static void find_levels_r(struct block *); - -static void find_levels(struct block *); -static void find_dom(struct block *); -static void propedom(struct edge *); -static void find_edom(struct block *); -static void find_closure(struct block *); -static int atomuse(struct stmt *); -static int atomdef(struct stmt *); -static void compute_local_ud(struct block *); -static void find_ud(struct block *); -static void init_val(void); -static long F(int, long, long); -static inline void vstore(struct stmt *, long *, long, int); -static void opt_blk(struct block *, int); -static int use_conflict(struct block *, struct block *); -static void opt_j(struct edge *); -static void or_pullup(struct block *); -static void and_pullup(struct block *); -static void opt_blks(struct block *, int); -static inline void link_inedge(struct edge *, struct block *); -static void find_inedges(struct block *); -static void opt_root(struct block **); -static void opt_loop(struct block *, int); -static void fold_op(struct stmt *, long, long); -static inline struct slist *this_op(struct slist *); -static void opt_not(struct block *); -static void opt_peep(struct block *); -static void opt_stmt(struct stmt *, long[], int); -static void deadstmt(struct stmt *, struct stmt *[]); -static void opt_deadstores(struct block *); -static void opt_blk(struct block *, int); -static int use_conflict(struct block *, struct block *); -static void opt_j(struct edge *); -static struct block *fold_edge(struct block *, struct edge *); -static inline int eq_blk(struct block *, struct block *); -static int slength(struct slist *); -static int count_blocks(struct block *); -static void number_blks_r(struct block *); -static int count_stmts(struct block *); -static void convert_code_r(struct block *); - -static int n_blocks; -struct block **blocks; -static int n_edges; -struct edge **edges; - -/* - * A bit vector set representation of the dominators. - * We round up the set size to the next power of two. - */ -static int nodewords; -static int edgewords; -struct block **levels; -u_long *space; -#define BITS_PER_WORD (8*sizeof(u_long)) -/* - * True if a is in uset {p} - */ -#define SET_MEMBER(p, a) \ -((p)[(unsigned)(a) / BITS_PER_WORD] & (1 << ((unsigned)(a) % BITS_PER_WORD))) - -/* - * Add 'a' to uset p. - */ -#define SET_INSERT(p, a) \ -(p)[(unsigned)(a) / BITS_PER_WORD] |= (1 << ((unsigned)(a) % BITS_PER_WORD)) - -/* - * Delete 'a' from uset p. - */ -#define SET_DELETE(p, a) \ -(p)[(unsigned)(a) / BITS_PER_WORD] &= ~(1 << ((unsigned)(a) % BITS_PER_WORD)) - -/* - * a := a intersect b - */ -#define SET_INTERSECT(a, b, n)\ -{\ - register u_long *_x = a, *_y = b;\ - register int _n = n;\ - while (--_n >= 0) *_x++ &= *_y++;\ -} - -/* - * a := a - b - */ -#define SET_SUBTRACT(a, b, n)\ -{\ - register u_long *_x = a, *_y = b;\ - register int _n = n;\ - while (--_n >= 0) *_x++ &=~ *_y++;\ -} - -/* - * a := a union b - */ -#define SET_UNION(a, b, n)\ -{\ - register u_long *_x = a, *_y = b;\ - register int _n = n;\ - while (--_n >= 0) *_x++ |= *_y++;\ -} - -static uset all_dom_sets; -static uset all_closure_sets; -static uset all_edge_sets; - -#ifndef MAX -#define MAX(a,b) ((a)>(b)?(a):(b)) -#endif - -static void -find_levels_r(b) - struct block *b; -{ - int level; - - if (isMarked(b)) - return; - - Mark(b); - b->link = 0; - - if (JT(b)) { - find_levels_r(JT(b)); - find_levels_r(JF(b)); - level = MAX(JT(b)->level, JF(b)->level) + 1; - } else - level = 0; - b->level = level; - b->link = levels[level]; - levels[level] = b; -} - -/* - * Level graph. The levels go from 0 at the leaves to - * N_LEVELS at the root. The levels[] array points to the - * first node of the level list, whose elements are linked - * with the 'link' field of the struct block. - */ -static void -find_levels(root) - struct block *root; -{ - memset((char *)levels, 0, n_blocks * sizeof(*levels)); - unMarkAll(); - find_levels_r(root); -} - -/* - * Find dominator relationships. - * Assumes graph has been leveled. - */ -static void -find_dom(root) - struct block *root; -{ - int i; - struct block *b; - u_long *x; - - /* - * Initialize sets to contain all nodes. - */ - x = all_dom_sets; - i = n_blocks * nodewords; - while (--i >= 0) - *x++ = ~0; - /* Root starts off empty. */ - for (i = nodewords; --i >= 0;) - root->dom[i] = 0; - - /* root->level is the highest level no found. */ - for (i = root->level; i >= 0; --i) { - for (b = levels[i]; b; b = b->link) { - SET_INSERT(b->dom, b->id); - if (JT(b) == 0) - continue; - SET_INTERSECT(JT(b)->dom, b->dom, nodewords); - SET_INTERSECT(JF(b)->dom, b->dom, nodewords); - } - } -} - -static void -propedom(ep) - struct edge *ep; -{ - SET_INSERT(ep->edom, ep->id); - if (ep->succ) { - SET_INTERSECT(ep->succ->et.edom, ep->edom, edgewords); - SET_INTERSECT(ep->succ->ef.edom, ep->edom, edgewords); - } -} - -/* - * Compute edge dominators. - * Assumes graph has been leveled and predecessors established. - */ -static void -find_edom(root) - struct block *root; -{ - int i; - uset x; - struct block *b; - - x = all_edge_sets; - for (i = n_edges * edgewords; --i >= 0; ) - x[i] = ~0; - - /* root->level is the highest level no found. */ - memset(root->et.edom, 0, edgewords * sizeof(*(uset)0)); - memset(root->ef.edom, 0, edgewords * sizeof(*(uset)0)); - for (i = root->level; i >= 0; --i) { - for (b = levels[i]; b != 0; b = b->link) { - propedom(&b->et); - propedom(&b->ef); - } - } -} - -/* - * Find the backwards transitive closure of the flow graph. These sets - * are backwards in the sense that we find the set of nodes that reach - * a given node, not the set of nodes that can be reached by a node. - * - * Assumes graph has been leveled. - */ -static void -find_closure(root) - struct block *root; -{ - int i; - struct block *b; - - /* - * Initialize sets to contain no nodes. - */ - memset((char *)all_closure_sets, 0, - n_blocks * nodewords * sizeof(*all_closure_sets)); - - /* root->level is the highest level no found. */ - for (i = root->level; i >= 0; --i) { - for (b = levels[i]; b; b = b->link) { - SET_INSERT(b->closure, b->id); - if (JT(b) == 0) - continue; - SET_UNION(JT(b)->closure, b->closure, nodewords); - SET_UNION(JF(b)->closure, b->closure, nodewords); - } - } -} - -/* - * Return the register number that is used by s. If A and X are both - * used, return AX_ATOM. If no register is used, return -1. - * - * The implementation should probably change to an array access. - */ -static int -atomuse(s) - struct stmt *s; -{ - register int c = s->code; - - if (c == NOP) - return -1; - - switch (BPF_CLASS(c)) { - - case BPF_RET: - return (BPF_RVAL(c) == BPF_A) ? A_ATOM : - (BPF_RVAL(c) == BPF_X) ? X_ATOM : -1; - - case BPF_LD: - case BPF_LDX: - return (BPF_MODE(c) == BPF_IND) ? X_ATOM : - (BPF_MODE(c) == BPF_MEM) ? s->k : -1; - - case BPF_ST: - return A_ATOM; - - case BPF_STX: - return X_ATOM; - - case BPF_JMP: - case BPF_ALU: - if (BPF_SRC(c) == BPF_X) - return AX_ATOM; - return A_ATOM; - - case BPF_MISC: - return BPF_MISCOP(c) == BPF_TXA ? X_ATOM : A_ATOM; - } - abort(); - /* NOTREACHED */ -} - -/* - * Return the register number that is defined by 's'. We assume that - * a single stmt cannot define more than one register. If no register - * is defined, return -1. - * - * The implementation should probably change to an array access. - */ -static int -atomdef(s) - struct stmt *s; -{ - if (s->code == NOP) - return -1; - - switch (BPF_CLASS(s->code)) { - - case BPF_LD: - case BPF_ALU: - return A_ATOM; - - case BPF_LDX: - return X_ATOM; - - case BPF_ST: - case BPF_STX: - return s->k; - - case BPF_MISC: - return BPF_MISCOP(s->code) == BPF_TAX ? X_ATOM : A_ATOM; - } - return -1; -} - -static void -compute_local_ud(b) - struct block *b; -{ - struct slist *s; - atomset def = 0, use = 0, kill = 0; - int atom; - - for (s = b->stmts; s; s = s->next) { - if (s->s.code == NOP) - continue; - atom = atomuse(&s->s); - if (atom >= 0) { - if (atom == AX_ATOM) { - if (!ATOMELEM(def, X_ATOM)) - use |= ATOMMASK(X_ATOM); - if (!ATOMELEM(def, A_ATOM)) - use |= ATOMMASK(A_ATOM); - } - else if (atom < N_ATOMS) { - if (!ATOMELEM(def, atom)) - use |= ATOMMASK(atom); - } - else - abort(); - } - atom = atomdef(&s->s); - if (atom >= 0) { - if (!ATOMELEM(use, atom)) - kill |= ATOMMASK(atom); - def |= ATOMMASK(atom); - } - } - if (!ATOMELEM(def, A_ATOM) && BPF_CLASS(b->s.code) == BPF_JMP) - use |= ATOMMASK(A_ATOM); - - b->def = def; - b->kill = kill; - b->in_use = use; -} - -/* - * Assume graph is already leveled. - */ -static void -find_ud(root) - struct block *root; -{ - int i, maxlevel; - struct block *p; - - /* - * root->level is the highest level no found; - * count down from there. - */ - maxlevel = root->level; - for (i = maxlevel; i >= 0; --i) - for (p = levels[i]; p; p = p->link) { - compute_local_ud(p); - p->out_use = 0; - } - - for (i = 1; i <= maxlevel; ++i) { - for (p = levels[i]; p; p = p->link) { - p->out_use |= JT(p)->in_use | JF(p)->in_use; - p->in_use |= p->out_use &~ p->kill; - } - } -} - -/* - * These data structures are used in a Cocke and Shwarz style - * value numbering scheme. Since the flowgraph is acyclic, - * exit values can be propagated from a node's predecessors - * provided it is uniquely defined. - */ -struct valnode { - int code; - long v0, v1; - long val; - struct valnode *next; -}; - -#define MODULUS 213 -static struct valnode *hashtbl[MODULUS]; -static int curval; -static int maxval; - -/* Integer constants mapped with the load immediate opcode. */ -#define K(i) F(BPF_LD|BPF_IMM|BPF_W, i, 0L) - -struct vmapinfo { - int is_const; - long const_val; -}; - -struct vmapinfo *vmap; -struct valnode *vnode_base; -struct valnode *next_vnode; - -static void -init_val() -{ - curval = 0; - next_vnode = vnode_base; - memset((char *)vmap, 0, maxval * sizeof(*vmap)); - memset((char *)hashtbl, 0, sizeof hashtbl); -} - -/* Because we really don't have an IR, this stuff is a little messy. */ -static long -F(code, v0, v1) - int code; - long v0, v1; -{ - u_int hash; - int val; - struct valnode *p; - - hash = (u_int)code ^ (v0 << 4) ^ (v1 << 8); - hash %= MODULUS; - - for (p = hashtbl[hash]; p; p = p->next) - if (p->code == code && p->v0 == v0 && p->v1 == v1) - return p->val; - - val = ++curval; - if (BPF_MODE(code) == BPF_IMM && - (BPF_CLASS(code) == BPF_LD || BPF_CLASS(code) == BPF_LDX)) { - vmap[val].const_val = v0; - vmap[val].is_const = 1; - } - p = next_vnode++; - p->val = val; - p->code = code; - p->v0 = v0; - p->v1 = v1; - p->next = hashtbl[hash]; - hashtbl[hash] = p; - - return val; -} - -static inline void -vstore(s, valp, newval, alter) - struct stmt *s; - long *valp; - long newval; - int alter; -{ - if (alter && *valp == newval) - s->code = NOP; - else - *valp = newval; -} - -static void -fold_op(s, v0, v1) - struct stmt *s; - long v0, v1; -{ - long a, b; - - a = vmap[v0].const_val; - b = vmap[v1].const_val; - - switch (BPF_OP(s->code)) { - case BPF_ADD: - a += b; - break; - - case BPF_SUB: - a -= b; - break; - - case BPF_MUL: - a *= b; - break; - - case BPF_DIV: - if (b == 0) - bpf_error("division by zero"); - a /= b; - break; - - case BPF_AND: - a &= b; - break; - - case BPF_OR: - a |= b; - break; - - case BPF_LSH: - a <<= b; - break; - - case BPF_RSH: - a >>= b; - break; - - case BPF_NEG: - a = -a; - break; - - default: - abort(); - } - s->k = a; - s->code = BPF_LD|BPF_IMM; - done = 0; -} - -static inline struct slist * -this_op(s) - struct slist *s; -{ - while (s != 0 && s->s.code == NOP) - s = s->next; - return s; -} - -static void -opt_not(b) - struct block *b; -{ - struct block *tmp = JT(b); - - JT(b) = JF(b); - JF(b) = tmp; -} - -static void -opt_peep(b) - struct block *b; -{ - struct slist *s; - struct slist *next, *last; - int val; - long v; - - s = b->stmts; - if (s == 0) - return; - - last = s; - while (1) { - s = this_op(s); - if (s == 0) - break; - next = this_op(s->next); - if (next == 0) - break; - last = next; - - /* - * st M[k] --> st M[k] - * ldx M[k] tax - */ - if (s->s.code == BPF_ST && - next->s.code == (BPF_LDX|BPF_MEM) && - s->s.k == next->s.k) { - done = 0; - next->s.code = BPF_MISC|BPF_TAX; - } - /* - * ld #k --> ldx #k - * tax txa - */ - if (s->s.code == (BPF_LD|BPF_IMM) && - next->s.code == (BPF_MISC|BPF_TAX)) { - s->s.code = BPF_LDX|BPF_IMM; - next->s.code = BPF_MISC|BPF_TXA; - done = 0; - } - /* - * This is an ugly special case, but it happens - * when you say tcp[k] or udp[k] where k is a constant. - */ - if (s->s.code == (BPF_LD|BPF_IMM)) { - struct slist *add, *tax, *ild; - - /* - * Check that X isn't used on exit from this - * block (which the optimizer might cause). - * We know the code generator won't generate - * any local dependencies. - */ - if (ATOMELEM(b->out_use, X_ATOM)) - break; - - if (next->s.code != (BPF_LDX|BPF_MSH|BPF_B)) - add = next; - else - add = this_op(next->next); - if (add == 0 || add->s.code != (BPF_ALU|BPF_ADD|BPF_X)) - break; - - tax = this_op(add->next); - if (tax == 0 || tax->s.code != (BPF_MISC|BPF_TAX)) - break; - - ild = this_op(tax->next); - if (ild == 0 || BPF_CLASS(ild->s.code) != BPF_LD || - BPF_MODE(ild->s.code) != BPF_IND) - break; - /* - * XXX We need to check that X is not - * subsequently used. We know we can eliminate the - * accumulator modifications since it is defined - * by the last stmt of this sequence. - * - * We want to turn this sequence: - * - * (004) ldi #0x2 {s} - * (005) ldxms [14] {next} -- optional - * (006) addx {add} - * (007) tax {tax} - * (008) ild [x+0] {ild} - * - * into this sequence: - * - * (004) nop - * (005) ldxms [14] - * (006) nop - * (007) nop - * (008) ild [x+2] - * - */ - ild->s.k += s->s.k; - s->s.code = NOP; - add->s.code = NOP; - tax->s.code = NOP; - done = 0; - } - s = next; - } - /* - * If we have a subtract to do a comparison, and the X register - * is a known constant, we can merge this value into the - * comparison. - */ - if (last->s.code == (BPF_ALU|BPF_SUB|BPF_X) && - !ATOMELEM(b->out_use, A_ATOM)) { - val = b->val[X_ATOM]; - if (vmap[val].is_const) { - b->s.k += vmap[val].const_val; - last->s.code = NOP; - done = 0; - } else if (b->s.k == 0) { - /* - * sub x -> nop - * j #0 j x - */ - last->s.code = NOP; - b->s.code = BPF_CLASS(b->s.code) | BPF_OP(b->s.code) | - BPF_X; - done = 0; - } - } - /* - * Likewise, a constant subtract can be simplified. - */ - else if (last->s.code == (BPF_ALU|BPF_SUB|BPF_K) && - !ATOMELEM(b->out_use, A_ATOM)) { - b->s.k += last->s.k; - last->s.code = NOP; - done = 0; - } - /* - * and #k nop - * jeq #0 -> jset #k - */ - if (last->s.code == (BPF_ALU|BPF_AND|BPF_K) && - !ATOMELEM(b->out_use, A_ATOM) && b->s.k == 0) { - b->s.k = last->s.k; - b->s.code = BPF_JMP|BPF_K|BPF_JSET; - last->s.code = NOP; - done = 0; - opt_not(b); - } - /* - * If the accumulator is a known constant, we can compute the - * comparison result. - */ - val = b->val[A_ATOM]; - if (vmap[val].is_const && BPF_SRC(b->s.code) == BPF_K) { - v = vmap[val].const_val; - switch (BPF_OP(b->s.code)) { - - case BPF_JEQ: - v = v == b->s.k; - break; - - case BPF_JGT: - v = v > b->s.k; - break; - - case BPF_JGE: - v = v >= b->s.k; - break; - - case BPF_JSET: - v &= b->s.k; - break; - - default: - abort(); - } - if (JF(b) != JT(b)) - done = 0; - if (v) - JF(b) = JT(b); - else - JT(b) = JF(b); - } -} - -/* - * Compute the symbolic value of expression of 's', and update - * anything it defines in the value table 'val'. If 'alter' is true, - * do various optimizations. This code would be cleaner if symbolic - * evaluation and code transformations weren't folded together. - */ -static void -opt_stmt(s, val, alter) - struct stmt *s; - long val[]; - int alter; -{ - int op; - long v; - - switch (s->code) { - - case BPF_LD|BPF_ABS|BPF_W: - case BPF_LD|BPF_ABS|BPF_H: - case BPF_LD|BPF_ABS|BPF_B: - v = F(s->code, s->k, 0L); - vstore(s, &val[A_ATOM], v, alter); - break; - - case BPF_LD|BPF_IND|BPF_W: - case BPF_LD|BPF_IND|BPF_H: - case BPF_LD|BPF_IND|BPF_B: - v = val[X_ATOM]; - if (alter && vmap[v].is_const) { - s->code = BPF_LD|BPF_ABS|BPF_SIZE(s->code); - s->k += vmap[v].const_val; - v = F(s->code, s->k, 0L); - done = 0; - } - else - v = F(s->code, s->k, v); - vstore(s, &val[A_ATOM], v, alter); - break; - - case BPF_LD|BPF_LEN: - v = F(s->code, 0L, 0L); - vstore(s, &val[A_ATOM], v, alter); - break; - - case BPF_LD|BPF_IMM: - v = K(s->k); - vstore(s, &val[A_ATOM], v, alter); - break; - - case BPF_LDX|BPF_IMM: - v = K(s->k); - vstore(s, &val[X_ATOM], v, alter); - break; - - case BPF_LDX|BPF_MSH|BPF_B: - v = F(s->code, s->k, 0L); - vstore(s, &val[X_ATOM], v, alter); - break; - - case BPF_ALU|BPF_NEG: - if (alter && vmap[val[A_ATOM]].is_const) { - s->code = BPF_LD|BPF_IMM; - s->k = -vmap[val[A_ATOM]].const_val; - val[A_ATOM] = K(s->k); - } - else - val[A_ATOM] = F(s->code, val[A_ATOM], 0L); - break; - - case BPF_ALU|BPF_ADD|BPF_K: - case BPF_ALU|BPF_SUB|BPF_K: - case BPF_ALU|BPF_MUL|BPF_K: - case BPF_ALU|BPF_DIV|BPF_K: - case BPF_ALU|BPF_AND|BPF_K: - case BPF_ALU|BPF_OR|BPF_K: - case BPF_ALU|BPF_LSH|BPF_K: - case BPF_ALU|BPF_RSH|BPF_K: - op = BPF_OP(s->code); - if (alter) { - if (s->k == 0) { - if (op == BPF_ADD || op == BPF_SUB || - op == BPF_LSH || op == BPF_RSH || - op == BPF_OR) { - s->code = NOP; - break; - } - if (op == BPF_MUL || op == BPF_AND) { - s->code = BPF_LD|BPF_IMM; - val[A_ATOM] = K(s->k); - break; - } - } - if (vmap[val[A_ATOM]].is_const) { - fold_op(s, val[A_ATOM], K(s->k)); - val[A_ATOM] = K(s->k); - break; - } - } - val[A_ATOM] = F(s->code, val[A_ATOM], K(s->k)); - break; - - case BPF_ALU|BPF_ADD|BPF_X: - case BPF_ALU|BPF_SUB|BPF_X: - case BPF_ALU|BPF_MUL|BPF_X: - case BPF_ALU|BPF_DIV|BPF_X: - case BPF_ALU|BPF_AND|BPF_X: - case BPF_ALU|BPF_OR|BPF_X: - case BPF_ALU|BPF_LSH|BPF_X: - case BPF_ALU|BPF_RSH|BPF_X: - op = BPF_OP(s->code); - if (alter && vmap[val[X_ATOM]].is_const) { - if (vmap[val[A_ATOM]].is_const) { - fold_op(s, val[A_ATOM], val[X_ATOM]); - val[A_ATOM] = K(s->k); - } - else { - s->code = BPF_ALU|BPF_K|op; - s->k = vmap[val[X_ATOM]].const_val; - done = 0; - val[A_ATOM] = - F(s->code, val[A_ATOM], K(s->k)); - } - break; - } - /* - * Check if we're doing something to an accumulator - * that is 0, and simplify. This may not seem like - * much of a simplification but it could open up further - * optimizations. - * XXX We could also check for mul by 1, and -1, etc. - */ - if (alter && vmap[val[A_ATOM]].is_const - && vmap[val[A_ATOM]].const_val == 0) { - if (op == BPF_ADD || op == BPF_OR || - op == BPF_LSH || op == BPF_RSH || op == BPF_SUB) { - s->code = BPF_MISC|BPF_TXA; - vstore(s, &val[A_ATOM], val[X_ATOM], alter); - break; - } - else if (op == BPF_MUL || op == BPF_DIV || - op == BPF_AND) { - s->code = BPF_LD|BPF_IMM; - s->k = 0; - vstore(s, &val[A_ATOM], K(s->k), alter); - break; - } - else if (op == BPF_NEG) { - s->code = NOP; - break; - } - } - val[A_ATOM] = F(s->code, val[A_ATOM], val[X_ATOM]); - break; - - case BPF_MISC|BPF_TXA: - vstore(s, &val[A_ATOM], val[X_ATOM], alter); - break; - - case BPF_LD|BPF_MEM: - v = val[s->k]; - if (alter && vmap[v].is_const) { - s->code = BPF_LD|BPF_IMM; - s->k = vmap[v].const_val; - done = 0; - } - vstore(s, &val[A_ATOM], v, alter); - break; - - case BPF_MISC|BPF_TAX: - vstore(s, &val[X_ATOM], val[A_ATOM], alter); - break; - - case BPF_LDX|BPF_MEM: - v = val[s->k]; - if (alter && vmap[v].is_const) { - s->code = BPF_LDX|BPF_IMM; - s->k = vmap[v].const_val; - done = 0; - } - vstore(s, &val[X_ATOM], v, alter); - break; - - case BPF_ST: - vstore(s, &val[s->k], val[A_ATOM], alter); - break; - - case BPF_STX: - vstore(s, &val[s->k], val[X_ATOM], alter); - break; - } -} - -static void -deadstmt(s, last) - register struct stmt *s; - register struct stmt *last[]; -{ - register int atom; - - atom = atomuse(s); - if (atom >= 0) { - if (atom == AX_ATOM) { - last[X_ATOM] = 0; - last[A_ATOM] = 0; - } - else - last[atom] = 0; - } - atom = atomdef(s); - if (atom >= 0) { - if (last[atom]) { - done = 0; - last[atom]->code = NOP; - } - last[atom] = s; - } -} - -static void -opt_deadstores(b) - register struct block *b; -{ - register struct slist *s; - register int atom; - struct stmt *last[N_ATOMS]; - - memset((char *)last, 0, sizeof last); - - for (s = b->stmts; s != 0; s = s->next) - deadstmt(&s->s, last); - deadstmt(&b->s, last); - - for (atom = 0; atom < N_ATOMS; ++atom) - if (last[atom] && !ATOMELEM(b->out_use, atom)) { - last[atom]->code = NOP; - done = 0; - } -} - -static void -opt_blk(b, do_stmts) - struct block *b; - int do_stmts; -{ - struct slist *s; - struct edge *p; - int i; - long aval; - - /* - * Initialize the atom values. - * If we have no predecessors, everything is undefined. - * Otherwise, we inherent our values from our predecessors. - * If any register has an ambiguous value (i.e. control paths are - * merging) give it the undefined value of 0. - */ - p = b->in_edges; - if (p == 0) - memset((char *)b->val, 0, sizeof(b->val)); - else { - memcpy((char *)b->val, (char *)p->pred->val, sizeof(b->val)); - while ((p = p->next) != NULL) { - for (i = 0; i < N_ATOMS; ++i) - if (b->val[i] != p->pred->val[i]) - b->val[i] = 0; - } - } - aval = b->val[A_ATOM]; - for (s = b->stmts; s; s = s->next) - opt_stmt(&s->s, b->val, do_stmts); - - /* - * This is a special case: if we don't use anything from this - * block, and we load the accumulator with value that is - * already there, eliminate all the statements. - */ - if (do_stmts && b->out_use == 0 && aval != 0 && - b->val[A_ATOM] == aval) - b->stmts = 0; - else { - opt_peep(b); - opt_deadstores(b); - } - /* - * Set up values for branch optimizer. - */ - if (BPF_SRC(b->s.code) == BPF_K) - b->oval = K(b->s.k); - else - b->oval = b->val[X_ATOM]; - b->et.code = b->s.code; - b->ef.code = -b->s.code; -} - -/* - * Return true if any register that is used on exit from 'succ', has - * an exit value that is different from the corresponding exit value - * from 'b'. - */ -static int -use_conflict(b, succ) - struct block *b, *succ; -{ - int atom; - atomset use = succ->out_use; - - if (use == 0) - return 0; - - for (atom = 0; atom < N_ATOMS; ++atom) - if (ATOMELEM(use, atom)) - if (b->val[atom] != succ->val[atom]) - return 1; - return 0; -} - -static struct block * -fold_edge(child, ep) - struct block *child; - struct edge *ep; -{ - int sense; - int aval0, aval1, oval0, oval1; - int code = ep->code; - - if (code < 0) { - code = -code; - sense = 0; - } else - sense = 1; - - if (child->s.code != code) - return 0; - - aval0 = child->val[A_ATOM]; - oval0 = child->oval; - aval1 = ep->pred->val[A_ATOM]; - oval1 = ep->pred->oval; - - if (aval0 != aval1) - return 0; - - if (oval0 == oval1) - /* - * The operands are identical, so the - * result is true if a true branch was - * taken to get here, otherwise false. - */ - return sense ? JT(child) : JF(child); - - if (sense && code == (BPF_JMP|BPF_JEQ|BPF_K)) - /* - * At this point, we only know the comparison if we - * came down the true branch, and it was an equality - * comparison with a constant. We rely on the fact that - * distinct constants have distinct value numbers. - */ - return JF(child); - - return 0; -} - -static void -opt_j(ep) - struct edge *ep; -{ - register int i, k; - register struct block *target; - - if (JT(ep->succ) == 0) - return; - - if (JT(ep->succ) == JF(ep->succ)) { - /* - * Common branch targets can be eliminated, provided - * there is no data dependency. - */ - if (!use_conflict(ep->pred, ep->succ->et.succ)) { - done = 0; - ep->succ = JT(ep->succ); - } - } - /* - * For each edge dominator that matches the successor of this - * edge, promote the edge successor to the its grandchild. - * - * XXX We violate the set abstraction here in favor a reasonably - * efficient loop. - */ - top: - for (i = 0; i < edgewords; ++i) { - register u_long x = ep->edom[i]; - - while (x != 0) { - k = ffs(x) - 1; - x &=~ (1 << k); - k += i * BITS_PER_WORD; - - target = fold_edge(ep->succ, edges[k]); - /* - * Check that there is no data dependency between - * nodes that will be violated if we move the edge. - */ - if (target != 0 && !use_conflict(ep->pred, target)) { - done = 0; - ep->succ = target; - if (JT(target) != 0) - /* - * Start over unless we hit a leaf. - */ - goto top; - return; - } - } - } -} - - -static void -or_pullup(b) - struct block *b; -{ - int val, at_top; - struct block *pull; - struct block **diffp, **samep; - struct edge *ep; - - ep = b->in_edges; - if (ep == 0) - return; - - /* - * Make sure each predecessor loads the same value. - * XXX why? - */ - val = ep->pred->val[A_ATOM]; - for (ep = ep->next; ep != 0; ep = ep->next) - if (val != ep->pred->val[A_ATOM]) - return; - - if (JT(b->in_edges->pred) == b) - diffp = &JT(b->in_edges->pred); - else - diffp = &JF(b->in_edges->pred); - - at_top = 1; - while (1) { - if (*diffp == 0) - return; - - if (JT(*diffp) != JT(b)) - return; - - if (!SET_MEMBER((*diffp)->dom, b->id)) - return; - - if ((*diffp)->val[A_ATOM] != val) - break; - - diffp = &JF(*diffp); - at_top = 0; - } - samep = &JF(*diffp); - while (1) { - if (*samep == 0) - return; - - if (JT(*samep) != JT(b)) - return; - - if (!SET_MEMBER((*samep)->dom, b->id)) - return; - - if ((*samep)->val[A_ATOM] == val) - break; - - /* XXX Need to check that there are no data dependencies - between dp0 and dp1. Currently, the code generator - will not produce such dependencies. */ - samep = &JF(*samep); - } -#ifdef notdef - /* XXX This doesn't cover everything. */ - for (i = 0; i < N_ATOMS; ++i) - if ((*samep)->val[i] != pred->val[i]) - return; -#endif - /* Pull up the node. */ - pull = *samep; - *samep = JF(pull); - JF(pull) = *diffp; - - /* - * At the top of the chain, each predecessor needs to point at the - * pulled up node. Inside the chain, there is only one predecessor - * to worry about. - */ - if (at_top) { - for (ep = b->in_edges; ep != 0; ep = ep->next) { - if (JT(ep->pred) == b) - JT(ep->pred) = pull; - else - JF(ep->pred) = pull; - } - } - else - *diffp = pull; - - done = 0; -} - -static void -and_pullup(b) - struct block *b; -{ - int val, at_top; - struct block *pull; - struct block **diffp, **samep; - struct edge *ep; - - ep = b->in_edges; - if (ep == 0) - return; - - /* - * Make sure each predecessor loads the same value. - */ - val = ep->pred->val[A_ATOM]; - for (ep = ep->next; ep != 0; ep = ep->next) - if (val != ep->pred->val[A_ATOM]) - return; - - if (JT(b->in_edges->pred) == b) - diffp = &JT(b->in_edges->pred); - else - diffp = &JF(b->in_edges->pred); - - at_top = 1; - while (1) { - if (*diffp == 0) - return; - - if (JF(*diffp) != JF(b)) - return; - - if (!SET_MEMBER((*diffp)->dom, b->id)) - return; - - if ((*diffp)->val[A_ATOM] != val) - break; - - diffp = &JT(*diffp); - at_top = 0; - } - samep = &JT(*diffp); - while (1) { - if (*samep == 0) - return; - - if (JF(*samep) != JF(b)) - return; - - if (!SET_MEMBER((*samep)->dom, b->id)) - return; - - if ((*samep)->val[A_ATOM] == val) - break; - - /* XXX Need to check that there are no data dependencies - between diffp and samep. Currently, the code generator - will not produce such dependencies. */ - samep = &JT(*samep); - } -#ifdef notdef - /* XXX This doesn't cover everything. */ - for (i = 0; i < N_ATOMS; ++i) - if ((*samep)->val[i] != pred->val[i]) - return; -#endif - /* Pull up the node. */ - pull = *samep; - *samep = JT(pull); - JT(pull) = *diffp; - - /* - * At the top of the chain, each predecessor needs to point at the - * pulled up node. Inside the chain, there is only one predecessor - * to worry about. - */ - if (at_top) { - for (ep = b->in_edges; ep != 0; ep = ep->next) { - if (JT(ep->pred) == b) - JT(ep->pred) = pull; - else - JF(ep->pred) = pull; - } - } - else - *diffp = pull; - - done = 0; -} - -static void -opt_blks(root, do_stmts) - struct block *root; - int do_stmts; -{ - int i, maxlevel; - struct block *p; - - init_val(); - maxlevel = root->level; - for (i = maxlevel; i >= 0; --i) - for (p = levels[i]; p; p = p->link) - opt_blk(p, do_stmts); - - if (do_stmts) - /* - * No point trying to move branches; it can't possibly - * make a difference at this point. - */ - return; - - for (i = 1; i <= maxlevel; ++i) { - for (p = levels[i]; p; p = p->link) { - opt_j(&p->et); - opt_j(&p->ef); - } - } - for (i = 1; i <= maxlevel; ++i) { - for (p = levels[i]; p; p = p->link) { - or_pullup(p); - and_pullup(p); - } - } -} - -static inline void -link_inedge(parent, child) - struct edge *parent; - struct block *child; -{ - parent->next = child->in_edges; - child->in_edges = parent; -} - -static void -find_inedges(root) - struct block *root; -{ - int i; - struct block *b; - - for (i = 0; i < n_blocks; ++i) - blocks[i]->in_edges = 0; - - /* - * Traverse the graph, adding each edge to the predecessor - * list of its successors. Skip the leaves (i.e. level 0). - */ - for (i = root->level; i > 0; --i) { - for (b = levels[i]; b != 0; b = b->link) { - link_inedge(&b->et, JT(b)); - link_inedge(&b->ef, JF(b)); - } - } -} - -static void -opt_root(b) - struct block **b; -{ - struct slist *tmp, *s; - - s = (*b)->stmts; - (*b)->stmts = 0; - while (BPF_CLASS((*b)->s.code) == BPF_JMP && JT(*b) == JF(*b)) - *b = JT(*b); - - tmp = (*b)->stmts; - if (tmp != 0) - sappend(s, tmp); - (*b)->stmts = s; -} - -static void -opt_loop(root, do_stmts) - struct block *root; - int do_stmts; -{ - -#ifdef BDEBUG - if (dflag > 1) - opt_dump(root); -#endif - do { - done = 1; - find_levels(root); - find_dom(root); - find_closure(root); - find_inedges(root); - find_ud(root); - find_edom(root); - opt_blks(root, do_stmts); -#ifdef BDEBUG - if (dflag > 1) - opt_dump(root); -#endif - } while (!done); -} - -/* - * Optimize the filter code in its dag representation. - */ -void -bpf_optimize(rootp) - struct block **rootp; -{ - struct block *root; - - root = *rootp; - - opt_init(root); - opt_loop(root, 0); - opt_loop(root, 1); - intern_blocks(root); - opt_root(rootp); - opt_cleanup(); -} - -static void -make_marks(p) - struct block *p; -{ - if (!isMarked(p)) { - Mark(p); - if (BPF_CLASS(p->s.code) != BPF_RET) { - make_marks(JT(p)); - make_marks(JF(p)); - } - } -} - -/* - * Mark code array such that isMarked(i) is true - * only for nodes that are alive. - */ -static void -mark_code(p) - struct block *p; -{ - cur_mark += 1; - make_marks(p); -} - -/* - * True iff the two stmt lists load the same value from the packet into - * the accumulator. - */ -static int -eq_slist(x, y) - struct slist *x, *y; -{ - while (1) { - while (x && x->s.code == NOP) - x = x->next; - while (y && y->s.code == NOP) - y = y->next; - if (x == 0) - return y == 0; - if (y == 0) - return x == 0; - if (x->s.code != y->s.code || x->s.k != y->s.k) - return 0; - x = x->next; - y = y->next; - } -} - -static inline int -eq_blk(b0, b1) - struct block *b0, *b1; -{ - if (b0->s.code == b1->s.code && - b0->s.k == b1->s.k && - b0->et.succ == b1->et.succ && - b0->ef.succ == b1->ef.succ) - return eq_slist(b0->stmts, b1->stmts); - return 0; -} - -static void -intern_blocks(root) - struct block *root; -{ - struct block *p; - int i, j; - int done; - top: - done = 1; - for (i = 0; i < n_blocks; ++i) - blocks[i]->link = 0; - - mark_code(root); - - for (i = n_blocks - 1; --i >= 0; ) { - if (!isMarked(blocks[i])) - continue; - for (j = i + 1; j < n_blocks; ++j) { - if (!isMarked(blocks[j])) - continue; - if (eq_blk(blocks[i], blocks[j])) { - blocks[i]->link = blocks[j]->link ? - blocks[j]->link : blocks[j]; - break; - } - } - } - for (i = 0; i < n_blocks; ++i) { - p = blocks[i]; - if (JT(p) == 0) - continue; - if (JT(p)->link) { - done = 0; - JT(p) = JT(p)->link; - } - if (JF(p)->link) { - done = 0; - JF(p) = JF(p)->link; - } - } - if (!done) - goto top; -} - -static void -opt_cleanup() -{ - free((void *)vnode_base); - free((void *)vmap); - free((void *)edges); - free((void *)space); - free((void *)levels); - free((void *)blocks); -} - -/* - * Return the number of stmts in 's'. - */ -static int -slength(s) - struct slist *s; -{ - int n = 0; - - for (; s; s = s->next) - if (s->s.code != NOP) - ++n; - return n; -} - -/* - * Return the number of nodes reachable by 'p'. - * All nodes should be initially unmarked. - */ -static int -count_blocks(p) - struct block *p; -{ - if (p == 0 || isMarked(p)) - return 0; - Mark(p); - return count_blocks(JT(p)) + count_blocks(JF(p)) + 1; -} - -/* - * Do a depth first search on the flow graph, numbering the - * the basic blocks, and entering them into the 'blocks' array.` - */ -static void -number_blks_r(p) - struct block *p; -{ - int n; - - if (p == 0 || isMarked(p)) - return; - - Mark(p); - n = n_blocks++; - p->id = n; - blocks[n] = p; - - number_blks_r(JT(p)); - number_blks_r(JF(p)); -} - -/* - * Return the number of stmts in the flowgraph reachable by 'p'. - * The nodes should be unmarked before calling. - */ -static int -count_stmts(p) - struct block *p; -{ - int n; - - if (p == 0 || isMarked(p)) - return 0; - Mark(p); - n = count_stmts(JT(p)) + count_stmts(JF(p)); - return slength(p->stmts) + n + 1; -} - -/* - * Allocate memory. All allocation is done before optimization - * is begun. A linear bound on the size of all data structures is computed - * from the total number of blocks and/or statements. - */ -static void -opt_init(root) - struct block *root; -{ - u_long *p; - int i, n, max_stmts; - - /* - * First, count the blocks, so we can malloc an array to map - * block number to block. Then, put the blocks into the array. - */ - unMarkAll(); - n = count_blocks(root); - blocks = (struct block **)malloc(n * sizeof(*blocks)); - unMarkAll(); - n_blocks = 0; - number_blks_r(root); - - n_edges = 2 * n_blocks; - edges = (struct edge **)malloc(n_edges * sizeof(*edges)); - - /* - * The number of levels is bounded by the number of nodes. - */ - levels = (struct block **)malloc(n_blocks * sizeof(*levels)); - - edgewords = n_edges / (8 * sizeof(u_long)) + 1; - nodewords = n_blocks / (8 * sizeof(u_long)) + 1; - - /* XXX */ - space = (u_long *)malloc(2 * n_blocks * nodewords * sizeof(*space) - + n_edges * edgewords * sizeof(*space)); - p = space; - all_dom_sets = p; - for (i = 0; i < n; ++i) { - blocks[i]->dom = p; - p += nodewords; - } - all_closure_sets = p; - for (i = 0; i < n; ++i) { - blocks[i]->closure = p; - p += nodewords; - } - all_edge_sets = p; - for (i = 0; i < n; ++i) { - register struct block *b = blocks[i]; - - b->et.edom = p; - p += edgewords; - b->ef.edom = p; - p += edgewords; - b->et.id = i; - edges[i] = &b->et; - b->ef.id = n_blocks + i; - edges[n_blocks + i] = &b->ef; - b->et.pred = b; - b->ef.pred = b; - } - max_stmts = 0; - for (i = 0; i < n; ++i) - max_stmts += slength(blocks[i]->stmts) + 1; - /* - * We allocate at most 3 value numbers per statement, - * so this is an upper bound on the number of valnodes - * we'll need. - */ - maxval = 3 * max_stmts; - vmap = (struct vmapinfo *)malloc(maxval * sizeof(*vmap)); - vnode_base = (struct valnode *)malloc(maxval * sizeof(*vmap)); -} - -/* - * Some pointers used to convert the basic block form of the code, - * into the array form that BPF requires. 'fstart' will point to - * the malloc'd array while 'ftail' is used during the recursive traversal. - */ -static struct bpf_insn *fstart; -static struct bpf_insn *ftail; - -#ifdef BDEBUG -int bids[1000]; -#endif - -static void -convert_code_r(p) - struct block *p; -{ - struct bpf_insn *dst; - struct slist *src; - int slen; - u_int off; - - if (p == 0 || isMarked(p)) - return; - Mark(p); - - convert_code_r(JF(p)); - convert_code_r(JT(p)); - - slen = slength(p->stmts); - dst = ftail -= slen + 1; - - p->offset = dst - fstart; - - for (src = p->stmts; src; src = src->next) { - if (src->s.code == NOP) - continue; - dst->code = (u_short)src->s.code; - dst->k = src->s.k; - ++dst; - } -#ifdef BDEBUG - bids[dst - fstart] = p->id + 1; -#endif - dst->code = (u_short)p->s.code; - dst->k = p->s.k; - if (JT(p)) { - off = JT(p)->offset - (p->offset + slen) - 1; - if (off >= 256) - bpf_error("long jumps not supported"); - dst->jt = off; - off = JF(p)->offset - (p->offset + slen) - 1; - if (off >= 256) - bpf_error("long jumps not supported"); - dst->jf = off; - } -} - - -/* - * Convert flowgraph intermediate representation to the - * BPF array representation. Set *lenp to the number of instructions. - */ -struct bpf_insn * -icode_to_fcode(root, lenp) - struct block *root; - int *lenp; -{ - int n; - struct bpf_insn *fp; - - unMarkAll(); - n = *lenp = count_stmts(root); - - fp = (struct bpf_insn *)malloc(sizeof(*fp) * n); - memset((char *)fp, 0, sizeof(*fp) * n); - fstart = fp; - ftail = fp + n; - - unMarkAll(); - convert_code_r(root); - - return fp; -} - -#ifdef BDEBUG -opt_dump(root) - struct block *root; -{ - struct bpf_program f; - - memset(bids, 0, sizeof bids); - f.bf_insns = icode_to_fcode(root, &f.bf_len); - bpf_dump(&f, 1); - putchar('\n'); - free((char *)f.bf_insns); -} -#endif diff --git a/lib/libpcap/pcap-bpf.c b/lib/libpcap/pcap-bpf.c deleted file mode 100644 index b576f04..0000000 --- a/lib/libpcap/pcap-bpf.c +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright (c) 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that: (1) source code distributions - * retain the above copyright notice and this paragraph in its entirety, (2) - * distributions including binary code include the above copyright notice and - * this paragraph in its entirety in the documentation or other materials - * provided with the distribution, and (3) all advertising materials mentioning - * features or use of this software display the following acknowledgement: - * ``This product includes software developed by the University of California, - * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of - * the University nor the names of its contributors may be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ -#ifndef lint -static char rcsid[] = - "@(#)$Header: /home/ncvs/src/lib/libpcap/pcap-bpf.c,v 1.1.1.1 1995/01/20 04:13:03 jkh Exp $ (LBL)"; -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <netdb.h> -#include <ctype.h> -#include <signal.h> -#include <errno.h> -#include <sys/param.h> /* optionally get BSD define */ -#include <sys/time.h> -#include <sys/timeb.h> -#include <sys/socket.h> -#include <sys/file.h> -#include <sys/ioctl.h> -#include <net/bpf.h> -#include <net/if.h> -#include <string.h> - -#include "pcap-int.h" - -int -pcap_stats(pcap_t *p, struct pcap_stat *ps) -{ - struct bpf_stat s; - - if (ioctl(p->fd, BIOCGSTATS, &s) < 0) { - sprintf(p->errbuf, "BIOCGSTATS: %s", pcap_strerror(errno)); - return (-1); - } - - ps->ps_recv = s.bs_recv; - ps->ps_drop = s.bs_drop; - return (0); -} - -int -pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) -{ - int cc; - int n = 0; - register u_char *bp, *ep; - - again: - cc = p->cc; - if (p->cc == 0) { - cc = read(p->fd, (char *)p->buffer, p->bufsize); - if (cc < 0) { - /* Don't choke when we get ptraced */ - switch (errno) { - - case EINTR: - goto again; - - case EWOULDBLOCK: - return (0); -#if defined(sun) && !defined(BSD) - /* - * Due to a SunOS bug, after 2^31 bytes, the kernel - * file offset overflows and read fails with EINVAL. - * The lseek() to 0 will fix things. - */ - case EINVAL: - if ((long)(tell(p->fd) + p->bufsize) < 0) { - (void)lseek(p->fd, 0, 0); - goto again; - } - /* fall through */ -#endif - } - sprintf(p->errbuf, "read: %s", pcap_strerror(errno)); - return (-1); - } - bp = p->buffer; - } else - bp = p->bp; - - /* - * Loop through each packet. - */ -#define bhp ((struct bpf_hdr *)bp) - ep = bp + cc; - while (bp < ep) { - register int caplen, hdrlen; - caplen = bhp->bh_caplen; - hdrlen = bhp->bh_hdrlen; - /* - * XXX A bpf_hdr matches a pcap_pkthdr. - */ - (*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen); - bp += BPF_WORDALIGN(caplen + hdrlen); - if (++n >= cnt && cnt > 0) { - p->bp = bp; - p->cc = ep - bp; - return (n); - } - } -#undef bhp - p->cc = 0; - return (n); -} - -static inline int -bpf_open(pcap_t *p, char *errbuf) -{ - int fd; - int n = 0; - char device[sizeof "/dev/bpf000"]; - - /* - * Go through all the minors and find one that isn't in use. - */ - do { - (void)sprintf(device, "/dev/bpf%d", n++); - fd = open(device, O_RDONLY); - } while (fd < 0 && errno == EBUSY); - - /* - * XXX better message for all minors used - */ - if (fd < 0) - sprintf(errbuf, "%s: %s", device, pcap_strerror(errno)); - - return (fd); -} - -pcap_t * -pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) -{ - int fd; - struct ifreq ifr; - struct bpf_version bv; - u_int v; - pcap_t *p; - - p = (pcap_t *)malloc(sizeof(*p)); - if (p == NULL) { - sprintf(ebuf, "malloc: %s", pcap_strerror(errno)); - return (NULL); - } - bzero(p, sizeof(*p)); - fd = bpf_open(p, ebuf); - if (fd < 0) - goto bad; - - p->fd = fd; - p->snapshot = snaplen; - - if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) { - sprintf(ebuf, "BIOCVERSION: %s", pcap_strerror(errno)); - goto bad; - } - if (bv.bv_major != BPF_MAJOR_VERSION || - bv.bv_minor < BPF_MINOR_VERSION) { - sprintf(ebuf, "kernel bpf filter out of date"); - goto bad; - } - (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); - if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) { - sprintf(ebuf, "%s: %s", device, pcap_strerror(errno)); - goto bad; - } - /* Get the data link layer type. */ - if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) { - sprintf(ebuf, "BIOCGDLT: %s", pcap_strerror(errno)); - goto bad; - } - p->linktype = v; - - /* set timeout */ - if (to_ms != 0) { - struct timeval to; - to.tv_sec = to_ms / 1000; - to.tv_usec = (to_ms * 1000) % 1000000; - if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) { - sprintf(ebuf, "BIOCSRTIMEOUT: %s", - pcap_strerror(errno)); - goto bad; - } - } - if (promisc) - /* set promiscuous mode, okay if it fails */ - (void)ioctl(p->fd, BIOCPROMISC, NULL); - - if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) { - sprintf(ebuf, "BIOCGBLEN: %s", pcap_strerror(errno)); - goto bad; - } - p->bufsize = v; - p->buffer = (u_char*)malloc(p->bufsize); - if (p->buffer == NULL) { - sprintf(ebuf, "malloc: %s", pcap_strerror(errno)); - goto bad; - } - - return (p); - bad: - free(p); - return (NULL); -} - -int -pcap_setfilter(pcap_t *p, struct bpf_program *fp) -{ - if (p->sf.rfile != NULL) - p->fcode = *fp; - else if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) { - sprintf(p->errbuf, "BIOCSETF: %s", pcap_strerror(errno)); - return (-1); - } - return (0); -} diff --git a/lib/libpcap/pcap-dlpi.c b/lib/libpcap/pcap-dlpi.c deleted file mode 100644 index adcffcd..0000000 --- a/lib/libpcap/pcap-dlpi.c +++ /dev/null @@ -1,506 +0,0 @@ -/* - * Copyright (c) 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that: (1) source code distributions - * retain the above copyright notice and this paragraph in its entirety, (2) - * distributions including binary code include the above copyright notice and - * this paragraph in its entirety in the documentation or other materials - * provided with the distribution, and (3) all advertising materials mentioning - * features or use of this software display the following acknowledgement: - * ``This product includes software developed by the University of California, - * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of - * the University nor the names of its contributors may be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * This code contributed by Atanu Ghosh (atanu@cs.ucl.ac.uk), - * University College London. - */ -#ifndef lint -static char rcsid[] = - "@(#)$Header: pcap-dlpi.c,v 1.22x 94/10/12 20:08:15 leres Exp $ (LBL)"; -#endif - -/* - * Packet capture routine for dlpi under SunOS 5 - * - * Notes: - * - * - Apparently the DLIOCRAW ioctl() is specific to SunOS. - * - * - There is a bug in bufmod(7) such that setting the snapshot - * length results in data being left of the front of the packet. - * - * - It might be desirable to use pfmod(7) to filter packets in the - * kernel. - */ - -#include <sys/types.h> -#include <sys/time.h> -#include <sys/bufmod.h> -#include <sys/dlpi.h> -#include <sys/stream.h> -#include <sys/systeminfo.h> - -#include <net/bpf.h> - -#include <ctype.h> -#include <errno.h> -#include <fcntl.h> -#include <memory.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <stropts.h> -#include <unistd.h> - -#include "pcap-int.h" - -#define MAXDLBUF 8192 - -/* Forwards */ -static int send_request(int, char *, int, char *, char *); -static int dlattachreq(int, u_long, char *); -static int dlinfoack(int, char *, char *); -static int dlinforeq(int, char *); -static int dlpromisconreq(int, u_long, char *); -static int dlokack(int, char *, char *); -static int strioctl(int, int, int, char *); -#ifdef SOLARIS -static char *getrelease(long *, long *, long *); -#endif - -int -pcap_stats(pcap_t *p, struct pcap_stat *ps) -{ - - *ps = p->md.stat; - return (0); -} - -int -pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) -{ - register int cc, n; - register u_char *bp, *ep, *pk; - register struct bpf_insn *fcode; - register struct sb_hdr *sbp; - int flags; - struct strbuf data; - struct pcap_pkthdr pkthdr; - - flags = 0; - cc = p->cc; - if (cc == 0) { - data.buf = (char *)p->buffer; - data.maxlen = MAXDLBUF; - data.len = 0; - do { - if (getmsg(p->fd, NULL, &data, &flags) < 0) { - /* Don't choke when we get ptraced */ - if (errno == EINTR) { - cc = 0; - continue; - } - strcpy(p->errbuf, pcap_strerror(errno)); - return (-1); - } - cc = data.len; - } while (cc == 0); - bp = p->buffer; - } else - bp = p->bp; - - /* Loop through packets */ - fcode = p->fcode.bf_insns; - ep = bp + cc; - n = 0; - while (bp < ep) { - sbp = (struct sb_hdr *)bp; - p->md.stat.ps_drop += sbp->sbh_drops; - ++p->md.stat.ps_recv; - pk = bp + sizeof(*sbp); - bp += sbp->sbh_totlen; - if (bpf_filter(fcode, pk, sbp->sbh_origlen, sbp->sbh_msglen)) { - pkthdr.ts = sbp->sbh_timestamp; - pkthdr.len = sbp->sbh_origlen; - pkthdr.caplen = sbp->sbh_msglen; - (*callback)(user, &pkthdr, pk); - if (++n >= cnt && cnt >= 0) { - p->cc = ep - bp; - p->bp = bp; - return (n); - } - } - } - p->cc = 0; - return (n); -} - -pcap_t * -pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) -{ - register pcap_t *p; - long buf[MAXDLBUF]; - int ppa; - int cppa; - register dl_info_ack_t *infop; - u_long ss, flag; -#ifdef SOLARIS - char *release; - long osmajor, osminor, osmicro; -#endif - char dname[100]; - - p = (pcap_t *)malloc(sizeof(*p)); - if (p == NULL) { - strcpy(ebuf, pcap_strerror(errno)); - return (NULL); - } - memset(p, 0, sizeof(*p)); - - /* - ** 1) In order to get the ppa take the last character of the device - ** name if it is a number then fail the open. - ** - ** 2) If the name starts with a '/' then this is an absolute pathname, - ** otherwise prepend '/dev/'. - ** - ** 3) Remove the trailing digit and try and open the device - ** not staggeringly intuitive but it should work. - ** - ** If there are more than 9 devices this code will fail. - */ - - cppa = device[strlen(device) - 1]; - if (!isdigit(cppa)) { - sprintf(ebuf, "%c is not a digit, therefore not a valid ppa", - cppa); - goto bad; - } - - dname[0] = '\0'; - if (device[0] != '/') - strcpy(dname, "/dev/"); - - strcat(dname, device); - dname[strlen(dname) - 1] = '\0'; - - if ((p->fd = open(dname, O_RDWR)) < 0) { - sprintf(ebuf, "%s: %s", dname, pcap_strerror(errno)); - goto bad; - } - p->snapshot = snaplen; - - ppa = cppa - '0'; - /* - ** Attach. - */ - if (dlattachreq(p->fd, ppa, ebuf) < 0 || - dlokack(p->fd, (char *)buf, ebuf) < 0) - goto bad; - - if (promisc) { - /* - ** enable promiscuous. - */ - if (dlpromisconreq(p->fd, DL_PROMISC_PHYS, ebuf) < 0 || - dlokack(p->fd, (char *)buf, ebuf) < 0) - goto bad; - if (dlpromisconreq(p->fd, DL_PROMISC_SAP, ebuf) < 0 || - dlokack(p->fd, (char *)buf, ebuf) < 0) - goto bad; - - /* - ** enable multicast, you would have thought promiscuous - ** would be sufficient. - */ - if (dlpromisconreq(p->fd, DL_PROMISC_MULTI, ebuf) < 0 || - dlokack(p->fd, (char *)buf, ebuf) < 0) - goto bad; - } - - /* - ** Determine link type - */ - if (dlinforeq(p->fd, ebuf) < 0 || - dlinfoack(p->fd, (char *)buf, ebuf) < 0) - goto bad; - - infop = &((union DL_primitives *)buf)->info_ack; - switch (infop->dl_mac_type) { - - case DL_ETHER: - p->linktype = DLT_EN10MB; - break; - - case DL_FDDI: - p->linktype = DLT_FDDI; - break; - - default: - sprintf(ebuf, "unknown mac type 0x%lu", infop->dl_mac_type); - goto bad; - } - -#ifdef DLIOCRAW - /* - ** This is a non standard SunOS hack to get the ethernet header. - */ - if (strioctl(p->fd, DLIOCRAW, 0, NULL) < 0) { - sprintf(ebuf, "DLIOCRAW: %s", pcap_strerror(errno)); - goto bad; - } -#endif - - /* - ** Another non standard call to get the data nicely buffered - */ - if (ioctl(p->fd, I_PUSH, "bufmod") != 0) { - sprintf(ebuf, "I_PUSH bufmod: %s", pcap_strerror(errno)); - goto bad; - } - - /* - ** Now that the bufmod is pushed lets configure it. - ** - ** There is a bug in bufmod(7). When dealing with messages of - ** less than snaplen size it strips data from the beginning not - ** the end. - ** - ** This bug is supposed to be fixed in 5.3.2. Also, there is a - ** patch available. Ask for bugid 1149065. - */ - ss = snaplen; -#ifdef SOLARIS - release = getrelease(&osmajor, &osminor, &osmicro); - if (osmajor == 5 && (osminor <= 2 || (osminor == 3 && osmicro < 2)) && - getenv("BUFMOD_FIXED") == NULL) { - fprintf(stderr, - "WARNING: bufmod is broken in SunOS %s; ignoring snaplen.\n", - release); - ss = 0; - } -#endif - if (ss > 0 && - strioctl(p->fd, SBIOCSSNAP, sizeof(u_long), (char *)&ss) != 0) { - sprintf(ebuf, "SBIOCSSNAP: %s", pcap_strerror(errno)); - goto bad; - } - - /* - ** Set up the bufmod flags - */ - if (strioctl(p->fd, SBIOCGFLAGS, sizeof(u_long), (char *)&flag) < 0) { - sprintf(ebuf, "SBIOCGFLAGS: %s", pcap_strerror(errno)); - goto bad; - } - flag |= SB_NO_DROPS; - if (strioctl(p->fd, SBIOCSFLAGS, sizeof(u_long), (char *)&flag) != 0) { - sprintf(ebuf, "SBIOCSFLAGS: %s", pcap_strerror(errno)); - goto bad; - } - /* - ** Set up the bufmod timeout - */ - if (to_ms != 0) { - struct timeval to; - - to.tv_sec = to_ms / 1000; - to.tv_usec = (to_ms * 1000) % 1000000; - if (strioctl(p->fd, SBIOCSTIME, sizeof(to), (char *)&to) != 0) { - sprintf(ebuf, "SBIOCSTIME: %s", pcap_strerror(errno)); - goto bad; - } - } - - /* - ** As the last operation flush the read side. - */ - if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) { - sprintf(ebuf, "FLUSHR: %s", pcap_strerror(errno)); - goto bad; - } - /* Allocate data buffer */ - p->bufsize = MAXDLBUF * sizeof(long); - p->buffer = (u_char *)malloc(p->bufsize); - return (p); -bad: - free(p); - return (NULL); -} - -int -pcap_setfilter(pcap_t *p, struct bpf_program *fp) -{ - - p->fcode = *fp; - return (0); -} - -static int -send_request(int fd, char *ptr, int len, char *what, char *ebuf) -{ - struct strbuf ctl; - int flags; - - ctl.maxlen = 0; - ctl.len = len; - ctl.buf = ptr; - - flags = 0; - if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0) { - sprintf(ebuf, "putmsg \"%s\"failed: %s", - what, pcap_strerror(errno)); - return (-1); - } - return (0); -} - -static int -dlattachreq(int fd, u_long ppa, char *ebuf) -{ - dl_attach_req_t req; - - req.dl_primitive = DL_ATTACH_REQ; - req.dl_ppa = ppa; - - return (send_request(fd, (char *)&req, sizeof(req), "attach", ebuf)); -} - -static int -dlpromisconreq(int fd, u_long level, char *ebuf) -{ - dl_promiscon_req_t req; - - req.dl_primitive = DL_PROMISCON_REQ; - req.dl_level = level; - - return (send_request(fd, (char *)&req, sizeof(req), "promiscon", ebuf)); -} - -static int -dlokack(int fd, char *bufp, char *ebuf) -{ - union DL_primitives *dlp; - struct strbuf ctl; - int flags; - - ctl.maxlen = MAXDLBUF; - ctl.len = 0; - ctl.buf = bufp; - - flags = 0; - if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0) { - sprintf(ebuf, "getmsg: %s", pcap_strerror(errno)); - return (-1); - } - - dlp = (union DL_primitives *) ctl.buf; - - if (dlp->dl_primitive != DL_OK_ACK) { - sprintf(ebuf, "dlokack unexpected primitive %d", - dlp->dl_primitive); - return (-1); - } - - if (ctl.len != sizeof(dl_ok_ack_t)) { - sprintf(ebuf, "dlokack incorrect size returned"); - return (-1); - } - return (0); -} - - -static int -dlinforeq(int fd, char *ebuf) -{ - dl_info_req_t req; - - req.dl_primitive = DL_INFO_REQ; - - return (send_request(fd, (char *)&req, sizeof(req), "info", ebuf)); -} - -static int -dlinfoack(int fd, char *bufp, char *ebuf) -{ - union DL_primitives *dlp; - struct strbuf ctl; - int flags; - - ctl.maxlen = MAXDLBUF; - ctl.len = 0; - ctl.buf = bufp; - - flags = 0; - if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) { - sprintf(ebuf, "dlinfoack: getmsg: %s", pcap_strerror(errno)); - return (-1); - } - - dlp = (union DL_primitives *) ctl.buf; - - if (dlp->dl_primitive != DL_INFO_ACK) { - sprintf(ebuf, "dlinfoack: unexpected primitive %ld", - dlp->dl_primitive); - return (-1); - } - - /* Extra stuff like the broadcast address can be returned */ - if (ctl.len < DL_INFO_ACK_SIZE) { - sprintf(ebuf, "dlinfoack: incorrect size returned"); - return (-1); - } - return (0); -} - -static int -strioctl(int fd, int cmd, int len, char *dp) -{ - struct strioctl str; - int rc; - - str.ic_cmd = cmd; - str.ic_timout = -1; - str.ic_len = len; - str.ic_dp = dp; - rc = ioctl(fd, I_STR, &str); - - if (rc < 0) - return (rc); - else - return (str.ic_len); -} - -#ifdef SOLARIS -static char * -getrelease(long *majorp, long *minorp, long *microp) -{ - char *cp; - static char buf[32]; - - *majorp = 0; - *minorp = 0; - *microp = 0; - if (sysinfo(SI_RELEASE, buf, sizeof(buf)) < 0) - return ("?"); - cp = buf; - if (!isdigit(*cp)) - return (buf); - *majorp = strtol(cp, &cp, 10); - if (*cp++ != '.') - return (buf); - *minorp = strtol(cp, &cp, 10); - if (*cp++ != '.') - return (buf); - *microp = strtol(cp, &cp, 10); - return (buf); -} -#endif diff --git a/lib/libpcap/pcap-enet.c b/lib/libpcap/pcap-enet.c deleted file mode 100644 index cb052eb..0000000 --- a/lib/libpcap/pcap-enet.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Stanford Enetfilter subroutines for tcpdump - * - * Based on the MERIT NNstat etherifrt.c and the Ultrix pcap-pf.c - * subroutines. - * - * Rayan Zachariassen, CA*Net - */ - -#include <sys/types.h> -#include <sys/time.h> -#include <sys/file.h> -#include <sys/ioctl.h> -#include <sys/socket.h> - -#include <net/if.h> -#include <net/bpf.h> -#include <net/enet.h> - -#include <netinet/in.h> -#include <netinet/if_ether.h> - -#include <stdio.h> -#include <errno.h> - -#include "interface.h" - -struct packet_header { -#ifdef IBMRTPC - struct LengthWords length; - struct tap_header tap; -#endif /* IBMRTPC */ - u_char packet[8] -}; - -extern int errno; - -#define BUFSPACE (4*1024) - -/* Forwards */ -static void efReadError(int, char *); - -void -readloop(int cnt, int if_fd, struct bpf_program *fp, printfunc printit) -{ -#ifdef IBMRTPC - register struct packet_header *ph; - register u_char *bp; - register int inc; -#else /* !IBMRTPC */ - static struct timeval tv = { 0 }; -#endif /* IBMRTPC */ - register int cc, caplen; - register struct bpf_insn *fcode = fp->bf_insns; - union { - struct packet_header hdr; - u_char p[BUFSPACE]; - u_short s; - } buf; - - while (1) { - if ((cc = read(if_fd, (char *)buf.p, sizeof(buf))) < 0) - efReadError(if_fd, "reader"); - -#ifdef IBMRTPC - /* - * Loop through each packet. - */ - bp = buf.p; - while (cc > 0) { - ph = (struct packet_header *)bp; - caplen = ph->tap.th_wirelen > snaplen ? snaplen : ph->tap -.th_wirelen ; - if (bpf_filter(fcode, (char *)ph->packet, - ph->tap.th_wirelen, caplen)) { - if (cnt >= 0 && --cnt < 0) - goto out; - (*printit)((char *)ph->packet, - (struct timeval *)ph->tap.th_timestamp, - ph->tap.th_wirelen, caplen); - } - inc = ph->length.PacketOffset; - cc -= inc; - bp += inc; - } -#else /* !IBMRTPC */ - caplen = cc > snaplen ? snaplen : cc ; - if (bpf_filter(fcode, buf.hdr.packet, cc, caplen)) { - if (cnt >= 0 && --cnt < 0) - goto out; - (*printit)(buf.hdr.packet, &tv, cc, caplen); - } -#endif /* IBMRTPC */ - } - out: - wrapup(if_fd); -} - -/* Call ONLY if read() has returned an error on packet filter */ -static void -efReadError(int fid, char *msg) -{ - if (errno == EINVAL) { /* read MAXINT bytes already! */ - if (lseek(fid, 0, 0) < 0) { - perror("tcpdump: efReadError/lseek"); - exit(-1); - } - else - return; - } - else { - (void) fprintf(stderr, "tcpdump: "); - perror(msg); - exit(-1); - } -} - -void -wrapup(int fd) -{ -#ifdef IBMRTPC - struct enstats es; - - if (ioctl(fd, EIOSTATS, &es) == -1) { - perror("tcpdump: enet ioctl EIOSTATS error"); - exit(-1); - } - - fprintf(stderr, "%d packets queued", es.enStat_Rcnt); - if (es.enStat_Rdrops > 0) - fprintf(stderr, ", %d dropped", es.enStat_Rdrops); - if (es.enStat_Reads > 0) - fprintf(stderr, ", %d tcpdump %s", es.enStat_Reads, - es.enStat_Reads > 1 ? "reads" : "read"); - if (es.enStat_MaxRead > 1) - fprintf(stderr, ", %d packets in largest read", - es.enStat_MaxRead); - putc('\n', stderr); -#endif /* IBMRTPC */ - close(fd); -} - -int -initdevice(char *device, int pflag, int *linktype) -{ - struct eniocb ctl; - struct enfilter filter; - u_int maxwaiting; - int if_fd; - -#ifdef IBMRTPC - GETENETDEVICE(0, O_RDONLY, &if_fd); -#else /* !IBMRTPC */ - if_fd = open("/dev/enet", O_RDONLY, 0); -#endif /* IBMRTPC */ - - if (if_fd == -1) { - perror("tcpdump: enet open error"); - error( -"your system may not be properly configured; see \"man enet(4)\""); - exit(-1); - } - - /* Get operating parameters. */ - - if (ioctl(if_fd, EIOCGETP, (char *)&ctl) == -1) { - perror("tcpdump: enet ioctl EIOCGETP error"); - exit(-1); - } - - /* Set operating parameters. */ - -#ifdef IBMRTPC - ctl.en_rtout = 1 * ctl.en_hz; - ctl.en_tr_etherhead = 1; - ctl.en_tap_network = 1; - ctl.en_multi_packet = 1; - ctl.en_maxlen = BUFSPACE; -#else /* !IBMRTPC */ - ctl.en_rtout = 64; /* randomly picked value for HZ */ -#endif /* IBMRTPC */ - if (ioctl(if_fd, EIOCSETP, &ctl) == -1) { - perror("tcpdump: enet ioctl EIOCSETP error"); - exit(-1); - } - - /* Flush the receive queue, since we've changed - the operating parameters and we otherwise might - receive data without headers. */ - - if (ioctl(if_fd, EIOCFLUSH) == -1) { - perror("tcpdump: enet ioctl EIOCFLUSH error"); - exit(-1); - } - - /* Set the receive queue depth to its maximum. */ - - maxwaiting = ctl.en_maxwaiting; - if (ioctl(if_fd, EIOCSETW, &maxwaiting) == -1) { - perror("tcpdump: enet ioctl EIOCSETW error"); - exit(-1); - } - -#ifdef IBMRTPC - /* Clear statistics. */ - - if (ioctl(if_fd, EIOCLRSTAT, 0) == -1) { - perror("tcpdump: enet ioctl EIOCLRSTAT error"); - exit(-1); - } -#endif /* IBMRTPC */ - - /* Set the filter (accept all packets). */ - - filter.enf_Priority = 3; - filter.enf_FilterLen = 0; - if (ioctl(if_fd, EIOCSETF, &filter) == -1) { - perror("tcpdump: enet ioctl EIOCSETF error"); - exit(-1); - } - /* - * "enetfilter" supports only ethernets. - */ - *linktype = DLT_EN10MB; - - return(if_fd); -} diff --git a/lib/libpcap/pcap-int.h b/lib/libpcap/pcap-int.h deleted file mode 100644 index db3677a..0000000 --- a/lib/libpcap/pcap-int.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the Computer Systems - * Engineering Group at Lawrence Berkeley Laboratory. - * 4. Neither the name of the University nor of the Laboratory may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#) $Header: /home/ncvs/src/lib/libpcap/pcap-int.h,v 1.1.1.1 1995/01/20 04:13:06 jkh Exp $ (LBL) - */ - -#ifndef pcap_int_h -#define pcap_int_h - -#include <pcap.h> - -/* - * Savefile - */ -struct pcap_sf { - FILE *rfile; - int swapped; - int version_major; - int version_minor; - u_char *base; -}; - -struct pcap_md { - struct pcap_stat stat; -#ifdef PCAP_PF - int use_bpf; - u_long TotPkts; /* can't oflow for 79 hrs on ether */ - u_long TotAccepted; /* count accepted by filter */ - u_long TotDrops; /* count of dropped packets */ - long TotMissed; /* missed by i/f during this run */ - long OrigMissed; /* missed by i/f before this run */ -#endif -}; - -struct pcap { - int fd; - int snapshot; - int linktype; - int tzoff; /* timezone offset */ - - struct pcap_sf sf; - struct pcap_md md; - - /* - * Read buffer. - */ - int bufsize; - u_char *buffer; - u_char *bp; - int cc; - - /* - * Place holder for pcap_next(). - */ - u_char *pkt; - - - /* - * Placeholder for filter code if bpf not in kernel. - */ - struct bpf_program fcode; - - char errbuf[PCAP_ERRBUF_SIZE]; -}; - -/* XXX should these be in pcap.h? */ -int pcap_offline_read(pcap_t *, int, pcap_handler, u_char *); -int pcap_read(pcap_t *, int cnt, pcap_handler, u_char *); -#endif diff --git a/lib/libpcap/pcap-namedb.h b/lib/libpcap/pcap-namedb.h deleted file mode 100644 index 3471227..0000000 --- a/lib/libpcap/pcap-namedb.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the Computer Systems - * Engineering Group at Lawrence Berkeley Laboratory. - * 4. Neither the name of the University nor of the Laboratory may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#) $Header: pcap-namedb.h,v 1.2 94/06/14 20:03:34 leres Exp $ (LBL) - */ - -#ifndef lib_pcap_ethers_h -#define lib_pcap_ethers_h - -/* - * As returned by the pcap_next_etherent() - * XXX this stuff doesn't belong in this inteface, but this - * library already must do name to address translation, so - * on systems that don't have support for /etc/ethers, we - * export these hooks since they'll - */ -struct pcap_etherent { - u_char addr[6]; - char name[122]; -}; -#ifndef PCAP_ETHERS_FILE -#define PCAP_ETHERS_FILE "/etc/ethers" -#endif -struct pcap_etherent *pcap_next_etherent(FILE *); -u_char *pcap_ether_hostton(const char*); -u_char *pcap_ether_aton(const char *); - -u_long **pcap_nametoaddr(const char *); -u_long pcap_nametonetaddr(const char *); - -int pcap_nametoport(const char *, int *, int *); -int pcap_nametoproto(const char *); -int pcap_nametoeproto(const char *); -/* - * If a protocol is unknown, PROTO_UNDEF is returned. - * Also, pcap_nametoport() returns the protocol along with the port number. - * If there are ambiguous entried in /etc/services (i.e. domain - * can be either tcp or udp) PROTO_UNDEF is returned. - */ -#define PROTO_UNDEF -1 - -/* XXX move these to pcap-int.h? */ -u_long __pcap_atodn(const char *); -u_long __pcap_atoin(const char *); -u_short __pcap_nametodnaddr(const char *); - -#endif diff --git a/lib/libpcap/pcap-nit.c b/lib/libpcap/pcap-nit.c deleted file mode 100644 index 125e14f..0000000 --- a/lib/libpcap/pcap-nit.c +++ /dev/null @@ -1,240 +0,0 @@ -/* - * Copyright (c) 1990, 1991, 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that: (1) source code distributions - * retain the above copyright notice and this paragraph in its entirety, (2) - * distributions including binary code include the above copyright notice and - * this paragraph in its entirety in the documentation or other materials - * provided with the distribution, and (3) all advertising materials mentioning - * features or use of this software display the following acknowledgement: - * ``This product includes software developed by the University of California, - * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of - * the University nor the names of its contributors may be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ -#ifndef lint -static char rcsid[] = - "@(#)$Header: pcap-nit.c,v 1.24 94/02/10 23:02:37 leres Exp $ (LBL)"; -#endif - -#include <sys/types.h> -#include <sys/time.h> -#include <sys/timeb.h> -#include <sys/file.h> -#include <sys/ioctl.h> -#include <sys/socket.h> - -#include <net/bpf.h> -#include <net/if.h> -#include <net/nit.h> - -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/if_ether.h> -#include <netinet/ip_var.h> -#include <netinet/udp.h> -#include <netinet/udp_var.h> -#include <netinet/tcp.h> -#include <netinet/tcpip.h> - -#include <ctype.h> -#include <errno.h> -#include <stdio.h> - -#include "pcap-int.h" - -/* - * The chunk size for NIT. This is the amount of buffering - * done for read calls. - */ -#define CHUNKSIZE (2*1024) - -/* - * The total buffer space used by NIT. - */ -#define BUFSPACE (4*CHUNKSIZE) - -/* Forwards */ -static int nit_setflags(int, int, int, char *); - -int -pcap_stats(pcap_t *p, struct pcap_stat *ps) -{ - - *ps = p->md.stat; - return (0); -} - -int -pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) -{ - register int cc, n; - register struct bpf_insn *fcode = p->fcode.bf_insns; - register u_char *bp, *cp, *ep; - register struct nit_hdr *nh; - register int caplen; - - cc = p->cc; - if (cc == 0) { - cc = read(p->fd, (char *)p->buffer, p->bufsize); - if (cc < 0) { - if (errno == EWOULDBLOCK) - return (0); - sprintf(p->errbuf, "pcap_read: %s", - pcap_strerror(errno)); - return (-1); - } - bp = p->buffer; - } else - bp = p->bp; - - /* - * Loop through each packet. The increment expression - * rounds up to the next int boundary past the end of - * the previous packet. - */ - n = 0; - ep = bp + cc; - while (bp < ep) { - nh = (struct nit_hdr *)bp; - cp = bp + sizeof(*nh); - - switch (nh->nh_state) { - - case NIT_CATCH: - break; - - case NIT_NOMBUF: - case NIT_NOCLUSTER: - case NIT_NOSPACE: - p->md.stat.ps_drop = nh->nh_dropped; - continue; - - case NIT_SEQNO: - continue; - - default: - sprintf(p->errbuf, "bad nit state %d", nh->nh_state); - return (-1); - } - ++p->md.stat.ps_recv; - bp += ((sizeof(struct nit_hdr) + nh->nh_datalen + - sizeof(int) - 1) & ~(sizeof(int) - 1)); - - caplen = nh->nh_wirelen; - if (caplen > p->snapshot) - caplen = p->snapshot; - if (bpf_filter(fcode, cp, nh->nh_wirelen, caplen)) { - struct pcap_pkthdr h; - h.ts = nh->nh_timestamp; - h.len = nh->nh_wirelen; - h.caplen = caplen; - (*callback)(user, &h, cp); - if (++n >= cnt && cnt >= 0) { - p->cc = ep - bp; - p->bp = bp; - return (n); - } - } - } - p->cc = 0; - return (n); -} - -static int -nit_setflags(int fd, int promisc, int to_ms, char *ebuf) -{ - struct nit_ioc nioc; - - bzero((char *)&nioc, sizeof(nioc)); - nioc.nioc_bufspace = BUFSPACE; - nioc.nioc_chunksize = CHUNKSIZE; - nioc.nioc_typetomatch = NT_ALLTYPES; - nioc.nioc_snaplen = p->snapshot; - nioc.nioc_bufalign = sizeof(int); - nioc.nioc_bufoffset = 0; - - if (to_ms != 0) { - nioc.nioc_flags |= NF_TIMEOUT; - nioc.nioc_timeout.tv_sec = to_ms / 1000; - nioc.nioc_timeout.tv_usec = (to_ms * 1000) % 1000000; - } - if (promisc) - nioc.nioc_flags |= NF_PROMISC; - - if (ioctl(fd, SIOCSNIT, &nioc) < 0) { - sprintf(ebuf, "SIOCSNIT: %s", pcap_strerror(errno)); - return (-1); - } - return (0); -} - -pcap_t * -pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) -{ - int fd; - struct sockaddr_nit snit; - register pcap_t *p; - - p = (pcap_t *)malloc(sizeof(*p)); - if (p == NULL) { - strcpy(ebuf, pcap_strerror(errno)); - return (NULL); - } - - if (snaplen < 96) - /* - * NIT requires a snapshot length of at least 96. - */ - snaplen = 96; - - bzero(p, sizeof(*p)); - p->fd = fd = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW); - if (fd < 0) { - sprintf(ebuf, "socket: %s", pcap_strerror(errno)); - goto bad; - } - snit.snit_family = AF_NIT; - (void)strncpy(snit.snit_ifname, device, NITIFSIZ); - - if (bind(fd, (struct sockaddr *)&snit, sizeof(snit))) { - sprintf(ebuf, "bind: %s: %s", snit.snit_ifname, - pcap_strerror(errno)); - goto bad; - } - p->snapshot = snaplen; - nit_setflags(p->fd, promisc, to_ms, ebuf); - - /* - * NIT supports only ethernets. - */ - p->linktype = DLT_EN10MB; - - p->bufsize = BUFSPACE; - p->buffer = (u_char *)malloc(p->bufsize); - if (p->buffer == NULL) { - strcpy(ebuf, pcap_strerror(errno)); - goto bad; - } - return (p); - bad: - if (fd >= 0) - close(fd); - free(p); - return (NULL); -} - -int -pcap_setfilter(pcap_t *p, struct bpf_program *fp) -{ - - p->fcode = *fp; - return (0); -} diff --git a/lib/libpcap/pcap-nit.h b/lib/libpcap/pcap-nit.h deleted file mode 100644 index dc1c9e8..0000000 --- a/lib/libpcap/pcap-nit.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 1990, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Lawrence Berkeley Laboratory, - * Berkeley, CA. The name of the University may not be used to - * endorse or promote products derived from this software without - * specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * @(#) $Header: pcap-nit.h,v 1.2 94/06/14 20:06:03 leres Exp $ (LBL) - */ diff --git a/lib/libpcap/pcap-pf.c b/lib/libpcap/pcap-pf.c deleted file mode 100644 index 483dc97..0000000 --- a/lib/libpcap/pcap-pf.c +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Copyright (c) 1990, 1991, 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that: (1) source code distributions - * retain the above copyright notice and this paragraph in its entirety, (2) - * distributions including binary code include the above copyright notice and - * this paragraph in its entirety in the documentation or other materials - * provided with the distribution, and (3) all advertising materials mentioning - * features or use of this software display the following acknowledgement: - * ``This product includes software developed by the University of California, - * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of - * the University nor the names of its contributors may be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ -#ifndef lint -static char rcsid[] = - "@(#)$Header: pcap-pf.c,v 1.32 94/06/10 17:41:01 mccanne Exp $ (LBL)"; -#endif - -/* - * packet filter subroutines for tcpdump - * Extraction/creation by Jeffrey Mogul, DECWRL - * - * Extracted from tcpdump.c. - */ - -#include <sys/types.h> -#include <sys/time.h> -#include <sys/timeb.h> -#include <sys/socket.h> -#include <sys/file.h> -#include <sys/ioctl.h> -#include <net/pfilt.h> - -#include <net/if.h> -#include <net/bpf.h> - -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/if_ether.h> -#include <netinet/ip_var.h> -#include <netinet/udp.h> -#include <netinet/udp_var.h> -#include <netinet/tcp.h> -#include <netinet/tcpip.h> - -#include <ctype.h> -#include <errno.h> -#include <netdb.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "pcap-int.h" - -/* - * BUFSPACE is the size in bytes of the packet read buffer. Most tcpdump - * applications aren't going to need more than 200 bytes of packet header - * and the read shouldn't return more packets than packetfilter's internal - * queue limit (bounded at 256). - */ -#define BUFSPACE (200*256) - -int -pcap_read(pcap_t *pc, int cnt, pcap_handler callback, u_char *user) -{ - u_char *p; - struct bpf_insn *fcode; - int cc; - register u_char *bp; - int buflen, inc; - struct enstamp stamp; - int n; - fcode = pc->md.use_bpf ? 0 : pc->fcode.bf_insns; - again: - cc = pc->cc; - if (cc == 0) { - cc = read(pc->fd, (char *)pc->buffer, pc->bufsize); - if (cc < 0) { - if (errno == EWOULDBLOCK) - return (0); - if (errno == EINVAL && - (long)(tell(pc->fd) + pc->bufsize) < 0) { - /* - * Due to a kernel bug, after 2^31 bytes, - * the kernel file offset overflows and - * read fails with EINVAL. The lseek() - * to 0 will fix things. - */ - (void)lseek(pc->fd, 0L, 0); - goto again; - } - sprintf(pc->errbuf, "pf read: %s", - pcap_strerror(errno)); - return (-1); - } - bp = pc->buffer; - } else - bp = pc->bp; - /* - * Loop through each packet. - */ - n = 0; - while (cc > 0) { - /* avoid alignment issues here */ - bcopy((char *)bp, (char *)&stamp, sizeof(stamp)); - if (stamp.ens_stamplen != sizeof(stamp)) - /* buffer is garbage, treat it as poison */ - break; - - p = bp + stamp.ens_stamplen; - - buflen = stamp.ens_count; - if (buflen > pc->snapshot) - buflen = pc->snapshot; - - /* - * Short-circuit evaluation: if using BPF filter - * in kernel, no need to do it now. - */ - if (fcode == 0 || - bpf_filter(fcode, p, stamp.ens_count, buflen)) { - struct pcap_pkthdr h; - pc->md.TotAccepted++; - h.ts = stamp.ens_tstamp; - h.len = stamp.ens_count; - h.caplen = buflen; - (*callback)(user, &h, p); - if (++n >= cnt && cnt > 0) { - inc = ENALIGN(buflen + stamp.ens_stamplen); - cc -= inc; - bp += inc; - pc->cc = cc; - pc->bp = bp; - return (n); - } - } - pc->md.TotPkts++; - pc->md.TotDrops += stamp.ens_dropped; - pc->md.TotMissed = stamp.ens_ifoverflows; - if (pc->md.OrigMissed < 0) - pc->md.OrigMissed = pc->md.TotMissed; - - inc = ENALIGN(buflen + stamp.ens_stamplen); - cc -= inc; - bp += inc; - } - pc->cc = 0; - return (n); -} - -int -pcap_stats(pcap_t *p, struct pcap_stat *ps) -{ - ps->ps_recv = p->md.TotAccepted; - ps->ps_drop = p->md.TotDrops; - ps->ps_ifdrop = p->md.TotMissed - p->md.OrigMissed; - return (0); -} - -pcap_t * -pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) -{ - pcap_t *p; - short enmode; - int backlog = -1; /* request the most */ - struct enfilter Filter; - struct endevp devparams; - - p = (pcap_t *)malloc(sizeof(*p)); - if (p == 0) { - strcpy(ebuf, "no swap"); - return (0); - } - bzero(p, sizeof(*p)); - p->fd = pfopen(device, 0); - if (p->fd < 0) { - sprintf(ebuf, "pf open: %s: %s\n\ -your system may not be properly configured; see \"man packetfilter(4)\"\n", - device, pcap_strerror(errno)); - goto bad; - } - p->md.OrigMissed = -1; - enmode = ENTSTAMP|ENBATCH|ENNONEXCL; - if (promisc) - enmode |= ENPROMISC; - if (ioctl(p->fd, EIOCMBIS, (caddr_t)&enmode) < 0) { - sprintf(ebuf, "EIOCMBIS: %s", pcap_strerror(errno)); - goto bad; - } -#ifdef ENCOPYALL - /* Try to set COPYALL mode so that we see packets to ourself */ - enmode = ENCOPYALL; - (void)ioctl(p->fd, EIOCMBIS, (caddr_t)&enmode);/* OK if this fails */ -#endif - /* set the backlog */ - if (ioctl(p->fd, EIOCSETW, (caddr_t)&backlog) < 0) { - sprintf(ebuf, "EIOCSETW: %s", pcap_strerror(errno)); - goto bad; - } - /* set truncation */ - if (ioctl(p->fd, EIOCTRUNCATE, (caddr_t)&snaplen) < 0) { - sprintf(ebuf, "EIOCTRUNCATE: %s", pcap_strerror(errno)); - goto bad; - } - p->snapshot = snaplen; - /* accept all packets */ - Filter.enf_Priority = 37; /* anything > 2 */ - Filter.enf_FilterLen = 0; /* means "always true" */ - if (ioctl(p->fd, EIOCSETF, (caddr_t)&Filter) < 0) { - sprintf(ebuf, "EIOCSETF: %s", pcap_strerror(errno)); - goto bad; - } - /* discover interface type */ - if (ioctl(p->fd, EIOCDEVP, (caddr_t)&devparams) < 0) { - sprintf(ebuf, "EIOCDEVP: %s", pcap_strerror(errno)); - goto bad; - } - /* HACK: to compile prior to Ultrix 4.2 */ -#ifndef ENDT_FDDI -#define ENDT_FDDI 4 -#endif - switch (devparams.end_dev_type) { - case ENDT_10MB: - p->linktype = DLT_EN10MB; - break; - - case ENDT_FDDI: - p->linktype = DLT_FDDI; - break; - - default: - /* - * XXX - * Currently, the Ultrix packet filter supports only - * Ethernet and FDDI. Eventually, support for SLIP and PPP - * (and possibly others: T1?) should be added. - */ -#ifdef notdef - warning( - "Packet filter data-link type %d unknown, assuming Ethernet", - devparams.end_dev_type); -#endif - p->linktype = DLT_EN10MB; - break; - } - - if (to_ms != 0) { - struct timeval timeout; - timeout.tv_sec = to_ms / 1000; - timeout.tv_usec = (to_ms * 1000) % 1000000; - if (ioctl(p->fd, EIOCSRTIMEOUT, (caddr_t)&timeout) < 0) { - sprintf(ebuf, "EIOCSRTIMEOUT: %s", - pcap_strerror(errno)); - goto bad; - } - } - p->bufsize = BUFSPACE; - p->buffer = (u_char*)malloc(p->bufsize); - - return (p); - bad: - free(p); - return (0); -} - -int -pcap_setfilter(pcap_t *p, struct bpf_program *fp) -{ - /* - * See if BIOCSETF works. If it does, the kernel supports - * BPF-style filters, and we do not need to do post-filtering. - */ - p->md.use_bpf = (ioctl(p->fd, BIOCSETF, (caddr_t)fp) >= 0); - if (p->md.use_bpf) { - struct bpf_version bv; - - if (ioctl(p->fd, BIOCVERSION, (caddr_t)&bv) < 0) { - sprintf(p->errbuf, "BIOCVERSION: %s", - pcap_strerror(errno)); - return (-1); - } - else if (bv.bv_major != BPF_MAJOR_VERSION || - bv.bv_minor < BPF_MINOR_VERSION) { - fprintf(stderr, - "requires bpf language %d.%d or higher; kernel is %d.%d", - BPF_MAJOR_VERSION, BPF_MINOR_VERSION, - bv.bv_major, bv.bv_minor); - /* don't give up, just be inefficient */ - p->md.use_bpf = 0; - } - } else - p->fcode = *fp; - - /*XXX this goes in tcpdump*/ - if (p->md.use_bpf) - fprintf(stderr, "tcpdump: Using kernel BPF filter\n"); - else - fprintf(stderr, "tcpdump: Filtering in user process\n"); - return (0); -} diff --git a/lib/libpcap/pcap-pf.h b/lib/libpcap/pcap-pf.h deleted file mode 100644 index 65ca067..0000000 --- a/lib/libpcap/pcap-pf.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 1990, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that the above copyright notice and this paragraph are - * duplicated in all such forms and that any documentation, - * advertising materials, and other materials related to such - * distribution and use acknowledge that the software was developed - * by the University of California, Lawrence Berkeley Laboratory, - * Berkeley, CA. The name of the University may not be used to - * endorse or promote products derived from this software without - * specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. - * - * @(#) $Header: pcap-pf.h,v 1.2 94/06/14 20:06:33 leres Exp $ (LBL) - */ diff --git a/lib/libpcap/pcap-snit.c b/lib/libpcap/pcap-snit.c deleted file mode 100644 index 562b965..0000000 --- a/lib/libpcap/pcap-snit.c +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright (c) 1990, 1991, 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that: (1) source code distributions - * retain the above copyright notice and this paragraph in its entirety, (2) - * distributions including binary code include the above copyright notice and - * this paragraph in its entirety in the documentation or other materials - * provided with the distribution, and (3) all advertising materials mentioning - * features or use of this software display the following acknowledgement: - * ``This product includes software developed by the University of California, - * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of - * the University nor the names of its contributors may be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ -#ifndef lint -static char rcsid[] = - "@(#)$Header: pcap-snit.c,v 1.33 94/06/23 13:51:17 leres Exp $ (LBL)"; -#endif - -/* - * Modifications made to accomodate the new SunOS4.0 NIT facility by - * Micky Liu, micky@cunixc.cc.columbia.edu, Columbia University in May, 1989. - * This module now handles the STREAMS based NIT. - */ - -#include <sys/types.h> -#include <sys/time.h> -#include <sys/timeb.h> -#include <sys/dir.h> -#include <sys/fcntlcom.h> -#include <sys/file.h> -#include <sys/ioctl.h> -#include <sys/socket.h> -#include <sys/stropts.h> - -#include <net/bpf.h> -#include <net/if.h> -#include <net/nit.h> -#include <net/nit_if.h> -#include <net/nit_pf.h> -#include <net/nit_buf.h> - -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/if_ether.h> -#include <netinet/ip_var.h> -#include <netinet/udp.h> -#include <netinet/udp_var.h> -#include <netinet/tcp.h> -#include <netinet/tcpip.h> - -#include <ctype.h> -#include <errno.h> -#include <stdio.h> -#include <string.h> - -#include "pcap-int.h" - -/* - * The chunk size for NIT. This is the amount of buffering - * done for read calls. - */ -#define CHUNKSIZE (2*1024) - -/* - * The total buffer space used by NIT. - */ -#define BUFSPACE (4*CHUNKSIZE) - -/* Forwards */ -static int nit_setflags(int, int, int, char *); - -int -pcap_stats(pcap_t *p, struct pcap_stat *ps) -{ - - *ps = p->md.stat; - return (0); -} - -int -pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) -{ - register int cc, n; - register struct bpf_insn *fcode = p->fcode.bf_insns; - register u_char *bp, *cp, *ep; - register struct nit_bufhdr *hdrp; - register struct nit_iftime *ntp; - register struct nit_iflen *nlp; - register struct nit_ifdrops *ndp; - register int caplen; - - cc = p->cc; - if (cc == 0) { - cc = read(p->fd, (char *)p->buffer, p->bufsize); - if (cc < 0) { - if (errno == EWOULDBLOCK) - return (0); - sprintf(p->errbuf, "pcap_read: %s", - pcap_strerror(errno)); - return (-1); - } - bp = p->buffer; - } else - bp = p->bp; - - /* - * loop through each snapshot in the chunk - */ - n = 0; - ep = bp + cc; - while (bp < ep) { - ++p->md.stat.ps_recv; - cp = bp; - - /* get past NIT buffer */ - hdrp = (struct nit_bufhdr *)cp; - cp += sizeof(*hdrp); - - /* get past NIT timer */ - ntp = (struct nit_iftime *)cp; - cp += sizeof(*ntp); - - ndp = (struct nit_ifdrops *)cp; - p->md.stat.ps_drop = ndp->nh_drops; - cp += sizeof *ndp; - - /* get past packet len */ - nlp = (struct nit_iflen *)cp; - cp += sizeof(*nlp); - - /* next snapshot */ - bp += hdrp->nhb_totlen; - - caplen = nlp->nh_pktlen; - if (caplen > p->snapshot) - caplen = p->snapshot; - - if (bpf_filter(fcode, cp, nlp->nh_pktlen, caplen)) { - struct pcap_pkthdr h; - h.ts = ntp->nh_timestamp; - h.len = nlp->nh_pktlen; - h.caplen = caplen; - (*callback)(user, &h, cp); - if (++n >= cnt && cnt >= 0) { - p->cc = ep - bp; - p->bp = bp; - return (n); - } - } - } - p->cc = 0; - return (n); -} - -static int -nit_setflags(int fd, int promisc, int to_ms, char *ebuf) -{ - u_long flags; - struct strioctl si; - struct timeval timeout; - - si.ic_timout = INFTIM; - if (to_ms != 0) { - timeout.tv_sec = to_ms / 1000; - timeout.tv_usec = (to_ms * 1000) % 1000000; - si.ic_cmd = NIOCSTIME; - si.ic_len = sizeof(timeout); - si.ic_dp = (char *)&timeout; - if (ioctl(fd, I_STR, (char *)&si) < 0) { - sprintf(ebuf, "NIOCSTIME: %s", pcap_strerror(errno)); - return (-1); - } - } - flags = NI_TIMESTAMP | NI_LEN | NI_DROPS; - if (promisc) - flags |= NI_PROMISC; - si.ic_cmd = NIOCSFLAGS; - si.ic_len = sizeof(flags); - si.ic_dp = (char *)&flags; - if (ioctl(fd, I_STR, (char *)&si) < 0) { - sprintf(ebuf, "NIOCSFLAGS: %s", pcap_strerror(errno)); - return (-1); - } - return (0); -} - -pcap_t * -pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) -{ - struct strioctl si; /* struct for ioctl() */ - struct ifreq ifr; /* interface request struct */ - int chunksize = CHUNKSIZE; - int fd; - static char dev[] = "/dev/nit"; - register pcap_t *p; - - p = (pcap_t *)malloc(sizeof(*p)); - if (p == NULL) { - strcpy(ebuf, pcap_strerror(errno)); - return (NULL); - } - - if (snaplen < 96) - /* - * NIT requires a snapshot length of at least 96. - */ - snaplen = 96; - - bzero(p, sizeof(*p)); - p->fd = fd = open(dev, O_RDONLY); - if (fd < 0) { - sprintf(ebuf, "%s: %s", dev, pcap_strerror(errno)); - goto bad; - } - - /* arrange to get discrete messages from the STREAM and use NIT_BUF */ - if (ioctl(fd, I_SRDOPT, (char *)RMSGD) < 0) { - sprintf(ebuf, "I_SRDOPT: %s", pcap_strerror(errno)); - goto bad; - } - if (ioctl(fd, I_PUSH, "nbuf") < 0) { - sprintf(ebuf, "push nbuf: %s", pcap_strerror(errno)); - goto bad; - } - /* set the chunksize */ - si.ic_cmd = NIOCSCHUNK; - si.ic_timout = INFTIM; - si.ic_len = sizeof(chunksize); - si.ic_dp = (char *)&chunksize; - if (ioctl(fd, I_STR, (char *)&si) < 0) { - sprintf(ebuf, "NIOCSCHUNK: %s", pcap_strerror(errno)); - goto bad; - } - - /* request the interface */ - strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); - ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = ' '; - si.ic_cmd = NIOCBIND; - si.ic_len = sizeof(ifr); - si.ic_dp = (char *)𝔦 - if (ioctl(fd, I_STR, (char *)&si) < 0) { - sprintf(ebuf, "NIOCBIND: %s: %s", - ifr.ifr_name, pcap_strerror(errno)); - goto bad; - } - - /* set the snapshot length */ - si.ic_cmd = NIOCSSNAP; - si.ic_len = sizeof(snaplen); - si.ic_dp = (char *)&snaplen; - if (ioctl(fd, I_STR, (char *)&si) < 0) { - sprintf(ebuf, "NIOCSSNAP: %s", pcap_strerror(errno)); - goto bad; - } - p->snapshot = snaplen; - if (nit_setflags(p->fd, promisc, to_ms, ebuf) < 0) - goto bad; - - (void)ioctl(fd, I_FLUSH, (char *)FLUSHR); - /* - * NIT supports only ethernets. - */ - p->linktype = DLT_EN10MB; - - p->bufsize = BUFSPACE; - p->buffer = (u_char *)malloc(p->bufsize); - if (p->buffer == NULL) { - strcpy(ebuf, pcap_strerror(errno)); - goto bad; - } - return (p); - bad: - if (fd >= 0) - close(fd); - free(p); - return (NULL); -} - -int -pcap_setfilter(pcap_t *p, struct bpf_program *fp) -{ - - p->fcode = *fp; - return (0); -} diff --git a/lib/libpcap/pcap-snoop.c b/lib/libpcap/pcap-snoop.c deleted file mode 100644 index 50f9785..0000000 --- a/lib/libpcap/pcap-snoop.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that: (1) source code distributions - * retain the above copyright notice and this paragraph in its entirety, (2) - * distributions including binary code include the above copyright notice and - * this paragraph in its entirety in the documentation or other materials - * provided with the distribution, and (3) all advertising materials mentioning - * features or use of this software display the following acknowledgement: - * ``This product includes software developed by the University of California, - * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of - * the University nor the names of its contributors may be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ -#ifndef lint -static char rcsid[] = - "@(#)$Header: pcap-snoop.c,v 1.6 94/01/31 05:26:09 leres Exp $ (LBL)"; -#endif - -#include <sys/param.h> -#include <stdio.h> -#include <netdb.h> -#include <ctype.h> -#include <signal.h> -#include <errno.h> -#include <sys/time.h> -#include <sys/socket.h> -#include <sys/file.h> -#include <sys/ioctl.h> - -#include <net/raw.h> - -#include <net/if.h> -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/if_ether.h> -#include <netinet/ip_var.h> -#include <netinet/udp.h> -#include <netinet/udp_var.h> -#include <netinet/tcp.h> -#include <netinet/tcpip.h> -#include <net/bpf.h> - -#include "pcap-int.h" - -static int hdrpad; /* XXX */ - -int -pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) -{ - int cc; - register struct snoopheader *sh; - register int datalen; - register int caplen; - register u_char *cp; - again: - cc = read(p->fd, (char *)p->buffer, p->bufsize); - if (cc < 0) { - switch (errno) { - case EWOULDBLOCK: - return (0); /* XXX */ - } - sprintf(p->errbuf, "read: %s", pcap_strerror(errno)); - return (-1); - } - sh = (struct snoopheader *)p->buffer; - datalen = sh->snoop_packetlen; - caplen = (datalen < p->snapshot) ? datalen : p->snapshot; - cp = (u_char *)(sh + 1) + hdrpad; /* XXX */ - - if (p->fcode.bf_insns == NULL || - bpf_filter(p->fcode.bf_insns, cp, datalen, caplen)) { - struct pcap_pkthdr h; - ++p->md.stat.ps_recv; - h.ts = sh->snoop_timestamp; - h.len = datalen; - h.caplen = caplen; - (*callback)(user, &h, cp); - return (1); - } - return (0); -} - -int -pcap_stats(pcap_t *p, struct pcap_stat *ps) -{ - register struct rawstats *rs; - struct rawstats rawstats; - - rs = &rawstats; - bzero((char *)rs, sizeof(*rs)); - if (ioctl(p->fd, SIOCRAWSTATS, (char *)rs) < 0) { - sprintf(p->errbuf, "SIOCRAWSTATS: %s", pcap_strerror(errno)); - return (-1); - } - - p->md.stat.ps_drop = - rs->rs_snoop.ss_ifdrops + rs->rs_snoop.ss_sbdrops + - rs->rs_drain.ds_ifdrops + rs->rs_drain.ds_sbdrops; - - *ps = p->md.stat; - return (0); -} - -/* XXX can't disable promiscuous */ -pcap_t * -pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) -{ - pcap_t *p; - struct sockaddr_raw sr; - int fd; - int v; - struct snoopfilter sf; - - p = (pcap_t *)malloc(sizeof(*p)); - if (p == NULL) { - strcpy(ebuf, "no swap"); - return (0); - } - bzero(p, sizeof(*p)); - p->fd = -1; - p->bufsize = 4096; /* XXX */ - p->buffer = (u_char *)malloc(p->bufsize); - if (p->buffer == NULL) { - strcpy(ebuf, "no swap"); - goto bad; - } - fd = p->fd = socket(PF_RAW, SOCK_RAW, RAWPROTO_SNOOP); - if (fd < 0) { - sprintf(ebuf, "snoop socket: %s", pcap_strerror(errno)); - goto bad; - } - sr.sr_family = AF_RAW; - sr.sr_port = 0; - (void)strncpy(sr.sr_ifname, device, sizeof(sr.sr_ifname)); - if (bind(fd, (struct sockaddr *)&sr, sizeof(sr))) { - sprintf(ebuf, "snoop bind: %s", pcap_strerror(errno)); - goto bad; - } - bzero((char *)&sf, sizeof(sf)); - if (ioctl(fd, SIOCADDSNOOP, &sf) < 0) { - sprintf(ebuf, "SIOCADDSNOOP: %s", pcap_strerror(errno)); - goto bad; - } - v = 64 * 1024; - (void)setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&v, sizeof(v)); - if (ioctl(fd, SIOCSNOOPLEN, &snaplen) < 0) { - sprintf(ebuf, "SIOCSNOOPLEN: %s", pcap_strerror(errno)); - goto bad; - } - p->snapshot = snaplen; - v = 1; - if (ioctl(fd, SIOCSNOOPING, &v) < 0) { - sprintf(ebuf, "SIOCSNOOPING: %s", pcap_strerror(errno)); - goto bad; - } - /* - * XXX hack - map device name to link later type - */ - if (strncmp("et", device, 2) == 0 || - strncmp("ec", device, 2) == 0) { - p->linktype = DLT_EN10MB; - hdrpad = RAW_HDRPAD(sizeof(struct ether_header)); - } else if (strncmp("ipg", device, 3) == 0 || - strncmp("xpi", device, 3) == 0) { - p->linktype = DLT_FDDI; - hdrpad = 3; /* XXX yeah? */ - } else { - sprintf(ebuf, "snoop: unknown physical layer type"); - goto bad; - } - return (p); - bad: - if (fd >= 0) - close(fd); - if (p->buffer != NULL) - free(p->buffer); - free(p); - return (0); -} - -int -pcap_setfilter(pcap_t *p, struct bpf_program *fp) -{ - - p->fcode = *fp; - return (0); -} diff --git a/lib/libpcap/pcap.3 b/lib/libpcap/pcap.3 deleted file mode 100644 index d298b40..0000000 --- a/lib/libpcap/pcap.3 +++ /dev/null @@ -1,325 +0,0 @@ -.\" Copyright (c) 1994 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that: (1) source code distributions -.\" retain the above copyright notice and this paragraph in its entirety, (2) -.\" distributions including binary code include the above copyright notice and -.\" this paragraph in its entirety in the documentation or other materials -.\" provided with the distribution, and (3) all advertising materials mentioning -.\" features or use of this software display the following acknowledgement: -.\" ``This product includes software developed by the University of California, -.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of -.\" the University nor the names of its contributors may be used to endorse -.\" or promote products derived from this software without specific prior -.\" written permission. -.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED -.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF -.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -.\" -.TH PCAP 3 "14 Jun 1994" -.SH NAME -pcap \- Packet Capture library -.SH SYNOPSIS -.nf -.ft B -#include <sys/types.h> -#include <stdio.h> -#include <pcap.h> -.ft -.LP -.ft B -pcap_t *pcap_open_live(char *device, int snaplen, -.ti +8 -int promisc, int to_ms, char *ebuf) -pcap_t *pcap_open_offline(char *fname, char *ebuf) -pcap_dumper_t *pcap_dump_open(pcap_t *p, char *fname) -.ft -.LP -.ft B -char errbuf[PCAP_ERRBUF_SIZE]; -char *pcap_lookupdev(char *errbuf) -int pcap_lookupnet(char *device, u_long *netp, -.ti +8 -u_long *maskp, char *errbuf) -.ft -.LP -.ft B -int pcap_dispatch(pcap_t *p, int cnt, -.ti +8 -pcap_handler callback, u_char *user) -int pcap_loop(pcap_t *p, int cnt, -.ti +8 -pcap_handler callback, u_char *user) -void pcap_dump(u_char *user, struct pcap_pkthdr *h, -.ti +8 -u_char *sp) -.ft -.LP -.ft B -int pcap_immediate(pcap_t *p) -.ft -.LP -.ft B -int pcap_compile(pcap_t *p, struct bpf_program *fp, -.ti +8 -char *str, int optimize, u_long netmask) -int pcap_setfilter(pcap_t *p, struct bpf_program *fp) -.ft -.LP -.ft B -u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h) -.ft -.LP -.ft B -int pcap_datalink(pcap_t *p) -int pcap_snapshot(pcap_t *p) -int pcap_is_swapped(pcap_t *p) -int pcap_major_version(pcap_t *p) -int pcap_minor_version(pcap_t *p) -int pcap_stats(pcap_t *p, struct pcap_stat *ps) -FILE *pcap_file(pcap_t *p) -int pcap_fileno(pcap_t *p) -void pcap_perror(pcap_t *p, char *prefix) -char *pcap_geterr(pcap_t *p) -char *pcap_strerror(int error) -.ft -.LP -.ft B -void pcap_close(pcap_t *p) -void pcap_dump_close(pcap_dumper_t *p) -.ft -.fi -.SH DESCRIPTION -The Packet Capture library -provides a high level interface to packet capture systems. All packets -on the network, even those destined for other hosts, are accessible -through this mechanism. -.PP -.SH ROUTINES -.B pcap_open_live() -is used to obtain a packet capture descriptor to look -at packets on the network. -.I device -is a string that specifies the network device to open. -.I snaplen -specifies the maximum number of bytes to capture. -.I to_ms -specifies the read timeout in milliseconds. -.I ebuf -is used to return error text and is only set when -.B pcap_open_live() -fails and returns -.BR NULL . -.PP -.B pcap_open_offline() -is called to open a ``savefile'' for reading. -.I fname -specifies the name of the file to open. The file has -the same format as those used by -.B tcpdump(1) -and -.BR tcpslice(1) . -The name "-" in a synonym for -.BR stdin . -.I ebuf -is used to return error text and is only set when -.B pcap_open_offline() -fails and returns -.BR NULL . -.PP -.B pcap_dump_open() -is called to open a ``savefile'' for writing. The name "-" in a synonym -for -.BR stdin . -.B NULL -is returned on failure. -.I p -is a -.I pcap -struct as returned by -.B pcap_open_offline() -or -.BR pcap_open_live() . -.I fname -specifies the name of the file to open. -If -.B NULL -is returned, -.B pcap_geterr() -can be used to get the error text. -.PP -.B pcap_lookupdev() -returns a pointer to a network device suitable for use with -.B pcap_open_live() -and -.BR pcap_lookupnet() . -If there is an error, -.B NULL -is returned and -.I errbuf -is filled in with with an appropriate error message. -.PP -.B pcap_lookupnet() -is used to determine the network number and mask -associated with the network device -.BR device . -Both -.I netp -and -.I maskp -are -.I u_long -pointers. -A return of -1 indicates an error in which case -.I errbuf -is filled in with with an appropriate error message. -.PP -.B pcap_dispatch() -is used to collect and process packets. -.I cnt -specifies the maximum number of packets to process before returning. A -.I cnt -of -1 processes all the packets received in one buffer. A -.I cnt -of 0 processes all packets until an error occurs (or -.B EOF -is reached). -.I callback -specifies a routine to be called with three arguments: -a -.I u_char -pointer which is passed in from -.BR pcap_dispatch() , -a pointer to the -.I pcap_pkthdr -struct (which precede the actual network headers and data), -and a length. The number of packets read is returned. -Zero is returned when -.B EOF -is reached in a ``savefile.'' A return of -1 indicates -an error in which case -.B pcap_perror() -or -.BR pcap_geterr() -may be used to display the error text. -.PP -.B pcap_dump() -outputs a packet to the ``savefile'' opened with -.BR pcap_dump_open() . -Note that its calling arguments are suitable for use with -.BR pcap_dispatch() . -.ft B -(??? this guy is kind of weird.) -.ft -.PP -.B pcap_immediate() -sets ``immediate'' mode. -If this isn't supported by the under lying packet capture, -1 is -returned and the error text can be obtained with -.B pcap_perror() -or -.BR pcap_geterr() . -.PP -.B pcap_compile() -is used to compile the string -.I str -into a filter program. -.I program -is a pointer to a -.I bpf_program -struct and is filled in by -.BR pcap_compile() . -.I optimize -controls whether optimization on the resulting code is performed. -.I netmask -specifies the netmask of the local net. -.PP -.B pcap_setfilter() -is used to specify the a filter program. -.I fp -is a pointer to an array of -.I bpf_program -struct, usually the result of a call to -.BR pcap_compile() . -.PP -.B pcap_loop() -is similar to -.B pcap_dispatch() -except it keeps reading packets until -.I cnt -packets are processed or an error occurs. -A negative -.I cnt -causes -.B pcap_loop() -to loop forever (or at least until an error occurs). -.PP -.B pcap_next() -returns a -.I u_char -pointer to the next packet. -.PP -.B pcap_datalink() -returns the link layer type, e.g. -.BR DLT_EN10MB . -.PP -.B pcap_snapshot() -returns the snapshot length specified when -.B pcap_open_live -was called. -.PP -.B pcap_is_swapped() -returns true if the current ``savefile'' uses a different byte order -than the current system. -.PP -.B pcap_major_version() -returns the major number of the version of the pcap used to write the -savefile. -.PP -.B pcap_minor_version() -returns the major number of the version of the pcap used to write the -savefile. -.PP -.B pcap_file() -returns the name of the ``savefile.'' -.PP -.B int pcap_stats() -returns 0 and fills in a -.B pcap_stat -struct with packet statistics. If there is an error or the under lying -packet capture doesn't support packet statistics, -1 is returned and -the error text can be obtained with -.B pcap_perror() -or -.BR pcap_geterr() . -.PP -.B pcap_fileno() -returns the file descriptor number of the ``savefile.'' -.PP -.B pcap_perror() -prints the text of the last pcap library error on -.BR stderr , -prefixed by -.IR prefix . -.PP -.B pcap_geterr() -returns the error text pertaining to the last pcap library error. -.PP -.B pcap_strerror() -is provided in case -.BR strerror (1) -isn't available. -.PP -.B pcap_close() -closes the files associated with -.I p -and deallocates resources. -.PP -.B pcap_dump_close() -closes the ``savefile.'' -.PP -.SH SEE ALSO -tcpdump(1), tcpslice(1) -.SH BUGS -.SH HISTORY diff --git a/lib/libpcap/pcap.c b/lib/libpcap/pcap.c deleted file mode 100644 index 398b6f3..0000000 --- a/lib/libpcap/pcap.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (c) 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the Computer Systems - * Engineering Group at Lawrence Berkeley Laboratory. - * 4. Neither the name of the University nor of the Laboratory may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char rcsid[] = - "@(#) $Header: /home/ncvs/src/lib/libpcap/pcap.c,v 1.3 1995/05/30 05:47:24 rgrimes Exp $ (LBL)"; -#endif - -#include <sys/types.h> - -#include <stdlib.h> -#include <unistd.h> -#include <string.h> - -#include "pcap-int.h" - -int -pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user) -{ - if (p->sf.rfile != NULL) - return (pcap_offline_read(p, cnt, callback, user)); - else - return (pcap_read(p, cnt, callback, user)); -} - -int -pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user) -{ - for (;;) { - int n = pcap_dispatch(p, cnt, callback, user); - if (n < 0) - return (n); - if (cnt > 0) { - cnt -= n; - if (cnt <= 0) - return (0); - } - } -} - -struct singleton { - struct pcap_pkthdr *hdr; - const u_char *pkt; -}; - - -static void -pcap_oneshot(u_char *userData, const struct pcap_pkthdr *h, const u_char *pkt) -{ - struct singleton *sp = (struct singleton *)userData; - *sp->hdr = *h; - sp->pkt = pkt; -} - -const u_char * -pcap_next(pcap_t *p, struct pcap_pkthdr *h) -{ - struct singleton s; - - s.hdr = h; - if (pcap_dispatch(p, 1, pcap_oneshot, (u_char*)&s) < 0) - return (0); - return (s.pkt); -} - -int -pcap_datalink(pcap_t *p) -{ - return (p->linktype); -} - -int -pcap_snapshot(pcap_t *p) -{ - return (p->snapshot); -} - -int -pcap_is_swapped(pcap_t *p) -{ - return (p->sf.swapped); -} - -int -pcap_major_version(pcap_t *p) -{ - return (p->sf.version_major); -} - -int -pcap_minor_version(pcap_t *p) -{ - return (p->sf.version_minor); -} - -FILE * -pcap_file(pcap_t *p) -{ - return (p->sf.rfile); -} - -int -pcap_fileno(pcap_t *p) -{ - return (p->fd); -} - -void -pcap_perror(pcap_t *p, char *prefix) -{ - fprintf(stderr, "%s: %s\n", prefix, p->errbuf); -} - -char * -pcap_geterr(pcap_t *p) -{ - return (p->errbuf); -} - -/* - * Not all systems have strerror(). - */ -char * -pcap_strerror(int errnum) -{ - return strerror(errnum); -} - -void -pcap_close(pcap_t *p) -{ - /*XXX*/ - if (p->fd >= 0) - close(p->fd); - if (p->sf.rfile != NULL) { - fclose(p->sf.rfile); - if (p->sf.base != NULL) - free(p->sf.base); - } else if (p->buffer != NULL) - free(p->buffer); - - free(p); -} diff --git a/lib/libpcap/pcap.h b/lib/libpcap/pcap.h deleted file mode 100644 index 506b15b..0000000 --- a/lib/libpcap/pcap.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the Computer Systems - * Engineering Group at Lawrence Berkeley Laboratory. - * 4. Neither the name of the University nor of the Laboratory may be used - * to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#) $Header: pcap.h,v 1.15 94/06/14 20:03:34 leres Exp $ (LBL) - */ - -#ifndef lib_pcap_h -#define lib_pcap_h - -#include <sys/types.h> -#include <sys/time.h> - -#include <net/bpf.h> - -#include <stdio.h> - -#define PCAP_VERSION_MAJOR 2 -#define PCAP_VERSION_MINOR 4 - -#define PCAP_ERRBUF_SIZE 256 - -/* - * Compatibility for systems that have a bpf.h that - * predates the bpf typedefs for 64-bit support. - */ -#if BPF_RELEASE - 0 < 199406 -typedef long bpf_int32; -typedef u_long bpf_u_int32; -#endif - -typedef struct pcap pcap_t; -typedef struct pcap_dumper pcap_dumper_t; - -/* - * The first record in the file contains saved values for some - * of the flags used in the printout phases of tcpdump. - * Many fields here are longs so compilers won't insert unwanted - * padding; these files need to be interchangeable across architectures. - */ -struct pcap_file_header { - bpf_u_int32 magic; - u_short version_major; - u_short version_minor; - bpf_int32 thiszone; /* gmt to local correction */ - bpf_u_int32 sigfigs; /* accuracy of timestamps */ - bpf_u_int32 snaplen; /* max length saved portion of each pkt */ - bpf_u_int32 linktype; /* data link type (DLT_*) */ -}; - -/* - * Each packet in the dump file is prepended with this generic header. - * This gets around the problem of different headers for different - * packet interfaces. - */ -struct pcap_pkthdr { - struct timeval ts; /* time stamp */ - bpf_u_int32 caplen; /* length of portion present */ - bpf_u_int32 len; /* length this packet (off wire) */ -}; - -/* - * As returned by the pcap_stats() - */ -struct pcap_stat { - u_int ps_recv; /* number of packets received */ - u_int ps_drop; /* number of packets dropped */ - u_int ps_ifdrop; /* drops by interface XXX not yet supported */ -}; - -typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *, - const u_char *); - -char *pcap_lookupdev(char *); -int pcap_lookupnet(char *, u_long *, u_long *, char *); -pcap_t *pcap_open_live(char *, int, int, int, char *); -pcap_t *pcap_open_offline(char *, char *); -void pcap_close(pcap_t *); -int pcap_loop(pcap_t *, int, pcap_handler, u_char *); -int pcap_dispatch(pcap_t *, int, pcap_handler, u_char *); -const u_char* - pcap_next(pcap_t *, struct pcap_pkthdr *); -int pcap_stats(pcap_t *, struct pcap_stat *); -int pcap_setfilter(pcap_t *, struct bpf_program *); -void pcap_perror(pcap_t *, char *); -char *pcap_strerror(int); -char *pcap_geterr(pcap_t *); -int pcap_compile(pcap_t *, struct bpf_program *, char *, int, u_long); -/* XXX */ -int pcap_freecode(pcap_t *, struct bpf_program *); -int pcap_datalink(pcap_t *); -int pcap_snapshot(pcap_t *); -int pcap_is_swapped(pcap_t *); -int pcap_major_version(pcap_t *); -int pcap_minor_version(pcap_t *); - -/* XXX */ -FILE *pcap_file(pcap_t *); -int pcap_fileno(pcap_t *); - -pcap_dumper_t *pcap_dump_open(pcap_t *, char *); -void pcap_dump_close(pcap_dumper_t *); -void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *); - -/* XXX this guy lives in the bpf tree */ -u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int); -char *bpf_image(struct bpf_insn *, int); - -#endif diff --git a/lib/libpcap/savefile.c b/lib/libpcap/savefile.c deleted file mode 100644 index 90ee723..0000000 --- a/lib/libpcap/savefile.c +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright (c) 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that: (1) source code distributions - * retain the above copyright notice and this paragraph in its entirety, (2) - * distributions including binary code include the above copyright notice and - * this paragraph in its entirety in the documentation or other materials - * provided with the distribution, and (3) all advertising materials mentioning - * features or use of this software display the following acknowledgement: - * ``This product includes software developed by the University of California, - * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of - * the University nor the names of its contributors may be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ -#ifndef lint -static char rcsid[] = - "@(#)$Header: savefile.c,v 1.16 94/06/20 19:07:56 leres Exp $ (LBL)"; -#endif - -/* - * savefile.c - supports offline use of tcpdump - * Extraction/creation by Jeffrey Mogul, DECWRL - * Modified by Steve McCanne, LBL. - * - * Used to save the received packet headers, after filtering, to - * a file, and then read them later. - * The first record in the file contains saved values for the machine - * dependent values so we can print the dump file on any architecture. - */ - -#include <sys/types.h> -#include <sys/time.h> - -#include <net/bpf.h> - -#include <errno.h> -#include <memory.h> -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> - -#include "pcap-int.h" - -#define TCPDUMP_MAGIC 0xa1b2c3d4 - -/* - * We use the "receiver-makes-right" approach to byte order, - * because time is at a premium when we are writing the file. - * In other words, the pcap_file_header and pcap_pkthdr, - * records are written in host byte order. - * Note that the packets are always written in network byte order. - * - * ntoh[ls] aren't sufficient because we might need to swap on a big-endian - * machine (if the file was written in little-end order). - */ -#define SWAPLONG(y) \ -((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff)) -#define SWAPSHORT(y) \ - ( (((y)&0xff)<<8) | (((y)&0xff00)>>8) ) - -#define SFERR_TRUNC 1 -#define SFERR_BADVERSION 2 -#define SFERR_BADF 3 -#define SFERR_EOF 4 /* not really an error, just a status */ - -static int -sf_write_header(FILE *fp, int linktype, int thiszone, int snaplen) -{ - struct pcap_file_header hdr; - - hdr.magic = TCPDUMP_MAGIC; - hdr.version_major = PCAP_VERSION_MAJOR; - hdr.version_minor = PCAP_VERSION_MINOR; - - hdr.thiszone = thiszone; - hdr.snaplen = snaplen; - hdr.sigfigs = 0; - hdr.linktype = linktype; - - if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1) - return (-1); - - return (0); -} - -static void -swap_hdr(struct pcap_file_header *hp) -{ - hp->version_major = SWAPSHORT(hp->version_major); - hp->version_minor = SWAPSHORT(hp->version_minor); - hp->thiszone = SWAPLONG(hp->thiszone); - hp->sigfigs = SWAPLONG(hp->sigfigs); - hp->snaplen = SWAPLONG(hp->snaplen); - hp->linktype = SWAPLONG(hp->linktype); -} - -pcap_t * -pcap_open_offline(char *fname, char *errbuf) -{ - register pcap_t *p; - register FILE *fp; - struct pcap_file_header hdr; - int linklen; - - p = (pcap_t *)malloc(sizeof(*p)); - if (p == NULL) { - strcpy(errbuf, "out of swap"); - return (NULL); - } - -#ifdef notdef - bzero(p, sizeof(*p)); -#else - memset(p, 0, sizeof(*p)); -#endif - /* - * Set this field so we don't close stdin in pcap_close! - */ - p->fd = -1; - - if (fname[0] == '-' && fname[1] == '\0') - fp = stdin; - else { - fp = fopen(fname, "r"); - if (fp == NULL) { - sprintf(errbuf, "%s: %s", fname, pcap_strerror(errno)); - goto bad; - } - } - if (fread((char *)&hdr, sizeof(hdr), 1, fp) != 1) { - sprintf(errbuf, "fread: %s", pcap_strerror(errno)); - goto bad; - } - if (hdr.magic != TCPDUMP_MAGIC) { - if (SWAPLONG(hdr.magic) != TCPDUMP_MAGIC) { - sprintf(errbuf, "bad dump file format"); - goto bad; - } - p->sf.swapped = 1; - swap_hdr(&hdr); - } - if (hdr.version_major < PCAP_VERSION_MAJOR) { - sprintf(errbuf, "archaic file format"); - goto bad; - } - p->tzoff = hdr.thiszone; - p->snapshot = hdr.snaplen; - p->linktype = hdr.linktype; - p->sf.rfile = fp; - p->bufsize = hdr.snaplen; - /* Align link header as required for proper data alignment */ - linklen = 14; /* XXX */ - p->sf.base = (u_char *)malloc(p->bufsize + BPF_ALIGNMENT); - p->buffer = p->sf.base + BPF_ALIGNMENT - (linklen % BPF_ALIGNMENT); - p->sf.version_major = hdr.version_major; - p->sf.version_minor = hdr.version_minor; - - return (p); - bad: - free(p); - return (NULL); -} - -/* - * Read sf_readfile and return the next packet. Return the header in hdr - * and the contents in buf. Return 0 on success, SFERR_EOF if there were - * no more packets, and SFERR_TRUNC if a partial packet was encountered. - */ -static int -sf_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char *buf, int buflen) -{ - FILE *fp = p->sf.rfile; - - /* read the stamp */ - if (fread((char *)hdr, sizeof(struct pcap_pkthdr), 1, fp) != 1) { - /* probably an EOF, though could be a truncated packet */ - return (1); - } - - if (p->sf.swapped) { - /* these were written in opposite byte order */ - hdr->caplen = SWAPLONG(hdr->caplen); - hdr->len = SWAPLONG(hdr->len); - hdr->ts.tv_sec = SWAPLONG(hdr->ts.tv_sec); - hdr->ts.tv_usec = SWAPLONG(hdr->ts.tv_usec); - } - /* - * We interchanged the caplen and len fields at version 2.3, - * in order to match the bpf header layout. But unfortunately - * some files were written with version 2.3 in their headers - * but without the interchanged fields. - */ - if (p->sf.version_minor < 3 || - (p->sf.version_minor == 3 && hdr->caplen > hdr->len)) { - int t = hdr->caplen; - hdr->caplen = hdr->len; - hdr->len = t; - } - - if (hdr->caplen > buflen) { - sprintf(p->errbuf, "bad dump file format"); - return (-1); - } - - /* read the packet itself */ - - if (fread((char *)buf, hdr->caplen, 1, fp) != 1) { - sprintf(p->errbuf, "truncated dump file"); - return (-1); - } - return (0); -} - -/* - * Print out packets stored in the file initialized by sf_read_init(). - * If cnt > 0, return after 'cnt' packets, otherwise continue until eof. - */ -int -pcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) -{ - struct bpf_insn *fcode = p->fcode.bf_insns; - int status = 0; - int n = 0; - - while (status == 0) { - struct pcap_pkthdr h; - - status = sf_next_packet(p, &h, p->buffer, p->bufsize); - if (status) - return (-1); - - if (fcode == NULL || - bpf_filter(fcode, p->buffer, h.len, h.caplen)) { - (*callback)(user, &h, p->buffer); - if (++n >= cnt && cnt > 0) - break; - } - } - /*XXX this breaks semantics tcpslice expects */ - return (n); -} - -/* - * Output a packet to the initialized dump file. - */ -void -pcap_dump(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) -{ - FILE * f = (FILE *)user; - (void)fwrite((char *)h, sizeof(*h), 1, f); - (void)fwrite((char *)sp, h->caplen, 1, f); -} - -/* - * Initialize so that sf_write() will output to the file named 'fname'. - */ -pcap_dumper_t * -pcap_dump_open(pcap_t *p, char *fname) -{ - FILE *f; - if (fname[0] == '-' && fname[1] == '\0') - f = stdout; - else { - f = fopen(fname, "w"); - if (f == NULL) { - sprintf(p->errbuf, "%s: %s", - fname, pcap_strerror(errno)); - return (NULL); - } - } - (void)sf_write_header(f, p->linktype, p->tzoff, p->snapshot); - return ((pcap_dumper_t *)f); -} - -void -pcap_dump_close(pcap_dumper_t *p) -{ - fclose((FILE *)p); -} diff --git a/lib/libpcap/scanner.l b/lib/libpcap/scanner.l deleted file mode 100644 index c2ff10d..0000000 --- a/lib/libpcap/scanner.l +++ /dev/null @@ -1,193 +0,0 @@ -%{ -/* - * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that: (1) source code distributions - * retain the above copyright notice and this paragraph in its entirety, (2) - * distributions including binary code include the above copyright notice and - * this paragraph in its entirety in the documentation or other materials - * provided with the distribution, and (3) all advertising materials mentioning - * features or use of this software display the following acknowledgement: - * ``This product includes software developed by the University of California, - * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of - * the University nor the names of its contributors may be used to endorse - * or promote products derived from this software without specific prior - * written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#ifndef lint -static char rcsid[] = - "@(#) $Header: scanner.l,v 1.40 94/06/10 17:21:44 mccanne Exp $ (LBL)"; -#endif - -#include <sys/types.h> -#include <sys/time.h> - -#include <ctype.h> -#include <pcap.h> -#include <pcap-namedb.h> - -#include "gencode.h" -#include "tokdefs.h" - -#ifndef __GNUC__ -#define inline -#endif - -static int stoi(char *); -static inline int xdtoi(int); - -#ifdef FLEX_SCANNER -#undef YY_INPUT -#define YY_INPUT(buf, result, max)\ - {\ - char *src = in_buffer;\ - int i;\ -\ - if (*src == 0)\ - result = YY_NULL;\ - else {\ - for (i = 0; *src && i < max; ++i)\ - buf[i] = *src++;\ - in_buffer += i;\ - result = i;\ - }\ - } -#else -#undef getc -#define getc(fp) (*in_buffer == 0 ? EOF : *in_buffer++) -#endif - -#define yylval pcap_lval -extern YYSTYPE yylval; - -static char *in_buffer; - -%} - -N ([0-9]+|(0X|0x)[0-9A-Fa-f]+) -B ([0-9A-Fa-f][0-9A-Fa-f]?) - -%a 3000 - -%% -dst return DST; -src return SRC; - -link|ether|ppp|slip return LINK; -fddi return LINK; -arp return ARP; -rarp return RARP; -ip return IP; -tcp return TCP; -udp return UDP; -icmp return ICMP; - -decnet return DECNET; -lat return LAT; -moprc return MOPRC; -mopdl return MOPDL; - -host return HOST; -net return NET; -port return PORT; -proto return PROTO; - -gateway return GATEWAY; - -less return LESS; -greater return GREATER; -byte return BYTE; -broadcast return TK_BROADCAST; -multicast return TK_MULTICAST; - -and|"&&" return AND; -or|"||" return OR; -not return '!'; - -len|length return LEN; -inbound return INBOUND; -outbound return OUTBOUND; - -[ \n\t] ; -[+\-*/:\[\]!<>()&|=] return yytext[0]; -">=" return GEQ; -"<=" return LEQ; -"!=" return NEQ; -"==" return '='; -"<<" return LSH; -">>" return RSH; -{N} { yylval.i = stoi((char *)yytext); return NUM; } -({N}\.{N})|({N}\.{N}\.{N})|({N}\.{N}\.{N}\.{N}) { - yylval.s = sdup((char *)yytext); return HID; -} -{B}:{B}:{B}:{B}:{B}:{B} { yylval.e = pcap_ether_aton((char *)yytext); - return EID; } -{B}:+({B}:+)+ { bpf_error("bogus ethernet address %s", yytext); } -[A-Za-z][-_.A-Za-z0-9]* { yylval.s = sdup((char *)yytext); return ID; } -"\\"[^ !()\n\t]+ { yylval.s = sdup((char *)yytext + 1); return ID; } -[^ \[\]\t\n\-_.A-Za-z0-9!<>()&|=]+ { bpf_error("illegal token: %s\n", yytext); } -. { bpf_error("illegal char '%c'", *yytext); } -%% -void -lex_init(buf) - char *buf; -{ - in_buffer = buf; -} - -/* - * Also define a yywrap. Note that if we're using flex, it will - * define a macro to map this identifier to pcap_wrap. - */ -int -yywrap() -{ - return 1; -} - -/* Hex digit to integer. */ -static inline int -xdtoi(c) - register int c; -{ - if (isdigit(c)) - return c - '0'; - else if (islower(c)) - return c - 'a' + 10; - else - return c - 'A' + 10; -} - -/* - * Convert string to integer. Just like atoi(), but checks for - * preceding 0x or 0 and uses hex or octal instead of decimal. - */ -static int -stoi(s) - char *s; -{ - int base = 10; - int n = 0; - - if (*s == '0') { - if (s[1] == 'x' || s[1] == 'X') { - s += 2; - base = 16; - } - else { - base = 8; - s += 1; - } - } - while (*s) - n = n * base + xdtoi(*s++); - - return n; -} - |