Add the Packet Capture Library from Michael Reifenberger.

Submitted by:	mr
This commit is contained in:
jkh 1995-01-20 04:13:07 +00:00
commit 92a97f198b
26 changed files with 9058 additions and 0 deletions

550
lib/libpcap/bpf_filter.c Normal file
View File

@ -0,0 +1,550 @@
/*-
* Copyright (c) 1990, 1991, 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from the Stanford/CMU enet packet filter,
* (net/enet.c) distributed as part of 4.3BSD, and code contributed
* to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
* Berkeley Laboratory.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)bpf.c 7.5 (Berkeley) 7/15/91
*
* static char rcsid[] =
* "$Header: bpf_filter.c,v 1.22 94/06/05 20:12:39 leres Exp $";
*/
#if !(defined(lint) || defined(KERNEL))
static char rcsid[] =
"@(#) $Header: bpf_filter.c,v 1.22 94/06/05 20:12:39 leres Exp $ (LBL)";
#endif
#include <sys/param.h>
#include <sys/types.h>
#include <sys/time.h>
#include <net/bpf.h>
#if defined(__alpha)
typedef int int32;
typedef u_int u_int32;
#else
typedef long int32;
typedef u_long u_int32;
#endif
#ifdef sun
#include <netinet/in.h>
#endif
#if defined(sparc) || defined(mips) || defined(ibm032) || defined(__alpha)
#define BPF_ALIGN
#endif
#ifndef BPF_ALIGN
#define EXTRACT_SHORT(p) ((u_short)ntohs(*(u_short *)p))
#define EXTRACT_LONG(p) (ntohl(*(u_int32 *)p))
#else
#define EXTRACT_SHORT(p)\
((u_short)\
((u_short)*((u_char *)p+0)<<8|\
(u_short)*((u_char *)p+1)<<0))
#define EXTRACT_LONG(p)\
((u_int32)*((u_char *)p+0)<<24|\
(u_int32)*((u_char *)p+1)<<16|\
(u_int32)*((u_char *)p+2)<<8|\
(u_int32)*((u_char *)p+3)<<0)
#endif
#ifdef KERNEL
#include <sys/mbuf.h>
#define MINDEX(m, k) \
{ \
register int len = m->m_len; \
\
while (k >= len) { \
k -= len; \
m = m->m_next; \
if (m == 0) \
return 0; \
len = m->m_len; \
} \
}
static int
m_xword(m, k, err)
register struct mbuf *m;
register int k, *err;
{
register int len;
register u_char *cp, *np;
register struct mbuf *m0;
len = m->m_len;
while (k >= len) {
k -= len;
m = m->m_next;
if (m == 0)
goto bad;
len = m->m_len;
}
cp = mtod(m, u_char *) + k;
if (len - k >= 4) {
*err = 0;
return EXTRACT_LONG(cp);
}
m0 = m->m_next;
if (m0 == 0 || m0->m_len + len - k < 4)
goto bad;
*err = 0;
np = mtod(m0, u_char *);
switch (len - k) {
case 1:
return (cp[k] << 24) | (np[0] << 16) | (np[1] << 8) | np[2];
case 2:
return (cp[k] << 24) | (cp[k + 1] << 16) | (np[0] << 8) |
np[1];
default:
return (cp[k] << 24) | (cp[k + 1] << 16) | (cp[k + 2] << 8) |
np[0];
}
bad:
*err = 1;
return 0;
}
static int
m_xhalf(m, k, err)
register struct mbuf *m;
register int k, *err;
{
register int len;
register u_char *cp;
register struct mbuf *m0;
len = m->m_len;
while (k >= len) {
k -= len;
m = m->m_next;
if (m == 0)
goto bad;
len = m->m_len;
}
cp = mtod(m, u_char *) + k;
if (len - k >= 2) {
*err = 0;
return EXTRACT_SHORT(cp);
}
m0 = m->m_next;
if (m0 == 0)
goto bad;
*err = 0;
return (cp[k] << 8) | mtod(m0, u_char *)[0];
bad:
*err = 1;
return 0;
}
#endif
/*
* Execute the filter program starting at pc on the packet p
* wirelen is the length of the original packet
* buflen is the amount of data present
*/
u_int
bpf_filter(pc, p, wirelen, buflen)
register struct bpf_insn *pc;
register u_char *p;
u_int wirelen;
register u_int buflen;
{
register u_int32 A, X;
register int k;
int32 mem[BPF_MEMWORDS];
if (pc == 0)
/*
* No filter means accept all.
*/
return (u_int)-1;
#ifdef lint
A = 0;
X = 0;
#endif
--pc;
while (1) {
++pc;
switch (pc->code) {
default:
#ifdef KERNEL
return 0;
#else
abort();
#endif
case BPF_RET|BPF_K:
return (u_int)pc->k;
case BPF_RET|BPF_A:
return (u_int)A;
case BPF_LD|BPF_W|BPF_ABS:
k = pc->k;
if (k + sizeof(int32) > buflen) {
#ifdef KERNEL
int merr;
if (buflen != 0)
return 0;
A = m_xword((struct mbuf *)p, k, &merr);
if (merr != 0)
return 0;
continue;
#else
return 0;
#endif
}
A = EXTRACT_LONG(&p[k]);
continue;
case BPF_LD|BPF_H|BPF_ABS:
k = pc->k;
if (k + sizeof(short) > buflen) {
#ifdef KERNEL
int merr;
if (buflen != 0)
return 0;
A = m_xhalf((struct mbuf *)p, k, &merr);
continue;
#else
return 0;
#endif
}
A = EXTRACT_SHORT(&p[k]);
continue;
case BPF_LD|BPF_B|BPF_ABS:
k = pc->k;
if (k >= buflen) {
#ifdef KERNEL
register struct mbuf *m;
if (buflen != 0)
return 0;
m = (struct mbuf *)p;
MINDEX(m, k);
A = mtod(m, u_char *)[k];
continue;
#else
return 0;
#endif
}
A = p[k];
continue;
case BPF_LD|BPF_W|BPF_LEN:
A = wirelen;
continue;
case BPF_LDX|BPF_W|BPF_LEN:
X = wirelen;
continue;
case BPF_LD|BPF_W|BPF_IND:
k = X + pc->k;
if (k + sizeof(int32) > buflen) {
#ifdef KERNEL
int merr;
if (buflen != 0)
return 0;
A = m_xword((struct mbuf *)p, k, &merr);
if (merr != 0)
return 0;
continue;
#else
return 0;
#endif
}
A = EXTRACT_LONG(&p[k]);
continue;
case BPF_LD|BPF_H|BPF_IND:
k = X + pc->k;
if (k + sizeof(short) > buflen) {
#ifdef KERNEL
int merr;
if (buflen != 0)
return 0;
A = m_xhalf((struct mbuf *)p, k, &merr);
if (merr != 0)
return 0;
continue;
#else
return 0;
#endif
}
A = EXTRACT_SHORT(&p[k]);
continue;
case BPF_LD|BPF_B|BPF_IND:
k = X + pc->k;
if (k >= buflen) {
#ifdef KERNEL
register struct mbuf *m;
if (buflen != 0)
return 0;
m = (struct mbuf *)p;
MINDEX(m, k);
A = mtod(m, char *)[k];
continue;
#else
return 0;
#endif
}
A = p[k];
continue;
case BPF_LDX|BPF_MSH|BPF_B:
k = pc->k;
if (k >= buflen) {
#ifdef KERNEL
register struct mbuf *m;
if (buflen != 0)
return 0;
m = (struct mbuf *)p;
MINDEX(m, k);
X = (mtod(m, char *)[k] & 0xf) << 2;
continue;
#else
return 0;
#endif
}
X = (p[pc->k] & 0xf) << 2;
continue;
case BPF_LD|BPF_IMM:
A = pc->k;
continue;
case BPF_LDX|BPF_IMM:
X = pc->k;
continue;
case BPF_LD|BPF_MEM:
A = mem[pc->k];
continue;
case BPF_LDX|BPF_MEM:
X = mem[pc->k];
continue;
case BPF_ST:
mem[pc->k] = A;
continue;
case BPF_STX:
mem[pc->k] = X;
continue;
case BPF_JMP|BPF_JA:
pc += pc->k;
continue;
case BPF_JMP|BPF_JGT|BPF_K:
pc += (A > pc->k) ? pc->jt : pc->jf;
continue;
case BPF_JMP|BPF_JGE|BPF_K:
pc += (A >= pc->k) ? pc->jt : pc->jf;
continue;
case BPF_JMP|BPF_JEQ|BPF_K:
pc += (A == pc->k) ? pc->jt : pc->jf;
continue;
case BPF_JMP|BPF_JSET|BPF_K:
pc += (A & pc->k) ? pc->jt : pc->jf;
continue;
case BPF_JMP|BPF_JGT|BPF_X:
pc += (A > X) ? pc->jt : pc->jf;
continue;
case BPF_JMP|BPF_JGE|BPF_X:
pc += (A >= X) ? pc->jt : pc->jf;
continue;
case BPF_JMP|BPF_JEQ|BPF_X:
pc += (A == X) ? pc->jt : pc->jf;
continue;
case BPF_JMP|BPF_JSET|BPF_X:
pc += (A & X) ? pc->jt : pc->jf;
continue;
case BPF_ALU|BPF_ADD|BPF_X:
A += X;
continue;
case BPF_ALU|BPF_SUB|BPF_X:
A -= X;
continue;
case BPF_ALU|BPF_MUL|BPF_X:
A *= X;
continue;
case BPF_ALU|BPF_DIV|BPF_X:
if (X == 0)
return 0;
A /= X;
continue;
case BPF_ALU|BPF_AND|BPF_X:
A &= X;
continue;
case BPF_ALU|BPF_OR|BPF_X:
A |= X;
continue;
case BPF_ALU|BPF_LSH|BPF_X:
A <<= X;
continue;
case BPF_ALU|BPF_RSH|BPF_X:
A >>= X;
continue;
case BPF_ALU|BPF_ADD|BPF_K:
A += pc->k;
continue;
case BPF_ALU|BPF_SUB|BPF_K:
A -= pc->k;
continue;
case BPF_ALU|BPF_MUL|BPF_K:
A *= pc->k;
continue;
case BPF_ALU|BPF_DIV|BPF_K:
A /= pc->k;
continue;
case BPF_ALU|BPF_AND|BPF_K:
A &= pc->k;
continue;
case BPF_ALU|BPF_OR|BPF_K:
A |= pc->k;
continue;
case BPF_ALU|BPF_LSH|BPF_K:
A <<= pc->k;
continue;
case BPF_ALU|BPF_RSH|BPF_K:
A >>= pc->k;
continue;
case BPF_ALU|BPF_NEG:
A = -A;
continue;
case BPF_MISC|BPF_TAX:
X = A;
continue;
case BPF_MISC|BPF_TXA:
A = X;
continue;
}
}
}
#ifdef KERNEL
/*
* Return true if the 'fcode' is a valid filter program.
* The constraints are that each jump be forward and to a valid
* code. The code must terminate with either an accept or reject.
* 'valid' is an array for use by the routine (it must be at least
* 'len' bytes long).
*
* The kernel needs to be able to verify an application's filter code.
* Otherwise, a bogus program could easily crash the system.
*/
int
bpf_validate(f, len)
struct bpf_insn *f;
int len;
{
register int i;
register struct bpf_insn *p;
for (i = 0; i < len; ++i) {
/*
* Check that that jumps are forward, and within
* the code block.
*/
p = &f[i];
if (BPF_CLASS(p->code) == BPF_JMP) {
register int from = i + 1;
if (BPF_OP(p->code) == BPF_JA) {
if (from + p->k >= len)
return 0;
}
else if (from + p->jt >= len || from + p->jf >= len)
return 0;
}
/*
* Check that memory operations use valid addresses.
*/
if ((BPF_CLASS(p->code) == BPF_ST ||
(BPF_CLASS(p->code) == BPF_LD &&
(p->code & 0xe0) == BPF_MEM)) &&
(p->k >= BPF_MEMWORDS || p->k < 0))
return 0;
/*
* Check for constant division by 0.
*/
if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0)
return 0;
}
return BPF_CLASS(f[len - 1].code) == BPF_RET;
}
#endif

284
lib/libpcap/bpf_image.c Normal file
View File

