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