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.9 2003/02/16 02:32:36 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.9 2003/02/16 02:32:36 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, s_type = -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 s_type = ph.pc_type; 143 printf("opened pcap file %s:\n", fname); 144 printf("\tid: %08x version: %d.%d type: %d snap %d\n", 145 ph.pc_id, ph.pc_v_maj, ph.pc_v_min, ph.pc_type, ph.pc_slen); 146 147 return fd; 148 } 149 150 151 static int pcap_close() 152 { 153 return close(pfd); 154 } 155 156 157 /* 158 * read in the header (and validate) which should be the first record 159 * in a pcap file. 160 */ 161 static int pcap_read_rec(rec) 162 struct pcap_pkthdr *rec; 163 { 164 int n, p; 165 166 if (read(pfd, (char *)rec, sizeof(*rec)) != sizeof(*rec)) 167 return -2; 168 169 if (swapped) { 170 rec->ph_clen = SWAPLONG(rec->ph_clen); 171 rec->ph_len = SWAPLONG(rec->ph_len); 172 rec->ph_ts.tv_sec = SWAPLONG(rec->ph_ts.tv_sec); 173 rec->ph_ts.tv_usec = SWAPLONG(rec->ph_ts.tv_usec); 174 } 175 p = rec->ph_clen; 176 n = MIN(p, rec->ph_len); 177 if (!n || n < 0) 178 return -3; 179 180 return p; 181 } 182 183 184 #ifdef notyet 185 /* 186 * read an entire pcap packet record. only the data part is copied into 187 * the available buffer, with the number of bytes copied returned. 188 */ 189 static int pcap_read(buf, cnt) 190 char *buf; 191 int cnt; 192 { 193 struct pcap_pkthdr rec; 194 static char *bufp = NULL; 195 int i, n; 196 197 if ((i = pcap_read_rec(&rec)) <= 0) 198 return i; 199 200 if (!bufp) 201 bufp = malloc(i); 202 else 203 bufp = realloc(bufp, i); 204 205 if (read(pfd, bufp, i) != i) 206 return -2; 207 208 n = MIN(i, cnt); 209 bcopy(bufp, buf, n); 210 return n; 211 } 212 #endif 213 214 215 /* 216 * return only an IP packet read into buf 217 */ 218 static int pcap_readip(buf, cnt, ifn, dir) 219 char *buf, **ifn; 220 int cnt, *dir; 221 { 222 static char *bufp = NULL; 223 struct pcap_pkthdr rec; 224 struct llc *l; 225 char *s, ty[4]; 226 int i, n; 227 228 l = llcp; 229 230 /* do { */ 231 if ((i = pcap_read_rec(&rec)) <= 0) 232 return i; 233 234 if (!bufp) 235 bufp = malloc(i); 236 else 237 bufp = realloc(bufp, i); 238 s = bufp; 239 240 if (read(pfd, s, i) != i) 241 return -2; 242 243 i -= l->lc_sz; 244 s += l->lc_to; 245 bcopy(s, ty, l->lc_tl); 246 s += l->lc_tl; 247 /* } while (ty[0] != 0x8 && ty[1] != 0); */ 248 n = MIN(i, cnt); 249 bcopy(s, buf, n); 250 return n; 251 } 252