1145519Sdarrenr/*	$FreeBSD$	*/
2145510Sdarrenr
3145510Sdarrenr/*
4170268Sdarrenr * Copyright (C) 2000-2003 by Darren Reed.
5145510Sdarrenr *
6145510Sdarrenr * See the IPFILTER.LICENCE file for details on licencing.
7145510Sdarrenr *
8170268Sdarrenr * $Id: ipft_sn.c,v 1.7.4.1 2006/06/16 17:21:03 darrenr Exp $
9145510Sdarrenr */
10145510Sdarrenr
11145510Sdarrenr/*
12145510Sdarrenr * Written to comply with the recent RFC 1761 from Sun.
13145510Sdarrenr */
14145510Sdarrenr#include "ipf.h"
15145510Sdarrenr#include "snoop.h"
16145510Sdarrenr#include "ipt.h"
17145510Sdarrenr
18145510Sdarrenr#if !defined(lint)
19170268Sdarrenrstatic const char rcsid[] = "@(#)$Id: ipft_sn.c,v 1.7.4.1 2006/06/16 17:21:03 darrenr Exp $";
20145510Sdarrenr#endif
21145510Sdarrenr
22145510Sdarrenrstruct	llc	{
23145510Sdarrenr	int	lc_sz;	/* LLC header length */
24145510Sdarrenr	int	lc_to;	/* LLC Type offset */
25145510Sdarrenr	int	lc_tl;	/* LLC Type length */
26145510Sdarrenr};
27145510Sdarrenr
28145510Sdarrenr/*
29145510Sdarrenr * While many of these maybe the same, some do have different header formats
30145510Sdarrenr * which make this useful.
31145510Sdarrenr */
32145510Sdarrenrstatic	struct	llc	llcs[SDL_MAX+1] = {
33145510Sdarrenr	{ 0, 0, 0 },	/* SDL_8023 */
34145510Sdarrenr	{ 0, 0, 0 },	/* SDL_8024 */
35145510Sdarrenr	{ 0, 0, 0 },	/* SDL_8025 */
36145510Sdarrenr	{ 0, 0, 0 },	/* SDL_8026 */
37145510Sdarrenr	{ 14, 12, 2 },	/* SDL_ETHER */
38145510Sdarrenr	{ 0, 0, 0 },	/* SDL_HDLC */
39145510Sdarrenr	{ 0, 0, 0 },	/* SDL_CHSYNC */
40145510Sdarrenr	{ 0, 0, 0 },	/* SDL_IBMCC */
41145510Sdarrenr	{ 0, 0, 0 },	/* SDL_FDDI */
42145510Sdarrenr	{ 0, 0, 0 },	/* SDL_OTHER */
43145510Sdarrenr};
44145510Sdarrenr
45145510Sdarrenrstatic	int	snoop_open __P((char *));
46145510Sdarrenrstatic	int	snoop_close __P((void));
47145510Sdarrenrstatic	int	snoop_readip __P((char *, int, char **, int *));
48145510Sdarrenr
49145510Sdarrenrstatic	int	sfd = -1, s_type = -1;
50145510Sdarrenrstatic	int	snoop_read_rec __P((struct snooppkt *));
51145510Sdarrenr
52145510Sdarrenrstruct	ipread	snoop = { snoop_open, snoop_close, snoop_readip, 0 };
53145510Sdarrenr
54145510Sdarrenr
55145510Sdarrenrstatic	int	snoop_open(fname)
56145510Sdarrenrchar	*fname;
57145510Sdarrenr{
58145510Sdarrenr	struct	snoophdr sh;
59145510Sdarrenr	int	fd;
60145510Sdarrenr	int s_v;
61145510Sdarrenr
62145510Sdarrenr	if (sfd != -1)
63145510Sdarrenr		return sfd;
64145510Sdarrenr
65145510Sdarrenr	if (!strcmp(fname, "-"))
66145510Sdarrenr		fd = 0;
67145510Sdarrenr	else if ((fd = open(fname, O_RDONLY)) == -1)
68145510Sdarrenr		return -1;
69145510Sdarrenr
70145510Sdarrenr	if (read(fd, (char *)&sh, sizeof(sh)) != sizeof(sh))
71145510Sdarrenr		return -2;
72145510Sdarrenr
73145510Sdarrenr	s_v = (int)ntohl(sh.s_v);
74145510Sdarrenr	s_type = (int)ntohl(sh.s_type);
75145510Sdarrenr
76145510Sdarrenr	if (s_v != SNOOP_VERSION ||
77145510Sdarrenr	    s_type < 0 || s_type > SDL_MAX) {
78145510Sdarrenr		(void) close(fd);
79145510Sdarrenr		return -2;
80145510Sdarrenr	}
81145510Sdarrenr
82145510Sdarrenr	sfd = fd;
83145510Sdarrenr	printf("opened snoop file %s:\n", fname);
84145510Sdarrenr	printf("\tid: %8.8s version: %d type: %d\n", sh.s_id, s_v, s_type);
85145510Sdarrenr
86145510Sdarrenr	return fd;
87145510Sdarrenr}
88145510Sdarrenr
89145510Sdarrenr
90145510Sdarrenrstatic	int	snoop_close()
91145510Sdarrenr{
92145510Sdarrenr	return close(sfd);
93145510Sdarrenr}
94145510Sdarrenr
95145510Sdarrenr
96145510Sdarrenr/*
97145510Sdarrenr * read in the header (and validate) which should be the first record
98145510Sdarrenr * in a snoop file.
99145510Sdarrenr */
100145510Sdarrenrstatic	int	snoop_read_rec(rec)
101145510Sdarrenrstruct	snooppkt *rec;
102145510Sdarrenr{
103145510Sdarrenr	int	n, plen, ilen;
104145510Sdarrenr
105145510Sdarrenr	if (read(sfd, (char *)rec, sizeof(*rec)) != sizeof(*rec))
106145510Sdarrenr		return -2;
107145510Sdarrenr
108145510Sdarrenr	ilen = (int)ntohl(rec->sp_ilen);
109145510Sdarrenr	plen = (int)ntohl(rec->sp_plen);
110145510Sdarrenr	if (ilen > plen || plen < sizeof(*rec))
111145510Sdarrenr		return -2;
112145510Sdarrenr
113145510Sdarrenr	plen -= sizeof(*rec);
114145510Sdarrenr	n = MIN(plen, ilen);
115145510Sdarrenr	if (!n || n < 0)
116145510Sdarrenr		return -3;
117145510Sdarrenr
118145510Sdarrenr	return plen;
119145510Sdarrenr}
120145510Sdarrenr
121145510Sdarrenr
122145510Sdarrenr#ifdef	notyet
123145510Sdarrenr/*
124145510Sdarrenr * read an entire snoop packet record.  only the data part is copied into
125145510Sdarrenr * the available buffer, with the number of bytes copied returned.
126145510Sdarrenr */
127145510Sdarrenrstatic	int	snoop_read(buf, cnt)
128145510Sdarrenrchar	*buf;
129145510Sdarrenrint	cnt;
130145510Sdarrenr{
131145510Sdarrenr	struct	snooppkt rec;
132145510Sdarrenr	static	char	*bufp = NULL;
133145510Sdarrenr	int	i, n;
134145510Sdarrenr
135145510Sdarrenr	if ((i = snoop_read_rec(&rec)) <= 0)
136145510Sdarrenr		return i;
137145510Sdarrenr
138145510Sdarrenr	if (!bufp)
139145510Sdarrenr		bufp = malloc(i);
140145510Sdarrenr	else
141145510Sdarrenr		bufp = realloc(bufp, i);
142145510Sdarrenr
143145510Sdarrenr	if (read(sfd, bufp, i) != i)
144145510Sdarrenr		return -2;
145145510Sdarrenr
146145510Sdarrenr	n = MIN(i, cnt);
147145510Sdarrenr	bcopy(bufp, buf, n);
148145510Sdarrenr	return n;
149145510Sdarrenr}
150145510Sdarrenr#endif
151145510Sdarrenr
152145510Sdarrenr
153145510Sdarrenr/*
154145510Sdarrenr * return only an IP packet read into buf
155145510Sdarrenr */
156145510Sdarrenrstatic	int	snoop_readip(buf, cnt, ifn, dir)
157145510Sdarrenrchar	*buf, **ifn;
158145510Sdarrenrint	cnt, *dir;
159145510Sdarrenr{
160145510Sdarrenr	static	char	*bufp = NULL;
161145510Sdarrenr	struct	snooppkt rec;
162145510Sdarrenr	struct	llc	*l;
163145510Sdarrenr	char	ty[4], *s;
164145510Sdarrenr	int	i, n;
165145510Sdarrenr
166145510Sdarrenr	do {
167145510Sdarrenr		if ((i = snoop_read_rec(&rec)) <= 0)
168145510Sdarrenr			return i;
169145510Sdarrenr
170145510Sdarrenr		if (!bufp)
171145510Sdarrenr			bufp = malloc(i);
172145510Sdarrenr		else
173145510Sdarrenr			bufp = realloc(bufp, i);
174145510Sdarrenr		s = bufp;
175145510Sdarrenr
176145510Sdarrenr		if (read(sfd, s, i) != i)
177145510Sdarrenr			return -2;
178145510Sdarrenr
179145510Sdarrenr		l = &llcs[s_type];
180145510Sdarrenr		i -= l->lc_to;
181145510Sdarrenr		s += l->lc_to;
182145510Sdarrenr		/*
183145510Sdarrenr		 * XXX - bogus assumption here on the part of the time field
184145510Sdarrenr		 * that it won't be greater than 4 bytes and the 1st two will
185145510Sdarrenr		 * have the values 8 and 0 for IP.  Should be a table of
186145510Sdarrenr		 * these too somewhere.  Really only works for SDL_ETHER.
187145510Sdarrenr		 */
188145510Sdarrenr		bcopy(s, ty, l->lc_tl);
189145510Sdarrenr	} while (ty[0] != 0x8 && ty[1] != 0);
190145510Sdarrenr
191145510Sdarrenr	i -= l->lc_tl;
192145510Sdarrenr	s += l->lc_tl;
193145510Sdarrenr	n = MIN(i, cnt);
194145510Sdarrenr	bcopy(s, buf, n);
195145510Sdarrenr
196145510Sdarrenr	return n;
197145510Sdarrenr}
198