xref: /illumos-gate/usr/src/cmd/ipf/lib/ipft_sn.c (revision 09fbbb7d1b5a956a9b81304070dcff318a4a158e)
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)
17 static const char rcsid[] = "@(#)$Id: ipft_sn.c,v 1.7 2003/02/16 02:32:36 darrenr Exp $";
18 #endif
19 
20 struct	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  */
30 static	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 
43 static	int	snoop_open __P((char *));
44 static	int	snoop_close __P((void));
45 static	int	snoop_readip __P((char *, int, char **, int *));
46 
47 static	int	sfd = -1, s_type = -1;
48 static	int	snoop_read_rec __P((struct snooppkt *));
49 
50 struct	ipread	snoop = { snoop_open, snoop_close, snoop_readip, 0 };
51 
52 
53 static	int	snoop_open(fname)
54 char	*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 
88 static	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  */
98 static	int	snoop_read_rec(rec)
99 struct	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  */
125 static	int	snoop_read(buf, cnt)
126 char	*buf;
127 int	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  */
154 static	int	snoop_readip(buf, cnt, ifn, dir)
155 char	*buf, **ifn;
156 int	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