@ -0,0 +1,284 @@
/*
* Copyright (c) 1990, 1991, 1992, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the University of California,
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef lint
static char rcsid[] =
"@(#) $Header: bpf_image.c,v 1.12 94/01/31 03:22:34 leres Exp $ (LBL)";
#endif
#include <sys/types.h>
#include <sys/time.h>
#include <net/bpf.h>
#include <pcap.h>
#include <stdio.h>
#include <string.h>
char *
bpf_image(p, n)
struct bpf_insn *p;
int n;
{
int v;
char *fmt, *op;
static char image[256];
char operand[64];
v = p->k;
switch (p->code) {
default:
op = "unimp";
fmt = "0x%x";
v = p->code;
break;
case BPF_RET|BPF_K:
op = "ret";
fmt = "#%d";
break;
case BPF_RET|BPF_A:
op = "ret";
fmt = "";
break;
case BPF_LD|BPF_W|BPF_ABS:
op = "ld";
fmt = "[%d]";
break;
case BPF_LD|BPF_H|BPF_ABS:
op = "ldh";
fmt = "[%d]";
break;
case BPF_LD|BPF_B|BPF_ABS:
op = "ldb";
fmt = "[%d]";
break;
case BPF_LD|BPF_W|BPF_LEN:
op = "ld";
fmt = "#pktlen";
break;
case BPF_LD|BPF_W|BPF_IND:
op = "ld";
fmt = "[x + %d]";
break;
case BPF_LD|BPF_H|BPF_IND:
op = "ldh";
fmt = "[x + %d]";
break;
case BPF_LD|BPF_B|BPF_IND:
op = "ldb";
fmt = "[x + %d]";
break;
case BPF_LD|BPF_IMM:
op = "ld";
fmt = "#0x%x";
break;
case BPF_LDX|BPF_IMM:
op = "ldx";
fmt = "#0x%x";
break;
case BPF_LDX|BPF_MSH|BPF_B:
op = "ldxb";
fmt = "4*([%d]&0xf)";
break;
case BPF_LD|BPF_MEM:
op = "ld";
fmt = "M[%d]";
break;
case BPF_LDX|BPF_MEM:
op = "ldx";
fmt = "M[%d]";
break;
case BPF_ST:
op = "st";
fmt = "M[%d]";
break;
case BPF_STX:
op = "stx";
fmt = "M[%d]";
break;
case BPF_JMP|BPF_JA:
op = "ja";
fmt = "%d";
v = n + p->k;
break;
case BPF_JMP|BPF_JGT|BPF_K:
op = "jgt";
fmt = "#0x%x";
break;
case BPF_JMP|BPF_JGE|BPF_K:
op = "jge";
fmt = "#0x%x";
break;
case BPF_JMP|BPF_JEQ|BPF_K:
op = "jeq";
fmt = "#0x%x";
break;
case BPF_JMP|BPF_JSET|BPF_K:
op = "jset";
fmt = "#0x%x";
break;
case BPF_JMP|BPF_JGT|BPF_X:
op = "jgt";
fmt = "x";
break;
case BPF_JMP|BPF_JGE|BPF_X:
op = "jge";
fmt = "x";
break;
case BPF_JMP|BPF_JEQ|BPF_X:
op = "jeq";
fmt = "x";
break;
case BPF_JMP|BPF_JSET|BPF_X:
op = "jset";
fmt = "x";
break;
case BPF_ALU|BPF_ADD|BPF_X:
op = "add";
fmt = "x";
break;
case BPF_ALU|BPF_SUB|BPF_X:
op = "sub";
fmt = "x";
break;
case BPF_ALU|BPF_MUL|BPF_X:
op = "mul";
fmt = "x";
break;
case BPF_ALU|BPF_DIV|BPF_X:
op = "div";
fmt = "x";
break;
case BPF_ALU|BPF_AND|BPF_X:
op = "and";
fmt = "x";
break;
case BPF_ALU|BPF_OR|BPF_X:
op = "or";
fmt = "x";
break;
case BPF_ALU|BPF_LSH|BPF_X:
op = "lsh";
fmt = "x";
break;
case BPF_ALU|BPF_RSH|BPF_X:
op = "rsh";
fmt = "x";
break;
case BPF_ALU|BPF_ADD|BPF_K:
op = "add";
fmt = "#%d";
break;
case BPF_ALU|BPF_SUB|BPF_K:
op = "sub";
fmt = "#%d";
break;
case BPF_ALU|BPF_MUL|BPF_K:
op = "mul";
fmt = "#%d";
break;
case BPF_ALU|BPF_DIV|BPF_K:
op = "div";
fmt = "#%d";
break;
case BPF_ALU|BPF_AND|BPF_K:
op = "and";
fmt = "#%d";
break;
case BPF_ALU|BPF_OR|BPF_K:
op = "or";
fmt = "#%d";
break;
case BPF_ALU|BPF_LSH|BPF_K:
op = "lsh";
fmt = "#%d";
break;
case BPF_ALU|BPF_RSH|BPF_K:
op = "rsh";
fmt = "#%d";
break;
case BPF_ALU|BPF_NEG:
op = "neg";
fmt = "";
break;
case BPF_MISC|BPF_TAX:
op = "tax";
fmt = "";
break;
case BPF_MISC|BPF_TXA:
op = "txa";
fmt = "";
break;
}
(void)sprintf(operand, fmt, v);
(void)sprintf(image,
(BPF_CLASS(p->code) == BPF_JMP &&
BPF_OP(p->code) != BPF_JA) ?
"(%03d) %-8s %-16s jt %d\tjf %d"
: "(%03d) %-8s %s",
n, op, operand, n + 1 + p->jt, n + 1 + p->jf);
return image;
}

148
lib/libpcap/etherent.c Normal file
View File

@ -0,0 +1,148 @@
/*
* Copyright (c) 1990, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the University of California,
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef lint
static char rcsid[] =
"@(#) $Header: etherent.c,v 1.8 94/06/20 19:07:50 leres Exp $ (LBL)";
#endif
#include <sys/types.h>
#include <ctype.h>
#include <pcap.h>
#include <pcap-namedb.h>
#include <stdio.h>
#ifndef __GNUC__
#define inline
#endif
static inline int xdtoi(int);
static inline int skip_space(FILE *);
static inline int skip_line(FILE *);
/* Hex digit to integer. */
static inline int
xdtoi(c)
register int c;
{
if (isdigit(c))
return c - '0';
else if (islower(c))
return c - 'a' + 10;
else
return c - 'A' + 10;
}
static inline int
skip_space(f)
FILE *f;
{
int c;
do {
c = getc(f);
} while (isspace(c) && c != '\n');
return c;
}
static inline int
skip_line(f)
FILE *f;
{
int c;
do
c = getc(f);
while (c != '\n' && c != EOF);
return c;
}
struct pcap_etherent *
pcap_next_etherent(FILE *fp)
{
register int c, d, i;
char *bp;
static struct pcap_etherent e;
static int nline = 1;
top:
while (nline) {
/* Find addr */
c = skip_space(fp);
if (c == '\n')
continue;
/* If this is a comment, or first thing on line
cannot be ethernet address, skip the line. */
else if (!isxdigit(c))
c = skip_line(fp);
else {
/* must be the start of an address */
for (i = 0; i < 6; i += 1) {
d = xdtoi(c);
c = getc(fp);
if (c != ':') {
d <<= 4;
d |= xdtoi(c);
c = getc(fp);
}
e.addr[i] = d;
if (c != ':')
break;
c = getc(fp);
}
nline = 0;
}
if (c == EOF)
return 0;
}
/* If we started a new line, 'c' holds the char past the ether addr,
which we assume is white space. If we are continuing a line,
'c' is garbage. In either case, we can throw it away. */
c = skip_space(fp);
if (c == '\n') {
nline = 1;
goto top;
}
else if (c == '#') {
(void)skip_line(fp);
nline = 1;
goto top;
}
else if (c == EOF)
return 0;
/* Must be a name. */
bp = e.name;
/* Use 'd' to prevent buffer overflow. */
d = sizeof(e.name) - 1;
do {
*bp++ = c;
c = getc(fp);
} while (!isspace(c) && c != EOF && --d > 0);
*bp = '\0';
if (c == '\n')
nline = 1;
return &e;
}

74
lib/libpcap/ethertype.h Normal file
View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the University of California,
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* @(#) $Header: ethertype.h,v 1.2 94/06/14 20:03:27 leres Exp $ (LBL)
*/
/* Map between Ethernet protocol types and names */
/* Add other Ethernet packet types here */
#ifndef ETHERTYPE_SPRITE
#define ETHERTYPE_SPRITE 0x0500
#endif
#ifndef ETHERTYPE_MOPDL
#define ETHERTYPE_MOPDL 0x6001
#endif
#ifndef ETHERTYPE_MOPRC
#define ETHERTYPE_MOPRC 0x6002
#endif
#ifndef ETHERTYPE_DN
#define ETHERTYPE_DN 0x6003
#endif
#ifndef ETHERTYPE_LAT
#define ETHERTYPE_LAT 0x6004
#endif
#ifndef ETHERTYPE_LANBRIDGE
#define ETHERTYPE_LANBRIDGE 0x8038
#endif
#ifndef ETHERTYPE_DECDNS
#define ETHERTYPE_DECDNS 0x803c
#endif
#ifndef ETHERTYPE_DECDTS
#define ETHERTYPE_DECDTS 0x803e
#endif
#ifndef ETHERTYPE_VEXP
#define ETHERTYPE_VEXP 0x805b
#endif
#ifndef ETHERTYPE_VPROD
#define ETHERTYPE_VPROD 0x805c
#endif
#ifndef ETHERTYPE_LOOPBACK
#define ETHERTYPE_LOOPBACK 0x9000
#endif
#ifndef ETHERTYPE_ATALK
#define ETHERTYPE_ATALK 0x809b /* XXX */
#endif
#ifndef ETHERTYPE_AARP
#define ETHERTYPE_AARP 0x80f3
#endif
#ifndef ETHERTYPE_NS
#define ETHERTYPE_NS 0x0600
#endif
#ifndef ETHERTYPE_REVARP
#define ETHERTYPE_REVARP 0x8035
#endif

1755
lib/libpcap/gencode.c Normal file

File diff suppressed because it is too large Load Diff

173
lib/libpcap/gencode.h Normal file
View File

@ -0,0 +1,173 @@
/*
* Copyright (c) 1990, 1991, 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the University of California,
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* @(#) $Header: gencode.h,v 1.20 94/06/12 14:29:30 leres Exp $ (LBL)
*/
/*
* filter.h must be included before this file.
*/
/* Address qualifers. */
#define Q_HOST 1
#define Q_NET 2
#define Q_PORT 3
#define Q_GATEWAY 4
#define Q_PROTO 5
/* Protocol qualifiers. */
#define Q_LINK 1
#define Q_IP 2
#define Q_ARP 3
#define Q_RARP 4
#define Q_TCP 5
#define Q_UDP 6
#define Q_ICMP 7
#define Q_DECNET 8
#define Q_LAT 9
#define Q_MOPRC 10
#define Q_MOPDL 11
/* Directional qualifers. */
#define Q_SRC 1
#define Q_DST 2
#define Q_OR 3
#define Q_AND 4
#define Q_DEFAULT 0
#define Q_UNDEF 255
struct stmt {
int code;
long k;
};
struct slist {
struct stmt s;
struct slist *next;
};
/*
* A bit vector to represent definition sets. We assume TOT_REGISTERS
* is smaller than 8*sizeof(atomset).
*/
typedef u_long atomset;
#define ATOMMASK(n) (1 << (n))
#define ATOMELEM(d, n) (d & ATOMMASK(n))
/*
* An unbounded set.
*/
typedef u_long *uset;
/*
* Total number of atomic entities, including accumulator (A) and index (X).
* We treat all these guys similarly during flow analysis.
*/
#define N_ATOMS (BPF_MEMWORDS+2)
struct edge {
int id;
int code;
uset edom;
struct block *succ;
struct block *pred;
struct edge *next; /* link list of incoming edges for a node */
};
struct block {
int id;
struct slist *stmts; /* side effect stmts */
struct stmt s; /* branch stmt */
int mark;
int level;
int offset;
int sense;
struct edge et;
struct edge ef;
struct block *head;
struct block *link; /* link field used by optimizer */
uset dom;
uset closure;
struct edge *in_edges;
atomset def, kill;
atomset in_use;
atomset out_use;
long oval;
long val[N_ATOMS];
};
struct arth {
struct block *b; /* protocol checks */
struct slist *s; /* stmt list */
int regno; /* virtual register number of result */
};
struct qual {
unsigned char addr;
unsigned char proto;
unsigned char dir;
unsigned char pad;
};
#ifndef __GNUC__
#define volatile
#endif
struct arth *gen_loadi(int);
struct arth *gen_load(int, struct arth *, int);
struct arth *gen_loadlen(void);
struct arth *gen_neg(struct arth *);
struct arth *gen_arth(int, struct arth *, struct arth *);
void gen_and(struct block *, struct block *);
void gen_or(struct block *, struct block *);
void gen_not(struct block *);
struct block *gen_scode(char *, struct qual);
struct block *gen_ecode(u_char *, struct qual);
struct block *gen_ncode(u_long, struct qual);
struct block *gen_proto_abbrev(int);
struct block *gen_relation(int, struct arth *, struct arth *, int);
struct block *gen_less(int);
struct block *gen_greater(int);
struct block *gen_byteop(int, int, int);
struct block *gen_broadcast(int);
struct block *gen_multicast(int);
struct block *gen_inbound(int);
void bpf_optimize(struct block **);
volatile void bpf_error(char *, ...);
void finish_parse(struct block *);
char *sdup(char *);
struct bpf_insn *icode_to_fcode(struct block *, int *);
int pcap_parse(void);
void lex_init(char *);
void sappend(struct slist *, struct slist *);
/* XXX */
#define JT(b) ((b)->et.succ)
#define JF(b) ((b)->ef.succ)

264
lib/libpcap/grammar.y Normal file
View File

@ -0,0 +1,264 @@
%{
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the University of California,
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
*/
#ifndef lint
static char rcsid[] =
"@(#) $Header: grammar.y,v 1.39 94/06/14 20:09:25 leres Exp $ (LBL)";
#endif
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/bpf.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <stdio.h>
#include <pcap.h>
#include <pcap-namedb.h>
#include "gencode.h"
#define QSET(q, p, d, a) (q).proto = (p),\
(q).dir = (d),\
(q).addr = (a)
int n_errors = 0;
static struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF };
static void
yyerror(char *msg)
{
++n_errors;
bpf_error(msg);
/* NOTREACHED */
}
#ifndef YYBISON
pcap_parse()
{
return (yyparse());
}
#endif
%}
%union {
int i;
u_long h;
u_char *e;
char *s;
struct stmt *stmt;
struct arth *a;
struct {
struct qual q;
struct block *b;
} blk;
struct block *rblk;
}
%type <blk> expr id nid pid term rterm qid
%type <blk> head
%type <i> pqual dqual aqual ndaqual
%type <a> arth narth
%type <i> byteop pname pnum relop irelop
%type <blk> and or paren not null prog
%type <rblk> other
%token DST SRC HOST GATEWAY
%token NET PORT LESS GREATER PROTO BYTE
%token ARP RARP IP TCP UDP ICMP
%token DECNET LAT MOPRC MOPDL
%token TK_BROADCAST TK_MULTICAST
%token NUM INBOUND OUTBOUND
%token LINK
%token GEQ LEQ NEQ
%token ID EID HID
%token LSH RSH
%token LEN
%type <s> ID
%type <e> EID
%type <h> HID
%type <i> NUM
%left OR AND
%nonassoc '!'
%left '|'
%left '&'
%left LSH RSH
%left '+' '-'
%left '*' '/'
%nonassoc UMINUS
%%
prog: null expr
{
finish_parse($2.b);
}
| null
;
null: /* null */ { $$.q = qerr; }
;
expr: term
| expr and term { gen_and($1.b, $3.b); $$ = $3; }
| expr and id { gen_and($1.b, $3.b); $$ = $3; }
| expr or term { gen_or($1.b, $3.b); $$ = $3; }
| expr or id { gen_or($1.b, $3.b); $$ = $3; }
;
and: AND { $$ = $<blk>0; }
;
or: OR { $$ = $<blk>0; }
;
id: nid
| pnum { $$.b = gen_ncode((u_long)$1,
$$.q = $<blk>0.q); }
| paren pid ')' { $$ = $2; }
;
nid: ID { $$.b = gen_scode($1, $$.q = $<blk>0.q); }
| HID {
/* Decide how to parse HID based on proto */
$$.q = $<blk>0.q;
switch ($$.q.proto) {
case Q_DECNET:
$$.b =
gen_ncode(__pcap_atodn((char *)$1),
$$.q);
break;
default:
$$.b =
gen_ncode(__pcap_atoin((char *)$1),
$$.q);
break;
}
}
| EID { $$.b = gen_ecode($1, $$.q = $<blk>0.q); }
| not id { gen_not($2.b); $$ = $2; }
;
not: '!' { $$ = $<blk>0; }
;
paren: '(' { $$ = $<blk>0; }
;
pid: nid
| qid and id { gen_and($1.b, $3.b); $$ = $3; }
| qid or id { gen_or($1.b, $3.b); $$ = $3; }
;
qid: pnum { $$.b = gen_ncode((u_long)$1,
$$.q = $<blk>0.q); }
| pid
;
term: rterm
| not term { gen_not($2.b); $$ = $2; }
;
head: pqual dqual aqual { QSET($$.q, $1, $2, $3); }
| pqual dqual { QSET($$.q, $1, $2, Q_DEFAULT); }
| pqual aqual { QSET($$.q, $1, Q_DEFAULT, $2); }
| pqual PROTO { QSET($$.q, $1, Q_DEFAULT, Q_PROTO); }
| pqual ndaqual { QSET($$.q, $1, Q_DEFAULT, $2); }
;
rterm: head id { $$ = $2; }
| paren expr ')' { $$.b = $2.b; $$.q = $1.q; }
| pname { $$.b = gen_proto_abbrev($1); $$.q = qerr; }
| arth relop arth { $$.b = gen_relation($2, $1, $3, 0);
$$.q = qerr; }
| arth irelop arth { $$.b = gen_relation($2, $1, $3, 1);
$$.q = qerr; }
| other { $$.b = $1; $$.q = qerr; }
;
/* protocol level qualifiers */
pqual: pname
| { $$ = Q_DEFAULT; }
;
/* 'direction' qualifiers */
dqual: SRC { $$ = Q_SRC; }
| DST { $$ = Q_DST; }
| SRC OR DST { $$ = Q_OR; }
| DST OR SRC { $$ = Q_OR; }
| SRC AND DST { $$ = Q_AND; }
| DST AND SRC { $$ = Q_AND; }
;
/* address type qualifiers */
aqual: HOST { $$ = Q_HOST; }
| NET { $$ = Q_NET; }
| PORT { $$ = Q_PORT; }
;
/* non-directional address type qualifiers */
ndaqual: GATEWAY { $$ = Q_GATEWAY; }
;
pname: LINK { $$ = Q_LINK; }
| IP { $$ = Q_IP; }
| ARP { $$ = Q_ARP; }
| RARP { $$ = Q_RARP; }
| TCP { $$ = Q_TCP; }
| UDP { $$ = Q_UDP; }
| ICMP { $$ = Q_ICMP; }
| DECNET { $$ = Q_DECNET; }
| LAT { $$ = Q_LAT; }
| MOPDL { $$ = Q_MOPDL; }
| MOPRC { $$ = Q_MOPRC; }
;
other: pqual TK_BROADCAST { $$ = gen_broadcast($1); }
| pqual TK_MULTICAST { $$ = gen_multicast($1); }
| LESS NUM { $$ = gen_less($2); }
| GREATER NUM { $$ = gen_greater($2); }
| BYTE NUM byteop NUM { $$ = gen_byteop($3, $2, $4); }
| INBOUND { $$ = gen_inbound(0); }
| OUTBOUND { $$ = gen_inbound(1); }
;
relop: '>' { $$ = BPF_JGT; }
| GEQ { $$ = BPF_JGE; }
| '=' { $$ = BPF_JEQ; }
;
irelop: LEQ { $$ = BPF_JGT; }
| '<' { $$ = BPF_JGE; }
| NEQ { $$ = BPF_JEQ; }
;
arth: pnum { $$ = gen_loadi($1); }
| narth
;
narth: pname '[' arth ']' { $$ = gen_load($1, $3, 1); }
| pname '[' arth ':' NUM ']' { $$ = gen_load($1, $3, $5); }
| arth '+' arth { $$ = gen_arth(BPF_ADD, $1, $3); }
| arth '-' arth { $$ = gen_arth(BPF_SUB, $1, $3); }
| arth '*' arth { $$ = gen_arth(BPF_MUL, $1, $3); }
| arth '/' arth { $$ = gen_arth(BPF_DIV, $1, $3); }
| arth '&' arth { $$ = gen_arth(BPF_AND, $1, $3); }
| arth '|' arth { $$ = gen_arth(BPF_OR, $1, $3); }
| arth LSH arth { $$ = gen_arth(BPF_LSH, $1, $3); }
| arth RSH arth { $$ = gen_arth(BPF_RSH, $1, $3); }
| '-' arth %prec UMINUS { $$ = gen_neg($2); }
| paren narth ')' { $$ = $2; }
| LEN { $$ = gen_loadlen(); }
;
byteop: '&' { $$ = '&'; }
| '|' { $$ = '|'; }
| '<' { $$ = '<'; }
| '>' { $$ = '>'; }
| '=' { $$ = '='; }
;
pnum: NUM
| paren pnum ')' { $$ = $2; }
;
%%

