1/*
2 * Copyright (C) 1993-2001 by Darren Reed.
3 *
4 * See the IPFILTER.LICENCE file for details on licencing.
5 *
6 * $Id: ipft_sn.c,v 1.7 2003/02/16 02:32:36 darrenr Exp $
7 */
8
9/*
10 * Written to comply with the recent RFC 1761 from Sun.
11 */
12#include "ipf.h"
13#include "snoop.h"
14#include "ipt.h"
15
16#if !defined(lint)
17static const char rcsid[] = "@(#)$Id: ipft_sn.c,v 1.7 2003/02/16 02:32:36 darrenr Exp $";
18#endif
19
20struct	llc	{
21	int	lc_sz;	/* LLC header length */
22	int	lc_to;	/* LLC Type offset */
23	int	lc_tl;	/* LLC Type length */
24};
25
26/*
27 * While many of these maybe the same, some do have different header formats
28 * which make this useful.
29 */
30static	struct	llc	llcs[SDL_MAX+1] = {
31	{ 0, 0, 0 },	/* SDL_8023 */
32	{ 0, 0, 0 },	/* SDL_8024 */
33	{ 0, 0, 0 },	/* SDL_8025 */
34	{ 0, 0, 0 },	/* SDL_8026 */
35	{ 14, 12, 2 },	/* SDL_ETHER */
36	{ 0, 0, 0 },	/* SDL_HDLC */
37	{ 0, 0, 0 },	/* SDL_CHSYNC */
38	{ 0, 0, 0 },	/* SDL_IBMCC */
39	{ 0, 0, 0 },	/* SDL_FDDI */
40	{ 0, 0, 0 },	/* SDL_OTHER */
41};
42
43static	int	snoop_open __P((char *));
44static	int	snoop_close __P((void));
45static	int	snoop_readip __P((char *, int, char **, int *));
46
47static	int	sfd = -1, s_type = -1;
48static	int	snoop_read_rec __P((struct snooppkt *));
49
50struct	ipread	snoop = { snoop_open, snoop_close, snoop_readip, 0 };
51
52
53static	int	snoop_open(fname)
54char	*fname;
55{
56	struct	snoophdr sh;
57	int	fd;
58	int s_v;
59
60	if (sfd != -1)
61		return sfd;
62
63	if (!strcmp(fname, "-"))
64		fd = 0;
65	else if ((fd = open(fname, O_RDONLY)) == -1)
66		return -1;
67
68	if (read(fd, (char *)&sh, sizeof(sh)) != sizeof(sh))
69		return -2;
70
71	s_v = (int)ntohl(sh.s_v);
72	s_type = (int)ntohl(sh.s_type);
73
74	if (s_v != SNOOP_VERSION ||
75	    s_type < 0 || s_type > SDL_MAX) {
76		(void) close(fd);
77		return -2;
78	}
79
80	sfd = fd;
81	printf("opened snoop file %s:\n", fname);
82	printf("\tid: %8.8s version: %d type: %d\n", sh.s_id, s_v, s_type);
83
84	return fd;
85}
86
87
88static	int	snoop_close()
89{
90	return close(sfd);
91}
92
93
94/*
95 * read in the header (and validate) which should be the first record
96 * in a snoop file.
97 */
98static	int	snoop_read_rec(rec)
99struct	snooppkt *rec;
100{
101	int	n, plen, ilen;
102
103	if (read(sfd, (char *)rec, sizeof(*rec)) != sizeof(*rec))
104		return -2;
105
106	ilen = (int)ntohl(rec->sp_ilen);
107	plen = (int)ntohl(rec->sp_plen);
108	if (ilen > plen || plen < sizeof(*rec))
109		return -2;
110
111	plen -= sizeof(*rec);
112	n = MIN(plen, ilen);
113	if (!n || n < 0)
114		return -3;
115
116	return plen;
117}
118
119
120#ifdef	notyet
121/*
122 * read an entire snoop packet record.  only the data part is copied into
123 * the available buffer, with the number of bytes copied returned.
124 */
125static	int	snoop_read(buf, cnt)
126char	*buf;
127int	cnt;
128{
129	struct	snooppkt rec;
130	static	char	*bufp = NULL;
131	int	i, n;
132
133	if ((i = snoop_read_rec(&rec)) <= 0)
134		return i;
135
136	if (!bufp)
137		bufp = malloc(i);
138	else
139		bufp = realloc(bufp, i);
140
141	if (read(sfd, bufp, i) != i)
142		return -2;
143
144	n = MIN(i, cnt);
145	bcopy(bufp, buf, n);
146	return n;
147}
148#endif
149
150
151/*
152 * return only an IP packet read into buf
153 */
154static	int	snoop_readip(buf, cnt, ifn, dir)
155char	*buf, **ifn;
156int	cnt, *dir;
157{
158	static	char	*bufp = NULL;
159	struct	snooppkt rec;
160	struct	llc	*l;
161	char	ty[4], *s;
162	int	i, n;
163
164	do {
165		if ((i = snoop_read_rec(&rec)) <= 0)
166			return i;
167
168		if (!bufp)
169			bufp = malloc(i);
170		else
171			bufp = realloc(bufp, i);
172		s = bufp;
173
174		if (read(sfd, s, i) != i)
175			return -2;
176
177		l = &llcs[s_type];
178		i -= l->lc_to;
179		s += l->lc_to;
180		/*
181		 * XXX - bogus assumption here on the part of the time field
182		 * that it won't be greater than 4 bytes and the 1st two will
183		 * have the values 8 and 0 for IP.  Should be a table of
184		 * these too somewhere.  Really only works for SDL_ETHER.
185		 */
186		bcopy(s, ty, l->lc_tl);
187	} while (ty[0] != 0x8 && ty[1] != 0);
188
189	i -= l->lc_tl;
190	s += l->lc_tl;
191	n = MIN(i, cnt);
192	bcopy(s, buf, n);
193
194	return n;
195}
196