xref: /illumos-gate/usr/src/cmd/ipf/lib/ipft_pc.c (revision f3ac6781)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * Copyright (C) 1993-2001 by Darren Reed.
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * See the IPFILTER.LICENCE file for details on licencing.
57c478bd9Sstevel@tonic-gate  *
6ab25eeb5Syz  * $Id: ipft_pc.c,v 1.10 2004/02/07 18:17:40 darrenr Exp $
77c478bd9Sstevel@tonic-gate  */
87c478bd9Sstevel@tonic-gate #include "ipf.h"
97c478bd9Sstevel@tonic-gate #include "pcap-ipf.h"
107c478bd9Sstevel@tonic-gate #include "bpf-ipf.h"
117c478bd9Sstevel@tonic-gate #include "ipt.h"
127c478bd9Sstevel@tonic-gate 
137c478bd9Sstevel@tonic-gate #if !defined(lint)
14ab25eeb5Syz static const char rcsid[] = "@(#)$Id: ipft_pc.c,v 1.10 2004/02/07 18:17:40 darrenr Exp $";
157c478bd9Sstevel@tonic-gate #endif
167c478bd9Sstevel@tonic-gate 
177c478bd9Sstevel@tonic-gate struct	llc	{
187c478bd9Sstevel@tonic-gate 	int	lc_type;
197c478bd9Sstevel@tonic-gate 	int	lc_sz;	/* LLC header length */
207c478bd9Sstevel@tonic-gate 	int	lc_to;	/* LLC Type offset */
217c478bd9Sstevel@tonic-gate 	int	lc_tl;	/* LLC Type length */
227c478bd9Sstevel@tonic-gate };
237c478bd9Sstevel@tonic-gate 
247c478bd9Sstevel@tonic-gate /*
257c478bd9Sstevel@tonic-gate  * While many of these maybe the same, some do have different header formats
267c478bd9Sstevel@tonic-gate  * which make this useful.
277c478bd9Sstevel@tonic-gate  */
287c478bd9Sstevel@tonic-gate 
297c478bd9Sstevel@tonic-gate static	struct	llc	llcs[] = {
307c478bd9Sstevel@tonic-gate 	{ DLT_NULL, 0, 0, 0 },
317c478bd9Sstevel@tonic-gate 	{ DLT_EN10MB, 14, 12, 2 },
327c478bd9Sstevel@tonic-gate 	{ DLT_EN3MB, 0, 0, 0 },
337c478bd9Sstevel@tonic-gate 	{ DLT_AX25, 0, 0, 0 },
347c478bd9Sstevel@tonic-gate 	{ DLT_PRONET, 0, 0, 0 },
357c478bd9Sstevel@tonic-gate 	{ DLT_CHAOS, 0, 0, 0 },
367c478bd9Sstevel@tonic-gate 	{ DLT_IEEE802, 0, 0, 0 },
377c478bd9Sstevel@tonic-gate 	{ DLT_ARCNET, 0, 0, 0 },
387c478bd9Sstevel@tonic-gate 	{ DLT_SLIP, 0, 0, 0 },
397c478bd9Sstevel@tonic-gate 	{ DLT_PPP, 0, 0, 0 },
407c478bd9Sstevel@tonic-gate 	{ DLT_FDDI, 0, 0, 0 },
417c478bd9Sstevel@tonic-gate #ifdef DLT_ATMRFC1483
427c478bd9Sstevel@tonic-gate 	{ DLT_ATMRFC1483, 0, 0, 0 },
437c478bd9Sstevel@tonic-gate #endif
447c478bd9Sstevel@tonic-gate 	{ DLT_RAW, 0, 0, 0 },
457c478bd9Sstevel@tonic-gate #ifdef	DLT_ENC
467c478bd9Sstevel@tonic-gate 	{ DLT_ENC, 0, 0, 0 },
477c478bd9Sstevel@tonic-gate #endif
487c478bd9Sstevel@tonic-gate #ifdef	DLT_SLIP_BSDOS
497c478bd9Sstevel@tonic-gate 	{ DLT_SLIP_BSDOS, 0, 0, 0 },
507c478bd9Sstevel@tonic-gate #endif
517c478bd9Sstevel@tonic-gate #ifdef	DLT_PPP_BSDOS
527c478bd9Sstevel@tonic-gate 	{ DLT_PPP_BSDOS, 0, 0, 0 },
537c478bd9Sstevel@tonic-gate #endif
547c478bd9Sstevel@tonic-gate #ifdef	DLT_HIPPI
557c478bd9Sstevel@tonic-gate 	{ DLT_HIPPI, 0, 0, 0 },
567c478bd9Sstevel@tonic-gate #endif
577c478bd9Sstevel@tonic-gate #ifdef	DLT_HDLC
587c478bd9Sstevel@tonic-gate 	{ DLT_HDLC, 0, 0, 0 },
597c478bd9Sstevel@tonic-gate #endif
607c478bd9Sstevel@tonic-gate #ifdef	DLT_PPP_SERIAL
617c478bd9Sstevel@tonic-gate 	{ DLT_PPP_SERIAL, 4, 4, 0 },
627c478bd9Sstevel@tonic-gate #endif
637c478bd9Sstevel@tonic-gate #ifdef	DLT_PPP_ETHER
647c478bd9Sstevel@tonic-gate 	{ DLT_PPP_ETHER, 8, 8, 0 },
657c478bd9Sstevel@tonic-gate #endif
667c478bd9Sstevel@tonic-gate #ifdef	DLT_ECONET
677c478bd9Sstevel@tonic-gate 	{ DLT_ECONET, 0, 0, 0 },
687c478bd9Sstevel@tonic-gate #endif
697c478bd9Sstevel@tonic-gate 	{ -1, -1, -1, -1 }
707c478bd9Sstevel@tonic-gate };
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate static	int	pcap_open __P((char *));
737c478bd9Sstevel@tonic-gate static	int	pcap_close __P((void));
747c478bd9Sstevel@tonic-gate static	int	pcap_readip __P((char *, int, char **, int *));
757c478bd9Sstevel@tonic-gate static	void	swap_hdr __P((pcaphdr_t *));
767c478bd9Sstevel@tonic-gate static	int	pcap_read_rec __P((struct pcap_pkthdr *));
777c478bd9Sstevel@tonic-gate 
78ab25eeb5Syz static	int	pfd = -1, swapped = 0;
797c478bd9Sstevel@tonic-gate static	struct llc	*llcp = NULL;
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate struct	ipread	pcap = { pcap_open, pcap_close, pcap_readip, 0 };
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate #define	SWAPLONG(y)	\
847c478bd9Sstevel@tonic-gate 	((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff))
857c478bd9Sstevel@tonic-gate #define	SWAPSHORT(y)	\
867c478bd9Sstevel@tonic-gate 	( (((y)&0xff)<<8) | (((y)&0xff00)>>8) )
877c478bd9Sstevel@tonic-gate 
swap_hdr(p)887c478bd9Sstevel@tonic-gate static	void	swap_hdr(p)
897c478bd9Sstevel@tonic-gate pcaphdr_t	*p;
907c478bd9Sstevel@tonic-gate {
917c478bd9Sstevel@tonic-gate 	p->pc_v_maj = SWAPSHORT(p->pc_v_maj);
927c478bd9Sstevel@tonic-gate 	p->pc_v_min = SWAPSHORT(p->pc_v_min);
937c478bd9Sstevel@tonic-gate 	p->pc_zone = SWAPLONG(p->pc_zone);
947c478bd9Sstevel@tonic-gate 	p->pc_sigfigs = SWAPLONG(p->pc_sigfigs);
957c478bd9Sstevel@tonic-gate 	p->pc_slen = SWAPLONG(p->pc_slen);
967c478bd9Sstevel@tonic-gate 	p->pc_type = SWAPLONG(p->pc_type);
977c478bd9Sstevel@tonic-gate }
987c478bd9Sstevel@tonic-gate 
pcap_open(fname)997c478bd9Sstevel@tonic-gate static	int	pcap_open(fname)
1007c478bd9Sstevel@tonic-gate char	*fname;
1017c478bd9Sstevel@tonic-gate {
1027c478bd9Sstevel@tonic-gate 	pcaphdr_t ph;
1037c478bd9Sstevel@tonic-gate 	int fd, i;
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate 	if (pfd != -1)
1067c478bd9Sstevel@tonic-gate 		return pfd;
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 	if (!strcmp(fname, "-"))
1097c478bd9Sstevel@tonic-gate 		fd = 0;
1107c478bd9Sstevel@tonic-gate 	else if ((fd = open(fname, O_RDONLY)) == -1)
1117c478bd9Sstevel@tonic-gate 		return -1;
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 	if (read(fd, (char *)&ph, sizeof(ph)) != sizeof(ph))
1147c478bd9Sstevel@tonic-gate 		return -2;
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate 	if (ph.pc_id != TCPDUMP_MAGIC) {
1177c478bd9Sstevel@tonic-gate 		if (SWAPLONG(ph.pc_id) != TCPDUMP_MAGIC) {
1187c478bd9Sstevel@tonic-gate 			(void) close(fd);
1197c478bd9Sstevel@tonic-gate 			return -2;
1207c478bd9Sstevel@tonic-gate 		}
1217c478bd9Sstevel@tonic-gate 		swapped = 1;
1227c478bd9Sstevel@tonic-gate 		swap_hdr(&ph);
1237c478bd9Sstevel@tonic-gate 	}
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 	if (ph.pc_v_maj != PCAP_VERSION_MAJ) {
1267c478bd9Sstevel@tonic-gate 		(void) close(fd);
1277c478bd9Sstevel@tonic-gate 		return -2;
1287c478bd9Sstevel@tonic-gate 	}
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 	for (i = 0; llcs[i].lc_type != -1; i++)
1317c478bd9Sstevel@tonic-gate 		if (llcs[i].lc_type == ph.pc_type) {
1327c478bd9Sstevel@tonic-gate 			llcp = llcs + i;
1337c478bd9Sstevel@tonic-gate 			break;
1347c478bd9Sstevel@tonic-gate 		}
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 	if (llcp == NULL) {
1377c478bd9Sstevel@tonic-gate 		(void) close(fd);
1387c478bd9Sstevel@tonic-gate 		return -2;
1397c478bd9Sstevel@tonic-gate 	}
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	pfd = fd;
1427c478bd9Sstevel@tonic-gate 	printf("opened pcap file %s:\n", fname);
1437c478bd9Sstevel@tonic-gate 	printf("\tid: %08x version: %d.%d type: %d snap %d\n",
1447c478bd9Sstevel@tonic-gate 		ph.pc_id, ph.pc_v_maj, ph.pc_v_min, ph.pc_type, ph.pc_slen);
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 	return fd;
1477c478bd9Sstevel@tonic-gate }
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 
pcap_close()1507c478bd9Sstevel@tonic-gate static	int	pcap_close()
1517c478bd9Sstevel@tonic-gate {
1527c478bd9Sstevel@tonic-gate 	return close(pfd);
1537c478bd9Sstevel@tonic-gate }
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate /*
1577c478bd9Sstevel@tonic-gate  * read in the header (and validate) which should be the first record
1587c478bd9Sstevel@tonic-gate  * in a pcap file.
1597c478bd9Sstevel@tonic-gate  */
pcap_read_rec(rec)1607c478bd9Sstevel@tonic-gate static	int	pcap_read_rec(rec)
1617c478bd9Sstevel@tonic-gate struct	pcap_pkthdr *rec;
1627c478bd9Sstevel@tonic-gate {
1637c478bd9Sstevel@tonic-gate 	int	n, p;
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 	if (read(pfd, (char *)rec, sizeof(*rec)) != sizeof(*rec))
1667c478bd9Sstevel@tonic-gate 		return -2;
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 	if (swapped) {
1697c478bd9Sstevel@tonic-gate 		rec->ph_clen = SWAPLONG(rec->ph_clen);
1707c478bd9Sstevel@tonic-gate 		rec->ph_len = SWAPLONG(rec->ph_len);
1717c478bd9Sstevel@tonic-gate 		rec->ph_ts.tv_sec = SWAPLONG(rec->ph_ts.tv_sec);
1727c478bd9Sstevel@tonic-gate 		rec->ph_ts.tv_usec = SWAPLONG(rec->ph_ts.tv_usec);
1737c478bd9Sstevel@tonic-gate 	}
1747c478bd9Sstevel@tonic-gate 	p = rec->ph_clen;
1757c478bd9Sstevel@tonic-gate 	n = MIN(p, rec->ph_len);
1767c478bd9Sstevel@tonic-gate 	if (!n || n < 0)
1777c478bd9Sstevel@tonic-gate 		return -3;
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 	return p;
1807c478bd9Sstevel@tonic-gate }
1817c478bd9Sstevel@tonic-gate 
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate #ifdef	notyet
1847c478bd9Sstevel@tonic-gate /*
1857c478bd9Sstevel@tonic-gate  * read an entire pcap packet record.  only the data part is copied into
1867c478bd9Sstevel@tonic-gate  * the available buffer, with the number of bytes copied returned.
1877c478bd9Sstevel@tonic-gate  */
pcap_read(buf,cnt)1887c478bd9Sstevel@tonic-gate static	int	pcap_read(buf, cnt)
1897c478bd9Sstevel@tonic-gate char	*buf;
1907c478bd9Sstevel@tonic-gate int	cnt;
1917c478bd9Sstevel@tonic-gate {
1927c478bd9Sstevel@tonic-gate 	struct	pcap_pkthdr rec;
1937c478bd9Sstevel@tonic-gate 	static	char	*bufp = NULL;
1947c478bd9Sstevel@tonic-gate 	int	i, n;
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 	if ((i = pcap_read_rec(&rec)) <= 0)
1977c478bd9Sstevel@tonic-gate 		return i;
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate 	if (!bufp)
2007c478bd9Sstevel@tonic-gate 		bufp = malloc(i);
2017c478bd9Sstevel@tonic-gate 	else
2027c478bd9Sstevel@tonic-gate 		bufp = realloc(bufp, i);
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 	if (read(pfd, bufp, i) != i)
2057c478bd9Sstevel@tonic-gate 		return -2;
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 	n = MIN(i, cnt);
2087c478bd9Sstevel@tonic-gate 	bcopy(bufp, buf, n);
2097c478bd9Sstevel@tonic-gate 	return n;
2107c478bd9Sstevel@tonic-gate }
2117c478bd9Sstevel@tonic-gate #endif
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate /*
2157c478bd9Sstevel@tonic-gate  * return only an IP packet read into buf
2167c478bd9Sstevel@tonic-gate  */
pcap_readip(buf,cnt,ifn,dir)2177c478bd9Sstevel@tonic-gate static	int	pcap_readip(buf, cnt, ifn, dir)
2187c478bd9Sstevel@tonic-gate char	*buf, **ifn;
2197c478bd9Sstevel@tonic-gate int	cnt, *dir;
2207c478bd9Sstevel@tonic-gate {
2217c478bd9Sstevel@tonic-gate 	static	char	*bufp = NULL;
2227c478bd9Sstevel@tonic-gate 	struct	pcap_pkthdr rec;
2237c478bd9Sstevel@tonic-gate 	struct	llc	*l;
2247c478bd9Sstevel@tonic-gate 	char	*s, ty[4];
2257c478bd9Sstevel@tonic-gate 	int	i, n;
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	l = llcp;
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 	/* do { */
2307c478bd9Sstevel@tonic-gate 		if ((i = pcap_read_rec(&rec)) <= 0)
2317c478bd9Sstevel@tonic-gate 			return i;
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 		if (!bufp)
2347c478bd9Sstevel@tonic-gate 			bufp = malloc(i);
2357c478bd9Sstevel@tonic-gate 		else
2367c478bd9Sstevel@tonic-gate 			bufp = realloc(bufp, i);
2377c478bd9Sstevel@tonic-gate 		s = bufp;
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate 		if (read(pfd, s, i) != i)
2407c478bd9Sstevel@tonic-gate 			return -2;
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 		i -= l->lc_sz;
2437c478bd9Sstevel@tonic-gate 		s += l->lc_to;
2447c478bd9Sstevel@tonic-gate 		bcopy(s, ty, l->lc_tl);
2457c478bd9Sstevel@tonic-gate 		s += l->lc_tl;
2467c478bd9Sstevel@tonic-gate 	/* } while (ty[0] != 0x8 && ty[1] != 0); */
2477c478bd9Sstevel@tonic-gate 	n = MIN(i, cnt);
2487c478bd9Sstevel@tonic-gate 	bcopy(s, buf, n);
2497c478bd9Sstevel@tonic-gate 	return n;
2507c478bd9Sstevel@tonic-gate }
251