196
lib/libpcap/inet.c Normal file
View File

@ -0,0 +1,196 @@
/*
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the Computer Systems
* Engineering Group at Lawrence Berkeley Laboratory.
* 4. Neither the name of the University nor of the Laboratory may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static char rcsid[] =
"@(#) $Header: inet.c,v 1.4 94/06/07 01:16:50 leres Exp $ (LBL)";
#endif
#include <sys/param.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#ifdef SOLARIS
#include <sys/sockio.h>
#endif
#include <net/if.h>
#include <netinet/in.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pcap.h>
/* Not all systems have IFF_LOOPBACK */
#ifdef IFF_LOOPBACK
#define ISLOOPBACK(p) ((p)->ifr_flags & IFF_LOOPBACK)
#else
#define ISLOOPBACK(p) (strcmp((p)->ifr_name, "lo0") == 0)
#endif
/*
* Return the name of a network interface attached to the system, or NULL
* if none can be found. The interface must be configured up; the
* lowest unit number is preferred; loopback is ignored.
*/
char *
pcap_lookupdev(errbuf)
register char *errbuf;
{
register int fd, minunit, n;
register char *cp;
register struct ifreq *ifrp, *ifend, *ifnext, *mp;
struct ifconf ifc;
struct ifreq ibuf[16], ifr;
static char device[sizeof(ifrp->ifr_name) + 1];
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
(void)sprintf(errbuf, "socket: %s", pcap_strerror(errno));
return (NULL);
}
ifc.ifc_len = sizeof ibuf;
ifc.ifc_buf = (caddr_t)ibuf;
if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0 ||
ifc.ifc_len < sizeof(struct ifreq)) {
(void)sprintf(errbuf, "SIOCGIFCONF: %s", pcap_strerror(errno));
(void)close(fd);
return (NULL);
}
ifrp = ibuf;
ifend = (struct ifreq *)((char *)ibuf + ifc.ifc_len);
mp = NULL;
minunit = 666;
for (; ifrp < ifend; ifrp = ifnext) {
#if BSD - 0 >= 199006
n = ifrp->ifr_addr.sa_len + sizeof(ifrp->ifr_name);
if (n < sizeof(*ifrp))
ifnext = ifrp + 1;
else
ifnext = (struct ifreq *)((char *)ifrp + n);
if (ifrp->ifr_addr.sa_family != AF_INET)
continue;
#else
ifnext = ifrp + 1;
#endif
/*
* Need a template to preserve address info that is
* used below to locate the next entry. (Otherwise,
* SIOCGIFFLAGS stomps over it because the requests
* are returned in a union.)
*/
strncpy(ifr.ifr_name, ifrp->ifr_name, sizeof(ifr.ifr_name));
if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
(void)sprintf(errbuf, "SIOCGIFFLAGS: %s",
pcap_strerror(errno));
(void)close(fd);
return (NULL);
}
/* Must be up and not the loopback */
if ((ifr.ifr_flags & IFF_UP) == 0 || ISLOOPBACK(&ifr))
continue;
for (cp = ifrp->ifr_name; !isdigit(*cp); ++cp)
continue;
n = atoi(cp);
if (n < minunit) {
minunit = n;
mp = ifrp;
}
}
(void)close(fd);
if (mp == NULL) {
(void)strcpy(errbuf, "no suitable device found");
return (NULL);
}
(void)strncpy(device, mp->ifr_name, sizeof(device) - 1);
device[sizeof(device) - 1] = '\0';
return (device);
}
int
pcap_lookupnet(device, netp, maskp, errbuf)
register char *device;
register u_long *netp, *maskp;
register char *errbuf;
{
register int fd;
register struct sockaddr_in *sin;
struct ifreq ifr;
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
(void)sprintf(errbuf, "socket: %s", pcap_strerror(errno));
return (-1);
}
(void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
(void)sprintf(errbuf, "SIOCGIFADDR: %s: %s",
device, pcap_strerror(errno));
(void)close(fd);
return (-1);
}
sin = (struct sockaddr_in *)&ifr.ifr_addr;
*netp = sin->sin_addr.s_addr;
if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
(void)sprintf(errbuf, "SIOCGIFNETMASK: %s: %s",
device, pcap_strerror(errno));
(void)close(fd);
return (-1);
}
(void)close(fd);
*maskp = sin->sin_addr.s_addr;
if (*maskp == 0) {
if (IN_CLASSA(*netp))
*maskp = IN_CLASSA_NET;
else if (IN_CLASSB(*netp))
*maskp = IN_CLASSB_NET;
else if (IN_CLASSC(*netp))
*maskp = IN_CLASSC_NET;
else {
(void)sprintf(errbuf, "inet class for 0x%x unknown",
*netp);
return (-1);
}
}
*netp &= *maskp;
return (0);
}

357
lib/libpcap/nametoaddr.c Normal file
View File

@ -0,0 +1,357 @@
/*
* Copyright (c) 1990, 1991, 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the University of California,
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* Name to id translation routines used by the scanner.
* These functions are not time critical.
*/
#ifndef lint
static char rcsid[] =
"@(#) $Header: nametoaddr.c,v 1.21 94/06/20 19:07:54 leres Exp $ (LBL)";
#endif
#include <sys/param.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
#include <netdb.h>
#include <pcap.h>
#include <pcap-namedb.h>
#include <stdio.h>
#include "gencode.h"
#ifndef __GNUC__
#define inline
#endif
#ifndef NTOHL
#define NTOHL(x) (x) = ntohl(x)
#define NTOHS(x) (x) = ntohs(x)
#endif
static inline int xdtoi(int);
/*
* Convert host name to internet address.
* Return 0 upon failure.
*/
u_long **
pcap_nametoaddr(const char *name)
{
#ifndef h_addr
static u_long *hlist[2];
#endif
u_long **p;
struct hostent *hp;
if ((hp = gethostbyname(name)) != NULL) {
#ifndef h_addr
hlist[0] = (u_long *)hp->h_addr;
NTOHL(hp->h_addr);
return hlist;
#else
for (p = (u_long **)hp->h_addr_list; *p; ++p)
NTOHL(**p);
return (u_long **)hp->h_addr_list;
#endif
}
else
return 0;
}
/*
* Convert net name to internet address.
* Return 0 upon failure.
*/
u_long
pcap_nametonetaddr(const char *name)
{
struct netent *np;
if ((np = getnetbyname(name)) != NULL)
return np->n_net;
else
return 0;
}
/*
* Convert a port name to its port and protocol numbers.
* We assume only TCP or UDP.
* Return 0 upon failure.
*/
int
pcap_nametoport(const char *name, int *port, int *proto)
{
struct servent *sp;
char *other;
sp = getservbyname(name, (char *)0);
if (sp != NULL) {
NTOHS(sp->s_port);
*port = sp->s_port;
*proto = pcap_nametoproto(sp->s_proto);
/*
* We need to check /etc/services for ambiguous entries.
* If we find the ambiguous entry, and it has the
* same port number, change the proto to PROTO_UNDEF
* so both TCP and UDP will be checked.
*/
if (*proto == IPPROTO_TCP)
other = "udp";
else
other = "tcp";
sp = getservbyname(name, other);
if (sp != 0) {
NTOHS(sp->s_port);
if (*port != sp->s_port)
/* Can't handle ambiguous names that refer
to different port numbers. */
#ifdef notdef
warning("ambiguous port %s in /etc/services",
name);
#else
;
#endif
*proto = PROTO_UNDEF;
}
return 1;
}
#if defined(ultrix) || defined(__osf__)
/* Special hack in case NFS isn't in /etc/services */
if (strcmp(name, "nfs") == 0) {
*port = 2049;
*proto = PROTO_UNDEF;
return 1;
}
#endif
return 0;
}
int
pcap_nametoproto(const char *str)
{
struct protoent *p;
p = getprotobyname(str);
if (p != 0)
return p->p_proto;
else
return PROTO_UNDEF;
}
#include "ethertype.h"
struct eproto {
char *s;
u_short p;
};
/* Static data base of ether protocol types. */
struct eproto eproto_db[] = {
{ "pup", ETHERTYPE_PUP },
{ "xns", ETHERTYPE_NS },
{ "ip", ETHERTYPE_IP },
{ "arp", ETHERTYPE_ARP },
{ "rarp", ETHERTYPE_REVARP },
{ "sprite", ETHERTYPE_SPRITE },
{ "mopdl", ETHERTYPE_MOPDL },
{ "moprc", ETHERTYPE_MOPRC },
{ "decnet", ETHERTYPE_DN },
{ "lat", ETHERTYPE_LAT },
{ "lanbridge", ETHERTYPE_LANBRIDGE },
{ "vexp", ETHERTYPE_VEXP },
{ "vprod", ETHERTYPE_VPROD },
{ "atalk", ETHERTYPE_ATALK },
{ "atalkarp", ETHERTYPE_AARP },
{ "loopback", ETHERTYPE_LOOPBACK },
{ "decdts", ETHERTYPE_DECDTS },
{ "decdns", ETHERTYPE_DECDNS },
{ (char *)0, 0 }
};
int
pcap_nametoeproto(const char *s)
{
struct eproto *p = eproto_db;
while (p->s != 0) {
if (strcmp(p->s, s) == 0)
return p->p;
p += 1;
}
return PROTO_UNDEF;
}
/* Hex digit to integer. */
static inline int
xdtoi(c)
register int c;
{
if (isdigit(c))
return c - '0';
else if (islower(c))
return c - 'a' + 10;
else
return c - 'A' + 10;
}
u_long
__pcap_atoin(const char *s)
{
u_long addr = 0;
u_int n;
while (1) {
n = 0;
while (*s && *s != '.')
n = n * 10 + *s++ - '0';
addr <<= 8;
addr |= n & 0xff;
if (*s == '\0')
return addr;
++s;
}
/* NOTREACHED */
}
u_long
__pcap_atodn(const char *s)
{
#define AREASHIFT 10
#define AREAMASK 0176000
#define NODEMASK 01777
u_long addr = 0;
u_int node, area;
if (sscanf((char *)s, "%d.%d", &area, &node) != 2)
bpf_error("malformed decnet address '%s'", s);
addr = (area << AREASHIFT) & AREAMASK;
addr |= (node & NODEMASK);
return(addr);
}
/*
* Convert 's' which has the form "xx:xx:xx:xx:xx:xx" into a new
* ethernet address. Assumes 's' is well formed.
*/
u_char *
pcap_ether_aton(const char *s)
{
register u_char *ep, *e;
register u_int d;
e = ep = (u_char *)malloc(6);
while (*s) {
if (*s == ':')
s += 1;
d = xdtoi(*s++);
if (isxdigit(*s)) {
d <<= 4;
d |= xdtoi(*s++);
}
*ep++ = d;
}
return (e);
}
#ifndef ETHER_SERVICE
/* Roll our own */
u_char *
pcap_ether_hostton(const char *name)
{
register struct pcap_etherent *ep;
register u_char *ap;
static FILE *fp = NULL;
static init = 0;
if (!init) {
fp = fopen(PCAP_ETHERS_FILE, "r");
++init;
if (fp == NULL)
return (NULL);
} else if (fp == NULL)
return (NULL);
else
rewind(fp);
while ((ep = pcap_next_etherent(fp)) != NULL) {
if (strcmp(ep->name, name) == 0) {
ap = (u_char *)malloc(6);
if (ap != NULL) {
memcpy(ap, ep->addr, 6);
return (ap);
}
break;
}
}
return (NULL);
}
#else
/* Use the os supplied routines */
u_char *
pcap_ether_hostton(const char *name)
{
register u_char *ap;
u_char a[6];
#ifndef sgi
extern int ether_hostton(char *, struct ether_addr *);
#endif
ap = NULL;
if (ether_hostton((char*)name, (struct ether_addr *)a) == 0) {
ap = (u_char *)malloc(6);
if (ap != NULL)
memcpy(ap, a, 6);
}
return (ap);
}
#endif
u_short
__pcap_nametodnaddr(const char *name)
{
#ifdef DECNETLIB
struct nodeent *getnodebyname();
struct nodeent *nep;
unsigned short res;
nep = getnodebyname(name);
if (nep == ((struct nodeent *)0))
bpf_error("unknown decnet host name '%s'\n", name);
memcpy((char *)&res, (char *)nep->n_addr, sizeof(unsigned short));
return(res);
#else
bpf_error("decnet name support not included, '%s' cannot be translated\n",
name);
#endif
}

1923
lib/libpcap/optimize.c Normal file

File diff suppressed because it is too large Load Diff

233
lib/libpcap/pcap-bpf.c Normal file
View File

