mirror of
https://git.FreeBSD.org/src.git
synced 2024-11-26 07:55:01 +00:00
Add the Packet Capture Library from Michael Reifenberger.
Submitted by: mr
This commit is contained in:
parent
4ed9828579
commit
609c85875a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/cvs2svn/branches/libpcap/; revision=5739
45
lib/libpcap/Makefile
Normal file
45
lib/libpcap/Makefile
Normal file
@ -0,0 +1,45 @@
|
||||
# Makefile for libpcap
|
||||
# $Id: Makefile,v 1.8 1994/11/16 11:54:09 ache Exp $
|
||||
|
||||
LIB= pcap
|
||||
|
||||
SRCS= \
|
||||
pcap-bpf.c \
|
||||
pcap.c inet.c gencode.c optimize.c nametoaddr.c etherent.c savefile.c \
|
||||
bpf_filter.c bpf_image.c \
|
||||
grammar.y \
|
||||
scanner.l
|
||||
|
||||
CLEANFILES+= lex.yy.c tokdefs.h grammar.c scanner.c
|
||||
CFLAGS+=-Wall -I. -I${.CURDIR} -DFDDI
|
||||
MAN3= pcap.3
|
||||
|
||||
beforeinstall:
|
||||
-cmp -s ${.CURDIR}/pcap.h ${DESTDIR}/usr/include/pcap.h.h || \
|
||||
( $(INSTALL) $(COPY) -o ${BINOWN} -g ${BINGRP} -m 444 \
|
||||
${.CURDIR}/pcap.h ${DESTDIR}/usr/include; )
|
||||
-cmp -s ${.CURDIR}/pcap-namedb.h ${DESTDIR}/usr/include/pcap-namedb.h || \
|
||||
( $(INSTALL) $(COPY) -o ${BINOWN} -g ${BINGRP} -m 444 \
|
||||
${.CURDIR}/pcap-namedb.h ${DESTDIR}/usr/include; )
|
||||
|
||||
|
||||
scanner.c: scanner.l
|
||||
rm -f $@
|
||||
$(LEX) -t $< > $@
|
||||
|
||||
scanner.o: scanner.c
|
||||
rm -f $@; $(CC) $(CFLAGS) $(LEX_DEFINES) -c $*.c
|
||||
|
||||
tokdefs.h: grammar.c
|
||||
|
||||
grammar.c: grammar.y
|
||||
rm -f grammar.c tokdefs.h
|
||||
$(YACC) -d $<
|
||||
mv y.tab.c grammar.c
|
||||
mv y.tab.h tokdefs.h
|
||||
|
||||
grammar.o: grammar.c
|
||||
$(CC) -c $(CFLAGS) -Dyylval=pcap_lval grammar.c
|
||||
|
||||
|
||||
.include <bsd.lib.mk>
|
550
lib/libpcap/bpf_filter.c
Normal file
550
lib/libpcap/bpf_filter.c
Normal 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
284
lib/libpcap/bpf_image.c
Normal 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
148
lib/libpcap/etherent.c
Normal 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
74
lib/libpcap/ethertype.h
Normal 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
1755
lib/libpcap/gencode.c
Normal file
File diff suppressed because it is too large
Load Diff
173
lib/libpcap/gencode.h
Normal file
173
lib/libpcap/gencode.h
Normal 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
264
lib/libpcap/grammar.y
Normal 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
196
lib/libpcap/inet.c
Normal 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
357
lib/libpcap/nametoaddr.c
Normal 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
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
233
lib/libpcap/pcap-bpf.c
Normal 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
506
lib/libpcap/pcap-dlpi.c
Normal 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
227
lib/libpcap/pcap-enet.c
Normal 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
98
lib/libpcap/pcap-int.h
Normal 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
76
lib/libpcap/pcap-namedb.h
Normal 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
240
lib/libpcap/pcap-nit.c
Normal 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
19
lib/libpcap/pcap-nit.h
Normal 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
310
lib/libpcap/pcap-pf.c
Normal 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
19
lib/libpcap/pcap-pf.h
Normal 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
293
lib/libpcap/pcap-snit.c
Normal 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 *)𝔦
|
||||
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
195
lib/libpcap/pcap-snoop.c
Normal 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
323
lib/libpcap/pcap.3
Normal 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
180
lib/libpcap/pcap.c
Normal 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
137
lib/libpcap/pcap.h
Normal 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
285
lib/libpcap/savefile.c
Normal 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
193
lib/libpcap/scanner.l
Normal 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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user