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
snoop_open(fname)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
snoop_close()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 */
snoop_read_rec(rec)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 */
snoop_read(buf,cnt)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 */
snoop_readip(buf,cnt,ifn,dir)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