@ -0,0 +1,233 @@
/*
* Copyright (c) 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the University of California,
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef lint
static char rcsid[] =
"@(#)$Header: pcap-bpf.c,v 1.14 94/06/03 19:58:49 leres 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 "pcap-int.h"
int
pcap_stats(pcap_t *p, struct pcap_stat *ps)
{
struct bpf_stat s;
if (ioctl(p->fd, BIOCGSTATS, &s) < 0) {
sprintf(p->errbuf, "BIOCGSTATS: %s", pcap_strerror(errno));
return (-1);
}
ps->ps_recv = s.bs_recv;
ps->ps_drop = s.bs_drop;
return (0);
}
int
pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
int cc;
int n = 0;
register u_char *bp, *ep;
again:
cc = p->cc;
if (p->cc == 0) {
cc = read(p->fd, (char *)p->buffer, p->bufsize);
if (cc < 0) {
/* Don't choke when we get ptraced */
switch (errno) {
case EINTR:
goto again;
case EWOULDBLOCK:
return (0);
#if defined(sun) && !defined(BSD)
/*
* Due to a SunOS bug, after 2^31 bytes, the kernel
* file offset overflows and read fails with EINVAL.
* The lseek() to 0 will fix things.
*/
case EINVAL:
if ((long)(tell(p->fd) + p->bufsize) < 0) {
(void)lseek(p->fd, 0, 0);
goto again;
}
/* fall through */
#endif
}
sprintf(p->errbuf, "read: %s", pcap_strerror(errno));
return (-1);
}
bp = p->buffer;
} else
bp = p->bp;
/*
* Loop through each packet.
*/
#define bhp ((struct bpf_hdr *)bp)
ep = bp + cc;
while (bp < ep) {
register int caplen, hdrlen;
caplen = bhp->bh_caplen;
hdrlen = bhp->bh_hdrlen;
/*
* XXX A bpf_hdr matches a pcap_pkthdr.
*/
(*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen);
bp += BPF_WORDALIGN(caplen + hdrlen);
if (++n >= cnt && cnt > 0) {
p->bp = bp;
p->cc = ep - bp;
return (n);
}
}
#undef bhp
p->cc = 0;
return (n);
}
static inline int
bpf_open(pcap_t *p, char *errbuf)
{
int fd;
int n = 0;
char device[sizeof "/dev/bpf000"];
/*
* Go through all the minors and find one that isn't in use.
*/
do {
(void)sprintf(device, "/dev/bpf%d", n++);
fd = open(device, O_RDONLY);
} while (fd < 0 && errno == EBUSY);
/*
* XXX better message for all minors used
*/
if (fd < 0)
sprintf(errbuf, "%s: %s", device, pcap_strerror(errno));
return (fd);
}
pcap_t *
pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
{
int fd;
struct ifreq ifr;
struct bpf_version bv;
u_int v;
pcap_t *p;
p = (pcap_t *)malloc(sizeof(*p));
if (p == NULL) {
sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
return (NULL);
}
bzero(p, sizeof(*p));
fd = bpf_open(p, ebuf);
if (fd < 0)
goto bad;
p->fd = fd;
p->snapshot = snaplen;
if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) {
sprintf(ebuf, "BIOCVERSION: %s", pcap_strerror(errno));
goto bad;
}
if (bv.bv_major != BPF_MAJOR_VERSION ||
bv.bv_minor < BPF_MINOR_VERSION) {
sprintf(ebuf, "kernel bpf filter out of date");
goto bad;
}
(void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
sprintf(ebuf, "%s: %s", device, pcap_strerror(errno));
goto bad;
}
/* Get the data link layer type. */
if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) {
sprintf(ebuf, "BIOCGDLT: %s", pcap_strerror(errno));
goto bad;
}
p->linktype = v;
/* set timeout */
if (to_ms != 0) {
struct timeval to;
to.tv_sec = to_ms / 1000;
to.tv_usec = (to_ms * 1000) % 1000000;
if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) {
sprintf(ebuf, "BIOCSRTIMEOUT: %s",
pcap_strerror(errno));
goto bad;
}
}
if (promisc)
/* set promiscuous mode, okay if it fails */
(void)ioctl(p->fd, BIOCPROMISC, NULL);
if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) {
sprintf(ebuf, "BIOCGBLEN: %s", pcap_strerror(errno));
goto bad;
}
p->bufsize = v;
p->buffer = (u_char*)malloc(p->bufsize);
if (p->buffer == NULL) {
sprintf(ebuf, "malloc: %s", pcap_strerror(errno));
goto bad;
}
return (p);
bad:
free(p);
return (NULL);
}
int
pcap_setfilter(pcap_t *p, struct bpf_program *fp)
{
if (p->sf.rfile != NULL)
p->fcode = *fp;
else if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) {
sprintf(p->errbuf, "BIOCSETF: %s", pcap_strerror(errno));
return (-1);
}
return (0);
}

506
lib/libpcap/pcap-dlpi.c Normal file
View File

@ -0,0 +1,506 @@
/*
* Copyright (c) 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the University of California,
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* This code contributed by Atanu Ghosh (atanu@cs.ucl.ac.uk),
* University College London.
*/
#ifndef lint
static char rcsid[] =
"@(#)$Header: pcap-dlpi.c,v 1.22x 94/10/12 20:08:15 leres Exp $ (LBL)";
#endif
/*
* Packet capture routine for dlpi under SunOS 5
*
* Notes:
*
* - Apparently the DLIOCRAW ioctl() is specific to SunOS.
*
* - There is a bug in bufmod(7) such that setting the snapshot
* length results in data being left of the front of the packet.
*
* - It might be desirable to use pfmod(7) to filter packets in the
* kernel.
*/
#include <sys/types.h>
#include <sys/time.h>
#include <sys/bufmod.h>
#include <sys/dlpi.h>
#include <sys/stream.h>
#include <sys/systeminfo.h>
#include <net/bpf.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <memory.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stropts.h>
#include <unistd.h>
#include "pcap-int.h"
#define MAXDLBUF 8192
/* Forwards */
static int send_request(int, char *, int, char *, char *);
static int dlattachreq(int, u_long, char *);
static int dlinfoack(int, char *, char *);
static int dlinforeq(int, char *);
static int dlpromisconreq(int, u_long, char *);
static int dlokack(int, char *, char *);
static int strioctl(int, int, int, char *);
#ifdef SOLARIS
static char *getrelease(long *, long *, long *);
#endif
int
pcap_stats(pcap_t *p, struct pcap_stat *ps)
{
*ps = p->md.stat;
return (0);
}
int
pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
register int cc, n;
register u_char *bp, *ep, *pk;
register struct bpf_insn *fcode;
register struct sb_hdr *sbp;
int flags;
struct strbuf data;
struct pcap_pkthdr pkthdr;
flags = 0;
cc = p->cc;
if (cc == 0) {
data.buf = (char *)p->buffer;
data.maxlen = MAXDLBUF;
data.len = 0;
do {
if (getmsg(p->fd, NULL, &data, &flags) < 0) {
/* Don't choke when we get ptraced */
if (errno == EINTR) {
cc = 0;
continue;
}
strcpy(p->errbuf, pcap_strerror(errno));
return (-1);
}
cc = data.len;
} while (cc == 0);
bp = p->buffer;
} else
bp = p->bp;
/* Loop through packets */
fcode = p->fcode.bf_insns;
ep = bp + cc;
n = 0;
while (bp < ep) {
sbp = (struct sb_hdr *)bp;
p->md.stat.ps_drop += sbp->sbh_drops;
++p->md.stat.ps_recv;
pk = bp + sizeof(*sbp);
bp += sbp->sbh_totlen;
if (bpf_filter(fcode, pk, sbp->sbh_origlen, sbp->sbh_msglen)) {
pkthdr.ts = sbp->sbh_timestamp;
pkthdr.len = sbp->sbh_origlen;
pkthdr.caplen = sbp->sbh_msglen;
(*callback)(user, &pkthdr, pk);
if (++n >= cnt && cnt >= 0) {
p->cc = ep - bp;
p->bp = bp;
return (n);
}
}
}
p->cc = 0;
return (n);
}
pcap_t *
pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
{
register pcap_t *p;
long buf[MAXDLBUF];
int ppa;
int cppa;
register dl_info_ack_t *infop;
u_long ss, flag;
#ifdef SOLARIS
char *release;
long osmajor, osminor, osmicro;
#endif
char dname[100];
p = (pcap_t *)malloc(sizeof(*p));
if (p == NULL) {
strcpy(ebuf, pcap_strerror(errno));
return (NULL);
}
memset(p, 0, sizeof(*p));
/*
** 1) In order to get the ppa take the last character of the device
** name if it is a number then fail the open.
**
** 2) If the name starts with a '/' then this is an absolute pathname,
** otherwise prepend '/dev/'.
**
** 3) Remove the trailing digit and try and open the device
** not staggeringly intuitive but it should work.
**
** If there are more than 9 devices this code will fail.
*/
cppa = device[strlen(device) - 1];
if (!isdigit(cppa)) {
sprintf(ebuf, "%c is not a digit, therefore not a valid ppa",
cppa);
goto bad;
}
dname[0] = '\0';
if (device[0] != '/')
strcpy(dname, "/dev/");
strcat(dname, device);
dname[strlen(dname) - 1] = '\0';
if ((p->fd = open(dname, O_RDWR)) < 0) {
sprintf(ebuf, "%s: %s", dname, pcap_strerror(errno));
goto bad;
}
p->snapshot = snaplen;
ppa = cppa - '0';
/*
** Attach.
*/
if (dlattachreq(p->fd, ppa, ebuf) < 0 ||
dlokack(p->fd, (char *)buf, ebuf) < 0)
goto bad;
if (promisc) {
/*
** enable promiscuous.
*/
if (dlpromisconreq(p->fd, DL_PROMISC_PHYS, ebuf) < 0 ||
dlokack(p->fd, (char *)buf, ebuf) < 0)
goto bad;
if (dlpromisconreq(p->fd, DL_PROMISC_SAP, ebuf) < 0 ||
dlokack(p->fd, (char *)buf, ebuf) < 0)
goto bad;
/*
** enable multicast, you would have thought promiscuous
** would be sufficient.
*/
if (dlpromisconreq(p->fd, DL_PROMISC_MULTI, ebuf) < 0 ||
dlokack(p->fd, (char *)buf, ebuf) < 0)
goto bad;
}
/*
** Determine link type
*/
if (dlinforeq(p->fd, ebuf) < 0 ||
dlinfoack(p->fd, (char *)buf, ebuf) < 0)
goto bad;
infop = &((union DL_primitives *)buf)->info_ack;
switch (infop->dl_mac_type) {
case DL_ETHER:
p->linktype = DLT_EN10MB;
break;
case DL_FDDI:
p->linktype = DLT_FDDI;
break;
default:
sprintf(ebuf, "unknown mac type 0x%lu", infop->dl_mac_type);
goto bad;
}
#ifdef DLIOCRAW
/*
** This is a non standard SunOS hack to get the ethernet header.
*/
if (strioctl(p->fd, DLIOCRAW, 0, NULL) < 0) {
sprintf(ebuf, "DLIOCRAW: %s", pcap_strerror(errno));
goto bad;
}
#endif
/*
** Another non standard call to get the data nicely buffered
*/
if (ioctl(p->fd, I_PUSH, "bufmod") != 0) {
sprintf(ebuf, "I_PUSH bufmod: %s", pcap_strerror(errno));
goto bad;
}
/*
** Now that the bufmod is pushed lets configure it.
**
** There is a bug in bufmod(7). When dealing with messages of
** less than snaplen size it strips data from the beginning not
** the end.
**
** This bug is supposed to be fixed in 5.3.2. Also, there is a
** patch available. Ask for bugid 1149065.
*/
ss = snaplen;
#ifdef SOLARIS
release = getrelease(&osmajor, &osminor, &osmicro);
if (osmajor == 5 && (osminor <= 2 || (osminor == 3 && osmicro < 2)) &&
getenv("BUFMOD_FIXED") == NULL) {
fprintf(stderr,
"WARNING: bufmod is broken in SunOS %s; ignoring snaplen.\n",
release);
ss = 0;
}
#endif
if (ss > 0 &&
strioctl(p->fd, SBIOCSSNAP, sizeof(u_long), (char *)&ss) != 0) {
sprintf(ebuf, "SBIOCSSNAP: %s", pcap_strerror(errno));
goto bad;
}
/*
** Set up the bufmod flags
*/
if (strioctl(p->fd, SBIOCGFLAGS, sizeof(u_long), (char *)&flag) < 0) {
sprintf(ebuf, "SBIOCGFLAGS: %s", pcap_strerror(errno));
goto bad;
}
flag |= SB_NO_DROPS;
if (strioctl(p->fd, SBIOCSFLAGS, sizeof(u_long), (char *)&flag) != 0) {
sprintf(ebuf, "SBIOCSFLAGS: %s", pcap_strerror(errno));
goto bad;
}
/*
** Set up the bufmod timeout
*/
if (to_ms != 0) {
struct timeval to;
to.tv_sec = to_ms / 1000;
to.tv_usec = (to_ms * 1000) % 1000000;
if (strioctl(p->fd, SBIOCSTIME, sizeof(to), (char *)&to) != 0) {
sprintf(ebuf, "SBIOCSTIME: %s", pcap_strerror(errno));
goto bad;
}
}
/*
** As the last operation flush the read side.
*/
if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) {
sprintf(ebuf, "FLUSHR: %s", pcap_strerror(errno));
goto bad;
}
/* Allocate data buffer */
p->bufsize = MAXDLBUF * sizeof(long);
p->buffer = (u_char *)malloc(p->bufsize);
return (p);
bad:
free(p);
return (NULL);
}
int
pcap_setfilter(pcap_t *p, struct bpf_program *fp)
{
p->fcode = *fp;
return (0);
}
static int
send_request(int fd, char *ptr, int len, char *what, char *ebuf)
{
struct strbuf ctl;
int flags;
ctl.maxlen = 0;
ctl.len = len;
ctl.buf = ptr;
flags = 0;
if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0) {
sprintf(ebuf, "putmsg \"%s\"failed: %s",
what, pcap_strerror(errno));
return (-1);
}
return (0);
}
static int
dlattachreq(int fd, u_long ppa, char *ebuf)
{
dl_attach_req_t req;
req.dl_primitive = DL_ATTACH_REQ;
req.dl_ppa = ppa;
return (send_request(fd, (char *)&req, sizeof(req), "attach", ebuf));
}
static int
dlpromisconreq(int fd, u_long level, char *ebuf)
{
dl_promiscon_req_t req;
req.dl_primitive = DL_PROMISCON_REQ;
req.dl_level = level;
return (send_request(fd, (char *)&req, sizeof(req), "promiscon", ebuf));
}
static int
dlokack(int fd, char *bufp, char *ebuf)
{
union DL_primitives *dlp;
struct strbuf ctl;
int flags;
ctl.maxlen = MAXDLBUF;
ctl.len = 0;
ctl.buf = bufp;
flags = 0;
if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0) {
sprintf(ebuf, "getmsg: %s", pcap_strerror(errno));
return (-1);
}
dlp = (union DL_primitives *) ctl.buf;
if (dlp->dl_primitive != DL_OK_ACK) {
sprintf(ebuf, "dlokack unexpected primitive %d",
dlp->dl_primitive);
return (-1);
}
if (ctl.len != sizeof(dl_ok_ack_t)) {
sprintf(ebuf, "dlokack incorrect size returned");
return (-1);
}
return (0);
}
static int
dlinforeq(int fd, char *ebuf)
{
dl_info_req_t req;
req.dl_primitive = DL_INFO_REQ;
return (send_request(fd, (char *)&req, sizeof(req), "info", ebuf));
}
static int
dlinfoack(int fd, char *bufp, char *ebuf)
{
union DL_primitives *dlp;
struct strbuf ctl;
int flags;
ctl.maxlen = MAXDLBUF;
ctl.len = 0;
ctl.buf = bufp;
flags = 0;
if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) {
sprintf(ebuf, "dlinfoack: getmsg: %s", pcap_strerror(errno));
return (-1);
}
dlp = (union DL_primitives *) ctl.buf;
if (dlp->dl_primitive != DL_INFO_ACK) {
sprintf(ebuf, "dlinfoack: unexpected primitive %ld",
dlp->dl_primitive);
return (-1);
}
/* Extra stuff like the broadcast address can be returned */
if (ctl.len < DL_INFO_ACK_SIZE) {
sprintf(ebuf, "dlinfoack: incorrect size returned");
return (-1);
}
return (0);
}
static int
strioctl(int fd, int cmd, int len, char *dp)
{
struct strioctl str;
int rc;
str.ic_cmd = cmd;
str.ic_timout = -1;
str.ic_len = len;
str.ic_dp = dp;
rc = ioctl(fd, I_STR, &str);
if (rc < 0)
return (rc);
else
return (str.ic_len);
}
#ifdef SOLARIS
static char *
getrelease(long *majorp, long *minorp, long *microp)
{
char *cp;
static char buf[32];
*majorp = 0;
*minorp = 0;
*microp = 0;
if (sysinfo(SI_RELEASE, buf, sizeof(buf)) < 0)
return ("?");
cp = buf;
if (!isdigit(*cp))
return (buf);
*majorp = strtol(cp, &cp, 10);
if (*cp++ != '.')
return (buf);
*minorp = strtol(cp, &cp, 10);
if (*cp++ != '.')
return (buf);
*microp = strtol(cp, &cp, 10);
return (buf);
}
#endif

