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