17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * Copyright (C) 1993-2001 by Darren Reed.
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * See the IPFILTER.LICENCE file for details on licencing.
57c478bd9Sstevel@tonic-gate *
6*ab25eeb5Syz155240 * $Id: ipft_pc.c,v 1.10 2004/02/07 18:17:40 darrenr Exp $
77c478bd9Sstevel@tonic-gate */
87c478bd9Sstevel@tonic-gate #include "ipf.h"
97c478bd9Sstevel@tonic-gate #include "pcap-ipf.h"
107c478bd9Sstevel@tonic-gate #include "bpf-ipf.h"
117c478bd9Sstevel@tonic-gate #include "ipt.h"
127c478bd9Sstevel@tonic-gate
137c478bd9Sstevel@tonic-gate #if !defined(lint)
14*ab25eeb5Syz155240 static const char rcsid[] = "@(#)$Id: ipft_pc.c,v 1.10 2004/02/07 18:17:40 darrenr Exp $";
157c478bd9Sstevel@tonic-gate #endif
167c478bd9Sstevel@tonic-gate
177c478bd9Sstevel@tonic-gate struct llc {
187c478bd9Sstevel@tonic-gate int lc_type;
197c478bd9Sstevel@tonic-gate int lc_sz; /* LLC header length */
207c478bd9Sstevel@tonic-gate int lc_to; /* LLC Type offset */
217c478bd9Sstevel@tonic-gate int lc_tl; /* LLC Type length */
227c478bd9Sstevel@tonic-gate };
237c478bd9Sstevel@tonic-gate
247c478bd9Sstevel@tonic-gate /*
257c478bd9Sstevel@tonic-gate * While many of these maybe the same, some do have different header formats
267c478bd9Sstevel@tonic-gate * which make this useful.
277c478bd9Sstevel@tonic-gate */
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate static struct llc llcs[] = {
307c478bd9Sstevel@tonic-gate { DLT_NULL, 0, 0, 0 },
317c478bd9Sstevel@tonic-gate { DLT_EN10MB, 14, 12, 2 },
327c478bd9Sstevel@tonic-gate { DLT_EN3MB, 0, 0, 0 },
337c478bd9Sstevel@tonic-gate { DLT_AX25, 0, 0, 0 },
347c478bd9Sstevel@tonic-gate { DLT_PRONET, 0, 0, 0 },
357c478bd9Sstevel@tonic-gate { DLT_CHAOS, 0, 0, 0 },
367c478bd9Sstevel@tonic-gate { DLT_IEEE802, 0, 0, 0 },
377c478bd9Sstevel@tonic-gate { DLT_ARCNET, 0, 0, 0 },
387c478bd9Sstevel@tonic-gate { DLT_SLIP, 0, 0, 0 },
397c478bd9Sstevel@tonic-gate { DLT_PPP, 0, 0, 0 },
407c478bd9Sstevel@tonic-gate { DLT_FDDI, 0, 0, 0 },
417c478bd9Sstevel@tonic-gate #ifdef DLT_ATMRFC1483
427c478bd9Sstevel@tonic-gate { DLT_ATMRFC1483, 0, 0, 0 },
437c478bd9Sstevel@tonic-gate #endif
447c478bd9Sstevel@tonic-gate { DLT_RAW, 0, 0, 0 },
457c478bd9Sstevel@tonic-gate #ifdef DLT_ENC
467c478bd9Sstevel@tonic-gate { DLT_ENC, 0, 0, 0 },
477c478bd9Sstevel@tonic-gate #endif
487c478bd9Sstevel@tonic-gate #ifdef DLT_SLIP_BSDOS
497c478bd9Sstevel@tonic-gate { DLT_SLIP_BSDOS, 0, 0, 0 },
507c478bd9Sstevel@tonic-gate #endif
517c478bd9Sstevel@tonic-gate #ifdef DLT_PPP_BSDOS
527c478bd9Sstevel@tonic-gate { DLT_PPP_BSDOS, 0, 0, 0 },
537c478bd9Sstevel@tonic-gate #endif
547c478bd9Sstevel@tonic-gate #ifdef DLT_HIPPI
557c478bd9Sstevel@tonic-gate { DLT_HIPPI, 0, 0, 0 },
567c478bd9Sstevel@tonic-gate #endif
577c478bd9Sstevel@tonic-gate #ifdef DLT_HDLC
587c478bd9Sstevel@tonic-gate { DLT_HDLC, 0, 0, 0 },
597c478bd9Sstevel@tonic-gate #endif
607c478bd9Sstevel@tonic-gate #ifdef DLT_PPP_SERIAL
617c478bd9Sstevel@tonic-gate { DLT_PPP_SERIAL, 4, 4, 0 },
627c478bd9Sstevel@tonic-gate #endif
637c478bd9Sstevel@tonic-gate #ifdef DLT_PPP_ETHER
647c478bd9Sstevel@tonic-gate { DLT_PPP_ETHER, 8, 8, 0 },
657c478bd9Sstevel@tonic-gate #endif
667c478bd9Sstevel@tonic-gate #ifdef DLT_ECONET
677c478bd9Sstevel@tonic-gate { DLT_ECONET, 0, 0, 0 },
687c478bd9Sstevel@tonic-gate #endif
697c478bd9Sstevel@tonic-gate { -1, -1, -1, -1 }
707c478bd9Sstevel@tonic-gate };
717c478bd9Sstevel@tonic-gate
727c478bd9Sstevel@tonic-gate static int pcap_open __P((char *));
737c478bd9Sstevel@tonic-gate static int pcap_close __P((void));
747c478bd9Sstevel@tonic-gate static int pcap_readip __P((char *, int, char **, int *));
757c478bd9Sstevel@tonic-gate static void swap_hdr __P((pcaphdr_t *));
767c478bd9Sstevel@tonic-gate static int pcap_read_rec __P((struct pcap_pkthdr *));
777c478bd9Sstevel@tonic-gate
78*ab25eeb5Syz155240 static int pfd = -1, swapped = 0;
797c478bd9Sstevel@tonic-gate static struct llc *llcp = NULL;
807c478bd9Sstevel@tonic-gate
817c478bd9Sstevel@tonic-gate struct ipread pcap = { pcap_open, pcap_close, pcap_readip, 0 };
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate #define SWAPLONG(y) \
847c478bd9Sstevel@tonic-gate ((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff))
857c478bd9Sstevel@tonic-gate #define SWAPSHORT(y) \
867c478bd9Sstevel@tonic-gate ( (((y)&0xff)<<8) | (((y)&0xff00)>>8) )
877c478bd9Sstevel@tonic-gate
swap_hdr(p)887c478bd9Sstevel@tonic-gate static void swap_hdr(p)
897c478bd9Sstevel@tonic-gate pcaphdr_t *p;
907c478bd9Sstevel@tonic-gate {
917c478bd9Sstevel@tonic-gate p->pc_v_maj = SWAPSHORT(p->pc_v_maj);
927c478bd9Sstevel@tonic-gate p->pc_v_min = SWAPSHORT(p->pc_v_min);
937c478bd9Sstevel@tonic-gate p->pc_zone = SWAPLONG(p->pc_zone);
947c478bd9Sstevel@tonic-gate p->pc_sigfigs = SWAPLONG(p->pc_sigfigs);
957c478bd9Sstevel@tonic-gate p->pc_slen = SWAPLONG(p->pc_slen);
967c478bd9Sstevel@tonic-gate p->pc_type = SWAPLONG(p->pc_type);
977c478bd9Sstevel@tonic-gate }
987c478bd9Sstevel@tonic-gate
pcap_open(fname)997c478bd9Sstevel@tonic-gate static int pcap_open(fname)
1007c478bd9Sstevel@tonic-gate char *fname;
1017c478bd9Sstevel@tonic-gate {
1027c478bd9Sstevel@tonic-gate pcaphdr_t ph;
1037c478bd9Sstevel@tonic-gate int fd, i;
1047c478bd9Sstevel@tonic-gate
1057c478bd9Sstevel@tonic-gate if (pfd != -1)
1067c478bd9Sstevel@tonic-gate return pfd;
1077c478bd9Sstevel@tonic-gate
1087c478bd9Sstevel@tonic-gate if (!strcmp(fname, "-"))
1097c478bd9Sstevel@tonic-gate fd = 0;
1107c478bd9Sstevel@tonic-gate else if ((fd = open(fname, O_RDONLY)) == -1)
1117c478bd9Sstevel@tonic-gate return -1;
1127c478bd9Sstevel@tonic-gate
1137c478bd9Sstevel@tonic-gate if (read(fd, (char *)&ph, sizeof(ph)) != sizeof(ph))
1147c478bd9Sstevel@tonic-gate return -2;
1157c478bd9Sstevel@tonic-gate
1167c478bd9Sstevel@tonic-gate if (ph.pc_id != TCPDUMP_MAGIC) {
1177c478bd9Sstevel@tonic-gate if (SWAPLONG(ph.pc_id) != TCPDUMP_MAGIC) {
1187c478bd9Sstevel@tonic-gate (void) close(fd);
1197c478bd9Sstevel@tonic-gate return -2;
1207c478bd9Sstevel@tonic-gate }
1217c478bd9Sstevel@tonic-gate swapped = 1;
1227c478bd9Sstevel@tonic-gate swap_hdr(&ph);
1237c478bd9Sstevel@tonic-gate }
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gate if (ph.pc_v_maj != PCAP_VERSION_MAJ) {
1267c478bd9Sstevel@tonic-gate (void) close(fd);
1277c478bd9Sstevel@tonic-gate return -2;
1287c478bd9Sstevel@tonic-gate }
1297c478bd9Sstevel@tonic-gate
1307c478bd9Sstevel@tonic-gate for (i = 0; llcs[i].lc_type != -1; i++)
1317c478bd9Sstevel@tonic-gate if (llcs[i].lc_type == ph.pc_type) {
1327c478bd9Sstevel@tonic-gate llcp = llcs + i;
1337c478bd9Sstevel@tonic-gate break;
1347c478bd9Sstevel@tonic-gate }
1357c478bd9Sstevel@tonic-gate
1367c478bd9Sstevel@tonic-gate if (llcp == NULL) {
1377c478bd9Sstevel@tonic-gate (void) close(fd);
1387c478bd9Sstevel@tonic-gate return -2;
1397c478bd9Sstevel@tonic-gate }
1407c478bd9Sstevel@tonic-gate
1417c478bd9Sstevel@tonic-gate pfd = fd;
1427c478bd9Sstevel@tonic-gate printf("opened pcap file %s:\n", fname);
1437c478bd9Sstevel@tonic-gate printf("\tid: %08x version: %d.%d type: %d snap %d\n",
1447c478bd9Sstevel@tonic-gate ph.pc_id, ph.pc_v_maj, ph.pc_v_min, ph.pc_type, ph.pc_slen);
1457c478bd9Sstevel@tonic-gate
1467c478bd9Sstevel@tonic-gate return fd;
1477c478bd9Sstevel@tonic-gate }
1487c478bd9Sstevel@tonic-gate
1497c478bd9Sstevel@tonic-gate
pcap_close()1507c478bd9Sstevel@tonic-gate static int pcap_close()
1517c478bd9Sstevel@tonic-gate {
1527c478bd9Sstevel@tonic-gate return close(pfd);
1537c478bd9Sstevel@tonic-gate }
1547c478bd9Sstevel@tonic-gate
1557c478bd9Sstevel@tonic-gate
1567c478bd9Sstevel@tonic-gate /*
1577c478bd9Sstevel@tonic-gate * read in the header (and validate) which should be the first record
1587c478bd9Sstevel@tonic-gate * in a pcap file.
1597c478bd9Sstevel@tonic-gate */
pcap_read_rec(rec)1607c478bd9Sstevel@tonic-gate static int pcap_read_rec(rec)
1617c478bd9Sstevel@tonic-gate struct pcap_pkthdr *rec;
1627c478bd9Sstevel@tonic-gate {
1637c478bd9Sstevel@tonic-gate int n, p;
1647c478bd9Sstevel@tonic-gate
1657c478bd9Sstevel@tonic-gate if (read(pfd, (char *)rec, sizeof(*rec)) != sizeof(*rec))
1667c478bd9Sstevel@tonic-gate return -2;
1677c478bd9Sstevel@tonic-gate
1687c478bd9Sstevel@tonic-gate if (swapped) {
1697c478bd9Sstevel@tonic-gate rec->ph_clen = SWAPLONG(rec->ph_clen);
1707c478bd9Sstevel@tonic-gate rec->ph_len = SWAPLONG(rec->ph_len);
1717c478bd9Sstevel@tonic-gate rec->ph_ts.tv_sec = SWAPLONG(rec->ph_ts.tv_sec);
1727c478bd9Sstevel@tonic-gate rec->ph_ts.tv_usec = SWAPLONG(rec->ph_ts.tv_usec);
1737c478bd9Sstevel@tonic-gate }
1747c478bd9Sstevel@tonic-gate p = rec->ph_clen;
1757c478bd9Sstevel@tonic-gate n = MIN(p, rec->ph_len);
1767c478bd9Sstevel@tonic-gate if (!n || n < 0)
1777c478bd9Sstevel@tonic-gate return -3;
1787c478bd9Sstevel@tonic-gate
1797c478bd9Sstevel@tonic-gate return p;
1807c478bd9Sstevel@tonic-gate }
1817c478bd9Sstevel@tonic-gate
1827c478bd9Sstevel@tonic-gate
1837c478bd9Sstevel@tonic-gate #ifdef notyet
1847c478bd9Sstevel@tonic-gate /*
1857c478bd9Sstevel@tonic-gate * read an entire pcap packet record. only the data part is copied into
1867c478bd9Sstevel@tonic-gate * the available buffer, with the number of bytes copied returned.
1877c478bd9Sstevel@tonic-gate */
pcap_read(buf,cnt)1887c478bd9Sstevel@tonic-gate static int pcap_read(buf, cnt)
1897c478bd9Sstevel@tonic-gate char *buf;
1907c478bd9Sstevel@tonic-gate int cnt;
1917c478bd9Sstevel@tonic-gate {
1927c478bd9Sstevel@tonic-gate struct pcap_pkthdr rec;
1937c478bd9Sstevel@tonic-gate static char *bufp = NULL;
1947c478bd9Sstevel@tonic-gate int i, n;
1957c478bd9Sstevel@tonic-gate
1967c478bd9Sstevel@tonic-gate if ((i = pcap_read_rec(&rec)) <= 0)
1977c478bd9Sstevel@tonic-gate return i;
1987c478bd9Sstevel@tonic-gate
1997c478bd9Sstevel@tonic-gate if (!bufp)
2007c478bd9Sstevel@tonic-gate bufp = malloc(i);
2017c478bd9Sstevel@tonic-gate else
2027c478bd9Sstevel@tonic-gate bufp = realloc(bufp, i);
2037c478bd9Sstevel@tonic-gate
2047c478bd9Sstevel@tonic-gate if (read(pfd, bufp, i) != i)
2057c478bd9Sstevel@tonic-gate return -2;
2067c478bd9Sstevel@tonic-gate
2077c478bd9Sstevel@tonic-gate n = MIN(i, cnt);
2087c478bd9Sstevel@tonic-gate bcopy(bufp, buf, n);
2097c478bd9Sstevel@tonic-gate return n;
2107c478bd9Sstevel@tonic-gate }
2117c478bd9Sstevel@tonic-gate #endif
2127c478bd9Sstevel@tonic-gate
2137c478bd9Sstevel@tonic-gate
2147c478bd9Sstevel@tonic-gate /*
2157c478bd9Sstevel@tonic-gate * return only an IP packet read into buf
2167c478bd9Sstevel@tonic-gate */
pcap_readip(buf,cnt,ifn,dir)2177c478bd9Sstevel@tonic-gate static int pcap_readip(buf, cnt, ifn, dir)
2187c478bd9Sstevel@tonic-gate char *buf, **ifn;
2197c478bd9Sstevel@tonic-gate int cnt, *dir;
2207c478bd9Sstevel@tonic-gate {
2217c478bd9Sstevel@tonic-gate static char *bufp = NULL;
2227c478bd9Sstevel@tonic-gate struct pcap_pkthdr rec;
2237c478bd9Sstevel@tonic-gate struct llc *l;
2247c478bd9Sstevel@tonic-gate char *s, ty[4];
2257c478bd9Sstevel@tonic-gate int i, n;
2267c478bd9Sstevel@tonic-gate
2277c478bd9Sstevel@tonic-gate l = llcp;
2287c478bd9Sstevel@tonic-gate
2297c478bd9Sstevel@tonic-gate /* do { */
2307c478bd9Sstevel@tonic-gate if ((i = pcap_read_rec(&rec)) <= 0)
2317c478bd9Sstevel@tonic-gate return i;
2327c478bd9Sstevel@tonic-gate
2337c478bd9Sstevel@tonic-gate if (!bufp)
2347c478bd9Sstevel@tonic-gate bufp = malloc(i);
2357c478bd9Sstevel@tonic-gate else
2367c478bd9Sstevel@tonic-gate bufp = realloc(bufp, i);
2377c478bd9Sstevel@tonic-gate s = bufp;
2387c478bd9Sstevel@tonic-gate
2397c478bd9Sstevel@tonic-gate if (read(pfd, s, i) != i)
2407c478bd9Sstevel@tonic-gate return -2;
2417c478bd9Sstevel@tonic-gate
2427c478bd9Sstevel@tonic-gate i -= l->lc_sz;
2437c478bd9Sstevel@tonic-gate s += l->lc_to;
2447c478bd9Sstevel@tonic-gate bcopy(s, ty, l->lc_tl);
2457c478bd9Sstevel@tonic-gate s += l->lc_tl;
2467c478bd9Sstevel@tonic-gate /* } while (ty[0] != 0x8 && ty[1] != 0); */
2477c478bd9Sstevel@tonic-gate n = MIN(i, cnt);
2487c478bd9Sstevel@tonic-gate bcopy(s, buf, n);
2497c478bd9Sstevel@tonic-gate return n;
2507c478bd9Sstevel@tonic-gate }
251