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