227
lib/libpcap/pcap-enet.c Normal file
View File

@ -0,0 +1,227 @@
/*
* Stanford Enetfilter subroutines for tcpdump
*
* Based on the MERIT NNstat etherifrt.c and the Ultrix pcap-pf.c
* subroutines.
*
* Rayan Zachariassen, CA*Net
*/
#include <sys/types.h>
#include <sys/time.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/bpf.h>
#include <net/enet.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <stdio.h>
#include <errno.h>
#include "interface.h"
struct packet_header {
#ifdef IBMRTPC
struct LengthWords length;
struct tap_header tap;
#endif /* IBMRTPC */
u_char packet[8]
};
extern int errno;
#define BUFSPACE (4*1024)
/* Forwards */
static void efReadError(int, char *);
void
readloop(int cnt, int if_fd, struct bpf_program *fp, printfunc printit)
{
#ifdef IBMRTPC
register struct packet_header *ph;
register u_char *bp;
register int inc;
#else /* !IBMRTPC */
static struct timeval tv = { 0 };
#endif /* IBMRTPC */
register int cc, caplen;
register struct bpf_insn *fcode = fp->bf_insns;
union {
struct packet_header hdr;
u_char p[BUFSPACE];
u_short s;
} buf;
while (1) {
if ((cc = read(if_fd, (char *)buf.p, sizeof(buf))) < 0)
efReadError(if_fd, "reader");
#ifdef IBMRTPC
/*
* Loop through each packet.
*/
bp = buf.p;
while (cc > 0) {
ph = (struct packet_header *)bp;
caplen = ph->tap.th_wirelen > snaplen ? snaplen : ph->tap
.th_wirelen ;
if (bpf_filter(fcode, (char *)ph->packet,
ph->tap.th_wirelen, caplen)) {
if (cnt >= 0 && --cnt < 0)
goto out;
(*printit)((char *)ph->packet,
(struct timeval *)ph->tap.th_timestamp,
ph->tap.th_wirelen, caplen);
}
inc = ph->length.PacketOffset;
cc -= inc;
bp += inc;
}
#else /* !IBMRTPC */
caplen = cc > snaplen ? snaplen : cc ;
if (bpf_filter(fcode, buf.hdr.packet, cc, caplen)) {
if (cnt >= 0 && --cnt < 0)
goto out;
(*printit)(buf.hdr.packet, &tv, cc, caplen);
}
#endif /* IBMRTPC */
}
out:
wrapup(if_fd);
}
/* Call ONLY if read() has returned an error on packet filter */
static void
efReadError(int fid, char *msg)
{
if (errno == EINVAL) { /* read MAXINT bytes already! */
if (lseek(fid, 0, 0) < 0) {
perror("tcpdump: efReadError/lseek");
exit(-1);
}
else
return;
}
else {
(void) fprintf(stderr, "tcpdump: ");
perror(msg);
exit(-1);
}
}
void
wrapup(int fd)
{
#ifdef IBMRTPC
struct enstats es;
if (ioctl(fd, EIOSTATS, &es) == -1) {
perror("tcpdump: enet ioctl EIOSTATS error");
exit(-1);
}
fprintf(stderr, "%d packets queued", es.enStat_Rcnt);
if (es.enStat_Rdrops > 0)
fprintf(stderr, ", %d dropped", es.enStat_Rdrops);
if (es.enStat_Reads > 0)
fprintf(stderr, ", %d tcpdump %s", es.enStat_Reads,
es.enStat_Reads > 1 ? "reads" : "read");
if (es.enStat_MaxRead > 1)
fprintf(stderr, ", %d packets in largest read",
es.enStat_MaxRead);
putc('\n', stderr);
#endif /* IBMRTPC */
close(fd);
}
int
initdevice(char *device, int pflag, int *linktype)
{
struct eniocb ctl;
struct enfilter filter;
u_int maxwaiting;
int if_fd;
#ifdef IBMRTPC
GETENETDEVICE(0, O_RDONLY, &if_fd);
#else /* !IBMRTPC */
if_fd = open("/dev/enet", O_RDONLY, 0);
#endif /* IBMRTPC */
if (if_fd == -1) {
perror("tcpdump: enet open error");
error(
"your system may not be properly configured; see \"man enet(4)\"");
exit(-1);
}
/* Get operating parameters. */
if (ioctl(if_fd, EIOCGETP, (char *)&ctl) == -1) {
perror("tcpdump: enet ioctl EIOCGETP error");
exit(-1);
}
/* Set operating parameters. */
#ifdef IBMRTPC
ctl.en_rtout = 1 * ctl.en_hz;
ctl.en_tr_etherhead = 1;
ctl.en_tap_network = 1;
ctl.en_multi_packet = 1;
ctl.en_maxlen = BUFSPACE;
#else /* !IBMRTPC */
ctl.en_rtout = 64; /* randomly picked value for HZ */
#endif /* IBMRTPC */
if (ioctl(if_fd, EIOCSETP, &ctl) == -1) {
perror("tcpdump: enet ioctl EIOCSETP error");
exit(-1);
}
/* Flush the receive queue, since we've changed
the operating parameters and we otherwise might
receive data without headers. */
if (ioctl(if_fd, EIOCFLUSH) == -1) {
perror("tcpdump: enet ioctl EIOCFLUSH error");
exit(-1);
}
/* Set the receive queue depth to its maximum. */
maxwaiting = ctl.en_maxwaiting;
if (ioctl(if_fd, EIOCSETW, &maxwaiting) == -1) {
perror("tcpdump: enet ioctl EIOCSETW error");
exit(-1);
}
#ifdef IBMRTPC
/* Clear statistics. */
if (ioctl(if_fd, EIOCLRSTAT, 0) == -1) {
perror("tcpdump: enet ioctl EIOCLRSTAT error");
exit(-1);
}
#endif /* IBMRTPC */
/* Set the filter (accept all packets). */
filter.enf_Priority = 3;
filter.enf_FilterLen = 0;
if (ioctl(if_fd, EIOCSETF, &filter) == -1) {
perror("tcpdump: enet ioctl EIOCSETF error");
exit(-1);
}
/*
* "enetfilter" supports only ethernets.
*/
*linktype = DLT_EN10MB;
return(if_fd);
}

98
lib/libpcap/pcap-int.h Normal file
View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the Computer Systems
* Engineering Group at Lawrence Berkeley Laboratory.
* 4. Neither the name of the University nor of the Laboratory may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#) $Header: pcap-int.h,v 1.7 94/06/14 20:03:33 leres Exp $ (LBL)
*/
#ifndef pcap_int_h
#define pcap_int_h
#include <pcap.h>
/*
* Savefile
*/
struct pcap_sf {
FILE *rfile;
int swapped;
int version_major;
int version_minor;
u_char *base;
};
struct pcap_md {
struct pcap_stat stat;
#ifdef PCAP_PF
int use_bpf;
u_long TotPkts; /* can't oflow for 79 hrs on ether */
u_long TotAccepted; /* count accepted by filter */
u_long TotDrops; /* count of dropped packets */
long TotMissed; /* missed by i/f during this run */
long OrigMissed; /* missed by i/f before this run */
#endif
};
struct pcap {
int fd;
int snapshot;
int linktype;
int tzoff; /* timezone offset */
struct pcap_sf sf;
struct pcap_md md;
/*
* Read buffer.
*/
int bufsize;
u_char *buffer;
u_char *bp;
int cc;
/*
* Place holder for pcap_next().
*/
u_char *pkt;
/*
* Placeholder for filter code if bpf not in kernel.
*/
struct bpf_program fcode;
char errbuf[PCAP_ERRBUF_SIZE];
};
/* XXX should these be in pcap.h? */
int pcap_offline_read(pcap_t *, int, pcap_handler, u_char *);
int pcap_read(pcap_t *, int cnt, pcap_handler, u_char *);
#endif

76
lib/libpcap/pcap-namedb.h Normal file
View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the Computer Systems
* Engineering Group at Lawrence Berkeley Laboratory.
* 4. Neither the name of the University nor of the Laboratory may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#) $Header: pcap-namedb.h,v 1.2 94/06/14 20:03:34 leres Exp $ (LBL)
*/
#ifndef lib_pcap_ethers_h
#define lib_pcap_ethers_h
/*
* As returned by the pcap_next_etherent()
* XXX this stuff doesn't belong in this inteface, but this
* library already must do name to address translation, so
* on systems that don't have support for /etc/ethers, we
* export these hooks since they'll
*/
struct pcap_etherent {
u_char addr[6];
char name[122];
};
#ifndef PCAP_ETHERS_FILE
#define PCAP_ETHERS_FILE "/etc/ethers"
#endif
struct pcap_etherent *pcap_next_etherent(FILE *);
u_char *pcap_ether_hostton(const char*);
u_char *pcap_ether_aton(const char *);
u_long **pcap_nametoaddr(const char *);
u_long pcap_nametonetaddr(const char *);
int pcap_nametoport(const char *, int *, int *);
int pcap_nametoproto(const char *);
int pcap_nametoeproto(const char *);
/*
* If a protocol is unknown, PROTO_UNDEF is returned.
* Also, pcap_nametoport() returns the protocol along with the port number.
* If there are ambiguous entried in /etc/services (i.e. domain
* can be either tcp or udp) PROTO_UNDEF is returned.
*/
#define PROTO_UNDEF -1
/* XXX move these to pcap-int.h? */
u_long __pcap_atodn(const char *);
u_long __pcap_atoin(const char *);
u_short __pcap_nametodnaddr(const char *);
#endif

240
lib/libpcap/pcap-nit.c Normal file
View File

@ -0,0 +1,240 @@
/*
* Copyright (c) 1990, 1991, 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the University of California,
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef lint
static char rcsid[] =
"@(#)$Header: pcap-nit.c,v 1.24 94/02/10 23:02:37 leres Exp $ (LBL)";
#endif
#include <sys/types.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/nit.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <netinet/ip_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include "pcap-int.h"
/*
* The chunk size for NIT. This is the amount of buffering
* done for read calls.
*/
#define CHUNKSIZE (2*1024)
/*
* The total buffer space used by NIT.
*/
#define BUFSPACE (4*CHUNKSIZE)
/* Forwards */
static int nit_setflags(int, int, int, char *);
int
pcap_stats(pcap_t *p, struct pcap_stat *ps)
{
*ps = p->md.stat;
return (0);
}
int
pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
register int cc, n;
register struct bpf_insn *fcode = p->fcode.bf_insns;
register u_char *bp, *cp, *ep;
register struct nit_hdr *nh;
register int caplen;
cc = p->cc;
if (cc == 0) {
cc = read(p->fd, (char *)p->buffer, p->bufsize);
if (cc < 0) {
if (errno == EWOULDBLOCK)
return (0);
sprintf(p->errbuf, "pcap_read: %s",
pcap_strerror(errno));
return (-1);
}
bp = p->buffer;
} else
bp = p->bp;
/*
* Loop through each packet. The increment expression
* rounds up to the next int boundary past the end of
* the previous packet.
*/
n = 0;
ep = bp + cc;
while (bp < ep) {
nh = (struct nit_hdr *)bp;
cp = bp + sizeof(*nh);
switch (nh->nh_state) {
case NIT_CATCH:
break;
case NIT_NOMBUF:
case NIT_NOCLUSTER:
case NIT_NOSPACE:
p->md.stat.ps_drop = nh->nh_dropped;
continue;
case NIT_SEQNO:
continue;
default:
sprintf(p->errbuf, "bad nit state %d", nh->nh_state);
return (-1);
}
++p->md.stat.ps_recv;
bp += ((sizeof(struct nit_hdr) + nh->nh_datalen +
sizeof(int) - 1) & ~(sizeof(int) - 1));
caplen = nh->nh_wirelen;
if (caplen > p->snapshot)
caplen = p->snapshot;
if (bpf_filter(fcode, cp, nh->nh_wirelen, caplen)) {
struct pcap_pkthdr h;
h.ts = nh->nh_timestamp;
h.len = nh->nh_wirelen;
h.caplen = caplen;
(*callback)(user, &h, cp);
if (++n >= cnt && cnt >= 0) {
p->cc = ep - bp;
p->bp = bp;
return (n);
}
}
}
p->cc = 0;
return (n);
}
static int
nit_setflags(int fd, int promisc, int to_ms, char *ebuf)
{
struct nit_ioc nioc;
bzero((char *)&nioc, sizeof(nioc));
nioc.nioc_bufspace = BUFSPACE;
nioc.nioc_chunksize = CHUNKSIZE;
nioc.nioc_typetomatch = NT_ALLTYPES;
nioc.nioc_snaplen = p->snapshot;
nioc.nioc_bufalign = sizeof(int);
nioc.nioc_bufoffset = 0;
if (to_ms != 0) {
nioc.nioc_flags |= NF_TIMEOUT;
nioc.nioc_timeout.tv_sec = to_ms / 1000;
nioc.nioc_timeout.tv_usec = (to_ms * 1000) % 1000000;
}
if (promisc)
nioc.nioc_flags |= NF_PROMISC;
if (ioctl(fd, SIOCSNIT, &nioc) < 0) {
sprintf(ebuf, "SIOCSNIT: %s", pcap_strerror(errno));
return (-1);
}
return (0);
}
pcap_t *
pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
{
int fd;
struct sockaddr_nit snit;
register pcap_t *p;
p = (pcap_t *)malloc(sizeof(*p));
if (p == NULL) {
strcpy(ebuf, pcap_strerror(errno));
return (NULL);
}
if (snaplen < 96)
/*
* NIT requires a snapshot length of at least 96.
*/
snaplen = 96;
bzero(p, sizeof(*p));
p->fd = fd = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW);
if (fd < 0) {
sprintf(ebuf, "socket: %s", pcap_strerror(errno));
goto bad;
}
snit.snit_family = AF_NIT;
(void)strncpy(snit.snit_ifname, device, NITIFSIZ);
if (bind(fd, (struct sockaddr *)&snit, sizeof(snit))) {
sprintf(ebuf, "bind: %s: %s", snit.snit_ifname,
pcap_strerror(errno));
goto bad;
}
p->snapshot = snaplen;
nit_setflags(p->fd, promisc, to_ms, ebuf);
/*
* NIT supports only ethernets.
*/
p->linktype = DLT_EN10MB;
p->bufsize = BUFSPACE;
p->buffer = (u_char *)malloc(p->bufsize);
if (p->buffer == NULL) {
strcpy(ebuf, pcap_strerror(errno));
goto bad;
}
return (p);
bad:
if (fd >= 0)
close(fd);
free(p);
return (NULL);
}
int
pcap_setfilter(pcap_t *p, struct bpf_program *fp)
{
p->fcode = *fp;
return (0);
}

