diff options
author | peter <peter@FreeBSD.org> | 1995-12-30 19:02:48 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 1995-12-30 19:02:48 +0000 |
commit | c3f352d4ad515968c54d216a0e53252eff8ab3ef (patch) | |
tree | 48ddeda3c6c8d8572cc34bf52ccf9cb9bd97d488 /usr.sbin/tcpdump | |
parent | ab124e78b0271ddb904b761b31e5c9a0cf24e070 (diff) | |
download | FreeBSD-src-c3f352d4ad515968c54d216a0e53252eff8ab3ef.zip FreeBSD-src-c3f352d4ad515968c54d216a0e53252eff8ab3ef.tar.gz |
This commit was generated by cvs2svn to compensate for changes in r13122,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'usr.sbin/tcpdump')
-rw-r--r-- | usr.sbin/tcpdump/tcpdump/bpf_image.c | 282 | ||||
-rw-r--r-- | usr.sbin/tcpdump/tcpdump/etherent.c | 144 | ||||
-rw-r--r-- | usr.sbin/tcpdump/tcpdump/etherent.h | 34 | ||||
-rw-r--r-- | usr.sbin/tcpdump/tcpdump/etherproto.h | 70 | ||||
-rw-r--r-- | usr.sbin/tcpdump/tcpdump/gencode.c | 1384 | ||||
-rw-r--r-- | usr.sbin/tcpdump/tcpdump/gencode.h | 156 | ||||
-rw-r--r-- | usr.sbin/tcpdump/tcpdump/inet.c | 172 | ||||
-rw-r--r-- | usr.sbin/tcpdump/tcpdump/md.c | 35 | ||||
-rw-r--r-- | usr.sbin/tcpdump/tcpdump/nametoaddr.c | 258 | ||||
-rw-r--r-- | usr.sbin/tcpdump/tcpdump/nametoaddr.h | 43 | ||||
-rw-r--r-- | usr.sbin/tcpdump/tcpdump/optimize.c | 1871 | ||||
-rw-r--r-- | usr.sbin/tcpdump/tcpdump/os.c | 26 | ||||
-rw-r--r-- | usr.sbin/tcpdump/tcpdump/pcap.c | 209 | ||||
-rw-r--r-- | usr.sbin/tcpdump/tcpdump/savefile.c | 303 | ||||
-rw-r--r-- | usr.sbin/tcpdump/tcpdump/savefile.h | 75 | ||||
-rw-r--r-- | usr.sbin/tcpdump/tcpdump/tcpgram.y | 232 |
16 files changed, 0 insertions, 5294 deletions
diff --git a/usr.sbin/tcpdump/tcpdump/bpf_image.c b/usr.sbin/tcpdump/tcpdump/bpf_image.c deleted file mode 100644 index d36eab2..0000000 --- a/usr.sbin/tcpdump/tcpdump/bpf_image.c +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright (c) 1988-1990 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.10 92/01/26 21:01:16 mccanne Exp $ (LBL)"; -#endif - -#include <stdio.h> -#include <string.h> - -#include <sys/types.h> -#include <sys/time.h> -#include <net/bpf.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/usr.sbin/tcpdump/tcpdump/etherent.c b/usr.sbin/tcpdump/tcpdump/etherent.c deleted file mode 100644 index 9d7ee80..0000000 --- a/usr.sbin/tcpdump/tcpdump/etherent.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 1990 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.2 90/09/20 23:16:06 mccanne Exp $ (LBL)"; -#endif - -#include <stdio.h> -#include <ctype.h> -#include <sys/types.h> -#include "interface.h" - -#ifndef ETHER_SERVICE - -#include "etherent.h" - -/* Hex digit to integer. */ -static inline int -xdtoi(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 etherent * -next_etherent(fp) - FILE *fp; -{ - register int c, d, i; - char *bp; - static struct 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 etehrnet 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 continuning 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; -} - -#endif diff --git a/usr.sbin/tcpdump/tcpdump/etherent.h b/usr.sbin/tcpdump/tcpdump/etherent.h deleted file mode 100644 index 83ebaab..0000000 --- a/usr.sbin/tcpdump/tcpdump/etherent.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 1990 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: etherent.h,v 1.2 90/09/20 23:16:17 mccanne Exp $ (LBL) - */ - -/* File name of ethernet address data base. */ - -#define ETHERS_FILE "/etc/ethers" - -struct etherent { - u_char addr[6]; - char name[122]; -}; - -struct etherent *next_etherent(); - diff --git a/usr.sbin/tcpdump/tcpdump/etherproto.h b/usr.sbin/tcpdump/tcpdump/etherproto.h deleted file mode 100644 index 5c0e245..0000000 --- a/usr.sbin/tcpdump/tcpdump/etherproto.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 1988-1990 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: etherproto.h,v 1.7 90/10/10 15:04:04 mccanne 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_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 - -struct eproto { - char *s; - u_short p; -}; - -extern struct eproto eproto_db[]; diff --git a/usr.sbin/tcpdump/tcpdump/gencode.c b/usr.sbin/tcpdump/tcpdump/gencode.c deleted file mode 100644 index 8cb48ea..0000000 --- a/usr.sbin/tcpdump/tcpdump/gencode.c +++ /dev/null @@ -1,1384 +0,0 @@ -/* - * Copyright (c) 1990 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: gencode.c,v 1.33 92/05/22 16:38:39 mccanne Exp $ (LBL)"; -#endif - -#ifdef __STDC__ -#include <stdlib.h> -#endif -#include <sys/types.h> -#include <sys/socket.h> -#include <net/if.h> -#include <netinet/in.h> -#include <netinet/if_ether.h> - -#include <sys/time.h> -#include <net/bpf.h> - -#include "interface.h" -#include "gencode.h" -#include "nametoaddr.h" -#include "extract.h" - -#define JMP(c) ((c)|BPF_JMP|BPF_K) - -extern struct bpf_insn *icode_to_fcode(); -extern u_long net_mask(); -static void init_linktype(); - -static int alloc_reg(); -static void free_reg(); - -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(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) - error("out of memory"); - size = CHUNK0SIZE << k; - cp->m = (void *)malloc(size); - bzero((char *)cp->m, size); - cp->n_left = size; - if (n > size) - 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); -} - -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() -{ - error("syntax error in filter expression"); -} - -static u_long netmask; - -struct bpf_program * -parse(buf, Oflag, linktype, mask) - char *buf; - int Oflag; - int linktype; - u_long mask; -{ - extern int n_errors; - static struct bpf_program F; - struct bpf_insn *p; - int len; - - netmask = mask; - - F.bf_insns = 0; - F.bf_len = 0; - - lex_init(buf ? buf : ""); - init_linktype(linktype); - yyparse(); - - if (n_errors) - syntax(); - - if (root == 0) - root = gen_retblk(snaplen); - - if (Oflag) { - optimize(&root); - if (root == 0 || - (root->s.code == (BPF_RET|BPF_K) && root->s.k == 0)) - error("expression rejects all packets"); - } - p = icode_to_fcode(root, &len); - F.bf_insns = p; - F.bf_len = len; - - freechunks(); - return &F; -} - -/* - * 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; -} - -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; -} - -struct block * -gen_bcmp(offset, size, v) - u_int offset; - u_int size; - u_char *v; -{ - struct block *b, *tmp; - int k; - - b = 0; - while (size >= 4) { - k = size - 4; - tmp = gen_cmp(offset + k, BPF_W, EXTRACT_LONG(&v[k])); - if (b != 0) - gen_and(b, tmp); - b = tmp; - size -= 4; - } - while (size >= 2) { - k = size - 2; - tmp = gen_cmp(offset + k, BPF_H, (long)EXTRACT_SHORT(&v[k])); - if (b != 0) - gen_and(b, tmp); - b = tmp; - size -= 2; - } - if (size > 0) { - tmp = gen_cmp(offset, BPF_B, (long)v[0]); - if (b != 0) - gen_and(b, tmp); - b = tmp; - } - return b; -} - -/* - * Various code contructs 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; - -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 = -1; - off_nl = 0; - return; - - case DLT_PPP: - off_linktype = 2; - off_nl = 4; - return; - - case DLT_FDDI: - off_linktype = 19; - off_nl = 21; - return; - - case DLT_IEEE802: - off_linktype = 20; - off_nl = 22; - return; - } - 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); -} - -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; - } - 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 */ -} - -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: - error("'tcp' modifier applied to host"); - - case Q_UDP: - error("'udp' modifier applied to host"); - - case Q_ICMP: - error("'icmp' modifier applied to host"); - } - 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) - error("direction applied to 'gateway'"); - - switch (proto) { - case Q_DEFAULT: - case Q_IP: - case Q_ARP: - case Q_RARP: - b0 = gen_ehostop(eaddr, Q_OR); - 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; - } - 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: - error("link layer applied in wrong context"); - - 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; - int proto; - int 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; -} - -int -lookup_proto(name, proto) - char *name; - int proto; -{ - int v; - - switch (proto) { - case Q_DEFAULT: - case Q_IP: - v = s_nametoproto(name); - if (v == PROTO_UNDEF) - error("unknown ip proto '%s'", name); - break; - - case Q_LINK: - /* XXX should look up h/w protocol type based on linktype */ - v = s_nametoeproto(name); - if (v == PROTO_UNDEF) - error("unknown ether proto '%s'", name); - break; - - default: - v = PROTO_UNDEF; - break; - } - return v; -} - -struct block * -gen_proto(v, proto, dir) - int v; - int proto; - int dir; -{ - struct block *b0, *b1; - - if (dir != Q_DEFAULT) - 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: - error("arp does not encapsulate another protocol"); - /* NOTREACHED */ - - case Q_RARP: - error("rarp does not encapsulate another protocol"); - /* NOTREACHED */ - - case Q_LINK: - return gen_linktype(v); - - case Q_UDP: - error("'udp proto' is bogus"); - - case Q_TCP: - error("'tcp proto' is bogus"); - - case Q_ICMP: - error("'icmp proto' is bogus"); - } - abort(); - /* NOTREACHED */ -} - -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 = s_nametonetaddr(name); - if (addr == 0) - 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) { - /* XXX Should lookup hw addr based on link layer */ - eaddr = ETHER_hostton(name); - if (eaddr == 0) - error("unknown ether host '%s'", name); - return gen_ehostop(eaddr, dir); - - } else { - alist = s_nametoaddr(name); - if (alist == 0 || *alist == 0) - error("uknown 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) - error("illegal qualifier of 'port'"); - if (s_nametoport(name, &port, &real_proto) == 0) - error("unknown port '%s'", name); - if (proto == Q_UDP) { - if (real_proto == IPPROTO_TCP) - error("port '%s' is tcp", name); - else - /* override PROTO_UNDEF */ - real_proto = IPPROTO_UDP; - } - if (proto == Q_TCP) { - if (real_proto == IPPROTO_UDP) - 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 = ETHER_hostton(name); - if (eaddr == 0) - error("unknown ether host: %s", name); - - alist = s_nametoaddr(name); - if (alist == 0 || *alist == 0) - error("uknown 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 - 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: - 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 - error("illegal qualifier of 'port'"); - - return gen_port((int)v, proto, dir); - - case Q_GATEWAY: - error("'gateway' requires a name"); - /* NOTREACHED */ - - case Q_PROTO: - return gen_proto((int)v, proto, dir); - - case Q_UNDEF: - syntax(); - /* NOTREACHED */ - } - abort(); - /* 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) - return gen_ehostop(eaddr, (int)q.dir); - else - 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; -} - -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; -} - -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: - 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: - 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: - /* 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; - } - } - 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; - int n; -{ - struct slist *s; - struct block *b; - - s = new_stmt(BPF_LD|BPF_LEN); - s->next = new_stmt(BPF_SUB|BPF_IMM); - 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; - int idx; - int 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_AND|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); - 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; - } - error("only ether/ip broadcast filters supported"); -} - -struct block * -gen_multicast(proto) - int proto; -{ - register struct block *b0, *b1, *b2; - register struct slist *s; - - switch (proto) { - - case Q_DEFAULT: - case Q_LINK: - if (linktype != DLT_EN10MB) - break; - - /* 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; - - 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; - } - error("only ether/ip multicast filters supported"); -} diff --git a/usr.sbin/tcpdump/tcpdump/gencode.h b/usr.sbin/tcpdump/tcpdump/gencode.h deleted file mode 100644 index b8f342d..0000000 --- a/usr.sbin/tcpdump/tcpdump/gencode.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 1990 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: gencode.h,v 1.14 92/02/14 15:18:55 mccanne 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 - -/* 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 */ -}; - -extern struct arth *gen_loadi(); -extern struct arth *gen_load(); -extern struct arth *gen_loadlen(); -extern struct arth *gen_neg(); -extern struct arth *gen_arth(); - -extern void gen_and(); -extern void gen_or(); -extern void gen_not(); - -extern struct block *gen_scode(); -extern struct block *gen_ecode(); -extern struct block *gen_ncode(); -extern struct block *gen_proto_abbrev(); -extern struct block *gen_relation(); -extern struct block *gen_less(); -extern struct block *gen_greater(); -extern struct block *gen_byteop(); -extern struct block *gen_broadcast(); -extern struct block *gen_multicast(); - -extern void optimize(); - -extern void finish_parse(); - -struct qual { - unsigned char addr; - unsigned char proto; - unsigned char dir; - unsigned char pad; -}; - -/* XXX */ -#define JT(b) ((b)->et.succ) -#define JF(b) ((b)->ef.succ) diff --git a/usr.sbin/tcpdump/tcpdump/inet.c b/usr.sbin/tcpdump/tcpdump/inet.c deleted file mode 100644 index 550129e..0000000 --- a/usr.sbin/tcpdump/tcpdump/inet.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) 1990 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: inet.c,v 1.12 92/01/29 12:46:18 mccanne Exp $ (LBL)"; -#endif - -#include <stdio.h> -#include <ctype.h> -#include <strings.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <sys/file.h> -#include <sys/ioctl.h> - -#include <net/if.h> -#include <netinet/in.h> - -#include "interface.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 0 - * if none can be found. The interface must be configured up; the - * lowest unit number is preferred; loopback is ignored. - */ -char * -lookup_device() -{ - struct ifreq ibuf[16], *ifrp, *ifend, *mp; - struct ifconf ifc; - int fd; - int minunit, n; - char *cp; - static char device[sizeof(ifrp->ifr_name)]; - - fd = socket(AF_INET, SOCK_DGRAM, 0); - if (fd < 0) { - perror("tcpdump: socket"); - exit(1); - } - ifc.ifc_len = sizeof ibuf; - ifc.ifc_buf = (caddr_t)ibuf; - - if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 || - ifc.ifc_len < sizeof(struct ifreq)) { - perror("tcpdump: SIOCGIFCONF: "); - exit(1); - } - ifrp = ibuf; - ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len); - - mp = 0; - minunit = 666; - while (ifrp < ifend) { - struct ifreq ifr; - /* - * 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.) - */ - bcopy(ifrp->ifr_name, ifr.ifr_name, sizeof(ifr.ifr_name)); - if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) { - fprintf(stderr, "tcpdump: SIOCGIFFLAGS: "); - perror(ifrp->ifr_name); - exit(1); - } - if ((ifr.ifr_flags & IFF_UP) && !ISLOOPBACK(&ifr)) { - for (cp = ifrp->ifr_name; !isdigit(*cp); ++cp) - ; - n = atoi(cp); - if (n < minunit) { - minunit = n; - mp = ifrp; - } - } -#if BSD >= 199006 - n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name); - if (n < sizeof(*ifrp)) - ++ifrp; - else - ifrp = (struct ifreq *)((char *)ifrp + n); -#else - ++ifrp; -#endif - } - close(fd); - if (mp == 0) - return (0); - - (void)strcpy(device, mp->ifr_name); - return (device); -} - -/* - * Get the netmask of an IP address. This routine is used if - * SIOCGIFNETMASK doesn't work. - */ -static u_long -ipaddrtonetmask(addr) - u_long addr; -{ - if (IN_CLASSA(addr)) - return (IN_CLASSA_NET); - if (IN_CLASSB(addr)) - return (IN_CLASSB_NET); - if (IN_CLASSC(addr)) - return (IN_CLASSC_NET); - error("unknown IP address class: %08X", addr); - /* NOTREACHED */ -} - -void -lookup_net(device, netp, maskp) - char *device; - u_long *netp; - u_long *maskp; -{ - int fd; - struct ifreq ifr; - struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr; - - /* Use data gram socket to get IP address. */ - if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - perror("tcpdump: socket"); - exit(1); - } - (void)strncpy(ifr.ifr_name, device, sizeof ifr.ifr_name); - if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) { - /* - * This will fail if an IP address hasn't been assigned. - */ - *netp = 0; - *maskp = 0; - return; - } - *netp = sin->sin_addr.s_addr; - if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) - *maskp = 0; - else - *maskp = sin->sin_addr.s_addr; - if (*maskp == 0) - *maskp = ipaddrtonetmask(*netp); - *netp &= *maskp; - (void)close(fd); -} diff --git a/usr.sbin/tcpdump/tcpdump/md.c b/usr.sbin/tcpdump/tcpdump/md.c deleted file mode 100644 index 6bb04b7..0000000 --- a/usr.sbin/tcpdump/tcpdump/md.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 1990 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: md-vax.c,v 1.3 90/10/03 14:14:33 mccanne Locked $ (LBL)"; -#endif - -/* Vaxen appear to have clocks accurate to 1 us, - but packetfilter is timestamping to 10 ms. */ - -int -clock_sigfigs() -{ - return 2; -} - diff --git a/usr.sbin/tcpdump/tcpdump/nametoaddr.c b/usr.sbin/tcpdump/tcpdump/nametoaddr.c deleted file mode 100644 index 6f2330f..0000000 --- a/usr.sbin/tcpdump/tcpdump/nametoaddr.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (c) 1988-1990 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: nametoaddr.c,v 1.9 91/02/04 16:56:46 mccanne Exp $ (LBL)"; -#endif - -#include <stdio.h> -#include <ctype.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <net/if.h> -#include <netdb.h> -#include <netinet/in.h> -#include <netinet/if_ether.h> -#include <errno.h> -#include <arpa/inet.h> - -#ifdef ultrix -#include <sys/time.h> -#include <rpc/types.h> -#include <nfs/nfs.h> -#endif - -#include "interface.h" -#include "etherent.h" -#include "nametoaddr.h" - -/* - * Convert host name to internet address. - * Return 0 upon failure. - */ -u_long ** -s_nametoaddr(name) - char *name; -{ -#ifndef h_addr - static u_long *hlist[2]; -#endif - u_long **p; - struct hostent *hp; - - if (hp = gethostbyname(name)) { -#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 -s_nametonetaddr(name) - char *name; -{ - struct netent *np; - - if (np = getnetbyname(name)) - 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. - */ -s_nametoport(name, port, proto) - char *name; - int *port; - int *proto; -{ - struct servent *sp; - char *other; - - sp = getservbyname(name, (char *)0); - if (sp != 0) { - NTOHS(sp->s_port); - *port = sp->s_port; - *proto = s_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 ambigous names that refer - to different port numbers. */ - warning("ambiguous port %s in /etc/services", - name); - *proto = PROTO_UNDEF; - } - return 1; - } -#ifdef ultrix - /* Special hack in case NFS isn't in /etc/services */ - if (strcmp(name, "nfs") == 0) { - *port = NFS_PORT; - *proto = PROTO_UNDEF; - return 1; - } -#endif - return 0; -} - -int -s_nametoproto(str) - char *str; -{ - struct protoent *p; - - p = getprotobyname(str); - if (p != 0) - return p->p_proto; - else - return PROTO_UNDEF; -} - -#include "etherproto.h" - -int -s_nametoeproto(s) - 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) -{ - if (isdigit(c)) - return c - '0'; - else if (islower(c)) - return c - 'a' + 10; - else - return c - 'A' + 10; -} - -u_long -atoin(s) - 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 */ -} - - -/* - * Convert 's' which has the form "xx:xx:xx:xx:xx:xx" into a new - * ethernet address. Assumes 's' is well formed. - */ -u_char * -ETHER_aton(s) - 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 -u_char * -ETHER_hostton(name) - char *name; -{ - struct etherent *ep; - FILE *fp; - u_char *ap; - - fp = fopen(ETHERS_FILE, "r"); - if (fp != 0) { - while (ep = next_etherent(fp)) { - if (strcmp(ep->name, name) == 0) { - ap = (u_char *)malloc(6); - bcopy(ep->addr, ap, 6); - return ap; - } - } - } - return (u_char *)0; -} -#endif diff --git a/usr.sbin/tcpdump/tcpdump/nametoaddr.h b/usr.sbin/tcpdump/tcpdump/nametoaddr.h deleted file mode 100644 index 23da3f2..0000000 --- a/usr.sbin/tcpdump/tcpdump/nametoaddr.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (c) 1988-1990 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: nametoaddr.h,v 1.6 90/09/24 12:50:41 mccanne Exp $ (LBL) - * - * Address to name translation routines. - */ - -extern u_long **s_nametoaddr(); -extern u_long s_nametonetaddr(); - -extern int s_nametoport(); -extern int s_nametoproto(); -extern int s_nametoeproto(); - -extern u_char *ETHER_hostton(); -extern u_char *ETHER_aton(); - -/* - * If a protocol is unknown, PROTO_UNDEF is returned. - * Also, s_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 - diff --git a/usr.sbin/tcpdump/tcpdump/optimize.c b/usr.sbin/tcpdump/tcpdump/optimize.c deleted file mode 100644 index 5064011..0000000 --- a/usr.sbin/tcpdump/tcpdump/optimize.c +++ /dev/null @@ -1,1871 +0,0 @@ -/* - * Copyright (c) 1988-1990 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: optimize.c,v 1.35 91/07/18 09:27:55 mccanne Exp $ (LBL)"; -#endif - -#include <stdio.h> -#include <sys/types.h> - -#include <sys/time.h> -#include <net/bpf.h> - -#include "interface.h" -#include "gencode.h" - -#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(); -static void opt_cleanup(); - -static void make_marks(); -static void mark_code(); - -static void intern_blocks(); - -static int eq_slist(); - -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; -{ - bzero((char *)levels, 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 estabished. - */ -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. */ - bzero(root->et.edom, edgewords * sizeof(*(uset)0)); - bzero(root->ef.edom, 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. - */ - bzero((char *)all_closure_sets, - 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(atom, use)) - 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; - bzero((char *)vmap, maxval * sizeof(*vmap)); - bzero((char *)hashtbl, 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) - 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 comparsion, 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 symblic - * 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]; - - bzero((char *)last, 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; -{ - 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) - bzero((char *)b->val, sizeof(b->val)); - else { - bcopy((char *)p->pred->val, (char *)b->val, sizeof(b->val)); - while (p = p->next) { - 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; -} - -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 equility - * 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 succesor to the its grandchild. - * - * XXX We violate the set abstraction here in favor a reasonbly - * 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 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; - struct edge *ep; - - for (i = 0; i < n_blocks; ++i) - blocks[i]->in_edges = 0; - - /* - * Traverse the graph, adding each edge to the predecessor - * list of its sucessors. 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; -{ - int passes = 0; -#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 -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) - error("long jumps not supported"); - dst->jt = off; - off = JF(p)->offset - (p->offset + slen) - 1; - if (off >= 256) - 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); - bzero((char *)fp, 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; - - bzero(bids, 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/usr.sbin/tcpdump/tcpdump/os.c b/usr.sbin/tcpdump/tcpdump/os.c deleted file mode 100644 index 856fb5a..0000000 --- a/usr.sbin/tcpdump/tcpdump/os.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 1990 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: os-bsd.c,v 1.2 90/09/21 02:12:17 mccanne Exp $ (LBL)"; -#endif - diff --git a/usr.sbin/tcpdump/tcpdump/pcap.c b/usr.sbin/tcpdump/tcpdump/pcap.c deleted file mode 100644 index 04c9695..0000000 --- a/usr.sbin/tcpdump/tcpdump/pcap.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) 1990 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-bpf.c,v 1.29 92/06/02 17:57:29 mccanne Exp $ (LBL)"; -#endif - -#include <stdio.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 "interface.h" - -extern int errno; - -static void -bpf_stats(fd) - int fd; -{ - struct bpf_stat s; - - if (ioctl(fd, BIOCGSTATS, &s) < 0) - return; - - (void)fflush(stdout); - (void)fprintf(stderr, "%d packets received by filter\n", s.bs_recv); - (void)fprintf(stderr, "%d packets dropped by kernel\n", s.bs_drop); -} - -void -readloop(cnt, if_fd, fp, printit) - int cnt; - int if_fd; - struct bpf_program *fp; - void (*printit)(); -{ - u_char *buf; - u_int bufsize; - int cc; - - if (ioctl(if_fd, BIOCGBLEN, (caddr_t)&bufsize) < 0) { - perror("tcpdump: BIOCGBLEN"); - exit(1); - } - buf = (u_char *)malloc(bufsize); - - if (ioctl(if_fd, BIOCSETF, (caddr_t)fp) < 0) { - perror("tcpdump: BIOCSETF"); - exit(1); - } - while (1) { - register u_char *bp, *ep; - - if ((cc = read(if_fd, (char *)buf, (int)bufsize)) < 0) { - /* Don't choke when we get ptraced */ - if (errno == EINTR) - continue; -#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. - */ - if (errno == EINVAL && - (long)(tell(if_fd) + bufsize) < 0) { - (void)lseek(if_fd, 0, 0); - continue; - } -#endif - perror("tcpdump: read"); - exit(1); - } - /* - * Loop through each packet. - */ -#define bhp ((struct bpf_hdr *)bp) - bp = buf; - ep = bp + cc; - while (bp < ep) { - register int caplen, hdrlen; - if (cnt >= 0 && --cnt < 0) - goto out; - (*printit)(bp + (hdrlen = bhp->bh_hdrlen), - &bhp->bh_tstamp, bhp->bh_datalen, - caplen = bhp->bh_caplen); - bp += BPF_WORDALIGN(caplen + hdrlen); - } -#undef bhp - } - out: - wrapup(if_fd); -} - -wrapup(fd) - int fd; -{ - bpf_stats(fd); - close(fd); -} - -static inline int -bpf_open() -{ - 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); - - if (fd < 0) { - (void) fprintf(stderr, "tcpdump: "); - perror(device); - exit(-1); - } - return fd; -} - -int -initdevice(device, pflag, linktype) - char *device; - int pflag; - int *linktype; -{ - struct timeval timeout; - int if_fd; - struct ifreq ifr; - struct bpf_version bv; - - if_fd = bpf_open(); - - if (ioctl(if_fd, BIOCVERSION, (caddr_t)&bv) < 0) - warning("kernel bpf interpreter may be out of date"); - else if (bv.bv_major != BPF_MAJOR_VERSION || - bv.bv_minor < BPF_MINOR_VERSION) - error("requires bpf language %d.%d or higher; kernel is %d.%d", - BPF_MAJOR_VERSION, BPF_MINOR_VERSION, - bv.bv_major, bv.bv_minor); - - (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); - if (ioctl(if_fd, BIOCSETIF, (caddr_t)&ifr) < 0) { - (void) fprintf(stderr, "tcpdump: BIOCSETIF: "); - perror(device); - exit(-1); - } - /* Get the data link layer type. */ - if (ioctl(if_fd, BIOCGDLT, (caddr_t)linktype) < 0) { - perror("tcpdump: BIOCGDLT"); - exit(-1); - } - /* set timeout */ - timeout.tv_sec = 1; - timeout.tv_usec = 0; - if (ioctl(if_fd, BIOCSRTIMEOUT, (caddr_t)&timeout) < 0) { - perror("tcpdump: BIOCSRTIMEOUT"); - exit(-1); - } - /* set promiscuous mode if requested, but only for broadcast nets */ - if (pflag == 0) { - switch (*linktype) { - - case DLT_SLIP: - case DLT_PPP: - case DLT_NULL: - break; - - default: - if (ioctl(if_fd, BIOCPROMISC, (void *)0) < 0) { - perror("tcpdump: BIOCPROMISC"); - exit(-1); - } - } - } - return(if_fd); -} diff --git a/usr.sbin/tcpdump/tcpdump/savefile.c b/usr.sbin/tcpdump/tcpdump/savefile.c deleted file mode 100644 index 79bb9e8..0000000 --- a/usr.sbin/tcpdump/tcpdump/savefile.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright (c) 1990,1991 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.27 92/01/26 21:29:26 mccanne 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 <stdio.h> -#include <sys/types.h> -#include <sys/time.h> -#include <net/bpf.h> - -#include "version.h" -#include "savefile.h" - -#define TCPDUMP_MAGIC 0xa1b2c3d4 - -/* - * 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 file_header { - u_long magic; - u_short version_major; - u_short version_minor; - long thiszone; /* gmt to local correction */ - u_long sigfigs; /* accuracy of timestamps */ - u_long snaplen; /* max length saved portion of each pkt */ - u_long linktype; -}; - -int sf_swapped; - -FILE *sf_readfile; -FILE *sf_writefile; - -static int -sf_write_header(fp, linktype, thiszone, snaplen, precision) - FILE *fp; - int linktype; - int thiszone; - int snaplen; - int precision; -{ - struct file_header hdr; - - hdr.magic = TCPDUMP_MAGIC; - hdr.version_major = VERSION_MAJOR; - hdr.version_minor = VERSION_MINOR; - - hdr.thiszone = thiszone; - hdr.snaplen = snaplen; - hdr.sigfigs = precision; - hdr.linktype = linktype; - - if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1) - return -1; - - return 0; -} - -static void -swap_hdr(hp) - struct 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); -} - -int -sf_read_init(fname, linktypep, thiszonep, snaplenp, precision) - char *fname; - int *linktypep, *thiszonep, *snaplenp, *precision; -{ - register FILE *fp; - struct file_header hdr; - - if (fname[0] == '-' && fname[1] == '\0') - fp = stdin; - else { - fp = fopen(fname, "r"); - if (fp == 0) { - (void) fprintf(stderr, "tcpdump: fopen: "); - perror(fname); - exit(1); - } - } - if (fread((char *)&hdr, sizeof(hdr), 1, fp) != 1) { - (void) fprintf(stderr, "tcpdump: fread: "); - perror(fname); - exit(1); - } - if (hdr.magic != TCPDUMP_MAGIC) { - if (SWAPLONG(hdr.magic) != TCPDUMP_MAGIC) - return SFERR_BADF; - sf_swapped = 1; - swap_hdr(&hdr); - } - if (hdr.version_major < VERSION_MAJOR) - return SFERR_BADVERSION; - - *thiszonep = hdr.thiszone; - *snaplenp = hdr.snaplen; - *linktypep = hdr.linktype; - *precision = hdr.sigfigs; - - sf_readfile = fp; - - return 0; -} - -/* - * Print out packets stored in the file initilized by sf_read_init(). - * If cnt >= 0, return after 'cnt' packets, otherwise continue until eof. - */ -int -sf_read(filtp, cnt, snaplen, printit) - struct bpf_program *filtp; - int cnt, snaplen; - void (*printit)(); -{ - struct packet_header h; - u_char *buf; - struct bpf_insn *fcode = filtp->bf_insns; - int status = 0; - - buf = (u_char *)malloc(snaplen); - - while (status == 0) { - status = sf_next_packet(&h, buf, snaplen); - - if (status) - break; - /* - * XXX It's possible (and likely) for us to screw up the - * network layer alignment when we pass down packets from - * this point (ip_print deals by copying the ip header - * to an aligned buffer). There doesn't seem to be a - * clean way to fix this. We could compute an offset - * from the link type (which would have to be passed in), - * but that only works for fixed size headers. - */ - if (bpf_filter(fcode, buf, h.len, h.caplen)) { - if (cnt >= 0 && --cnt < 0) - break; - (*printit)(buf, &h.ts, h.len, h.caplen); - } - } - - if (status == SFERR_EOF) - /* treat EOF's as okay status */ - status = 0; - - free((char *)buf); - return status; -} - -/* - * 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. - */ -int -sf_next_packet(hdr, buf, buflen) - struct packet_header *hdr; - u_char *buf; - int buflen; -{ - FILE *fp = sf_readfile; - - /* read the stamp */ - if (fread((char *)hdr, sizeof(struct packet_header), 1, fp) != 1) { - /* probably an EOF, though could be a truncated packet */ - return SFERR_EOF; - } - - if (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); - } - - if (hdr->caplen > buflen) - return SFERR_BADF; - - /* read the packet itself */ - - if (fread((char *)buf, hdr->caplen, 1, fp) != 1) - return SFERR_TRUNC; - - return 0; -} - -/* - * Initialize so that sf_write() will output to the file named 'fname'. - */ -void -sf_write_init(fname, linktype, thiszone, snaplen, precision) - char *fname; - int linktype; - int thiszone; - int snaplen; - int precision; -{ - if (fname[0] == '-' && fname[1] == '\0') - sf_writefile = stdout; - else { - sf_writefile = fopen(fname, "w"); - if (sf_writefile == 0) { - (void) fprintf(stderr, "tcpdump: fopen: "); - perror(fname); - exit(1); - } - } - (void)sf_write_header(sf_writefile, - linktype, thiszone, snaplen, precision); -} - -/* - * Output a packet to the intialized dump file. - */ -void -sf_write(sp, tvp, length, caplen) - u_char *sp; - struct timeval *tvp; - int length; - int caplen; -{ - struct packet_header h; - - h.ts.tv_sec = tvp->tv_sec; - h.ts.tv_usec = tvp->tv_usec; - h.len = length; - h.caplen = caplen; - - (void)fwrite((char *)&h, sizeof h, 1, sf_writefile); - (void)fwrite((char *)sp, caplen, 1, sf_writefile); -} - -void -sf_err(code) - int code; -{ - switch (code) { - case SFERR_BADVERSION: - error("archaic file format"); - /* NOTREACHED */ - - case SFERR_BADF: - error("bad dump file format"); - /* NOTREACHED */ - - case SFERR_TRUNC: - error("truncated dump file"); - /* NOTREACHED */ - - case SFERR_EOF: - error("EOF reading dump file"); - /* NOTREACHED */ - - default: - error("unknown dump file error code in sf_err()"); - /* NOTREACHED */ - } - abort(); -} diff --git a/usr.sbin/tcpdump/tcpdump/savefile.h b/usr.sbin/tcpdump/tcpdump/savefile.h deleted file mode 100644 index a5082f9..0000000 --- a/usr.sbin/tcpdump/tcpdump/savefile.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 1990 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: savefile.h,v 1.10 90/12/17 13:48:58 mccanne Exp $ - * - * Header for offline storage info. - * Extraction/creation by Jeffrey Mogul, DECWRL. - * - * Used to save the received packet headers, after filtering, to - * a file, and then read them later. - */ - -/* - * 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 packet_header { - struct timeval ts; /* time stamp */ - u_long len; /* length this packet (off wire) */ - u_long caplen; /* length of portion present */ -}; - -/* true if the contents of the savefile being read are byte-swapped */ -extern int sf_swapped; - -/* macros for when sf_swapped is true: */ -/* - * 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 file_header and packet_header 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) ) - - -extern FILE *sf_readfile; /* dump file being read from */ -extern FILE *sf_writefile; /* dump file being written to */ - -int sf_read_init(); -int sf_read(); -int sf_next_packet(); -void sf_write_init(); -void sf_write(); -void sf_err(); - -#define SFERR_TRUNC 1 -#define SFERR_BADVERSION 2 -#define SFERR_BADF 3 -#define SFERR_EOF 4 /* not really an error, just a status */ - diff --git a/usr.sbin/tcpdump/tcpdump/tcpgram.y b/usr.sbin/tcpdump/tcpdump/tcpgram.y deleted file mode 100644 index da235d0..0000000 --- a/usr.sbin/tcpdump/tcpdump/tcpgram.y +++ /dev/null @@ -1,232 +0,0 @@ -%{ -/* - * Copyright (c) 1988-1990 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. - * - * Grammar for tcpdump. - */ -#ifndef lint -static char rcsid[] = - "@(#) $Header: tcpgram.y,v 1.29 92/03/17 13:45:08 mccanne Exp $ (LBL)"; -#endif - -#include <stdio.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <net/if.h> -#include <netinet/in.h> -#include <netinet/if_ether.h> - -#include "interface.h" - -#include <sys/time.h> -#include <net/bpf.h> - -#include "gencode.h" - -#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() -{ - ++n_errors; -} - -%} - -%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 TK_BROADCAST TK_MULTICAST -%token NUM -%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 { $$.b = gen_ncode($1, $$.q = $<blk>0.q); } - | 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; } - ; -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); } - ; -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; } - ; -%% |