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