ip_scan.c revision 1.2.2.2 1 1.2.2.2 joerg /* $NetBSD: ip_scan.c,v 1.2.2.2 2012/04/17 19:25:21 joerg Exp $ */
2 1.2.2.2 joerg
3 1.2.2.2 joerg /*
4 1.2.2.2 joerg * Copyright (C) 2009 by Darren Reed.
5 1.2.2.2 joerg *
6 1.2.2.2 joerg * See the IPFILTER.LICENCE file for details on licencing.
7 1.2.2.2 joerg */
8 1.2.2.2 joerg #if defined(KERNEL) || defined(_KERNEL)
9 1.2.2.2 joerg # undef KERNEL
10 1.2.2.2 joerg # undef _KERNEL
11 1.2.2.2 joerg # define KERNEL 1
12 1.2.2.2 joerg # define _KERNEL 1
13 1.2.2.2 joerg #endif
14 1.2.2.2 joerg #include <sys/param.h>
15 1.2.2.2 joerg #if defined(__hpux) && (HPUXREV >= 1111) && !defined(_KERNEL)
16 1.2.2.2 joerg # include <sys/kern_svcs.h>
17 1.2.2.2 joerg #endif
18 1.2.2.2 joerg #include <sys/types.h>
19 1.2.2.2 joerg #include <sys/time.h>
20 1.2.2.2 joerg #include <sys/errno.h>
21 1.2.2.2 joerg #if !defined(_KERNEL)
22 1.2.2.2 joerg # include <stdlib.h>
23 1.2.2.2 joerg # include <string.h>
24 1.2.2.2 joerg # define _KERNEL
25 1.2.2.2 joerg # ifdef __OpenBSD__
26 1.2.2.2 joerg struct file;
27 1.2.2.2 joerg # endif
28 1.2.2.2 joerg # include <sys/uio.h>
29 1.2.2.2 joerg # undef _KERNEL
30 1.2.2.2 joerg #else
31 1.2.2.2 joerg # include <sys/systm.h>
32 1.2.2.2 joerg # if !defined(__svr4__) && !defined(__SVR4)
33 1.2.2.2 joerg # include <sys/mbuf.h>
34 1.2.2.2 joerg # endif
35 1.2.2.2 joerg #endif
36 1.2.2.2 joerg #include <sys/socket.h>
37 1.2.2.2 joerg #if !defined(__hpux) && !defined(__osf__) && !defined(linux) && !defined(AIX)
38 1.2.2.2 joerg # include <sys/ioccom.h>
39 1.2.2.2 joerg #endif
40 1.2.2.2 joerg #ifdef __FreeBSD__
41 1.2.2.2 joerg # include <sys/filio.h>
42 1.2.2.2 joerg # include <sys/malloc.h>
43 1.2.2.2 joerg #else
44 1.2.2.2 joerg # include <sys/ioctl.h>
45 1.2.2.2 joerg #endif
46 1.2.2.2 joerg
47 1.2.2.2 joerg #include <netinet/in.h>
48 1.2.2.2 joerg #include <netinet/in_systm.h>
49 1.2.2.2 joerg #include <netinet/ip.h>
50 1.2.2.2 joerg #include <netinet/tcp.h>
51 1.2.2.2 joerg
52 1.2.2.2 joerg #include <net/if.h>
53 1.2.2.2 joerg
54 1.2.2.2 joerg
55 1.2.2.2 joerg #include "netinet/ip_compat.h"
56 1.2.2.2 joerg #include "netinet/ip_fil.h"
57 1.2.2.2 joerg #include "netinet/ip_state.h"
58 1.2.2.2 joerg #include "netinet/ip_scan.h"
59 1.2.2.2 joerg /* END OF INCLUDES */
60 1.2.2.2 joerg
61 1.2.2.2 joerg #if !defined(lint)
62 1.2.2.2 joerg #if defined(__NetBSD__)
63 1.2.2.2 joerg #include <sys/cdefs.h>
64 1.2.2.2 joerg __KERNEL_RCSID(0, "$NetBSD: ip_scan.c,v 1.2.2.2 2012/04/17 19:25:21 joerg Exp $");
65 1.2.2.2 joerg #else
66 1.2.2.2 joerg static const char sccsid[] = "@(#)ip_state.c 1.8 6/5/96 (C) 1993-2000 Darren Reed";
67 1.2.2.2 joerg static const char rcsid[] = "@(#)Id: ip_scan.c,v 2.53.2.2 2012/01/29 03:08:31 darrenr Exp";
68 1.2.2.2 joerg #endif
69 1.2.2.2 joerg #endif
70 1.2.2.2 joerg
71 1.2.2.2 joerg #ifdef IPFILTER_SCAN /* endif at bottom of file */
72 1.2.2.2 joerg
73 1.2.2.2 joerg
74 1.2.2.2 joerg ipscan_t *ipf_scan_list = NULL,
75 1.2.2.2 joerg *ipf_scan_tail = NULL;
76 1.2.2.2 joerg ipscanstat_t ipf_scan_stat;
77 1.2.2.2 joerg # ifdef USE_MUTEXES
78 1.2.2.2 joerg ipfrwlock_t ipf_scan_rwlock;
79 1.2.2.2 joerg # endif
80 1.2.2.2 joerg
81 1.2.2.2 joerg # ifndef isalpha
82 1.2.2.2 joerg # define isalpha(x) (((x) >= 'A' && 'Z' >= (x)) || \
83 1.2.2.2 joerg ((x) >= 'a' && 'z' >= (x)))
84 1.2.2.2 joerg # endif
85 1.2.2.2 joerg
86 1.2.2.2 joerg
87 1.2.2.2 joerg int ipf_scan_add(void *);
88 1.2.2.2 joerg int ipf_scan_remove(void *);
89 1.2.2.2 joerg struct ipscan *ipf_scan_lookup(char *);
90 1.2.2.2 joerg int ipf_scan_matchstr(sinfo_t *, char *, int);
91 1.2.2.2 joerg int ipf_scan_matchisc(ipscan_t *, ipstate_t *, int, int, int *);
92 1.2.2.2 joerg int ipf_scan_match(ipstate_t *);
93 1.2.2.2 joerg
94 1.2.2.2 joerg static int ipf_scan_inited = 0;
95 1.2.2.2 joerg
96 1.2.2.2 joerg
97 1.2.2.2 joerg int
98 1.2.2.2 joerg ipf_scan_init()
99 1.2.2.2 joerg {
100 1.2.2.2 joerg RWLOCK_INIT(&ipf_scan_rwlock, "ip scan rwlock");
101 1.2.2.2 joerg ipf_scan_inited = 1;
102 1.2.2.2 joerg return 0;
103 1.2.2.2 joerg }
104 1.2.2.2 joerg
105 1.2.2.2 joerg
106 1.2.2.2 joerg void
107 1.2.2.2 joerg ipf_scan_unload(void *arg)
108 1.2.2.2 joerg {
109 1.2.2.2 joerg if (ipf_scan_inited == 1) {
110 1.2.2.2 joerg RW_DESTROY(&ipf_scan_rwlock);
111 1.2.2.2 joerg ipf_scan_inited = 0;
112 1.2.2.2 joerg }
113 1.2.2.2 joerg }
114 1.2.2.2 joerg
115 1.2.2.2 joerg
116 1.2.2.2 joerg int
117 1.2.2.2 joerg ipf_scan_add(data)
118 1.2.2.2 joerg void *data;
119 1.2.2.2 joerg {
120 1.2.2.2 joerg ipscan_t *i, *isc;
121 1.2.2.2 joerg int err;
122 1.2.2.2 joerg
123 1.2.2.2 joerg KMALLOC(isc, ipscan_t *);
124 1.2.2.2 joerg if (!isc) {
125 1.2.2.2 joerg ipf_interror = 90001;
126 1.2.2.2 joerg return ENOMEM;
127 1.2.2.2 joerg }
128 1.2.2.2 joerg
129 1.2.2.2 joerg err = copyinptr(data, isc, sizeof(*isc));
130 1.2.2.2 joerg if (err) {
131 1.2.2.2 joerg KFREE(isc);
132 1.2.2.2 joerg return err;
133 1.2.2.2 joerg }
134 1.2.2.2 joerg
135 1.2.2.2 joerg WRITE_ENTER(&ipf_scan_rwlock);
136 1.2.2.2 joerg
137 1.2.2.2 joerg i = ipf_scan_lookup(isc->ipsc_tag);
138 1.2.2.2 joerg if (i != NULL) {
139 1.2.2.2 joerg RWLOCK_EXIT(&ipf_scan_rwlock);
140 1.2.2.2 joerg KFREE(isc);
141 1.2.2.2 joerg ipf_interror = 90002;
142 1.2.2.2 joerg return EEXIST;
143 1.2.2.2 joerg }
144 1.2.2.2 joerg
145 1.2.2.2 joerg if (ipf_scan_tail) {
146 1.2.2.2 joerg ipf_scan_tail->ipsc_next = isc;
147 1.2.2.2 joerg isc->ipsc_pnext = &ipf_scan_tail->ipsc_next;
148 1.2.2.2 joerg ipf_scan_tail = isc;
149 1.2.2.2 joerg } else {
150 1.2.2.2 joerg ipf_scan_list = isc;
151 1.2.2.2 joerg ipf_scan_tail = isc;
152 1.2.2.2 joerg isc->ipsc_pnext = &ipf_scan_list;
153 1.2.2.2 joerg }
154 1.2.2.2 joerg isc->ipsc_next = NULL;
155 1.2.2.2 joerg
156 1.2.2.2 joerg isc->ipsc_hits = 0;
157 1.2.2.2 joerg isc->ipsc_fref = 0;
158 1.2.2.2 joerg isc->ipsc_sref = 0;
159 1.2.2.2 joerg isc->ipsc_active = 0;
160 1.2.2.2 joerg
161 1.2.2.2 joerg ipf_scan_stat.iscs_entries++;
162 1.2.2.2 joerg RWLOCK_EXIT(&ipf_scan_rwlock);
163 1.2.2.2 joerg return 0;
164 1.2.2.2 joerg }
165 1.2.2.2 joerg
166 1.2.2.2 joerg
167 1.2.2.2 joerg int
168 1.2.2.2 joerg ipf_scan_remove(data)
169 1.2.2.2 joerg void *data;
170 1.2.2.2 joerg {
171 1.2.2.2 joerg ipscan_t isc, *i;
172 1.2.2.2 joerg int err;
173 1.2.2.2 joerg
174 1.2.2.2 joerg err = copyinptr(data, &isc, sizeof(isc));
175 1.2.2.2 joerg if (err)
176 1.2.2.2 joerg return err;
177 1.2.2.2 joerg
178 1.2.2.2 joerg WRITE_ENTER(&ipf_scan_rwlock);
179 1.2.2.2 joerg
180 1.2.2.2 joerg i = ipf_scan_lookup(isc.ipsc_tag);
181 1.2.2.2 joerg if (i == NULL)
182 1.2.2.2 joerg err = ENOENT;
183 1.2.2.2 joerg else {
184 1.2.2.2 joerg if (i->ipsc_fref) {
185 1.2.2.2 joerg RWLOCK_EXIT(&ipf_scan_rwlock);
186 1.2.2.2 joerg ipf_interror = 90003;
187 1.2.2.2 joerg return EBUSY;
188 1.2.2.2 joerg }
189 1.2.2.2 joerg
190 1.2.2.2 joerg *i->ipsc_pnext = i->ipsc_next;
191 1.2.2.2 joerg if (i->ipsc_next)
192 1.2.2.2 joerg i->ipsc_next->ipsc_pnext = i->ipsc_pnext;
193 1.2.2.2 joerg else {
194 1.2.2.2 joerg if (i->ipsc_pnext == &ipf_scan_list)
195 1.2.2.2 joerg ipf_scan_tail = NULL;
196 1.2.2.2 joerg else
197 1.2.2.2 joerg ipf_scan_tail = *(*i->ipsc_pnext)->ipsc_pnext;
198 1.2.2.2 joerg }
199 1.2.2.2 joerg
200 1.2.2.2 joerg ipf_scan_stat.iscs_entries--;
201 1.2.2.2 joerg KFREE(i);
202 1.2.2.2 joerg }
203 1.2.2.2 joerg RWLOCK_EXIT(&ipf_scan_rwlock);
204 1.2.2.2 joerg return err;
205 1.2.2.2 joerg }
206 1.2.2.2 joerg
207 1.2.2.2 joerg
208 1.2.2.2 joerg struct ipscan *
209 1.2.2.2 joerg ipf_scan_lookup(tag)
210 1.2.2.2 joerg char *tag;
211 1.2.2.2 joerg {
212 1.2.2.2 joerg ipscan_t *i;
213 1.2.2.2 joerg
214 1.2.2.2 joerg for (i = ipf_scan_list; i; i = i->ipsc_next)
215 1.2.2.2 joerg if (!strcmp(i->ipsc_tag, tag))
216 1.2.2.2 joerg return i;
217 1.2.2.2 joerg return NULL;
218 1.2.2.2 joerg }
219 1.2.2.2 joerg
220 1.2.2.2 joerg
221 1.2.2.2 joerg int
222 1.2.2.2 joerg ipf_scan_attachfr(fr)
223 1.2.2.2 joerg struct frentry *fr;
224 1.2.2.2 joerg {
225 1.2.2.2 joerg ipscan_t *i;
226 1.2.2.2 joerg
227 1.2.2.2 joerg if (fr->fr_isctag != -1) {
228 1.2.2.2 joerg READ_ENTER(&ipf_scan_rwlock);
229 1.2.2.2 joerg i = ipf_scan_lookup(fr->fr_isctag + fr->fr_names);
230 1.2.2.2 joerg if (i != NULL) {
231 1.2.2.2 joerg ATOMIC_INC32(i->ipsc_fref);
232 1.2.2.2 joerg }
233 1.2.2.2 joerg RWLOCK_EXIT(&ipf_scan_rwlock);
234 1.2.2.2 joerg if (i == NULL) {
235 1.2.2.2 joerg ipf_interror = 90004;
236 1.2.2.2 joerg return ENOENT;
237 1.2.2.2 joerg }
238 1.2.2.2 joerg fr->fr_isc = i;
239 1.2.2.2 joerg }
240 1.2.2.2 joerg return 0;
241 1.2.2.2 joerg }
242 1.2.2.2 joerg
243 1.2.2.2 joerg
244 1.2.2.2 joerg int
245 1.2.2.2 joerg ipf_scan_attachis(is)
246 1.2.2.2 joerg struct ipstate *is;
247 1.2.2.2 joerg {
248 1.2.2.2 joerg frentry_t *fr;
249 1.2.2.2 joerg ipscan_t *i;
250 1.2.2.2 joerg
251 1.2.2.2 joerg READ_ENTER(&ipf_scan_rwlock);
252 1.2.2.2 joerg fr = is->is_rule;
253 1.2.2.2 joerg if (fr != NULL) {
254 1.2.2.2 joerg i = fr->fr_isc;
255 1.2.2.2 joerg if ((i != NULL) && (i != (ipscan_t *)-1)) {
256 1.2.2.2 joerg is->is_isc = i;
257 1.2.2.2 joerg ATOMIC_INC32(i->ipsc_sref);
258 1.2.2.2 joerg if (i->ipsc_clen)
259 1.2.2.2 joerg is->is_flags |= IS_SC_CLIENT;
260 1.2.2.2 joerg else
261 1.2.2.2 joerg is->is_flags |= IS_SC_MATCHC;
262 1.2.2.2 joerg if (i->ipsc_slen)
263 1.2.2.2 joerg is->is_flags |= IS_SC_SERVER;
264 1.2.2.2 joerg else
265 1.2.2.2 joerg is->is_flags |= IS_SC_MATCHS;
266 1.2.2.2 joerg }
267 1.2.2.2 joerg }
268 1.2.2.2 joerg RWLOCK_EXIT(&ipf_scan_rwlock);
269 1.2.2.2 joerg return 0;
270 1.2.2.2 joerg }
271 1.2.2.2 joerg
272 1.2.2.2 joerg
273 1.2.2.2 joerg int
274 1.2.2.2 joerg ipf_scan_detachfr(fr)
275 1.2.2.2 joerg struct frentry *fr;
276 1.2.2.2 joerg {
277 1.2.2.2 joerg ipscan_t *i;
278 1.2.2.2 joerg
279 1.2.2.2 joerg i = fr->fr_isc;
280 1.2.2.2 joerg if (i != NULL) {
281 1.2.2.2 joerg ATOMIC_DEC32(i->ipsc_fref);
282 1.2.2.2 joerg }
283 1.2.2.2 joerg return 0;
284 1.2.2.2 joerg }
285 1.2.2.2 joerg
286 1.2.2.2 joerg
287 1.2.2.2 joerg int
288 1.2.2.2 joerg ipf_scan_detachis(is)
289 1.2.2.2 joerg struct ipstate *is;
290 1.2.2.2 joerg {
291 1.2.2.2 joerg ipscan_t *i;
292 1.2.2.2 joerg
293 1.2.2.2 joerg READ_ENTER(&ipf_scan_rwlock);
294 1.2.2.2 joerg if ((i = is->is_isc) && (i != (ipscan_t *)-1)) {
295 1.2.2.2 joerg ATOMIC_DEC32(i->ipsc_sref);
296 1.2.2.2 joerg is->is_isc = NULL;
297 1.2.2.2 joerg is->is_flags &= ~(IS_SC_CLIENT|IS_SC_SERVER);
298 1.2.2.2 joerg }
299 1.2.2.2 joerg RWLOCK_EXIT(&ipf_scan_rwlock);
300 1.2.2.2 joerg return 0;
301 1.2.2.2 joerg }
302 1.2.2.2 joerg
303 1.2.2.2 joerg
304 1.2.2.2 joerg /*
305 1.2.2.2 joerg * 'string' compare for scanning
306 1.2.2.2 joerg */
307 1.2.2.2 joerg int
308 1.2.2.2 joerg ipf_scan_matchstr(sp, str, n)
309 1.2.2.2 joerg sinfo_t *sp;
310 1.2.2.2 joerg char *str;
311 1.2.2.2 joerg int n;
312 1.2.2.2 joerg {
313 1.2.2.2 joerg char *s, *t, *up;
314 1.2.2.2 joerg int i = n;
315 1.2.2.2 joerg
316 1.2.2.2 joerg if (i > sp->s_len)
317 1.2.2.2 joerg i = sp->s_len;
318 1.2.2.2 joerg up = str;
319 1.2.2.2 joerg
320 1.2.2.2 joerg for (s = sp->s_txt, t = sp->s_msk; i; i--, s++, t++, up++)
321 1.2.2.2 joerg switch ((int)*t)
322 1.2.2.2 joerg {
323 1.2.2.2 joerg case '.' :
324 1.2.2.2 joerg if (*s != *up)
325 1.2.2.2 joerg return 1;
326 1.2.2.2 joerg break;
327 1.2.2.2 joerg case '?' :
328 1.2.2.2 joerg if (!ISALPHA(*up) || ((*s & 0x5f) != (*up & 0x5f)))
329 1.2.2.2 joerg return 1;
330 1.2.2.2 joerg break;
331 1.2.2.2 joerg case '*' :
332 1.2.2.2 joerg break;
333 1.2.2.2 joerg }
334 1.2.2.2 joerg return 0;
335 1.2.2.2 joerg }
336 1.2.2.2 joerg
337 1.2.2.2 joerg
338 1.2.2.2 joerg /*
339 1.2.2.2 joerg * Returns 3 if both server and client match, 2 if just server,
340 1.2.2.2 joerg * 1 if just client
341 1.2.2.2 joerg */
342 1.2.2.2 joerg int
343 1.2.2.2 joerg ipf_scan_matchisc(isc, is, cl, sl, maxm)
344 1.2.2.2 joerg ipscan_t *isc;
345 1.2.2.2 joerg ipstate_t *is;
346 1.2.2.2 joerg int cl, sl, maxm[2];
347 1.2.2.2 joerg {
348 1.2.2.2 joerg int i, j, k, n, ret = 0, flags;
349 1.2.2.2 joerg
350 1.2.2.2 joerg flags = is->is_flags;
351 1.2.2.2 joerg
352 1.2.2.2 joerg /*
353 1.2.2.2 joerg * If we've already matched more than what is on offer, then
354 1.2.2.2 joerg * assume we have a better match already and forget this one.
355 1.2.2.2 joerg */
356 1.2.2.2 joerg if (maxm != NULL) {
357 1.2.2.2 joerg if (isc->ipsc_clen < maxm[0])
358 1.2.2.2 joerg return 0;
359 1.2.2.2 joerg if (isc->ipsc_slen < maxm[1])
360 1.2.2.2 joerg return 0;
361 1.2.2.2 joerg j = maxm[0];
362 1.2.2.2 joerg k = maxm[1];
363 1.2.2.2 joerg } else {
364 1.2.2.2 joerg j = 0;
365 1.2.2.2 joerg k = 0;
366 1.2.2.2 joerg }
367 1.2.2.2 joerg
368 1.2.2.2 joerg if (!isc->ipsc_clen)
369 1.2.2.2 joerg ret = 1;
370 1.2.2.2 joerg else if (((flags & (IS_SC_MATCHC|IS_SC_CLIENT)) == IS_SC_CLIENT) &&
371 1.2.2.2 joerg cl && isc->ipsc_clen) {
372 1.2.2.2 joerg i = 0;
373 1.2.2.2 joerg n = MIN(cl, isc->ipsc_clen);
374 1.2.2.2 joerg if ((n > 0) && (!maxm || (n >= maxm[1]))) {
375 1.2.2.2 joerg if (!ipf_scan_matchstr(&isc->ipsc_cl,
376 1.2.2.2 joerg is->is_sbuf[0], n)) {
377 1.2.2.2 joerg i++;
378 1.2.2.2 joerg ret |= 1;
379 1.2.2.2 joerg if (n > j)
380 1.2.2.2 joerg j = n;
381 1.2.2.2 joerg }
382 1.2.2.2 joerg }
383 1.2.2.2 joerg }
384 1.2.2.2 joerg
385 1.2.2.2 joerg if (!isc->ipsc_slen)
386 1.2.2.2 joerg ret |= 2;
387 1.2.2.2 joerg else if (((flags & (IS_SC_MATCHS|IS_SC_SERVER)) == IS_SC_SERVER) &&
388 1.2.2.2 joerg sl && isc->ipsc_slen) {
389 1.2.2.2 joerg i = 0;
390 1.2.2.2 joerg n = MIN(cl, isc->ipsc_slen);
391 1.2.2.2 joerg if ((n > 0) && (!maxm || (n >= maxm[1]))) {
392 1.2.2.2 joerg if (!ipf_scan_matchstr(&isc->ipsc_sl,
393 1.2.2.2 joerg is->is_sbuf[1], n)) {
394 1.2.2.2 joerg i++;
395 1.2.2.2 joerg ret |= 2;
396 1.2.2.2 joerg if (n > k)
397 1.2.2.2 joerg k = n;
398 1.2.2.2 joerg }
399 1.2.2.2 joerg }
400 1.2.2.2 joerg }
401 1.2.2.2 joerg
402 1.2.2.2 joerg if (maxm && (ret == 3)) {
403 1.2.2.2 joerg maxm[0] = j;
404 1.2.2.2 joerg maxm[1] = k;
405 1.2.2.2 joerg }
406 1.2.2.2 joerg return ret;
407 1.2.2.2 joerg }
408 1.2.2.2 joerg
409 1.2.2.2 joerg
410 1.2.2.2 joerg int
411 1.2.2.2 joerg ipf_scan_match(is)
412 1.2.2.2 joerg ipstate_t *is;
413 1.2.2.2 joerg {
414 1.2.2.2 joerg int i, j, k, n, cl, sl, maxm[2];
415 1.2.2.2 joerg ipscan_t *isc, *lm;
416 1.2.2.2 joerg tcpdata_t *t;
417 1.2.2.2 joerg
418 1.2.2.2 joerg for (cl = 0, n = is->is_smsk[0]; n & 1; n >>= 1)
419 1.2.2.2 joerg cl++;
420 1.2.2.2 joerg for (sl = 0, n = is->is_smsk[1]; n & 1; n >>= 1)
421 1.2.2.2 joerg sl++;
422 1.2.2.2 joerg
423 1.2.2.2 joerg j = 0;
424 1.2.2.2 joerg isc = is->is_isc;
425 1.2.2.2 joerg if (isc != NULL) {
426 1.2.2.2 joerg /*
427 1.2.2.2 joerg * Known object to scan for.
428 1.2.2.2 joerg */
429 1.2.2.2 joerg i = ipf_scan_matchisc(isc, is, cl, sl, NULL);
430 1.2.2.2 joerg if (i & 1) {
431 1.2.2.2 joerg is->is_flags |= IS_SC_MATCHC;
432 1.2.2.2 joerg is->is_flags &= ~IS_SC_CLIENT;
433 1.2.2.2 joerg } else if (cl >= isc->ipsc_clen)
434 1.2.2.2 joerg is->is_flags &= ~IS_SC_CLIENT;
435 1.2.2.2 joerg if (i & 2) {
436 1.2.2.2 joerg is->is_flags |= IS_SC_MATCHS;
437 1.2.2.2 joerg is->is_flags &= ~IS_SC_SERVER;
438 1.2.2.2 joerg } else if (sl >= isc->ipsc_slen)
439 1.2.2.2 joerg is->is_flags &= ~IS_SC_SERVER;
440 1.2.2.2 joerg } else {
441 1.2.2.2 joerg i = 0;
442 1.2.2.2 joerg lm = NULL;
443 1.2.2.2 joerg maxm[0] = 0;
444 1.2.2.2 joerg maxm[1] = 0;
445 1.2.2.2 joerg for (k = 0, isc = ipf_scan_list; isc; isc = isc->ipsc_next) {
446 1.2.2.2 joerg i = ipf_scan_matchisc(isc, is, cl, sl, maxm);
447 1.2.2.2 joerg if (i) {
448 1.2.2.2 joerg /*
449 1.2.2.2 joerg * We only want to remember the best match
450 1.2.2.2 joerg * and the number of times we get a best
451 1.2.2.2 joerg * match.
452 1.2.2.2 joerg */
453 1.2.2.2 joerg if ((j == 3) && (i < 3))
454 1.2.2.2 joerg continue;
455 1.2.2.2 joerg if ((i == 3) && (j != 3))
456 1.2.2.2 joerg k = 1;
457 1.2.2.2 joerg else
458 1.2.2.2 joerg k++;
459 1.2.2.2 joerg j = i;
460 1.2.2.2 joerg lm = isc;
461 1.2.2.2 joerg }
462 1.2.2.2 joerg }
463 1.2.2.2 joerg if (k == 1)
464 1.2.2.2 joerg isc = lm;
465 1.2.2.2 joerg if (isc == NULL)
466 1.2.2.2 joerg return 0;
467 1.2.2.2 joerg
468 1.2.2.2 joerg /*
469 1.2.2.2 joerg * No matches or partial matches, so reset the respective
470 1.2.2.2 joerg * search flag.
471 1.2.2.2 joerg */
472 1.2.2.2 joerg if (!(j & 1))
473 1.2.2.2 joerg is->is_flags &= ~IS_SC_CLIENT;
474 1.2.2.2 joerg
475 1.2.2.2 joerg if (!(j & 2))
476 1.2.2.2 joerg is->is_flags &= ~IS_SC_SERVER;
477 1.2.2.2 joerg
478 1.2.2.2 joerg /*
479 1.2.2.2 joerg * If we found the best match, then set flags appropriately.
480 1.2.2.2 joerg */
481 1.2.2.2 joerg if ((j == 3) && (k == 1)) {
482 1.2.2.2 joerg is->is_flags &= ~(IS_SC_SERVER|IS_SC_CLIENT);
483 1.2.2.2 joerg is->is_flags |= (IS_SC_MATCHS|IS_SC_MATCHC);
484 1.2.2.2 joerg }
485 1.2.2.2 joerg }
486 1.2.2.2 joerg
487 1.2.2.2 joerg /*
488 1.2.2.2 joerg * If the acknowledged side of a connection has moved past the data in
489 1.2.2.2 joerg * which we are interested, then reset respective flag.
490 1.2.2.2 joerg */
491 1.2.2.2 joerg t = &is->is_tcp.ts_data[0];
492 1.2.2.2 joerg if (t->td_end > is->is_s0[0] + 15)
493 1.2.2.2 joerg is->is_flags &= ~IS_SC_CLIENT;
494 1.2.2.2 joerg
495 1.2.2.2 joerg t = &is->is_tcp.ts_data[1];
496 1.2.2.2 joerg if (t->td_end > is->is_s0[1] + 15)
497 1.2.2.2 joerg is->is_flags &= ~IS_SC_SERVER;
498 1.2.2.2 joerg
499 1.2.2.2 joerg /*
500 1.2.2.2 joerg * Matching complete ?
501 1.2.2.2 joerg */
502 1.2.2.2 joerg j = ISC_A_NONE;
503 1.2.2.2 joerg if ((is->is_flags & IS_SC_MATCHALL) == IS_SC_MATCHALL) {
504 1.2.2.2 joerg j = isc->ipsc_action;
505 1.2.2.2 joerg ipf_scan_stat.iscs_acted++;
506 1.2.2.2 joerg } else if ((is->is_isc != NULL) &&
507 1.2.2.2 joerg ((is->is_flags & IS_SC_MATCHALL) != IS_SC_MATCHALL) &&
508 1.2.2.2 joerg !(is->is_flags & (IS_SC_CLIENT|IS_SC_SERVER))) {
509 1.2.2.2 joerg /*
510 1.2.2.2 joerg * Matching failed...
511 1.2.2.2 joerg */
512 1.2.2.2 joerg j = isc->ipsc_else;
513 1.2.2.2 joerg ipf_scan_stat.iscs_else++;
514 1.2.2.2 joerg }
515 1.2.2.2 joerg
516 1.2.2.2 joerg switch (j)
517 1.2.2.2 joerg {
518 1.2.2.2 joerg case ISC_A_CLOSE :
519 1.2.2.2 joerg /*
520 1.2.2.2 joerg * If as a result of a successful match we are to
521 1.2.2.2 joerg * close a connection, change the "keep state" info.
522 1.2.2.2 joerg * to block packets and generate TCP RST's.
523 1.2.2.2 joerg */
524 1.2.2.2 joerg is->is_pass &= ~FR_RETICMP;
525 1.2.2.2 joerg is->is_pass |= FR_RETRST;
526 1.2.2.2 joerg break;
527 1.2.2.2 joerg default :
528 1.2.2.2 joerg break;
529 1.2.2.2 joerg }
530 1.2.2.2 joerg
531 1.2.2.2 joerg return i;
532 1.2.2.2 joerg }
533 1.2.2.2 joerg
534 1.2.2.2 joerg
535 1.2.2.2 joerg /*
536 1.2.2.2 joerg * check if a packet matches what we're scanning for
537 1.2.2.2 joerg */
538 1.2.2.2 joerg int
539 1.2.2.2 joerg ipf_scan_packet(fin, is)
540 1.2.2.2 joerg fr_info_t *fin;
541 1.2.2.2 joerg ipstate_t *is;
542 1.2.2.2 joerg {
543 1.2.2.2 joerg int i, j, rv, dlen, off, thoff;
544 1.2.2.2 joerg u_32_t seq, s0;
545 1.2.2.2 joerg tcphdr_t *tcp;
546 1.2.2.2 joerg
547 1.2.2.2 joerg rv = !IP6_EQ(&fin->fin_fi.fi_src, &is->is_src);
548 1.2.2.2 joerg tcp = fin->fin_dp;
549 1.2.2.2 joerg seq = ntohl(tcp->th_seq);
550 1.2.2.2 joerg
551 1.2.2.2 joerg if (!is->is_s0[rv])
552 1.2.2.2 joerg return 1;
553 1.2.2.2 joerg
554 1.2.2.2 joerg /*
555 1.2.2.2 joerg * check if this packet has more data that falls within the first
556 1.2.2.2 joerg * 16 bytes sent in either direction.
557 1.2.2.2 joerg */
558 1.2.2.2 joerg s0 = is->is_s0[rv];
559 1.2.2.2 joerg off = seq - s0;
560 1.2.2.2 joerg if ((off > 15) || (off < 0))
561 1.2.2.2 joerg return 1;
562 1.2.2.2 joerg thoff = TCP_OFF(tcp) << 2;
563 1.2.2.2 joerg dlen = fin->fin_dlen - thoff;
564 1.2.2.2 joerg if (dlen <= 0)
565 1.2.2.2 joerg return 1;
566 1.2.2.2 joerg if (dlen > 16)
567 1.2.2.2 joerg dlen = 16;
568 1.2.2.2 joerg if (off + dlen > 16)
569 1.2.2.2 joerg dlen = 16 - off;
570 1.2.2.2 joerg
571 1.2.2.2 joerg j = 0xffff >> (16 - dlen);
572 1.2.2.2 joerg i = (0xffff & j) << off;
573 1.2.2.2 joerg #ifdef _KERNEL
574 1.2.2.2 joerg COPYDATA(*(mb_t **)fin->fin_mp, fin->fin_plen - fin->fin_dlen + thoff,
575 1.2.2.2 joerg dlen, (void *)is->is_sbuf[rv] + off);
576 1.2.2.2 joerg #endif
577 1.2.2.2 joerg is->is_smsk[rv] |= i;
578 1.2.2.2 joerg for (j = 0, i = is->is_smsk[rv]; i & 1; i >>= 1)
579 1.2.2.2 joerg j++;
580 1.2.2.2 joerg if (j == 0)
581 1.2.2.2 joerg return 1;
582 1.2.2.2 joerg
583 1.2.2.2 joerg (void) ipf_scan_match(is);
584 1.2.2.2 joerg #if 0
585 1.2.2.2 joerg /*
586 1.2.2.2 joerg * There is the potential here for plain text passwords to get
587 1.2.2.2 joerg * buffered and stored for some time...
588 1.2.2.2 joerg */
589 1.2.2.2 joerg if (!(is->is_flags & IS_SC_CLIENT))
590 1.2.2.2 joerg bzero(is->is_sbuf[0], sizeof(is->is_sbuf[0]));
591 1.2.2.2 joerg if (!(is->is_flags & IS_SC_SERVER))
592 1.2.2.2 joerg bzero(is->is_sbuf[1], sizeof(is->is_sbuf[1]));
593 1.2.2.2 joerg #endif
594 1.2.2.2 joerg return 0;
595 1.2.2.2 joerg }
596 1.2.2.2 joerg
597 1.2.2.2 joerg
598 1.2.2.2 joerg int
599 1.2.2.2 joerg ipf_scan_ioctl(data, cmd, mode, uid, ctx)
600 1.2.2.2 joerg void *data;
601 1.2.2.2 joerg ioctlcmd_t cmd;
602 1.2.2.2 joerg int mode, uid;
603 1.2.2.2 joerg void *ctx;
604 1.2.2.2 joerg {
605 1.2.2.2 joerg ipscanstat_t ipscs;
606 1.2.2.2 joerg int err = 0;
607 1.2.2.2 joerg
608 1.2.2.2 joerg switch (cmd)
609 1.2.2.2 joerg {
610 1.2.2.2 joerg case SIOCADSCA :
611 1.2.2.2 joerg err = ipf_scan_add(data);
612 1.2.2.2 joerg break;
613 1.2.2.2 joerg case SIOCRMSCA :
614 1.2.2.2 joerg err = ipf_scan_remove(data);
615 1.2.2.2 joerg break;
616 1.2.2.2 joerg case SIOCGSCST :
617 1.2.2.2 joerg bcopy((char *)&ipf_scan_stat, (char *)&ipscs, sizeof(ipscs));
618 1.2.2.2 joerg ipscs.iscs_list = ipf_scan_list;
619 1.2.2.2 joerg err = BCOPYOUT(&ipscs, data, sizeof(ipscs));
620 1.2.2.2 joerg if (err != 0) {
621 1.2.2.2 joerg ipf_interror = 90005;
622 1.2.2.2 joerg err = EFAULT;
623 1.2.2.2 joerg }
624 1.2.2.2 joerg break;
625 1.2.2.2 joerg default :
626 1.2.2.2 joerg err = EINVAL;
627 1.2.2.2 joerg break;
628 1.2.2.2 joerg }
629 1.2.2.2 joerg
630 1.2.2.2 joerg return err;
631 1.2.2.2 joerg }
632 1.2.2.2 joerg #endif /* IPFILTER_SCAN */
633