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