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