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