10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * Copyright (C) 1993-2001 by Darren Reed.
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * See the IPFILTER.LICENCE file for details on licencing.
50Sstevel@tonic-gate *
6*2393Syz155240 * $Id: ipft_pc.c,v 1.10 2004/02/07 18:17:40 darrenr Exp $
70Sstevel@tonic-gate */
80Sstevel@tonic-gate #include "ipf.h"
90Sstevel@tonic-gate #include "pcap-ipf.h"
100Sstevel@tonic-gate #include "bpf-ipf.h"
110Sstevel@tonic-gate #include "ipt.h"
120Sstevel@tonic-gate
130Sstevel@tonic-gate #if !defined(lint)
14*2393Syz155240 static const char rcsid[] = "@(#)$Id: ipft_pc.c,v 1.10 2004/02/07 18:17:40 darrenr Exp $";
150Sstevel@tonic-gate #endif
160Sstevel@tonic-gate
170Sstevel@tonic-gate struct llc {
180Sstevel@tonic-gate int lc_type;
190Sstevel@tonic-gate int lc_sz; /* LLC header length */
200Sstevel@tonic-gate int lc_to; /* LLC Type offset */
210Sstevel@tonic-gate int lc_tl; /* LLC Type length */
220Sstevel@tonic-gate };
230Sstevel@tonic-gate
240Sstevel@tonic-gate /*
250Sstevel@tonic-gate * While many of these maybe the same, some do have different header formats
260Sstevel@tonic-gate * which make this useful.
270Sstevel@tonic-gate */
280Sstevel@tonic-gate
290Sstevel@tonic-gate static struct llc llcs[] = {
300Sstevel@tonic-gate { DLT_NULL, 0, 0, 0 },
310Sstevel@tonic-gate { DLT_EN10MB, 14, 12, 2 },
320Sstevel@tonic-gate { DLT_EN3MB, 0, 0, 0 },
330Sstevel@tonic-gate { DLT_AX25, 0, 0, 0 },
340Sstevel@tonic-gate { DLT_PRONET, 0, 0, 0 },
350Sstevel@tonic-gate { DLT_CHAOS, 0, 0, 0 },
360Sstevel@tonic-gate { DLT_IEEE802, 0, 0, 0 },
370Sstevel@tonic-gate { DLT_ARCNET, 0, 0, 0 },
380Sstevel@tonic-gate { DLT_SLIP, 0, 0, 0 },
390Sstevel@tonic-gate { DLT_PPP, 0, 0, 0 },
400Sstevel@tonic-gate { DLT_FDDI, 0, 0, 0 },
410Sstevel@tonic-gate #ifdef DLT_ATMRFC1483
420Sstevel@tonic-gate { DLT_ATMRFC1483, 0, 0, 0 },
430Sstevel@tonic-gate #endif
440Sstevel@tonic-gate { DLT_RAW, 0, 0, 0 },
450Sstevel@tonic-gate #ifdef DLT_ENC
460Sstevel@tonic-gate { DLT_ENC, 0, 0, 0 },
470Sstevel@tonic-gate #endif
480Sstevel@tonic-gate #ifdef DLT_SLIP_BSDOS
490Sstevel@tonic-gate { DLT_SLIP_BSDOS, 0, 0, 0 },
500Sstevel@tonic-gate #endif
510Sstevel@tonic-gate #ifdef DLT_PPP_BSDOS
520Sstevel@tonic-gate { DLT_PPP_BSDOS, 0, 0, 0 },
530Sstevel@tonic-gate #endif
540Sstevel@tonic-gate #ifdef DLT_HIPPI
550Sstevel@tonic-gate { DLT_HIPPI, 0, 0, 0 },
560Sstevel@tonic-gate #endif
570Sstevel@tonic-gate #ifdef DLT_HDLC
580Sstevel@tonic-gate { DLT_HDLC, 0, 0, 0 },
590Sstevel@tonic-gate #endif
600Sstevel@tonic-gate #ifdef DLT_PPP_SERIAL
610Sstevel@tonic-gate { DLT_PPP_SERIAL, 4, 4, 0 },
620Sstevel@tonic-gate #endif
630Sstevel@tonic-gate #ifdef DLT_PPP_ETHER
640Sstevel@tonic-gate { DLT_PPP_ETHER, 8, 8, 0 },
650Sstevel@tonic-gate #endif
660Sstevel@tonic-gate #ifdef DLT_ECONET
670Sstevel@tonic-gate { DLT_ECONET, 0, 0, 0 },
680Sstevel@tonic-gate #endif
690Sstevel@tonic-gate { -1, -1, -1, -1 }
700Sstevel@tonic-gate };
710Sstevel@tonic-gate
720Sstevel@tonic-gate static int pcap_open __P((char *));
730Sstevel@tonic-gate static int pcap_close __P((void));
740Sstevel@tonic-gate static int pcap_readip __P((char *, int, char **, int *));
750Sstevel@tonic-gate static void swap_hdr __P((pcaphdr_t *));
760Sstevel@tonic-gate static int pcap_read_rec __P((struct pcap_pkthdr *));
770Sstevel@tonic-gate
78*2393Syz155240 static int pfd = -1, swapped = 0;
790Sstevel@tonic-gate static struct llc *llcp = NULL;
800Sstevel@tonic-gate
810Sstevel@tonic-gate struct ipread pcap = { pcap_open, pcap_close, pcap_readip, 0 };
820Sstevel@tonic-gate
830Sstevel@tonic-gate #define SWAPLONG(y) \
840Sstevel@tonic-gate ((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff))
850Sstevel@tonic-gate #define SWAPSHORT(y) \
860Sstevel@tonic-gate ( (((y)&0xff)<<8) | (((y)&0xff00)>>8) )
870Sstevel@tonic-gate
swap_hdr(p)880Sstevel@tonic-gate static void swap_hdr(p)
890Sstevel@tonic-gate pcaphdr_t *p;
900Sstevel@tonic-gate {
910Sstevel@tonic-gate p->pc_v_maj = SWAPSHORT(p->pc_v_maj);
920Sstevel@tonic-gate p->pc_v_min = SWAPSHORT(p->pc_v_min);
930Sstevel@tonic-gate p->pc_zone = SWAPLONG(p->pc_zone);
940Sstevel@tonic-gate p->pc_sigfigs = SWAPLONG(p->pc_sigfigs);
950Sstevel@tonic-gate p->pc_slen = SWAPLONG(p->pc_slen);
960Sstevel@tonic-gate p->pc_type = SWAPLONG(p->pc_type);
970Sstevel@tonic-gate }
980Sstevel@tonic-gate
pcap_open(fname)990Sstevel@tonic-gate static int pcap_open(fname)
1000Sstevel@tonic-gate char *fname;
1010Sstevel@tonic-gate {
1020Sstevel@tonic-gate pcaphdr_t ph;
1030Sstevel@tonic-gate int fd, i;
1040Sstevel@tonic-gate
1050Sstevel@tonic-gate if (pfd != -1)
1060Sstevel@tonic-gate return pfd;
1070Sstevel@tonic-gate
1080Sstevel@tonic-gate if (!strcmp(fname, "-"))
1090Sstevel@tonic-gate fd = 0;
1100Sstevel@tonic-gate else if ((fd = open(fname, O_RDONLY)) == -1)
1110Sstevel@tonic-gate return -1;
1120Sstevel@tonic-gate
1130Sstevel@tonic-gate if (read(fd, (char *)&ph, sizeof(ph)) != sizeof(ph))
1140Sstevel@tonic-gate return -2;
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate if (ph.pc_id != TCPDUMP_MAGIC) {
1170Sstevel@tonic-gate if (SWAPLONG(ph.pc_id) != TCPDUMP_MAGIC) {
1180Sstevel@tonic-gate (void) close(fd);
1190Sstevel@tonic-gate return -2;
1200Sstevel@tonic-gate }
1210Sstevel@tonic-gate swapped = 1;
1220Sstevel@tonic-gate swap_hdr(&ph);
1230Sstevel@tonic-gate }
1240Sstevel@tonic-gate
1250Sstevel@tonic-gate if (ph.pc_v_maj != PCAP_VERSION_MAJ) {
1260Sstevel@tonic-gate (void) close(fd);
1270Sstevel@tonic-gate return -2;
1280Sstevel@tonic-gate }
1290Sstevel@tonic-gate
1300Sstevel@tonic-gate for (i = 0; llcs[i].lc_type != -1; i++)
1310Sstevel@tonic-gate if (llcs[i].lc_type == ph.pc_type) {
1320Sstevel@tonic-gate llcp = llcs + i;
1330Sstevel@tonic-gate break;
1340Sstevel@tonic-gate }
1350Sstevel@tonic-gate
1360Sstevel@tonic-gate if (llcp == NULL) {
1370Sstevel@tonic-gate (void) close(fd);
1380Sstevel@tonic-gate return -2;
1390Sstevel@tonic-gate }
1400Sstevel@tonic-gate
1410Sstevel@tonic-gate pfd = fd;
1420Sstevel@tonic-gate printf("opened pcap file %s:\n", fname);
1430Sstevel@tonic-gate printf("\tid: %08x version: %d.%d type: %d snap %d\n",
1440Sstevel@tonic-gate ph.pc_id, ph.pc_v_maj, ph.pc_v_min, ph.pc_type, ph.pc_slen);
1450Sstevel@tonic-gate
1460Sstevel@tonic-gate return fd;
1470Sstevel@tonic-gate }
1480Sstevel@tonic-gate
1490Sstevel@tonic-gate
pcap_close()1500Sstevel@tonic-gate static int pcap_close()
1510Sstevel@tonic-gate {
1520Sstevel@tonic-gate return close(pfd);
1530Sstevel@tonic-gate }
1540Sstevel@tonic-gate
1550Sstevel@tonic-gate
1560Sstevel@tonic-gate /*
1570Sstevel@tonic-gate * read in the header (and validate) which should be the first record
1580Sstevel@tonic-gate * in a pcap file.
1590Sstevel@tonic-gate */
pcap_read_rec(rec)1600Sstevel@tonic-gate static int pcap_read_rec(rec)
1610Sstevel@tonic-gate struct pcap_pkthdr *rec;
1620Sstevel@tonic-gate {
1630Sstevel@tonic-gate int n, p;
1640Sstevel@tonic-gate
1650Sstevel@tonic-gate if (read(pfd, (char *)rec, sizeof(*rec)) != sizeof(*rec))
1660Sstevel@tonic-gate return -2;
1670Sstevel@tonic-gate
1680Sstevel@tonic-gate if (swapped) {
1690Sstevel@tonic-gate rec->ph_clen = SWAPLONG(rec->ph_clen);
1700Sstevel@tonic-gate rec->ph_len = SWAPLONG(rec->ph_len);
1710Sstevel@tonic-gate rec->ph_ts.tv_sec = SWAPLONG(rec->ph_ts.tv_sec);
1720Sstevel@tonic-gate rec->ph_ts.tv_usec = SWAPLONG(rec->ph_ts.tv_usec);
1730Sstevel@tonic-gate }
1740Sstevel@tonic-gate p = rec->ph_clen;
1750Sstevel@tonic-gate n = MIN(p, rec->ph_len);
1760Sstevel@tonic-gate if (!n || n < 0)
1770Sstevel@tonic-gate return -3;
1780Sstevel@tonic-gate
1790Sstevel@tonic-gate return p;
1800Sstevel@tonic-gate }
1810Sstevel@tonic-gate
1820Sstevel@tonic-gate
1830Sstevel@tonic-gate #ifdef notyet
1840Sstevel@tonic-gate /*
1850Sstevel@tonic-gate * read an entire pcap packet record. only the data part is copied into
1860Sstevel@tonic-gate * the available buffer, with the number of bytes copied returned.
1870Sstevel@tonic-gate */
pcap_read(buf,cnt)1880Sstevel@tonic-gate static int pcap_read(buf, cnt)
1890Sstevel@tonic-gate char *buf;
1900Sstevel@tonic-gate int cnt;
1910Sstevel@tonic-gate {
1920Sstevel@tonic-gate struct pcap_pkthdr rec;
1930Sstevel@tonic-gate static char *bufp = NULL;
1940Sstevel@tonic-gate int i, n;
1950Sstevel@tonic-gate
1960Sstevel@tonic-gate if ((i = pcap_read_rec(&rec)) <= 0)
1970Sstevel@tonic-gate return i;
1980Sstevel@tonic-gate
1990Sstevel@tonic-gate if (!bufp)
2000Sstevel@tonic-gate bufp = malloc(i);
2010Sstevel@tonic-gate else
2020Sstevel@tonic-gate bufp = realloc(bufp, i);
2030Sstevel@tonic-gate
2040Sstevel@tonic-gate if (read(pfd, bufp, i) != i)
2050Sstevel@tonic-gate return -2;
2060Sstevel@tonic-gate
2070Sstevel@tonic-gate n = MIN(i, cnt);
2080Sstevel@tonic-gate bcopy(bufp, buf, n);
2090Sstevel@tonic-gate return n;
2100Sstevel@tonic-gate }
2110Sstevel@tonic-gate #endif
2120Sstevel@tonic-gate
2130Sstevel@tonic-gate
2140Sstevel@tonic-gate /*
2150Sstevel@tonic-gate * return only an IP packet read into buf
2160Sstevel@tonic-gate */
pcap_readip(buf,cnt,ifn,dir)2170Sstevel@tonic-gate static int pcap_readip(buf, cnt, ifn, dir)
2180Sstevel@tonic-gate char *buf, **ifn;
2190Sstevel@tonic-gate int cnt, *dir;
2200Sstevel@tonic-gate {
2210Sstevel@tonic-gate static char *bufp = NULL;
2220Sstevel@tonic-gate struct pcap_pkthdr rec;
2230Sstevel@tonic-gate struct llc *l;
2240Sstevel@tonic-gate char *s, ty[4];
2250Sstevel@tonic-gate int i, n;
2260Sstevel@tonic-gate
2270Sstevel@tonic-gate l = llcp;
2280Sstevel@tonic-gate
2290Sstevel@tonic-gate /* do { */
2300Sstevel@tonic-gate if ((i = pcap_read_rec(&rec)) <= 0)
2310Sstevel@tonic-gate return i;
2320Sstevel@tonic-gate
2330Sstevel@tonic-gate if (!bufp)
2340Sstevel@tonic-gate bufp = malloc(i);
2350Sstevel@tonic-gate else
2360Sstevel@tonic-gate bufp = realloc(bufp, i);
2370Sstevel@tonic-gate s = bufp;
2380Sstevel@tonic-gate
2390Sstevel@tonic-gate if (read(pfd, s, i) != i)
2400Sstevel@tonic-gate return -2;
2410Sstevel@tonic-gate
2420Sstevel@tonic-gate i -= l->lc_sz;
2430Sstevel@tonic-gate s += l->lc_to;
2440Sstevel@tonic-gate bcopy(s, ty, l->lc_tl);
2450Sstevel@tonic-gate s += l->lc_tl;
2460Sstevel@tonic-gate /* } while (ty[0] != 0x8 && ty[1] != 0); */
2470Sstevel@tonic-gate n = MIN(i, cnt);
2480Sstevel@tonic-gate bcopy(s, buf, n);
2490Sstevel@tonic-gate return n;
2500Sstevel@tonic-gate }
251