19
lib/libpcap/pcap-nit.h Normal file
View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 1990, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Lawrence Berkeley Laboratory,
* Berkeley, CA. The name of the University may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* @(#) $Header: pcap-nit.h,v 1.2 94/06/14 20:06:03 leres Exp $ (LBL)
*/

310
lib/libpcap/pcap-pf.c Normal file
View File

@ -0,0 +1,310 @@
/*
* Copyright (c) 1990, 1991, 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the University of California,
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef lint
static char rcsid[] =
"@(#)$Header: pcap-pf.c,v 1.32 94/06/10 17:41:01 mccanne Exp $ (LBL)";
#endif
/*
* packet filter subroutines for tcpdump
* Extraction/creation by Jeffrey Mogul, DECWRL
*
* Extracted from tcpdump.c.
*/
#include <sys/types.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <net/pfilt.h>
#include <net/if.h>
#include <net/bpf.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <netinet/ip_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#include <ctype.h>
#include <errno.h>
#include <netdb.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "pcap-int.h"
/*
* BUFSPACE is the size in bytes of the packet read buffer. Most tcpdump
* applications aren't going to need more than 200 bytes of packet header
* and the read shouldn't return more packets than packetfilter's internal
* queue limit (bounded at 256).
*/
#define BUFSPACE (200*256)
int
pcap_read(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
{
u_char *p;
struct bpf_insn *fcode;
int cc;
register u_char *bp;
int buflen, inc;
struct enstamp stamp;
int n;
fcode = pc->md.use_bpf ? 0 : pc->fcode.bf_insns;
again:
cc = pc->cc;
if (cc == 0) {
cc = read(pc->fd, (char *)pc->buffer, pc->bufsize);
if (cc < 0) {
if (errno == EWOULDBLOCK)
return (0);
if (errno == EINVAL &&
(long)(tell(pc->fd) + pc->bufsize) < 0) {
/*
* Due to a kernel bug, after 2^31 bytes,
* the kernel file offset overflows and
* read fails with EINVAL. The lseek()
* to 0 will fix things.
*/
(void)lseek(pc->fd, 0L, 0);
goto again;
}
sprintf(pc->errbuf, "pf read: %s",
pcap_strerror(errno));
return (-1);
}
bp = pc->buffer;
} else
bp = pc->bp;
/*
* Loop through each packet.
*/
n = 0;
while (cc > 0) {
/* avoid alignment issues here */
bcopy((char *)bp, (char *)&stamp, sizeof(stamp));
if (stamp.ens_stamplen != sizeof(stamp))
/* buffer is garbage, treat it as poison */
break;
p = bp + stamp.ens_stamplen;
buflen = stamp.ens_count;
if (buflen > pc->snapshot)
buflen = pc->snapshot;
/*
* Short-circuit evaluation: if using BPF filter
* in kernel, no need to do it now.
*/
if (fcode == 0 ||
bpf_filter(fcode, p, stamp.ens_count, buflen)) {
struct pcap_pkthdr h;
pc->md.TotAccepted++;
h.ts = stamp.ens_tstamp;
h.len = stamp.ens_count;
h.caplen = buflen;
(*callback)(user, &h, p);
if (++n >= cnt && cnt > 0) {
inc = ENALIGN(buflen + stamp.ens_stamplen);
cc -= inc;
bp += inc;
pc->cc = cc;
pc->bp = bp;
return (n);
}
}
pc->md.TotPkts++;
pc->md.TotDrops += stamp.ens_dropped;
pc->md.TotMissed = stamp.ens_ifoverflows;
if (pc->md.OrigMissed < 0)
pc->md.OrigMissed = pc->md.TotMissed;
inc = ENALIGN(buflen + stamp.ens_stamplen);
cc -= inc;
bp += inc;
}
pc->cc = 0;
return (n);
}
int
pcap_stats(pcap_t *p, struct pcap_stat *ps)
{
ps->ps_recv = p->md.TotAccepted;
ps->ps_drop = p->md.TotDrops;
ps->ps_ifdrop = p->md.TotMissed - p->md.OrigMissed;
return (0);
}
pcap_t *
pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
{
pcap_t *p;
short enmode;
int backlog = -1; /* request the most */
struct enfilter Filter;
struct endevp devparams;
p = (pcap_t *)malloc(sizeof(*p));
if (p == 0) {
strcpy(ebuf, "no swap");
return (0);
}
bzero(p, sizeof(*p));
p->fd = pfopen(device, 0);
if (p->fd < 0) {
sprintf(ebuf, "pf open: %s: %s\n\
your system may not be properly configured; see \"man packetfilter(4)\"\n",
device, pcap_strerror(errno));
goto bad;
}
p->md.OrigMissed = -1;
enmode = ENTSTAMP|ENBATCH|ENNONEXCL;
if (promisc)
enmode |= ENPROMISC;
if (ioctl(p->fd, EIOCMBIS, (caddr_t)&enmode) < 0) {
sprintf(ebuf, "EIOCMBIS: %s", pcap_strerror(errno));
goto bad;
}
#ifdef ENCOPYALL
/* Try to set COPYALL mode so that we see packets to ourself */
enmode = ENCOPYALL;
(void)ioctl(p->fd, EIOCMBIS, (caddr_t)&enmode);/* OK if this fails */
#endif
/* set the backlog */
if (ioctl(p->fd, EIOCSETW, (caddr_t)&backlog) < 0) {
sprintf(ebuf, "EIOCSETW: %s", pcap_strerror(errno));
goto bad;
}
/* set truncation */
if (ioctl(p->fd, EIOCTRUNCATE, (caddr_t)&snaplen) < 0) {
sprintf(ebuf, "EIOCTRUNCATE: %s", pcap_strerror(errno));
goto bad;
}
p->snapshot = snaplen;
/* accept all packets */
Filter.enf_Priority = 37; /* anything > 2 */
Filter.enf_FilterLen = 0; /* means "always true" */
if (ioctl(p->fd, EIOCSETF, (caddr_t)&Filter) < 0) {
sprintf(ebuf, "EIOCSETF: %s", pcap_strerror(errno));
goto bad;
}
/* discover interface type */
if (ioctl(p->fd, EIOCDEVP, (caddr_t)&devparams) < 0) {
sprintf(ebuf, "EIOCDEVP: %s", pcap_strerror(errno));
goto bad;
}
/* HACK: to compile prior to Ultrix 4.2 */
#ifndef ENDT_FDDI
#define ENDT_FDDI 4
#endif
switch (devparams.end_dev_type) {
case ENDT_10MB:
p->linktype = DLT_EN10MB;
break;
case ENDT_FDDI:
p->linktype = DLT_FDDI;
break;
default:
/*
* XXX
* Currently, the Ultrix packet filter supports only
* Ethernet and FDDI. Eventually, support for SLIP and PPP
* (and possibly others: T1?) should be added.
*/
#ifdef notdef
warning(
"Packet filter data-link type %d unknown, assuming Ethernet",
devparams.end_dev_type);
#endif
p->linktype = DLT_EN10MB;
break;
}
if (to_ms != 0) {
struct timeval timeout;
timeout.tv_sec = to_ms / 1000;
timeout.tv_usec = (to_ms * 1000) % 1000000;
if (ioctl(p->fd, EIOCSRTIMEOUT, (caddr_t)&timeout) < 0) {
sprintf(ebuf, "EIOCSRTIMEOUT: %s",
pcap_strerror(errno));
goto bad;
}
}
p->bufsize = BUFSPACE;
p->buffer = (u_char*)malloc(p->bufsize);
return (p);
bad:
free(p);
return (0);
}
int
pcap_setfilter(pcap_t *p, struct bpf_program *fp)
{
/*
* See if BIOCSETF works. If it does, the kernel supports
* BPF-style filters, and we do not need to do post-filtering.
*/
p->md.use_bpf = (ioctl(p->fd, BIOCSETF, (caddr_t)fp) >= 0);
if (p->md.use_bpf) {
struct bpf_version bv;
if (ioctl(p->fd, BIOCVERSION, (caddr_t)&bv) < 0) {
sprintf(p->errbuf, "BIOCVERSION: %s",
pcap_strerror(errno));
return (-1);
}
else if (bv.bv_major != BPF_MAJOR_VERSION ||
bv.bv_minor < BPF_MINOR_VERSION) {
fprintf(stderr,
"requires bpf language %d.%d or higher; kernel is %d.%d",
BPF_MAJOR_VERSION, BPF_MINOR_VERSION,
bv.bv_major, bv.bv_minor);
/* don't give up, just be inefficient */
p->md.use_bpf = 0;
}
} else
p->fcode = *fp;
/*XXX this goes in tcpdump*/
if (p->md.use_bpf)
fprintf(stderr, "tcpdump: Using kernel BPF filter\n");
else
fprintf(stderr, "tcpdump: Filtering in user process\n");
return (0);
}

19
lib/libpcap/pcap-pf.h Normal file
View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 1990, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Lawrence Berkeley Laboratory,
* Berkeley, CA. The name of the University may not be used to
* endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*
* @(#) $Header: pcap-pf.h,v 1.2 94/06/14 20:06:33 leres Exp $ (LBL)
*/

293
lib/libpcap/pcap-snit.c Normal file
View File

@ -0,0 +1,293 @@
/*
* Copyright (c) 1990, 1991, 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the University of California,
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef lint
static char rcsid[] =
"@(#)$Header: pcap-snit.c,v 1.33 94/06/23 13:51:17 leres Exp $ (LBL)";
#endif
/*
* Modifications made to accomodate the new SunOS4.0 NIT facility by
* Micky Liu, micky@cunixc.cc.columbia.edu, Columbia University in May, 1989.
* This module now handles the STREAMS based NIT.
*/
#include <sys/types.h>
#include <sys/time.h>
#include <sys/timeb.h>
#include <sys/dir.h>
#include <sys/fcntlcom.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stropts.h>
#include <net/bpf.h>
#include <net/if.h>
#include <net/nit.h>
#include <net/nit_if.h>
#include <net/nit_pf.h>
#include <net/nit_buf.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <netinet/ip_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include "pcap-int.h"
/*
* The chunk size for NIT. This is the amount of buffering
* done for read calls.
*/
#define CHUNKSIZE (2*1024)
/*
* The total buffer space used by NIT.
*/
#define BUFSPACE (4*CHUNKSIZE)
/* Forwards */
static int nit_setflags(int, int, int, char *);
int
pcap_stats(pcap_t *p, struct pcap_stat *ps)
{
*ps = p->md.stat;
return (0);
}
int
pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
register int cc, n;
register struct bpf_insn *fcode = p->fcode.bf_insns;
register u_char *bp, *cp, *ep;
register struct nit_bufhdr *hdrp;
register struct nit_iftime *ntp;
register struct nit_iflen *nlp;
register struct nit_ifdrops *ndp;
register int caplen;
cc = p->cc;
if (cc == 0) {
cc = read(p->fd, (char *)p->buffer, p->bufsize);
if (cc < 0) {
if (errno == EWOULDBLOCK)
return (0);
sprintf(p->errbuf, "pcap_read: %s",
pcap_strerror(errno));
return (-1);
}
bp = p->buffer;
} else
bp = p->bp;
/*
* loop through each snapshot in the chunk
*/
n = 0;
ep = bp + cc;
while (bp < ep) {
++p->md.stat.ps_recv;
cp = bp;
/* get past NIT buffer */
hdrp = (struct nit_bufhdr *)cp;
cp += sizeof(*hdrp);
/* get past NIT timer */
ntp = (struct nit_iftime *)cp;
cp += sizeof(*ntp);
ndp = (struct nit_ifdrops *)cp;
p->md.stat.ps_drop = ndp->nh_drops;
cp += sizeof *ndp;
/* get past packet len */
nlp = (struct nit_iflen *)cp;
cp += sizeof(*nlp);
/* next snapshot */
bp += hdrp->nhb_totlen;
caplen = nlp->nh_pktlen;
if (caplen > p->snapshot)
caplen = p->snapshot;
if (bpf_filter(fcode, cp, nlp->nh_pktlen, caplen)) {
struct pcap_pkthdr h;
h.ts = ntp->nh_timestamp;
h.len = nlp->nh_pktlen;
h.caplen = caplen;
(*callback)(user, &h, cp);
if (++n >= cnt && cnt >= 0) {
p->cc = ep - bp;
p->bp = bp;
return (n);
}
}
}
p->cc = 0;
return (n);
}
static int
nit_setflags(int fd, int promisc, int to_ms, char *ebuf)
{
u_long flags;
struct strioctl si;
struct timeval timeout;
si.ic_timout = INFTIM;
if (to_ms != 0) {
timeout.tv_sec = to_ms / 1000;
timeout.tv_usec = (to_ms * 1000) % 1000000;
si.ic_cmd = NIOCSTIME;
si.ic_len = sizeof(timeout);
si.ic_dp = (char *)&timeout;
if (ioctl(fd, I_STR, (char *)&si) < 0) {
sprintf(ebuf, "NIOCSTIME: %s", pcap_strerror(errno));
return (-1);
}
}
flags = NI_TIMESTAMP | NI_LEN | NI_DROPS;
if (promisc)
flags |= NI_PROMISC;
si.ic_cmd = NIOCSFLAGS;
si.ic_len = sizeof(flags);
si.ic_dp = (char *)&flags;
if (ioctl(fd, I_STR, (char *)&si) < 0) {
sprintf(ebuf, "NIOCSFLAGS: %s", pcap_strerror(errno));
return (-1);
}
return (0);
}
pcap_t *
pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
{
struct strioctl si; /* struct for ioctl() */
struct ifreq ifr; /* interface request struct */
int chunksize = CHUNKSIZE;
int fd;
static char dev[] = "/dev/nit";
register pcap_t *p;
p = (pcap_t *)malloc(sizeof(*p));
if (p == NULL) {
strcpy(ebuf, pcap_strerror(errno));
return (NULL);
}
if (snaplen < 96)
/*
* NIT requires a snapshot length of at least 96.
*/
snaplen = 96;
bzero(p, sizeof(*p));
p->fd = fd = open(dev, O_RDONLY);
if (fd < 0) {
sprintf(ebuf, "%s: %s", dev, pcap_strerror(errno));
goto bad;
}
/* arrange to get discrete messages from the STREAM and use NIT_BUF */
if (ioctl(fd, I_SRDOPT, (char *)RMSGD) < 0) {
sprintf(ebuf, "I_SRDOPT: %s", pcap_strerror(errno));
goto bad;
}
if (ioctl(fd, I_PUSH, "nbuf") < 0) {
sprintf(ebuf, "push nbuf: %s", pcap_strerror(errno));
goto bad;
}
/* set the chunksize */
si.ic_cmd = NIOCSCHUNK;
si.ic_timout = INFTIM;
si.ic_len = sizeof(chunksize);
si.ic_dp = (char *)&chunksize;
if (ioctl(fd, I_STR, (char *)&si) < 0) {
sprintf(ebuf, "NIOCSCHUNK: %s", pcap_strerror(errno));
goto bad;
}
/* request the interface */
strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = ' ';
si.ic_cmd = NIOCBIND;
si.ic_len = sizeof(ifr);
si.ic_dp = (char *)&ifr;
if (ioctl(fd, I_STR, (char *)&si) < 0) {
sprintf(ebuf, "NIOCBIND: %s: %s",
ifr.ifr_name, pcap_strerror(errno));
goto bad;
}
/* set the snapshot length */
si.ic_cmd = NIOCSSNAP;
si.ic_len = sizeof(snaplen);
si.ic_dp = (char *)&snaplen;
if (ioctl(fd, I_STR, (char *)&si) < 0) {
sprintf(ebuf, "NIOCSSNAP: %s", pcap_strerror(errno));
goto bad;
}
p->snapshot = snaplen;
if (nit_setflags(p->fd, promisc, to_ms, ebuf) < 0)
goto bad;
(void)ioctl(fd, I_FLUSH, (char *)FLUSHR);
/*
* NIT supports only ethernets.
*/
p->linktype = DLT_EN10MB;
p->bufsize = BUFSPACE;
p->buffer = (u_char *)malloc(p->bufsize);
if (p->buffer == NULL) {
strcpy(ebuf, pcap_strerror(errno));
goto bad;
}
return (p);
bad:
if (fd >= 0)
close(fd);
free(p);
return (NULL);
}
int
pcap_setfilter(pcap_t *p, struct bpf_program *fp)
{
p->fcode = *fp;
return (0);
}

195
lib/libpcap/pcap-snoop.c Normal file
View File

@ -0,0 +1,195 @@
/*
* Copyright (c) 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the University of California,
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef lint
static char rcsid[] =
"@(#)$Header: pcap-snoop.c,v 1.6 94/01/31 05:26:09 leres Exp $ (LBL)";
#endif
#include <sys/param.h>
#include <stdio.h>
#include <netdb.h>
#include <ctype.h>
#include <signal.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <net/raw.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/if_ether.h>
#include <netinet/ip_var.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <netinet/tcp.h>
#include <netinet/tcpip.h>
#include <net/bpf.h>
#include "pcap-int.h"
static int hdrpad; /* XXX */
int
pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
int cc;
register struct snoopheader *sh;
register int datalen;
register int caplen;
register u_char *cp;
again:
cc = read(p->fd, (char *)p->buffer, p->bufsize);
if (cc < 0) {
switch (errno) {
case EWOULDBLOCK:
return (0); /* XXX */
}
sprintf(p->errbuf, "read: %s", pcap_strerror(errno));
return (-1);
}
sh = (struct snoopheader *)p->buffer;
datalen = sh->snoop_packetlen;
caplen = (datalen < p->snapshot) ? datalen : p->snapshot;
cp = (u_char *)(sh + 1) + hdrpad; /* XXX */
if (p->fcode.bf_insns == NULL ||
bpf_filter(p->fcode.bf_insns, cp, datalen, caplen)) {
struct pcap_pkthdr h;
++p->md.stat.ps_recv;
h.ts = sh->snoop_timestamp;
h.len = datalen;
h.caplen = caplen;
(*callback)(user, &h, cp);
return (1);
}
return (0);
}
int
pcap_stats(pcap_t *p, struct pcap_stat *ps)
{
register struct rawstats *rs;
struct rawstats rawstats;
rs = &rawstats;
bzero((char *)rs, sizeof(*rs));
if (ioctl(p->fd, SIOCRAWSTATS, (char *)rs) < 0) {
sprintf(p->errbuf, "SIOCRAWSTATS: %s", pcap_strerror(errno));
return (-1);
}
p->md.stat.ps_drop =
rs->rs_snoop.ss_ifdrops + rs->rs_snoop.ss_sbdrops +
rs->rs_drain.ds_ifdrops + rs->rs_drain.ds_sbdrops;
*ps = p->md.stat;
return (0);
}
/* XXX can't disable promiscuous */
pcap_t *
pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
{
pcap_t *p;
struct sockaddr_raw sr;
int fd;
int v;
struct snoopfilter sf;
p = (pcap_t *)malloc(sizeof(*p));
if (p == NULL) {
strcpy(ebuf, "no swap");
return (0);
}
bzero(p, sizeof(*p));
p->fd = -1;
p->bufsize = 4096; /* XXX */
p->buffer = (u_char *)malloc(p->bufsize);
if (p->buffer == NULL) {
strcpy(ebuf, "no swap");
goto bad;
}
fd = p->fd = socket(PF_RAW, SOCK_RAW, RAWPROTO_SNOOP);
if (fd < 0) {
sprintf(ebuf, "snoop socket: %s", pcap_strerror(errno));
goto bad;
}
sr.sr_family = AF_RAW;
sr.sr_port = 0;
(void)strncpy(sr.sr_ifname, device, sizeof(sr.sr_ifname));
if (bind(fd, (struct sockaddr *)&sr, sizeof(sr))) {
sprintf(ebuf, "snoop bind: %s", pcap_strerror(errno));
goto bad;
}
bzero((char *)&sf, sizeof(sf));
if (ioctl(fd, SIOCADDSNOOP, &sf) < 0) {
sprintf(ebuf, "SIOCADDSNOOP: %s", pcap_strerror(errno));
goto bad;
}
v = 64 * 1024;
(void)setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&v, sizeof(v));
if (ioctl(fd, SIOCSNOOPLEN, &snaplen) < 0) {
sprintf(ebuf, "SIOCSNOOPLEN: %s", pcap_strerror(errno));
goto bad;
}
p->snapshot = snaplen;
v = 1;
if (ioctl(fd, SIOCSNOOPING, &v) < 0) {
sprintf(ebuf, "SIOCSNOOPING: %s", pcap_strerror(errno));
goto bad;
}
/*
* XXX hack - map device name to link later type
*/
if (strncmp("et", device, 2) == 0 ||
strncmp("ec", device, 2) == 0) {
p->linktype = DLT_EN10MB;
hdrpad = RAW_HDRPAD(sizeof(struct ether_header));
} else if (strncmp("ipg", device, 3) == 0 ||
strncmp("xpi", device, 3) == 0) {
p->linktype = DLT_FDDI;
hdrpad = 3; /* XXX yeah? */
} else {
sprintf(ebuf, "snoop: unknown physical layer type");
goto bad;
}
return (p);
bad:
if (fd >= 0)
close(fd);
if (p->buffer != NULL)
free(p->buffer);
free(p);
return (0);
}
int
pcap_setfilter(pcap_t *p, struct bpf_program *fp)
{
p->fcode = *fp;
return (0);
}

