1/* $FreeBSD$ */ 2 3/* 4 * Copyright (C) 2000-2005 by Darren Reed. 5 * 6 * See the IPFILTER.LICENCE file for details on licencing. 7 * 8 * $Id: ipft_pc.c,v 1.10.2.2 2006/06/16 17:21:03 darrenr Exp $ 9 */ 10#include "ipf.h" 11#include "pcap-ipf.h" 12#include "bpf-ipf.h" 13#include "ipt.h" 14 15#if !defined(lint) 16static const char rcsid[] = "@(#)$Id: ipft_pc.c,v 1.10.2.2 2006/06/16 17:21:03 darrenr Exp $"; 17#endif 18 19struct llc { 20 int lc_type; 21 int lc_sz; /* LLC header length */ 22 int lc_to; /* LLC Type offset */ 23 int lc_tl; /* LLC Type length */ 24}; 25 26/* 27 * While many of these maybe the same, some do have different header formats 28 * which make this useful. 29 */ 30 31static struct llc llcs[] = { 32 { DLT_NULL, 0, 0, 0 }, 33 { DLT_EN10MB, 14, 12, 2 }, 34 { DLT_EN3MB, 0, 0, 0 }, 35 { DLT_AX25, 0, 0, 0 }, 36 { DLT_PRONET, 0, 0, 0 }, 37 { DLT_CHAOS, 0, 0, 0 }, 38 { DLT_IEEE802, 0, 0, 0 }, 39 { DLT_ARCNET, 0, 0, 0 }, 40 { DLT_SLIP, 0, 0, 0 }, 41 { DLT_PPP, 0, 0, 0 }, 42 { DLT_FDDI, 0, 0, 0 }, 43#ifdef DLT_ATMRFC1483 44 { DLT_ATMRFC1483, 0, 0, 0 }, 45#endif 46 { DLT_RAW, 0, 0, 0 }, 47#ifdef DLT_ENC 48 { DLT_ENC, 0, 0, 0 }, 49#endif 50#ifdef DLT_SLIP_BSDOS 51 { DLT_SLIP_BSDOS, 0, 0, 0 }, 52#endif 53#ifdef DLT_PPP_BSDOS 54 { DLT_PPP_BSDOS, 0, 0, 0 }, 55#endif 56#ifdef DLT_HIPPI 57 { DLT_HIPPI, 0, 0, 0 }, 58#endif 59#ifdef DLT_HDLC 60 { DLT_HDLC, 0, 0, 0 }, 61#endif 62#ifdef DLT_PPP_SERIAL 63 { DLT_PPP_SERIAL, 4, 4, 0 }, 64#endif 65#ifdef DLT_PPP_ETHER 66 { DLT_PPP_ETHER, 8, 8, 0 }, 67#endif 68#ifdef DLT_ECONET 69 { DLT_ECONET, 0, 0, 0 }, 70#endif 71 { -1, -1, -1, -1 } 72}; 73 74static int pcap_open __P((char *)); 75static int pcap_close __P((void)); 76static int pcap_readip __P((char *, int, char **, int *)); 77static void swap_hdr __P((pcaphdr_t *)); 78static int pcap_read_rec __P((struct pcap_pkthdr *)); 79 80static int pfd = -1, swapped = 0; 81static struct llc *llcp = NULL; 82 83struct ipread pcap = { pcap_open, pcap_close, pcap_readip, 0 }; 84 85#define SWAPLONG(y) \ 86 ((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff)) 87#define SWAPSHORT(y) \ 88 ( (((y)&0xff)<<8) | (((y)&0xff00)>>8) ) 89 90static void swap_hdr(p) 91pcaphdr_t *p; 92{ 93 p->pc_v_maj = SWAPSHORT(p->pc_v_maj); 94 p->pc_v_min = SWAPSHORT(p->pc_v_min); 95 p->pc_zone = SWAPLONG(p->pc_zone); 96 p->pc_sigfigs = SWAPLONG(p->pc_sigfigs); 97 p->pc_slen = SWAPLONG(p->pc_slen); 98 p->pc_type = SWAPLONG(p->pc_type); 99} 100 101static int pcap_open(fname) 102char *fname; 103{ 104 pcaphdr_t ph; 105 int fd, i; 106 107 if (pfd != -1) 108 return pfd; 109 110 if (!strcmp(fname, "-")) 111 fd = 0; 112 else if ((fd = open(fname, O_RDONLY)) == -1) 113 return -1; 114 115 if (read(fd, (char *)&ph, sizeof(ph)) != sizeof(ph)) 116 return -2; 117 118 if (ph.pc_id != TCPDUMP_MAGIC) { 119 if (SWAPLONG(ph.pc_id) != TCPDUMP_MAGIC) { 120 (void) close(fd); 121 return -2; 122 } 123 swapped = 1; 124 swap_hdr(&ph); 125 } 126 127 if (ph.pc_v_maj != PCAP_VERSION_MAJ) { 128 (void) close(fd); 129 return -2; 130 } 131 132 for (i = 0; llcs[i].lc_type != -1; i++) 133 if (llcs[i].lc_type == ph.pc_type) { 134 llcp = llcs + i; 135 break; 136 } 137 138 if (llcp == NULL) { 139 (void) close(fd); 140 return -2; 141 } 142 143 pfd = fd; 144 printf("opened pcap file %s:\n", fname); 145 printf("\tid: %08x version: %d.%d type: %d snap %d\n", 146 ph.pc_id, ph.pc_v_maj, ph.pc_v_min, ph.pc_type, ph.pc_slen); 147 148 return fd; 149} 150 151 152static int pcap_close() 153{ 154 return close(pfd); 155} 156 157 158/* 159 * read in the header (and validate) which should be the first record 160 * in a pcap file. 161 */ 162static int pcap_read_rec(rec) 163struct pcap_pkthdr *rec; 164{ 165 int n, p, i; 166 char *s; 167 168 s = (char *)rec; 169 n = sizeof(*rec); 170 171 while (n > 0) { 172 i = read(pfd, (char *)rec, sizeof(*rec)); 173 if (i <= 0) 174 return -2; 175 s += i; 176 n -= i; 177 } 178 179 if (swapped) { 180 rec->ph_clen = SWAPLONG(rec->ph_clen); 181 rec->ph_len = SWAPLONG(rec->ph_len); 182 rec->ph_ts.tv_sec = SWAPLONG(rec->ph_ts.tv_sec); 183 rec->ph_ts.tv_usec = SWAPLONG(rec->ph_ts.tv_usec); 184 } 185 p = rec->ph_clen; 186 n = MIN(p, rec->ph_len); 187 if (!n || n < 0) 188 return -3; 189 190 if (p < 0 || p > 65536) 191 return -4; 192 return p; 193} 194 195 196#ifdef notyet 197/* 198 * read an entire pcap packet record. only the data part is copied into 199 * the available buffer, with the number of bytes copied returned. 200 */ 201static int pcap_read(buf, cnt) 202char *buf; 203int cnt; 204{ 205 struct pcap_pkthdr rec; 206 static char *bufp = NULL; 207 int i, n; 208 209 if ((i = pcap_read_rec(&rec)) <= 0) 210 return i; 211 212 if (!bufp) 213 bufp = malloc(i); 214 else 215 bufp = realloc(bufp, i); 216 217 if (read(pfd, bufp, i) != i) 218 return -2; 219 220 n = MIN(i, cnt); 221 bcopy(bufp, buf, n); 222 return n; 223} 224#endif 225 226 227/* 228 * return only an IP packet read into buf 229 */ 230static int pcap_readip(buf, cnt, ifn, dir) 231char *buf, **ifn; 232int cnt, *dir; 233{ 234 static char *bufp = NULL; 235 struct pcap_pkthdr rec; 236 struct llc *l; 237 char *s, ty[4]; 238 int i, j, n; 239 240 l = llcp; 241 242 /* do { */ 243 if ((i = pcap_read_rec(&rec)) <= 0) 244 return i; 245 246 if (!bufp) 247 bufp = malloc(i); 248 else 249 bufp = realloc(bufp, i); 250 s = bufp; 251 252 for (j = i, n = 0; j > 0; ) { 253 n = read(pfd, s, j); 254 if (n <= 0) 255 return -2; 256 j -= n; 257 s += n; 258 } 259 s = bufp; 260 261 i -= l->lc_sz; 262 s += l->lc_to; 263 bcopy(s, ty, l->lc_tl); 264 s += l->lc_tl; 265 /* } while (ty[0] != 0x8 && ty[1] != 0); */ 266 n = MIN(i, cnt); 267 bcopy(s, buf, n); 268 return n; 269} 270