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 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 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 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 */ 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 */ 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 */ 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