323
lib/libpcap/pcap.3 Normal file
View File

@ -0,0 +1,323 @@
.\" Copyright (c) 1994
.\" The Regents of the University of California. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that: (1) source code distributions
.\" retain the above copyright notice and this paragraph in its entirety, (2)
.\" distributions including binary code include the above copyright notice and
.\" this paragraph in its entirety in the documentation or other materials
.\" provided with the distribution, and (3) all advertising materials mentioning
.\" features or use of this software display the following acknowledgement:
.\" ``This product includes software developed by the University of California,
.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
.\" the University nor the names of its contributors may be used to endorse
.\" or promote products derived from this software without specific prior
.\" written permission.
.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
.\"
.TH PCAP 3 "14 Jun 1994"
.SH NAME
pcap \- Packet Capture library
.SH SYNOPSIS
.nf
.ft B
#include <pcap.h>
.ft
.LP
.ft B
pcap_t *pcap_open_live(char *device, int snaplen,
.ti +8
int promisc, int to_ms, char *ebuf)
pcap_t *pcap_open_offline(char *fname, char *ebuf)
pcap_dumper_t *pcap_dump_open(pcap_t *p, char *fname)
.ft
.LP
.ft B
char errbuf[PCAP_ERRBUF_SIZE];
char *pcap_lookupdev(char *errbuf)
int pcap_lookupnet(char *device, u_long *netp,
.ti +8
u_long *maskp, char *errbuf)
.ft
.LP
.ft B
int pcap_dispatch(pcap_t *p, int cnt,
.ti +8
pcap_handler callback, u_char *user)
int pcap_loop(pcap_t *p, int cnt,
.ti +8
pcap_handler callback, u_char *user)
void pcap_dump(u_char *user, struct pcap_pkthdr *h,
.ti +8
u_char *sp)
.ft
.LP
.ft B
int pcap_immediate(pcap_t *p)
.ft
.LP
.ft B
int pcap_compile(pcap_t *p, struct bpf_program *fp,
.ti +8
char *str, int optimize, u_long netmask)
int pcap_setfilter(pcap_t *p, struct bpf_program *fp)
.ft
.LP
.ft B
u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h)
.ft
.LP
.ft B
int pcap_datalink(pcap_t *p)
int pcap_snapshot(pcap_t *p)
int pcap_is_swapped(pcap_t *p)
int pcap_major_version(pcap_t *p)
int pcap_minor_version(pcap_t *p)
int pcap_stats(pcap_t *p, struct pcap_stat *ps)
FILE *pcap_file(pcap_t *p)
int pcap_fileno(pcap_t *p)
void pcap_perror(pcap_t *p, char *prefix)
char *pcap_geterr(pcap_t *p)
char *pcap_strerror(int error)
.ft
.LP
.ft B
void pcap_close(pcap_t *p)
void pcap_dump_close(pcap_dumper_t *p)
.ft
.fi
.SH DESCRIPTION
The Packet Capture library
provides a high level interface to packet capture systems. All packets
on the network, even those destined for other hosts, are accessible
through this mechanism.
.PP
.SH ROUTINES
.B pcap_open_live()
is used to obtain a packet capture descriptor to look
at packets on the network.
.I device
is a string that specifies the network device to open.
.I snaplen
specifies the maximum number of bytes to capture.
.I to_ms
specifies the read timeout in milliseconds.
.I ebuf
is used to return error text and is only set when
.B pcap_open_live()
fails and returns
.BR NULL .
.PP
.B pcap_open_offline()
is called to open a ``savefile'' for reading.
.I fname
specifies the name of the file to open. The file has
the same format as those used by
.B tcpdump(1)
and
.BR tcpslice(1) .
The name "-" in a synonym for
.BR stdin .
.I ebuf
is used to return error text and is only set when
.B pcap_open_offline()
fails and returns
.BR NULL .
.PP
.B pcap_dump_open()
is called to open a ``savefile'' for writing. The name "-" in a synonym
for
.BR stdin .
.B NULL
is returned on failure.
.I p
is a
.I pcap
struct as returned by
.B pcap_open_offline()
or
.BR pcap_open_live() .
.I fname
specifies the name of the file to open.
If
.B NULL
is returned,
.B pcap_geterr()
can be used to get the error text.
.PP
.B pcap_lookupdev()
returns a pointer to a network device suitable for use with
.B pcap_open_live()
and
.BR pcap_lookupnet() .
If there is an error,
.B NULL
is returned and
.I errbuf
is filled in with with an appropriate error message.
.PP
.B pcap_lookupnet()
is used to determine the network number and mask
associated with the network device
.BR device .
Both
.I netp
and
.I maskp
are
.I u_long
pointers.
A return of -1 indicates an error in which case
.I errbuf
is filled in with with an appropriate error message.
.PP
.B pcap_dispatch()
is used to collect and process packets.
.I cnt
specifies the maximum number of packets to process before returning. A
.I cnt
of -1 processes all the packets received in one buffer. A
.I cnt
of 0 processes all packets until an error occurs (or
.B EOF
is reached).
.I callback
specifies a routine to be called with three arguments:
a
.I u_char
pointer which is passed in from
.BR pcap_dispatch() ,
a pointer to the
.I pcap_pkthdr
struct (which precede the actual network headers and data),
and a length. The number of packets read is returned.
Zero is returned when
.B EOF
is reached in a ``savefile.'' A return of -1 indicates
an error in which case
.B pcap_perror()
or
.BR pcap_geterr()
may be used to display the error text.
.PP
.B pcap_dump()
outputs a packet to the ``savefile'' opened with
.BR pcap_dump_open() .
Note that its calling arguments are suitable for use with
.BR pcap_dispatch() .
.ft B
(??? this guy is kind of weird.)
.ft
.PP
.B pcap_immediate()
sets ``immediate'' mode.
If this isn't supported by the under lying packet capture, -1 is
returned and the error text can be obtained with
.B pcap_perror()
or
.BR pcap_geterr() .
.PP
.B pcap_compile()
is used to compile the string
.I str
into a filter program.
.I program
is a pointer to a
.I bpf_program
struct and is filled in by
.BR pcap_compile() .
.I optimize
controls whether optimization on the resulting code is performed.
.I netmask
specifies the netmask of the local net.
.PP
.B pcap_setfilter()
is used to specify the a filter program.
.I fp
is a pointer to an array of
.I bpf_program
struct, usually the result of a call to
.BR pcap_compile() .
.PP
.B pcap_loop()
is similar to
.B pcap_dispatch()
except it keeps reading packets until
.I cnt
packets are processed or an error occurs.
A negative
.I cnt
causes
.B pcap_loop()
to loop forever (or at least until an error occurs).
.PP
.B pcap_next()
returns a
.I u_char
pointer to the next packet.
.PP
.B pcap_datalink()
returns the link layer type, e.g.
.BR DLT_EN10MB .
.PP
.B pcap_snapshot()
returns the snapshot length specified when
.B pcap_open_live
was called.
.PP
.B pcap_is_swapped()
returns true if the current ``savefile'' uses a different byte order
than the current system.
.PP
.B pcap_major_version()
returns the major number of the version of the pcap used to write the
savefile.
.PP
.B pcap_minor_version()
returns the major number of the version of the pcap used to write the
savefile.
.PP
.B pcap_file()
returns the name of the ``savefile.''
.PP
.B int pcap_stats()
returns 0 and fills in a
.B pcap_stat
struct with packet statistics. If there is an error or the under lying
packet capture doesn't support packet statistics, -1 is returned and
the error text can be obtained with
.B pcap_perror()
or
.BR pcap_geterr() .
.PP
.B pcap_fileno()
returns the file descriptor number of the ``savefile.''
.PP
.B pcap_perror()
prints the text of the last pcap library error on
.BR stderr ,
prefixed by
.IR prefix .
.PP
.B pcap_geterr()
returns the error text pertaining to the last pcap library error.
.PP
.B pcap_strerror()
is provided in case
.BR strerror (1)
isn't available.
.PP
.B pcap_close()
closes the files associated with
.I p
and deallocates resources.
.PP
.B pcap_dump_close()
closes the ``savefile.''
.PP
.SH SEE ALSO
tcpdump(1), tcpslice(1)
.SH BUGS
.SH HISTORY

180
lib/libpcap/pcap.c Normal file
View File

@ -0,0 +1,180 @@
/*
* Copyright (c) 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the Computer Systems
* Engineering Group at Lawrence Berkeley Laboratory.
* 4. Neither the name of the University nor of the Laboratory may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef lint
static char rcsid[] =
"@(#) $Header: pcap.c,v 1.12 94/06/12 14:32:23 leres Exp $ (LBL)";
#endif
#include <sys/types.h>
#include <unistd.h>
#include "pcap-int.h"
int
pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
if (p->sf.rfile != NULL)
return (pcap_offline_read(p, cnt, callback, user));
else
return (pcap_read(p, cnt, callback, user));
}
int
pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
for (;;) {
int n = pcap_dispatch(p, cnt, callback, user);
if (n < 0)
return (n);
if (cnt > 0) {
cnt -= n;
if (cnt <= 0)
return (0);
}
}
}
struct singleton {
struct pcap_pkthdr *hdr;
const u_char *pkt;
};
static void
pcap_oneshot(u_char *userData, const struct pcap_pkthdr *h, const u_char *pkt)
{
struct singleton *sp = (struct singleton *)userData;
*sp->hdr = *h;
sp->pkt = pkt;
}
const u_char *
pcap_next(pcap_t *p, struct pcap_pkthdr *h)
{
struct singleton s;
s.hdr = h;
if (pcap_dispatch(p, 1, pcap_oneshot, (u_char*)&s) < 0)
return (0);
return (s.pkt);
}
int
pcap_datalink(pcap_t *p)
{
return (p->linktype);
}
int
pcap_snapshot(pcap_t *p)
{
return (p->snapshot);
}
int
pcap_is_swapped(pcap_t *p)
{
return (p->sf.swapped);
}
int
pcap_major_version(pcap_t *p)
{
return (p->sf.version_major);
}
int
pcap_minor_version(pcap_t *p)
{
return (p->sf.version_minor);
}
FILE *
pcap_file(pcap_t *p)
{
return (p->sf.rfile);
}
int
pcap_fileno(pcap_t *p)
{
return (p->fd);
}
void
pcap_perror(pcap_t *p, char *prefix)
{
fprintf(stderr, "%s: %s\n", prefix, p->errbuf);
}
char *
pcap_geterr(pcap_t *p)
{
return (p->errbuf);
}
/*
* Not all systems have strerror().
*/
char *
pcap_strerror(int errnum)
{
extern int sys_nerr;
/*
extern char *sys_errlist[];
*/
static char ebuf[20];
if ((unsigned int)errnum < sys_nerr)
return (sys_errlist[errnum]);
(void)sprintf(ebuf, "Unknown error: %d", errnum);
return(ebuf);
}
void
pcap_close(pcap_t *p)
{
/*XXX*/
if (p->fd >= 0)
close(p->fd);
if (p->sf.rfile != NULL) {
fclose(p->sf.rfile);
if (p->sf.base != NULL)
free(p->sf.base);
} else if (p->buffer != NULL)
free(p->buffer);
free(p);
}

