1 /* $FreeBSD$ */
2
3 /*
4 * Copyright (C) 2012 by Darren Reed.
5 *
6 * See the IPFILTER.LICENCE file for details on licencing.
7 */
8 #if defined(KERNEL) || defined(_KERNEL)
9 # undef KERNEL
10 # undef _KERNEL
11 # define KERNEL 1
12 # define _KERNEL 1
13 #endif
14 #include <sys/param.h>
15 #include <sys/types.h>
16 #include <sys/errno.h>
17 #include <sys/time.h>
18 #include <sys/file.h>
19 #if !defined(_KERNEL)
20 # include <stdlib.h>
21 # include <string.h>
22 # define _KERNEL
23 # include <sys/uio.h>
24 # undef _KERNEL
25 #endif
26 #include <sys/socket.h>
27 #if defined(__FreeBSD_version)
28 # include <sys/malloc.h>
29 #endif
30 #if defined(__FreeBSD__)
31 # include <sys/cdefs.h>
32 # include <sys/proc.h>
33 #endif
34 #if !defined(__SVR4)
35 # include <sys/mbuf.h>
36 #endif
37 #if defined(_KERNEL)
38 # include <sys/systm.h>
39 #else
40 # include "ipf.h"
41 #endif
42 #include <netinet/in.h>
43 #include <net/if.h>
44
45 #include "netinet/ip_compat.h"
46 #include "netinet/ip_fil.h"
47 #include "netinet/ip_lookup.h"
48 #include "netinet/ip_htable.h"
49 /* END OF INCLUDES */
50
51 #if !defined(lint)
52 static const char rcsid[] = "@(#)$Id$";
53 #endif
54
55 # ifdef USE_INET6
56 static iphtent_t *ipf_iphmfind6 __P((iphtable_t *, i6addr_t *));
57 # endif
58 static iphtent_t *ipf_iphmfind __P((iphtable_t *, struct in_addr *));
59 static int ipf_iphmfindip __P((ipf_main_softc_t *, void *, int, void *, u_int));
60 static int ipf_htable_clear __P((ipf_main_softc_t *, void *, iphtable_t *));
61 static int ipf_htable_create __P((ipf_main_softc_t *, void *, iplookupop_t *));
62 static int ipf_htable_deref __P((ipf_main_softc_t *, void *, void *));
63 static int ipf_htable_destroy __P((ipf_main_softc_t *, void *, int, char *));
64 static void *ipf_htable_exists __P((void *, int, char *));
65 static size_t ipf_htable_flush __P((ipf_main_softc_t *, void *,
66 iplookupflush_t *));
67 static void ipf_htable_free __P((void *, iphtable_t *));
68 static int ipf_htable_iter_deref __P((ipf_main_softc_t *, void *, int,
69 int, void *));
70 static int ipf_htable_iter_next __P((ipf_main_softc_t *, void *, ipftoken_t *,
71 ipflookupiter_t *));
72 static int ipf_htable_node_add __P((ipf_main_softc_t *, void *,
73 iplookupop_t *, int));
74 static int ipf_htable_node_del __P((ipf_main_softc_t *, void *,
75 iplookupop_t *, int));
76 static int ipf_htable_remove __P((ipf_main_softc_t *, void *, iphtable_t *));
77 static void *ipf_htable_soft_create __P((ipf_main_softc_t *));
78 static void ipf_htable_soft_destroy __P((ipf_main_softc_t *, void *));
79 static int ipf_htable_soft_init __P((ipf_main_softc_t *, void *));
80 static void ipf_htable_soft_fini __P((ipf_main_softc_t *, void *));
81 static int ipf_htable_stats_get __P((ipf_main_softc_t *, void *,
82 iplookupop_t *));
83 static int ipf_htable_table_add __P((ipf_main_softc_t *, void *,
84 iplookupop_t *));
85 static int ipf_htable_table_del __P((ipf_main_softc_t *, void *,
86 iplookupop_t *));
87 static int ipf_htent_deref __P((void *, iphtent_t *));
88 static iphtent_t *ipf_htent_find __P((iphtable_t *, iphtent_t *));
89 static int ipf_htent_insert __P((ipf_main_softc_t *, void *, iphtable_t *,
90 iphtent_t *));
91 static int ipf_htent_remove __P((ipf_main_softc_t *, void *, iphtable_t *,
92 iphtent_t *));
93 static void *ipf_htable_select_add_ref __P((void *, int, char *));
94 static void ipf_htable_expire __P((ipf_main_softc_t *, void *));
95
96
97 typedef struct ipf_htable_softc_s {
98 u_long ipht_nomem[LOOKUP_POOL_SZ];
99 u_long ipf_nhtables[LOOKUP_POOL_SZ];
100 u_long ipf_nhtnodes[LOOKUP_POOL_SZ];
101 iphtable_t *ipf_htables[LOOKUP_POOL_SZ];
102 iphtent_t *ipf_node_explist;
103 } ipf_htable_softc_t;
104
105 ipf_lookup_t ipf_htable_backend = {
106 IPLT_HASH,
107 ipf_htable_soft_create,
108 ipf_htable_soft_destroy,
109 ipf_htable_soft_init,
110 ipf_htable_soft_fini,
111 ipf_iphmfindip,
112 ipf_htable_flush,
113 ipf_htable_iter_deref,
114 ipf_htable_iter_next,
115 ipf_htable_node_add,
116 ipf_htable_node_del,
117 ipf_htable_stats_get,
118 ipf_htable_table_add,
119 ipf_htable_table_del,
120 ipf_htable_deref,
121 ipf_htable_exists,
122 ipf_htable_select_add_ref,
123 NULL,
124 ipf_htable_expire,
125 NULL
126 };
127
128
129 /* ------------------------------------------------------------------------ */
130 /* Function: ipf_htable_soft_create */
131 /* Returns: void * - NULL = failure, else pointer to local context */
132 /* Parameters: softc(I) - pointer to soft context main structure */
133 /* */
134 /* Initialise the routing table data structures where required. */
135 /* ------------------------------------------------------------------------ */
136 static void *
ipf_htable_soft_create(softc)137 ipf_htable_soft_create(softc)
138 ipf_main_softc_t *softc;
139 {
140 ipf_htable_softc_t *softh;
141
142 KMALLOC(softh, ipf_htable_softc_t *);
143 if (softh == NULL) {
144 IPFERROR(30026);
145 return NULL;
146 }
147
148 bzero((char *)softh, sizeof(*softh));
149
150 return softh;
151 }
152
153
154 /* ------------------------------------------------------------------------ */
155 /* Function: ipf_htable_soft_destroy */
156 /* Returns: Nil */
157 /* Parameters: softc(I) - pointer to soft context main structure */
158 /* arg(I) - pointer to local context to use */
159 /* */
160 /* Clean up the pool by free'ing the radix tree associated with it and free */
161 /* up the pool context too. */
162 /* ------------------------------------------------------------------------ */
163 static void
ipf_htable_soft_destroy(softc,arg)164 ipf_htable_soft_destroy(softc, arg)
165 ipf_main_softc_t *softc;
166 void *arg;
167 {
168 ipf_htable_softc_t *softh = arg;
169
170 KFREE(softh);
171 }
172
173
174 /* ------------------------------------------------------------------------ */
175 /* Function: ipf_htable_soft_init */
176 /* Returns: int - 0 = success, else error */
177 /* Parameters: softc(I) - pointer to soft context main structure */
178 /* arg(I) - pointer to local context to use */
179 /* */
180 /* Initialise the hash table ready for use. */
181 /* ------------------------------------------------------------------------ */
182 static int
ipf_htable_soft_init(softc,arg)183 ipf_htable_soft_init(softc, arg)
184 ipf_main_softc_t *softc;
185 void *arg;
186 {
187 ipf_htable_softc_t *softh = arg;
188
189 bzero((char *)softh, sizeof(*softh));
190
191 return 0;
192 }
193
194
195 /* ------------------------------------------------------------------------ */
196 /* Function: ipf_htable_soft_fini */
197 /* Returns: Nil */
198 /* Parameters: softc(I) - pointer to soft context main structure */
199 /* arg(I) - pointer to local context to use */
200 /* Locks: WRITE(ipf_global) */
201 /* */
202 /* Clean up all the pool data structures allocated and call the cleanup */
203 /* function for the radix tree that supports the pools. ipf_pool_destroy is */
204 /* used to delete the pools one by one to ensure they're properly freed up. */
205 /* ------------------------------------------------------------------------ */
206 static void
ipf_htable_soft_fini(softc,arg)207 ipf_htable_soft_fini(softc, arg)
208 ipf_main_softc_t *softc;
209 void *arg;
210 {
211 iplookupflush_t fop;
212
213 fop.iplf_type = IPLT_HASH;
214 fop.iplf_unit = IPL_LOGALL;
215 fop.iplf_arg = 0;
216 fop.iplf_count = 0;
217 *fop.iplf_name = '\0';
218 ipf_htable_flush(softc, arg, &fop);
219 }
220
221
222 /* ------------------------------------------------------------------------ */
223 /* Function: ipf_htable_stats_get */
224 /* Returns: int - 0 = success, else error */
225 /* Parameters: softc(I) - pointer to soft context main structure */
226 /* arg(I) - pointer to local context to use */
227 /* op(I) - pointer to lookup operation data */
228 /* */
229 /* Copy the relevant statistics out of internal structures and into the */
230 /* structure used to export statistics. */
231 /* ------------------------------------------------------------------------ */
232 static int
ipf_htable_stats_get(softc,arg,op)233 ipf_htable_stats_get(softc, arg, op)
234 ipf_main_softc_t *softc;
235 void *arg;
236 iplookupop_t *op;
237 {
238 ipf_htable_softc_t *softh = arg;
239 iphtstat_t stats;
240 int err;
241
242 if (op->iplo_size != sizeof(stats)) {
243 IPFERROR(30001);
244 return EINVAL;
245 }
246
247 stats.iphs_tables = softh->ipf_htables[op->iplo_unit + 1];
248 stats.iphs_numtables = softh->ipf_nhtables[op->iplo_unit + 1];
249 stats.iphs_numnodes = softh->ipf_nhtnodes[op->iplo_unit + 1];
250 stats.iphs_nomem = softh->ipht_nomem[op->iplo_unit + 1];
251
252 err = COPYOUT(&stats, op->iplo_struct, sizeof(stats));
253 if (err != 0) {
254 IPFERROR(30013);
255 return EFAULT;
256 }
257 return 0;
258
259 }
260
261
262 /* ------------------------------------------------------------------------ */
263 /* Function: ipf_htable_create */
264 /* Returns: int - 0 = success, else error */
265 /* Parameters: softc(I) - pointer to soft context main structure */
266 /* arg(I) - pointer to local context to use */
267 /* op(I) - pointer to lookup operation data */
268 /* */
269 /* Create a new hash table using the template passed. */
270 /* ------------------------------------------------------------------------ */
271 static int
ipf_htable_create(softc,arg,op)272 ipf_htable_create(softc, arg, op)
273 ipf_main_softc_t *softc;
274 void *arg;
275 iplookupop_t *op;
276 {
277 ipf_htable_softc_t *softh = arg;
278 iphtable_t htab, *iph, *oiph;
279 char name[FR_GROUPLEN];
280 int err, i, unit;
281
282 if (op->iplo_size != sizeof(htab)) {
283 IPFERROR(30024);
284 return EINVAL;
285 }
286 err = COPYIN(op->iplo_struct, &htab, sizeof(htab));
287 if (err != 0) {
288 IPFERROR(30003);
289 return EFAULT;
290 }
291
292 unit = op->iplo_unit;
293 if (htab.iph_unit != unit) {
294 IPFERROR(30005);
295 return EINVAL;
296 }
297 if (htab.iph_size < 1) {
298 IPFERROR(30025);
299 return EINVAL;
300 }
301
302
303 if ((op->iplo_arg & IPHASH_ANON) == 0) {
304 iph = ipf_htable_exists(softh, unit, op->iplo_name);
305 if (iph != NULL) {
306 if ((iph->iph_flags & IPHASH_DELETE) == 0) {
307 IPFERROR(30004);
308 return EEXIST;
309 }
310 iph->iph_flags &= ~IPHASH_DELETE;
311 iph->iph_ref++;
312 return 0;
313 }
314 }
315
316 KMALLOC(iph, iphtable_t *);
317 if (iph == NULL) {
318 softh->ipht_nomem[op->iplo_unit + 1]++;
319 IPFERROR(30002);
320 return ENOMEM;
321 }
322 *iph = htab;
323
324 if ((op->iplo_arg & IPHASH_ANON) != 0) {
325 i = IPHASH_ANON;
326 do {
327 i++;
328 #if defined(SNPRINTF) && defined(_KERNEL)
329 SNPRINTF(name, sizeof(name), "%u", i);
330 #else
331 (void)sprintf(name, "%u", i);
332 #endif
333 for (oiph = softh->ipf_htables[unit + 1]; oiph != NULL;
334 oiph = oiph->iph_next)
335 if (strncmp(oiph->iph_name, name,
336 sizeof(oiph->iph_name)) == 0)
337 break;
338 } while (oiph != NULL);
339
340 (void)strncpy(iph->iph_name, name, sizeof(iph->iph_name));
341 (void)strncpy(op->iplo_name, name, sizeof(op->iplo_name));
342 iph->iph_type |= IPHASH_ANON;
343 } else {
344 (void)strncpy(iph->iph_name, op->iplo_name,
345 sizeof(iph->iph_name));
346 iph->iph_name[sizeof(iph->iph_name) - 1] = '\0';
347 }
348
349 KMALLOCS(iph->iph_table, iphtent_t **,
350 iph->iph_size * sizeof(*iph->iph_table));
351 if (iph->iph_table == NULL) {
352 KFREE(iph);
353 softh->ipht_nomem[unit + 1]++;
354 IPFERROR(30006);
355 return ENOMEM;
356 }
357
358 bzero((char *)iph->iph_table, iph->iph_size * sizeof(*iph->iph_table));
359 iph->iph_maskset[0] = 0;
360 iph->iph_maskset[1] = 0;
361 iph->iph_maskset[2] = 0;
362 iph->iph_maskset[3] = 0;
363
364 iph->iph_ref = 1;
365 iph->iph_list = NULL;
366 iph->iph_tail = &iph->iph_list;
367 iph->iph_next = softh->ipf_htables[unit + 1];
368 iph->iph_pnext = &softh->ipf_htables[unit + 1];
369 if (softh->ipf_htables[unit + 1] != NULL)
370 softh->ipf_htables[unit + 1]->iph_pnext = &iph->iph_next;
371 softh->ipf_htables[unit + 1] = iph;
372
373 softh->ipf_nhtables[unit + 1]++;
374
375 return 0;
376 }
377
378
379 /* ------------------------------------------------------------------------ */
380 /* Function: ipf_htable_table_del */
381 /* Returns: int - 0 = success, else error */
382 /* Parameters: softc(I) - pointer to soft context main structure */
383 /* arg(I) - pointer to local context to use */
384 /* op(I) - pointer to lookup operation data */
385 /* */
386 /* ------------------------------------------------------------------------ */
387 static int
ipf_htable_table_del(softc,arg,op)388 ipf_htable_table_del(softc, arg, op)
389 ipf_main_softc_t *softc;
390 void *arg;
391 iplookupop_t *op;
392 {
393 return ipf_htable_destroy(softc, arg, op->iplo_unit, op->iplo_name);
394 }
395
396
397 /* ------------------------------------------------------------------------ */
398 /* Function: ipf_htable_destroy */
399 /* Returns: int - 0 = success, else error */
400 /* Parameters: softc(I) - pointer to soft context main structure */
401 /* arg(I) - pointer to local context to use */
402 /* op(I) - pointer to lookup operation data */
403 /* */
404 /* Find the hash table that belongs to the relevant part of ipfilter with a */
405 /* matching name and attempt to destroy it. If it is in use, empty it out */
406 /* and mark it for deletion so that when all the references disappear, it */
407 /* can be removed. */
408 /* ------------------------------------------------------------------------ */
409 static int
ipf_htable_destroy(softc,arg,unit,name)410 ipf_htable_destroy(softc, arg, unit, name)
411 ipf_main_softc_t *softc;
412 void *arg;
413 int unit;
414 char *name;
415 {
416 iphtable_t *iph;
417
418 iph = ipf_htable_find(arg, unit, name);
419 if (iph == NULL) {
420 IPFERROR(30007);
421 return ESRCH;
422 }
423
424 if (iph->iph_unit != unit) {
425 IPFERROR(30008);
426 return EINVAL;
427 }
428
429 if (iph->iph_ref != 0) {
430 ipf_htable_clear(softc, arg, iph);
431 iph->iph_flags |= IPHASH_DELETE;
432 return 0;
433 }
434
435 ipf_htable_remove(softc, arg, iph);
436
437 return 0;
438 }
439
440
441 /* ------------------------------------------------------------------------ */
442 /* Function: ipf_htable_clear */
443 /* Returns: int - 0 = success, else error */
444 /* Parameters: softc(I) - pointer to soft context main structure */
445 /* arg(I) - pointer to local context to use */
446 /* iph(I) - pointer to hash table to destroy */
447 /* */
448 /* Clean out the hash table by walking the list of entries and removing */
449 /* each one, one by one. */
450 /* ------------------------------------------------------------------------ */
451 static int
ipf_htable_clear(softc,arg,iph)452 ipf_htable_clear(softc, arg, iph)
453 ipf_main_softc_t *softc;
454 void *arg;
455 iphtable_t *iph;
456 {
457 iphtent_t *ipe;
458
459 while ((ipe = iph->iph_list) != NULL)
460 if (ipf_htent_remove(softc, arg, iph, ipe) != 0)
461 return 1;
462 return 0;
463 }
464
465
466 /* ------------------------------------------------------------------------ */
467 /* Function: ipf_htable_free */
468 /* Returns: Nil */
469 /* Parameters: arg(I) - pointer to local context to use */
470 /* iph(I) - pointer to hash table to destroy */
471 /* */
472 /* ------------------------------------------------------------------------ */
473 static void
ipf_htable_free(arg,iph)474 ipf_htable_free(arg, iph)
475 void *arg;
476 iphtable_t *iph;
477 {
478 ipf_htable_softc_t *softh = arg;
479
480 if (iph->iph_next != NULL)
481 iph->iph_next->iph_pnext = iph->iph_pnext;
482 if (iph->iph_pnext != NULL)
483 *iph->iph_pnext = iph->iph_next;
484 iph->iph_pnext = NULL;
485 iph->iph_next = NULL;
486
487 softh->ipf_nhtables[iph->iph_unit + 1]--;
488
489 KFREES(iph->iph_table, iph->iph_size * sizeof(*iph->iph_table));
490 KFREE(iph);
491 }
492
493
494 /* ------------------------------------------------------------------------ */
495 /* Function: ipf_htable_remove */
496 /* Returns: int - 0 = success, else error */
497 /* Parameters: softc(I) - pointer to soft context main structure */
498 /* arg(I) - pointer to local context to use */
499 /* iph(I) - pointer to hash table to destroy */
500 /* */
501 /* It is necessary to unlink here as well as free (called by deref) so that */
502 /* the while loop in ipf_htable_flush() functions properly. */
503 /* ------------------------------------------------------------------------ */
504 static int
ipf_htable_remove(softc,arg,iph)505 ipf_htable_remove(softc, arg, iph)
506 ipf_main_softc_t *softc;
507 void *arg;
508 iphtable_t *iph;
509 {
510
511 if (ipf_htable_clear(softc, arg, iph) != 0)
512 return 1;
513
514 if (iph->iph_pnext != NULL)
515 *iph->iph_pnext = iph->iph_next;
516 if (iph->iph_next != NULL)
517 iph->iph_next->iph_pnext = iph->iph_pnext;
518 iph->iph_pnext = NULL;
519 iph->iph_next = NULL;
520
521 return ipf_htable_deref(softc, arg, iph);
522 }
523
524
525 /* ------------------------------------------------------------------------ */
526 /* Function: ipf_htable_node_del */
527 /* Returns: int - 0 = success, else error */
528 /* Parameters: softc(I) - pointer to soft context main structure */
529 /* arg(I) - pointer to local context to use */
530 /* op(I) - pointer to lookup operation data */
531 /* uid(I) - real uid of process doing operation */
532 /* */
533 /* ------------------------------------------------------------------------ */
534 static int
ipf_htable_node_del(softc,arg,op,uid)535 ipf_htable_node_del(softc, arg, op, uid)
536 ipf_main_softc_t *softc;
537 void *arg;
538 iplookupop_t *op;
539 int uid;
540 {
541 iphtable_t *iph;
542 iphtent_t hte, *ent;
543 int err;
544
545 if (op->iplo_size != sizeof(hte)) {
546 IPFERROR(30014);
547 return EINVAL;
548 }
549
550 err = COPYIN(op->iplo_struct, &hte, sizeof(hte));
551 if (err != 0) {
552 IPFERROR(30015);
553 return EFAULT;
554 }
555
556 iph = ipf_htable_find(arg, op->iplo_unit, op->iplo_name);
557 if (iph == NULL) {
558 IPFERROR(30016);
559 return ESRCH;
560 }
561
562 ent = ipf_htent_find(iph, &hte);
563 if (ent == NULL) {
564 IPFERROR(30022);
565 return ESRCH;
566 }
567
568 if ((uid != 0) && (ent->ipe_uid != uid)) {
569 IPFERROR(30023);
570 return EACCES;
571 }
572
573 err = ipf_htent_remove(softc, arg, iph, ent);
574
575 return err;
576 }
577
578
579 /* ------------------------------------------------------------------------ */
580 /* Function: ipf_htable_node_del */
581 /* Returns: int - 0 = success, else error */
582 /* Parameters: softc(I) - pointer to soft context main structure */
583 /* arg(I) - pointer to local context to use */
584 /* op(I) - pointer to lookup operation data */
585 /* */
586 /* ------------------------------------------------------------------------ */
587 static int
ipf_htable_table_add(softc,arg,op)588 ipf_htable_table_add(softc, arg, op)
589 ipf_main_softc_t *softc;
590 void *arg;
591 iplookupop_t *op;
592 {
593 int err;
594
595 if (ipf_htable_find(arg, op->iplo_unit, op->iplo_name) != NULL) {
596 IPFERROR(30017);
597 err = EEXIST;
598 } else {
599 err = ipf_htable_create(softc, arg, op);
600 }
601
602 return err;
603 }
604
605
606 /* ------------------------------------------------------------------------ */
607 /* Function: ipf_htent_remove */
608 /* Returns: int - 0 = success, else error */
609 /* Parameters: softc(I) - pointer to soft context main structure */
610 /* arg(I) - pointer to local context to use */
611 /* iph(I) - pointer to hash table */
612 /* ipe(I) - pointer to hash table entry to remove */
613 /* */
614 /* Delete an entry from a hash table. */
615 /* ------------------------------------------------------------------------ */
616 static int
ipf_htent_remove(softc,arg,iph,ipe)617 ipf_htent_remove(softc, arg, iph, ipe)
618 ipf_main_softc_t *softc;
619 void *arg;
620 iphtable_t *iph;
621 iphtent_t *ipe;
622 {
623
624 if (iph->iph_tail == &ipe->ipe_next)
625 iph->iph_tail = ipe->ipe_pnext;
626
627 if (ipe->ipe_hnext != NULL)
628 ipe->ipe_hnext->ipe_phnext = ipe->ipe_phnext;
629 if (ipe->ipe_phnext != NULL)
630 *ipe->ipe_phnext = ipe->ipe_hnext;
631 ipe->ipe_phnext = NULL;
632 ipe->ipe_hnext = NULL;
633
634 if (ipe->ipe_dnext != NULL)
635 ipe->ipe_dnext->ipe_pdnext = ipe->ipe_pdnext;
636 if (ipe->ipe_pdnext != NULL)
637 *ipe->ipe_pdnext = ipe->ipe_dnext;
638 ipe->ipe_pdnext = NULL;
639 ipe->ipe_dnext = NULL;
640
641 if (ipe->ipe_next != NULL)
642 ipe->ipe_next->ipe_pnext = ipe->ipe_pnext;
643 if (ipe->ipe_pnext != NULL)
644 *ipe->ipe_pnext = ipe->ipe_next;
645 ipe->ipe_pnext = NULL;
646 ipe->ipe_next = NULL;
647
648 switch (iph->iph_type & ~IPHASH_ANON)
649 {
650 case IPHASH_GROUPMAP :
651 if (ipe->ipe_group != NULL)
652 ipf_group_del(softc, ipe->ipe_ptr, NULL);
653 break;
654
655 default :
656 ipe->ipe_ptr = NULL;
657 ipe->ipe_value = 0;
658 break;
659 }
660
661 return ipf_htent_deref(arg, ipe);
662 }
663
664
665 /* ------------------------------------------------------------------------ */
666 /* Function: ipf_htable_deref */
667 /* Returns: int - 0 = success, else error */
668 /* Parameters: softc(I) - pointer to soft context main structure */
669 /* arg(I) - pointer to local context to use */
670 /* object(I) - pointer to hash table */
671 /* */
672 /* ------------------------------------------------------------------------ */
673 static int
ipf_htable_deref(softc,arg,object)674 ipf_htable_deref(softc, arg, object)
675 ipf_main_softc_t *softc;
676 void *arg, *object;
677 {
678 ipf_htable_softc_t *softh = arg;
679 iphtable_t *iph = object;
680 int refs;
681
682 iph->iph_ref--;
683 refs = iph->iph_ref;
684
685 if (iph->iph_ref == 0) {
686 ipf_htable_free(softh, iph);
687 }
688
689 return refs;
690 }
691
692
693 /* ------------------------------------------------------------------------ */
694 /* Function: ipf_htent_deref */
695 /* Parameters: arg(I) - pointer to local context to use */
696 /* ipe(I) - */
697 /* */
698 /* ------------------------------------------------------------------------ */
699 static int
ipf_htent_deref(arg,ipe)700 ipf_htent_deref(arg, ipe)
701 void *arg;
702 iphtent_t *ipe;
703 {
704 ipf_htable_softc_t *softh = arg;
705
706 ipe->ipe_ref--;
707 if (ipe->ipe_ref == 0) {
708 softh->ipf_nhtnodes[ipe->ipe_unit + 1]--;
709 KFREE(ipe);
710
711 return 0;
712 }
713
714 return ipe->ipe_ref;
715 }
716
717
718 /* ------------------------------------------------------------------------ */
719 /* Function: ipf_htable_exists */
720 /* Parameters: arg(I) - pointer to local context to use */
721 /* */
722 /* ------------------------------------------------------------------------ */
723 static void *
ipf_htable_exists(arg,unit,name)724 ipf_htable_exists(arg, unit, name)
725 void *arg;
726 int unit;
727 char *name;
728 {
729 ipf_htable_softc_t *softh = arg;
730 iphtable_t *iph;
731
732 if (unit == IPL_LOGALL) {
733 int i;
734
735 for (i = 0; i <= LOOKUP_POOL_MAX; i++) {
736 for (iph = softh->ipf_htables[i]; iph != NULL;
737 iph = iph->iph_next) {
738 if (strncmp(iph->iph_name, name,
739 sizeof(iph->iph_name)) == 0)
740 break;
741 }
742 if (iph != NULL)
743 break;
744 }
745 } else {
746 for (iph = softh->ipf_htables[unit + 1]; iph != NULL;
747 iph = iph->iph_next) {
748 if (strncmp(iph->iph_name, name,
749 sizeof(iph->iph_name)) == 0)
750 break;
751 }
752 }
753 return iph;
754 }
755
756
757 /* ------------------------------------------------------------------------ */
758 /* Function: ipf_htable_select_add_ref */
759 /* Returns: void * - NULL = failure, else pointer to the hash table */
760 /* Parameters: arg(I) - pointer to local context to use */
761 /* unit(I) - ipfilter device to which we are working on */
762 /* name(I) - name of the hash table */
763 /* */
764 /* ------------------------------------------------------------------------ */
765 static void *
ipf_htable_select_add_ref(arg,unit,name)766 ipf_htable_select_add_ref(arg, unit, name)
767 void *arg;
768 int unit;
769 char *name;
770 {
771 iphtable_t *iph;
772
773 iph = ipf_htable_exists(arg, unit, name);
774 if (iph != NULL) {
775 ATOMIC_INC32(iph->iph_ref);
776 }
777 return iph;
778 }
779
780
781 /* ------------------------------------------------------------------------ */
782 /* Function: ipf_htable_find */
783 /* Returns: void * - NULL = failure, else pointer to the hash table */
784 /* Parameters: arg(I) - pointer to local context to use */
785 /* unit(I) - ipfilter device to which we are working on */
786 /* name(I) - name of the hash table */
787 /* */
788 /* This function is exposed becaues it is used in the group-map feature. */
789 /* ------------------------------------------------------------------------ */
790 iphtable_t *
ipf_htable_find(arg,unit,name)791 ipf_htable_find(arg, unit, name)
792 void *arg;
793 int unit;
794 char *name;
795 {
796 iphtable_t *iph;
797
798 iph = ipf_htable_exists(arg, unit, name);
799 if ((iph != NULL) && (iph->iph_flags & IPHASH_DELETE) == 0)
800 return iph;
801
802 return NULL;
803 }
804
805
806 /* ------------------------------------------------------------------------ */
807 /* Function: ipf_htable_flush */
808 /* Returns: size_t - number of entries flushed */
809 /* Parameters: softc(I) - pointer to soft context main structure */
810 /* arg(I) - pointer to local context to use */
811 /* op(I) - pointer to lookup operation data */
812 /* */
813 /* ------------------------------------------------------------------------ */
814 static size_t
ipf_htable_flush(softc,arg,op)815 ipf_htable_flush(softc, arg, op)
816 ipf_main_softc_t *softc;
817 void *arg;
818 iplookupflush_t *op;
819 {
820 ipf_htable_softc_t *softh = arg;
821 iphtable_t *iph;
822 size_t freed;
823 int i;
824
825 freed = 0;
826
827 for (i = -1; i <= IPL_LOGMAX; i++) {
828 if (op->iplf_unit == i || op->iplf_unit == IPL_LOGALL) {
829 while ((iph = softh->ipf_htables[i + 1]) != NULL) {
830 if (ipf_htable_remove(softc, arg, iph) == 0) {
831 freed++;
832 } else {
833 iph->iph_flags |= IPHASH_DELETE;
834 }
835 }
836 }
837 }
838
839 return freed;
840 }
841
842
843 /* ------------------------------------------------------------------------ */
844 /* Function: ipf_htable_node_add */
845 /* Returns: int - 0 = success, else error */
846 /* Parameters: softc(I) - pointer to soft context main structure */
847 /* arg(I) - pointer to local context to use */
848 /* op(I) - pointer to lookup operation data */
849 /* uid(I) - real uid of process doing operation */
850 /* */
851 /* ------------------------------------------------------------------------ */
852 static int
ipf_htable_node_add(softc,arg,op,uid)853 ipf_htable_node_add(softc, arg, op, uid)
854 ipf_main_softc_t *softc;
855 void *arg;
856 iplookupop_t *op;
857 int uid;
858 {
859 iphtable_t *iph;
860 iphtent_t hte;
861 int err;
862
863 if (op->iplo_size != sizeof(hte)) {
864 IPFERROR(30018);
865 return EINVAL;
866 }
867
868 err = COPYIN(op->iplo_struct, &hte, sizeof(hte));
869 if (err != 0) {
870 IPFERROR(30019);
871 return EFAULT;
872 }
873 hte.ipe_uid = uid;
874
875 iph = ipf_htable_find(arg, op->iplo_unit, op->iplo_name);
876 if (iph == NULL) {
877 IPFERROR(30020);
878 return ESRCH;
879 }
880
881 if (ipf_htent_find(iph, &hte) != NULL) {
882 IPFERROR(30021);
883 return EEXIST;
884 }
885
886 err = ipf_htent_insert(softc, arg, iph, &hte);
887
888 return err;
889 }
890
891
892 /* ------------------------------------------------------------------------ */
893 /* Function: ipf_htent_insert */
894 /* Returns: int - 0 = success, -1 = error */
895 /* Parameters: softc(I) - pointer to soft context main structure */
896 /* arg(I) - pointer to local context to use */
897 /* op(I) - pointer to lookup operation data */
898 /* ipeo(I) - */
899 /* */
900 /* Add an entry to a hash table. */
901 /* ------------------------------------------------------------------------ */
902 static int
ipf_htent_insert(softc,arg,iph,ipeo)903 ipf_htent_insert(softc, arg, iph, ipeo)
904 ipf_main_softc_t *softc;
905 void *arg;
906 iphtable_t *iph;
907 iphtent_t *ipeo;
908 {
909 ipf_htable_softc_t *softh = arg;
910 iphtent_t *ipe;
911 u_int hv;
912 int bits;
913
914 KMALLOC(ipe, iphtent_t *);
915 if (ipe == NULL)
916 return -1;
917
918 bcopy((char *)ipeo, (char *)ipe, sizeof(*ipe));
919 ipe->ipe_addr.i6[0] &= ipe->ipe_mask.i6[0];
920 if (ipe->ipe_family == AF_INET) {
921 bits = count4bits(ipe->ipe_mask.in4_addr);
922 ipe->ipe_addr.i6[1] = 0;
923 ipe->ipe_addr.i6[2] = 0;
924 ipe->ipe_addr.i6[3] = 0;
925 ipe->ipe_mask.i6[1] = 0;
926 ipe->ipe_mask.i6[2] = 0;
927 ipe->ipe_mask.i6[3] = 0;
928 hv = IPE_V4_HASH_FN(ipe->ipe_addr.in4_addr,
929 ipe->ipe_mask.in4_addr, iph->iph_size);
930 } else
931 #ifdef USE_INET6
932 if (ipe->ipe_family == AF_INET6) {
933 ipe->ipe_addr.i6[1] &= ipe->ipe_mask.i6[1];
934 ipe->ipe_addr.i6[2] &= ipe->ipe_mask.i6[2];
935 ipe->ipe_addr.i6[3] &= ipe->ipe_mask.i6[3];
936
937 bits = count6bits(ipe->ipe_mask.i6);
938 hv = IPE_V6_HASH_FN(ipe->ipe_addr.i6,
939 ipe->ipe_mask.i6, iph->iph_size);
940 } else
941 #endif
942 {
943 KFREE(ipe);
944 return -1;
945 }
946
947 ipe->ipe_owner = iph;
948 ipe->ipe_ref = 1;
949 ipe->ipe_hnext = iph->iph_table[hv];
950 ipe->ipe_phnext = iph->iph_table + hv;
951
952 if (iph->iph_table[hv] != NULL)
953 iph->iph_table[hv]->ipe_phnext = &ipe->ipe_hnext;
954 iph->iph_table[hv] = ipe;
955
956 ipe->ipe_pnext = iph->iph_tail;
957 *iph->iph_tail = ipe;
958 iph->iph_tail = &ipe->ipe_next;
959 ipe->ipe_next = NULL;
960
961 if (ipe->ipe_die != 0) {
962 /*
963 * If the new node has a given expiration time, insert it
964 * into the list of expiring nodes with the ones to be
965 * removed first added to the front of the list. The
966 * insertion is O(n) but it is kept sorted for quick scans
967 * at expiration interval checks.
968 */
969 iphtent_t *n;
970
971 ipe->ipe_die = softc->ipf_ticks + IPF_TTLVAL(ipe->ipe_die);
972 for (n = softh->ipf_node_explist; n != NULL; n = n->ipe_dnext) {
973 if (ipe->ipe_die < n->ipe_die)
974 break;
975 if (n->ipe_dnext == NULL) {
976 /*
977 * We've got to the last node and everything
978 * wanted to be expired before this new node,
979 * so we have to tack it on the end...
980 */
981 n->ipe_dnext = ipe;
982 ipe->ipe_pdnext = &n->ipe_dnext;
983 n = NULL;
984 break;
985 }
986 }
987
988 if (softh->ipf_node_explist == NULL) {
989 softh->ipf_node_explist = ipe;
990 ipe->ipe_pdnext = &softh->ipf_node_explist;
991 } else if (n != NULL) {
992 ipe->ipe_dnext = n;
993 ipe->ipe_pdnext = n->ipe_pdnext;
994 n->ipe_pdnext = &ipe->ipe_dnext;
995 }
996 }
997
998 if (ipe->ipe_family == AF_INET) {
999 ipf_inet_mask_add(bits, &iph->iph_v4_masks);
1000 }
1001 #ifdef USE_INET6
1002 else if (ipe->ipe_family == AF_INET6) {
1003 ipf_inet6_mask_add(bits, &ipe->ipe_mask, &iph->iph_v6_masks);
1004 }
1005 #endif
1006
1007 switch (iph->iph_type & ~IPHASH_ANON)
1008 {
1009 case IPHASH_GROUPMAP :
1010 ipe->ipe_ptr = ipf_group_add(softc, ipe->ipe_group, NULL,
1011 iph->iph_flags, IPL_LOGIPF,
1012 softc->ipf_active);
1013 break;
1014
1015 default :
1016 ipe->ipe_ptr = NULL;
1017 ipe->ipe_value = 0;
1018 break;
1019 }
1020
1021 ipe->ipe_unit = iph->iph_unit;
1022 softh->ipf_nhtnodes[ipe->ipe_unit + 1]++;
1023
1024 return 0;
1025 }
1026
1027
1028 /* ------------------------------------------------------------------------ */
1029 /* Function: ipf_htent_find */
1030 /* Returns: int - 0 = success, else error */
1031 /* Parameters: iph(I) - pointer to table to search */
1032 /* ipeo(I) - pointer to entry to find */
1033 /* */
1034 /* While it isn't absolutely necessary to for the address and mask to be */
1035 /* passed in through an iphtent_t structure, one is always present when it */
1036 /* is time to call this function, so it is just more convenient. */
1037 /* ------------------------------------------------------------------------ */
1038 static iphtent_t *
ipf_htent_find(iph,ipeo)1039 ipf_htent_find(iph, ipeo)
1040 iphtable_t *iph;
1041 iphtent_t *ipeo;
1042 {
1043 iphtent_t ipe, *ent;
1044 u_int hv;
1045 int bits;
1046
1047 bcopy((char *)ipeo, (char *)&ipe, sizeof(ipe));
1048 ipe.ipe_addr.i6[0] &= ipe.ipe_mask.i6[0];
1049 ipe.ipe_addr.i6[1] &= ipe.ipe_mask.i6[1];
1050 ipe.ipe_addr.i6[2] &= ipe.ipe_mask.i6[2];
1051 ipe.ipe_addr.i6[3] &= ipe.ipe_mask.i6[3];
1052 if (ipe.ipe_family == AF_INET) {
1053 bits = count4bits(ipe.ipe_mask.in4_addr);
1054 ipe.ipe_addr.i6[1] = 0;
1055 ipe.ipe_addr.i6[2] = 0;
1056 ipe.ipe_addr.i6[3] = 0;
1057 ipe.ipe_mask.i6[1] = 0;
1058 ipe.ipe_mask.i6[2] = 0;
1059 ipe.ipe_mask.i6[3] = 0;
1060 hv = IPE_V4_HASH_FN(ipe.ipe_addr.in4_addr,
1061 ipe.ipe_mask.in4_addr, iph->iph_size);
1062 } else
1063 #ifdef USE_INET6
1064 if (ipe.ipe_family == AF_INET6) {
1065 bits = count6bits(ipe.ipe_mask.i6);
1066 hv = IPE_V6_HASH_FN(ipe.ipe_addr.i6,
1067 ipe.ipe_mask.i6, iph->iph_size);
1068 } else
1069 #endif
1070 return NULL;
1071
1072 for (ent = iph->iph_table[hv]; ent != NULL; ent = ent->ipe_hnext) {
1073 if (ent->ipe_family != ipe.ipe_family)
1074 continue;
1075 if (IP6_NEQ(&ipe.ipe_addr, &ent->ipe_addr))
1076 continue;
1077 if (IP6_NEQ(&ipe.ipe_mask, &ent->ipe_mask))
1078 continue;
1079 break;
1080 }
1081
1082 return ent;
1083 }
1084
1085
1086 /* ------------------------------------------------------------------------ */
1087 /* Function: ipf_iphmfindgroup */
1088 /* Returns: int - 0 = success, else error */
1089 /* Parameters: softc(I) - pointer to soft context main structure */
1090 /* tptr(I) - */
1091 /* aptr(I) - */
1092 /* */
1093 /* Search a hash table for a matching entry and return the pointer stored */
1094 /* in it for use as the next group of rules to search. */
1095 /* */
1096 /* This function is exposed becaues it is used in the group-map feature. */
1097 /* ------------------------------------------------------------------------ */
1098 void *
ipf_iphmfindgroup(softc,tptr,aptr)1099 ipf_iphmfindgroup(softc, tptr, aptr)
1100 ipf_main_softc_t *softc;
1101 void *tptr, *aptr;
1102 {
1103 struct in_addr *addr;
1104 iphtable_t *iph;
1105 iphtent_t *ipe;
1106 void *rval;
1107
1108 READ_ENTER(&softc->ipf_poolrw);
1109 iph = tptr;
1110 addr = aptr;
1111
1112 ipe = ipf_iphmfind(iph, addr);
1113 if (ipe != NULL)
1114 rval = ipe->ipe_ptr;
1115 else
1116 rval = NULL;
1117 RWLOCK_EXIT(&softc->ipf_poolrw);
1118 return rval;
1119 }
1120
1121
1122 /* ------------------------------------------------------------------------ */
1123 /* Function: ipf_iphmfindip */
1124 /* Returns: int - 0 == +ve match, -1 == error, 1 == -ve/no match */
1125 /* Parameters: softc(I) - pointer to soft context main structure */
1126 /* tptr(I) - pointer to the pool to search */
1127 /* ipversion(I) - IP protocol version (4 or 6) */
1128 /* aptr(I) - pointer to address information */
1129 /* bytes(I) - packet length */
1130 /* */
1131 /* Search the hash table for a given address and return a search result. */
1132 /* ------------------------------------------------------------------------ */
1133 static int
ipf_iphmfindip(softc,tptr,ipversion,aptr,bytes)1134 ipf_iphmfindip(softc, tptr, ipversion, aptr, bytes)
1135 ipf_main_softc_t *softc;
1136 void *tptr, *aptr;
1137 int ipversion;
1138 u_int bytes;
1139 {
1140 struct in_addr *addr;
1141 iphtable_t *iph;
1142 iphtent_t *ipe;
1143 int rval;
1144
1145 if (tptr == NULL || aptr == NULL)
1146 return -1;
1147
1148 iph = tptr;
1149 addr = aptr;
1150
1151 READ_ENTER(&softc->ipf_poolrw);
1152 if (ipversion == 4) {
1153 ipe = ipf_iphmfind(iph, addr);
1154 #ifdef USE_INET6
1155 } else if (ipversion == 6) {
1156 ipe = ipf_iphmfind6(iph, (i6addr_t *)addr);
1157 #endif
1158 } else {
1159 ipe = NULL;
1160 }
1161
1162 if (ipe != NULL) {
1163 rval = 0;
1164 ipe->ipe_hits++;
1165 ipe->ipe_bytes += bytes;
1166 } else {
1167 rval = 1;
1168 }
1169 RWLOCK_EXIT(&softc->ipf_poolrw);
1170 return rval;
1171 }
1172
1173
1174 /* ------------------------------------------------------------------------ */
1175 /* Function: ipf_iphmfindip */
1176 /* Parameters: iph(I) - pointer to hash table */
1177 /* addr(I) - pointer to IPv4 address */
1178 /* Locks: ipf_poolrw */
1179 /* */
1180 /* ------------------------------------------------------------------------ */
1181 static iphtent_t *
ipf_iphmfind(iph,addr)1182 ipf_iphmfind(iph, addr)
1183 iphtable_t *iph;
1184 struct in_addr *addr;
1185 {
1186 u_32_t msk, ips;
1187 iphtent_t *ipe;
1188 u_int hv;
1189 int i;
1190
1191 i = 0;
1192 maskloop:
1193 msk = iph->iph_v4_masks.imt4_active[i];
1194 ips = addr->s_addr & msk;
1195 hv = IPE_V4_HASH_FN(ips, msk, iph->iph_size);
1196 for (ipe = iph->iph_table[hv]; (ipe != NULL); ipe = ipe->ipe_hnext) {
1197 if ((ipe->ipe_family != AF_INET) ||
1198 (ipe->ipe_mask.in4_addr != msk) ||
1199 (ipe->ipe_addr.in4_addr != ips)) {
1200 continue;
1201 }
1202 break;
1203 }
1204
1205 if (ipe == NULL) {
1206 i++;
1207 if (i < iph->iph_v4_masks.imt4_max)
1208 goto maskloop;
1209 }
1210 return ipe;
1211 }
1212
1213
1214 /* ------------------------------------------------------------------------ */
1215 /* Function: ipf_htable_iter_next */
1216 /* Returns: int - 0 = success, else error */
1217 /* Parameters: softc(I) - pointer to soft context main structure */
1218 /* arg(I) - pointer to local context to use */
1219 /* token(I) - */
1220 /* ilp(I) - */
1221 /* */
1222 /* ------------------------------------------------------------------------ */
1223 static int
ipf_htable_iter_next(softc,arg,token,ilp)1224 ipf_htable_iter_next(softc, arg, token, ilp)
1225 ipf_main_softc_t *softc;
1226 void *arg;
1227 ipftoken_t *token;
1228 ipflookupiter_t *ilp;
1229 {
1230 ipf_htable_softc_t *softh = arg;
1231 iphtent_t *node, zn, *nextnode;
1232 iphtable_t *iph, zp, *nextiph;
1233 void *hnext;
1234 int err;
1235
1236 err = 0;
1237 iph = NULL;
1238 node = NULL;
1239 nextiph = NULL;
1240 nextnode = NULL;
1241
1242 READ_ENTER(&softc->ipf_poolrw);
1243
1244 switch (ilp->ili_otype)
1245 {
1246 case IPFLOOKUPITER_LIST :
1247 iph = token->ipt_data;
1248 if (iph == NULL) {
1249 nextiph = softh->ipf_htables[(int)ilp->ili_unit + 1];
1250 } else {
1251 nextiph = iph->iph_next;
1252 }
1253
1254 if (nextiph != NULL) {
1255 ATOMIC_INC(nextiph->iph_ref);
1256 token->ipt_data = nextiph;
1257 } else {
1258 bzero((char *)&zp, sizeof(zp));
1259 nextiph = &zp;
1260 token->ipt_data = NULL;
1261 }
1262 hnext = nextiph->iph_next;
1263 break;
1264
1265 case IPFLOOKUPITER_NODE :
1266 node = token->ipt_data;
1267 if (node == NULL) {
1268 iph = ipf_htable_find(arg, ilp->ili_unit,
1269 ilp->ili_name);
1270 if (iph == NULL) {
1271 IPFERROR(30009);
1272 err = ESRCH;
1273 } else {
1274 nextnode = iph->iph_list;
1275 }
1276 } else {
1277 nextnode = node->ipe_next;
1278 }
1279
1280 if (nextnode != NULL) {
1281 ATOMIC_INC(nextnode->ipe_ref);
1282 token->ipt_data = nextnode;
1283 } else {
1284 bzero((char *)&zn, sizeof(zn));
1285 nextnode = &zn;
1286 token->ipt_data = NULL;
1287 }
1288 hnext = nextnode->ipe_next;
1289 break;
1290
1291 default :
1292 IPFERROR(30010);
1293 err = EINVAL;
1294 hnext = NULL;
1295 break;
1296 }
1297
1298 RWLOCK_EXIT(&softc->ipf_poolrw);
1299 if (err != 0)
1300 return err;
1301
1302 switch (ilp->ili_otype)
1303 {
1304 case IPFLOOKUPITER_LIST :
1305 err = COPYOUT(nextiph, ilp->ili_data, sizeof(*nextiph));
1306 if (err != 0) {
1307 IPFERROR(30011);
1308 err = EFAULT;
1309 }
1310 if (iph != NULL) {
1311 WRITE_ENTER(&softc->ipf_poolrw);
1312 ipf_htable_deref(softc, softh, iph);
1313 RWLOCK_EXIT(&softc->ipf_poolrw);
1314 }
1315 break;
1316
1317 case IPFLOOKUPITER_NODE :
1318 err = COPYOUT(nextnode, ilp->ili_data, sizeof(*nextnode));
1319 if (err != 0) {
1320 IPFERROR(30012);
1321 err = EFAULT;
1322 }
1323 if (node != NULL) {
1324 WRITE_ENTER(&softc->ipf_poolrw);
1325 ipf_htent_deref(softc, node);
1326 RWLOCK_EXIT(&softc->ipf_poolrw);
1327 }
1328 break;
1329 }
1330
1331 if (hnext == NULL)
1332 ipf_token_mark_complete(token);
1333
1334 return err;
1335 }
1336
1337
1338 /* ------------------------------------------------------------------------ */
1339 /* Function: ipf_htable_iter_deref */
1340 /* Returns: int - 0 = success, else error */
1341 /* Parameters: softc(I) - pointer to soft context main structure */
1342 /* arg(I) - pointer to local context to use */
1343 /* otype(I) - which data structure type is being walked */
1344 /* unit(I) - ipfilter device to which we are working on */
1345 /* data(I) - pointer to old data structure */
1346 /* */
1347 /* ------------------------------------------------------------------------ */
1348 static int
ipf_htable_iter_deref(softc,arg,otype,unit,data)1349 ipf_htable_iter_deref(softc, arg, otype, unit, data)
1350 ipf_main_softc_t *softc;
1351 void *arg;
1352 int otype;
1353 int unit;
1354 void *data;
1355 {
1356
1357 if (data == NULL)
1358 return EFAULT;
1359
1360 if (unit < -1 || unit > IPL_LOGMAX)
1361 return EINVAL;
1362
1363 switch (otype)
1364 {
1365 case IPFLOOKUPITER_LIST :
1366 ipf_htable_deref(softc, arg, (iphtable_t *)data);
1367 break;
1368
1369 case IPFLOOKUPITER_NODE :
1370 ipf_htent_deref(arg, (iphtent_t *)data);
1371 break;
1372 default :
1373 break;
1374 }
1375
1376 return 0;
1377 }
1378
1379
1380 #ifdef USE_INET6
1381 /* ------------------------------------------------------------------------ */
1382 /* Function: ipf_iphmfind6 */
1383 /* Parameters: iph(I) - pointer to hash table */
1384 /* addr(I) - pointer to IPv6 address */
1385 /* Locks: ipf_poolrw */
1386 /* */
1387 /* ------------------------------------------------------------------------ */
1388 static iphtent_t *
ipf_iphmfind6(iph,addr)1389 ipf_iphmfind6(iph, addr)
1390 iphtable_t *iph;
1391 i6addr_t *addr;
1392 {
1393 i6addr_t *msk, ips;
1394 iphtent_t *ipe;
1395 u_int hv;
1396 int i;
1397
1398 i = 0;
1399 maskloop:
1400 msk = iph->iph_v6_masks.imt6_active + i;
1401 ips.i6[0] = addr->i6[0] & msk->i6[0];
1402 ips.i6[1] = addr->i6[1] & msk->i6[1];
1403 ips.i6[2] = addr->i6[2] & msk->i6[2];
1404 ips.i6[3] = addr->i6[3] & msk->i6[3];
1405 hv = IPE_V6_HASH_FN(ips.i6, msk->i6, iph->iph_size);
1406 for (ipe = iph->iph_table[hv]; (ipe != NULL); ipe = ipe->ipe_next) {
1407 if ((ipe->ipe_family != AF_INET6) ||
1408 IP6_NEQ(&ipe->ipe_mask, msk) ||
1409 IP6_NEQ(&ipe->ipe_addr, &ips)) {
1410 continue;
1411 }
1412 break;
1413 }
1414
1415 if (ipe == NULL) {
1416 i++;
1417 if (i < iph->iph_v6_masks.imt6_max)
1418 goto maskloop;
1419 }
1420 return ipe;
1421 }
1422 #endif
1423
1424
1425 static void
ipf_htable_expire(softc,arg)1426 ipf_htable_expire(softc, arg)
1427 ipf_main_softc_t *softc;
1428 void *arg;
1429 {
1430 ipf_htable_softc_t *softh = arg;
1431 iphtent_t *n;
1432
1433 while ((n = softh->ipf_node_explist) != NULL) {
1434 if (n->ipe_die > softc->ipf_ticks)
1435 break;
1436
1437 ipf_htent_remove(softc, softh, n->ipe_owner, n);
1438 }
1439 }
1440
1441
1442 #ifndef _KERNEL
1443
1444 /* ------------------------------------------------------------------------ */
1445 /* */
1446 /* ------------------------------------------------------------------------ */
1447 void
ipf_htable_dump(softc,arg)1448 ipf_htable_dump(softc, arg)
1449 ipf_main_softc_t *softc;
1450 void *arg;
1451 {
1452 ipf_htable_softc_t *softh = arg;
1453 iphtable_t *iph;
1454 int i;
1455
1456 printf("List of configured hash tables\n");
1457 for (i = 0; i < IPL_LOGSIZE; i++)
1458 for (iph = softh->ipf_htables[i]; iph != NULL;
1459 iph = iph->iph_next)
1460 printhash(iph, bcopywrap, NULL, opts, NULL);
1461
1462 }
1463 #endif
1464