xref: /netbsd-src/external/bsd/ipf/dist/lib/ipft_pc.c (revision 07967fb18af5b87d2d477c5b3e1e438bf0c293fb)
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