137
lib/libpcap/pcap.h Normal file
View File

@ -0,0 +1,137 @@
/*
* Copyright (c) 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the Computer Systems
* Engineering Group at Lawrence Berkeley Laboratory.
* 4. Neither the name of the University nor of the Laboratory may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#) $Header: pcap.h,v 1.15 94/06/14 20:03:34 leres Exp $ (LBL)
*/
#ifndef lib_pcap_h
#define lib_pcap_h
#include <sys/types.h>
#include <sys/time.h>
#include <net/bpf.h>
#include <stdio.h>
#define PCAP_VERSION_MAJOR 2
#define PCAP_VERSION_MINOR 4
#define PCAP_ERRBUF_SIZE 256
/*
* Compatibility for systems that have a bpf.h that
* predates the bpf typedefs for 64-bit support.
*/
#if BPF_RELEASE - 0 < 199406
typedef long bpf_int32;
typedef u_long bpf_u_int32;
#endif
typedef struct pcap pcap_t;
typedef struct pcap_dumper pcap_dumper_t;
/*
* The first record in the file contains saved values for some
* of the flags used in the printout phases of tcpdump.
* Many fields here are longs so compilers won't insert unwanted
* padding; these files need to be interchangeable across architectures.
*/
struct pcap_file_header {
bpf_u_int32 magic;
u_short version_major;
u_short version_minor;
bpf_int32 thiszone; /* gmt to local correction */
bpf_u_int32 sigfigs; /* accuracy of timestamps */
bpf_u_int32 snaplen; /* max length saved portion of each pkt */
bpf_u_int32 linktype; /* data link type (DLT_*) */
};
/*
* Each packet in the dump file is prepended with this generic header.
* This gets around the problem of different headers for different
* packet interfaces.
*/
struct pcap_pkthdr {
struct timeval ts; /* time stamp */
bpf_u_int32 caplen; /* length of portion present */
bpf_u_int32 len; /* length this packet (off wire) */
};
/*
* As returned by the pcap_stats()
*/
struct pcap_stat {
u_int ps_recv; /* number of packets received */
u_int ps_drop; /* number of packets dropped */
u_int ps_ifdrop; /* drops by interface XXX not yet supported */
};
typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
const u_char *);
char *pcap_lookupdev(char *);
int pcap_lookupnet(char *, u_long *, u_long *, char *);
pcap_t *pcap_open_live(char *, int, int, int, char *);
pcap_t *pcap_open_offline(char *, char *);
void pcap_close(pcap_t *);
int pcap_loop(pcap_t *, int, pcap_handler, u_char *);
int pcap_dispatch(pcap_t *, int, pcap_handler, u_char *);
const u_char*
pcap_next(pcap_t *, struct pcap_pkthdr *);
int pcap_stats(pcap_t *, struct pcap_stat *);
int pcap_setfilter(pcap_t *, struct bpf_program *);
void pcap_perror(pcap_t *, char *);
char *pcap_strerror(int);
char *pcap_geterr(pcap_t *);
int pcap_compile(pcap_t *, struct bpf_program *, char *, int, u_long);
/* XXX */
int pcap_freecode(pcap_t *, struct bpf_program *);
int pcap_datalink(pcap_t *);
int pcap_snapshot(pcap_t *);
int pcap_is_swapped(pcap_t *);
int pcap_major_version(pcap_t *);
int pcap_minor_version(pcap_t *);
/* XXX */
FILE *pcap_file(pcap_t *);
int pcap_fileno(pcap_t *);
pcap_dumper_t *pcap_dump_open(pcap_t *, char *);
void pcap_dump_close(pcap_dumper_t *);
void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *);
/* XXX this guy lives in the bpf tree */
u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int);
char *bpf_image(struct bpf_insn *, int);
#endif

285
lib/libpcap/savefile.c Normal file
View File

@ -0,0 +1,285 @@
/*
* Copyright (c) 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the University of California,
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef lint
static char rcsid[] =
"@(#)$Header: savefile.c,v 1.16 94/06/20 19:07:56 leres Exp $ (LBL)";
#endif
/*
* savefile.c - supports offline use of tcpdump
* Extraction/creation by Jeffrey Mogul, DECWRL
* Modified by Steve McCanne, LBL.
*
* Used to save the received packet headers, after filtering, to
* a file, and then read them later.
* The first record in the file contains saved values for the machine
* dependent values so we can print the dump file on any architecture.
*/
#include <sys/types.h>
#include <sys/time.h>
#include <net/bpf.h>
#include <errno.h>
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "pcap-int.h"
#define TCPDUMP_MAGIC 0xa1b2c3d4
/*
* We use the "receiver-makes-right" approach to byte order,
* because time is at a premium when we are writing the file.
* In other words, the pcap_file_header and pcap_pkthdr,
* records are written in host byte order.
* Note that the packets are always written in network byte order.
*
* ntoh[ls] aren't sufficient because we might need to swap on a big-endian
* machine (if the file was written in little-end order).
*/
#define SWAPLONG(y) \
((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff))
#define SWAPSHORT(y) \
( (((y)&0xff)<<8) | (((y)&0xff00)>>8) )
#define SFERR_TRUNC 1
#define SFERR_BADVERSION 2
#define SFERR_BADF 3
#define SFERR_EOF 4 /* not really an error, just a status */
static int
sf_write_header(FILE *fp, int linktype, int thiszone, int snaplen)
{
struct pcap_file_header hdr;
hdr.magic = TCPDUMP_MAGIC;
hdr.version_major = PCAP_VERSION_MAJOR;
hdr.version_minor = PCAP_VERSION_MINOR;
hdr.thiszone = thiszone;
hdr.snaplen = snaplen;
hdr.sigfigs = 0;
hdr.linktype = linktype;
if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1)
return (-1);
return (0);
}
static void
swap_hdr(struct pcap_file_header *hp)
{
hp->version_major = SWAPSHORT(hp->version_major);
hp->version_minor = SWAPSHORT(hp->version_minor);
hp->thiszone = SWAPLONG(hp->thiszone);
hp->sigfigs = SWAPLONG(hp->sigfigs);
hp->snaplen = SWAPLONG(hp->snaplen);
hp->linktype = SWAPLONG(hp->linktype);
}
pcap_t *
pcap_open_offline(char *fname, char *errbuf)
{
register pcap_t *p;
register FILE *fp;
struct pcap_file_header hdr;
int linklen;
p = (pcap_t *)malloc(sizeof(*p));
if (p == NULL) {
strcpy(errbuf, "out of swap");
return (NULL);
}
#ifdef notdef
bzero(p, sizeof(*p));
#else
memset(p, 0, sizeof(*p));
#endif
/*
* Set this field so we don't close stdin in pcap_close!
*/
p->fd = -1;
if (fname[0] == '-' && fname[1] == '\0')
fp = stdin;
else {
fp = fopen(fname, "r");
if (fp == NULL) {
sprintf(errbuf, "%s: %s", fname, pcap_strerror(errno));
goto bad;
}
}
if (fread((char *)&hdr, sizeof(hdr), 1, fp) != 1) {
sprintf(errbuf, "fread: %s", pcap_strerror(errno));
goto bad;
}
if (hdr.magic != TCPDUMP_MAGIC) {
if (SWAPLONG(hdr.magic) != TCPDUMP_MAGIC) {
sprintf(errbuf, "bad dump file format");
goto bad;
}
p->sf.swapped = 1;
swap_hdr(&hdr);
}
if (hdr.version_major < PCAP_VERSION_MAJOR) {
sprintf(errbuf, "archaic file format");
goto bad;
}
p->tzoff = hdr.thiszone;
p->snapshot = hdr.snaplen;
p->linktype = hdr.linktype;
p->sf.rfile = fp;
p->bufsize = hdr.snaplen;
/* Align link header as required for proper data alignment */
linklen = 14; /* XXX */
p->sf.base = (u_char *)malloc(p->bufsize + BPF_ALIGNMENT);
p->buffer = p->sf.base + BPF_ALIGNMENT - (linklen % BPF_ALIGNMENT);
p->sf.version_major = hdr.version_major;
p->sf.version_minor = hdr.version_minor;
return (p);
bad:
free(p);
return (NULL);
}
/*
* Read sf_readfile and return the next packet. Return the header in hdr
* and the contents in buf. Return 0 on success, SFERR_EOF if there were
* no more packets, and SFERR_TRUNC if a partial packet was encountered.
*/
static int
sf_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char *buf, int buflen)
{
FILE *fp = p->sf.rfile;
/* read the stamp */
if (fread((char *)hdr, sizeof(struct pcap_pkthdr), 1, fp) != 1) {
/* probably an EOF, though could be a truncated packet */
return (1);
}
if (p->sf.swapped) {
/* these were written in opposite byte order */
hdr->caplen = SWAPLONG(hdr->caplen);
hdr->len = SWAPLONG(hdr->len);
hdr->ts.tv_sec = SWAPLONG(hdr->ts.tv_sec);
hdr->ts.tv_usec = SWAPLONG(hdr->ts.tv_usec);
}
/*
* We interchanged the caplen and len fields at version 2.3,
* in order to match the bpf header layout. But unfortunately
* some files were written with version 2.3 in their headers
* but without the interchanged fields.
*/
if (p->sf.version_minor < 3 ||
(p->sf.version_minor == 3 && hdr->caplen > hdr->len)) {
int t = hdr->caplen;
hdr->caplen = hdr->len;
hdr->len = t;
}
if (hdr->caplen > buflen) {
sprintf(p->errbuf, "bad dump file format");
return (-1);
}
/* read the packet itself */
if (fread((char *)buf, hdr->caplen, 1, fp) != 1) {
sprintf(p->errbuf, "truncated dump file");
return (-1);
}
return (0);
}
/*
* Print out packets stored in the file initialized by sf_read_init().
* If cnt > 0, return after 'cnt' packets, otherwise continue until eof.
*/
int
pcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
struct bpf_insn *fcode = p->fcode.bf_insns;
int status = 0;
int n = 0;
while (status == 0) {
struct pcap_pkthdr h;
status = sf_next_packet(p, &h, p->buffer, p->bufsize);
if (status)
return (-1);
if (fcode == NULL ||
bpf_filter(fcode, p->buffer, h.len, h.caplen)) {
(*callback)(user, &h, p->buffer);
if (++n >= cnt && cnt > 0)
break;
}
}
/*XXX this breaks semantics tcpslice expects */
return (n);
}
/*
* Output a packet to the initialized dump file.
*/
void
pcap_dump(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
{
FILE * f = (FILE *)user;
(void)fwrite((char *)h, sizeof(*h), 1, f);
(void)fwrite((char *)sp, h->caplen, 1, f);
}
/*
* Initialize so that sf_write() will output to the file named 'fname'.
*/
pcap_dumper_t *
pcap_dump_open(pcap_t *p, char *fname)
{
FILE *f;
if (fname[0] == '-' && fname[1] == '\0')
f = stdout;
else {
f = fopen(fname, "w");
if (f == NULL) {
sprintf(p->errbuf, "%s: %s",
fname, pcap_strerror(errno));
return (NULL);
}
}
(void)sf_write_header(f, p->linktype, p->tzoff, p->snapshot);
return ((pcap_dumper_t *)f);
}
void
pcap_dump_close(pcap_dumper_t *p)
{
fclose((FILE *)p);
}

193
lib/libpcap/scanner.l Normal file
View File

@ -0,0 +1,193 @@
%{
/*
* Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that: (1) source code distributions
* retain the above copyright notice and this paragraph in its entirety, (2)
* distributions including binary code include the above copyright notice and
* this paragraph in its entirety in the documentation or other materials
* provided with the distribution, and (3) all advertising materials mentioning
* features or use of this software display the following acknowledgement:
* ``This product includes software developed by the University of California,
* Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
* the University nor the names of its contributors may be used to endorse
* or promote products derived from this software without specific prior
* written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#ifndef lint
static char rcsid[] =
"@(#) $Header: scanner.l,v 1.40 94/06/10 17:21:44 mccanne Exp $ (LBL)";
#endif
#include <sys/types.h>
#include <sys/time.h>
#include <ctype.h>
#include <pcap.h>
#include <pcap-namedb.h>
#include "gencode.h"
#include "tokdefs.h"
#ifndef __GNUC__
#define inline
#endif
static int stoi(char *);
static inline int xdtoi(int);
#ifdef FLEX_SCANNER
#undef YY_INPUT
#define YY_INPUT(buf, result, max)\
{\
char *src = in_buffer;\
int i;\
\
if (*src == 0)\
result = YY_NULL;\
else {\
for (i = 0; *src && i < max; ++i)\
buf[i] = *src++;\
in_buffer += i;\
result = i;\
}\
}
#else
#undef getc
#define getc(fp) (*in_buffer == 0 ? EOF : *in_buffer++)
#endif
#define yylval pcap_lval
extern YYSTYPE yylval;
static char *in_buffer;
%}
N ([0-9]+|(0X|0x)[0-9A-Fa-f]+)
B ([0-9A-Fa-f][0-9A-Fa-f]?)
%a 3000
%%
dst return DST;
src return SRC;
link|ether|ppp|slip return LINK;
fddi return LINK;
arp return ARP;
rarp return RARP;
ip return IP;
tcp return TCP;
udp return UDP;
icmp return ICMP;
decnet return DECNET;
lat return LAT;
moprc return MOPRC;
mopdl return MOPDL;
host return HOST;
net return NET;
port return PORT;
proto return PROTO;
gateway return GATEWAY;
less return LESS;
greater return GREATER;
byte return BYTE;
broadcast return TK_BROADCAST;
multicast return TK_MULTICAST;
and|"&&" return AND;
or|"||" return OR;
not return '!';
len|length return LEN;
inbound return INBOUND;
outbound return OUTBOUND;
[ \n\t] ;
[+\-*/:\[\]!<>()&|=] return yytext[0];
">=" return GEQ;
"<=" return LEQ;
"!=" return NEQ;
"==" return '=';
"<<" return LSH;
">>" return RSH;
{N} { yylval.i = stoi((char *)yytext); return NUM; }
({N}\.{N})|({N}\.{N}\.{N})|({N}\.{N}\.{N}\.{N}) {
yylval.s = sdup((char *)yytext); return HID;
}
{B}:{B}:{B}:{B}:{B}:{B} { yylval.e = pcap_ether_aton((char *)yytext);
return EID; }
{B}:+({B}:+)+ { bpf_error("bogus ethernet address %s", yytext); }
[A-Za-z][-_.A-Za-z0-9]* { yylval.s = sdup((char *)yytext); return ID; }
"\\"[^ !()\n\t]+ { yylval.s = sdup((char *)yytext + 1); return ID; }
[^ \[\]\t\n\-_.A-Za-z0-9!<>()&|=]+ { bpf_error("illegal token: %s\n", yytext); }
. { bpf_error("illegal char '%c'", *yytext); }
%%
void
lex_init(buf)
char *buf;
{
in_buffer = buf;
}
/*
* Also define a yywrap. Note that if we're using flex, it will
* define a macro to map this identifier to pcap_wrap.
*/
int
yywrap()
{
return 1;
}
/* Hex digit to integer. */
static inline int
xdtoi(c)
register int c;
{
if (isdigit(c))
return c - '0';
else if (islower(c))
return c - 'a' + 10;
else
return c - 'A' + 10;
}
/*
* Convert string to integer. Just like atoi(), but checks for
* preceding 0x or 0 and uses hex or octal instead of decimal.
*/
static int
stoi(s)
char *s;
{
int base = 10;
int n = 0;
if (*s == '0') {
if (s[1] == 'x' || s[1] == 'X') {
s += 2;
base = 16;
}
else {
base = 8;
s += 1;
}
}
while (*s)
n = n * base + xdtoi(*s++);
return n;
}