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_unit = unit;
347 iph->iph_next = softh->ipf_htables[unit + 1];
348 iph->iph_pnext = &softh->ipf_htables[unit + 1];
349 if (softh->ipf_htables[unit + 1] != NULL)
350 softh->ipf_htables[unit + 1]->iph_pnext = &iph->iph_next;
351 softh->ipf_htables[unit + 1] = iph;
352
353 softh->ipf_nhtables[unit + 1]++;
354
355 return (0);
356 }
357
358
359 /* ------------------------------------------------------------------------ */
360 /* Function: ipf_htable_table_del */
361 /* Returns: int - 0 = success, else error */
362 /* Parameters: softc(I) - pointer to soft context main structure */
363 /* arg(I) - pointer to local context to use */
364 /* op(I) - pointer to lookup operation data */
365 /* */
366 /* ------------------------------------------------------------------------ */
367 static int
ipf_htable_table_del(ipf_main_softc_t * softc,void * arg,iplookupop_t * op)368 ipf_htable_table_del(ipf_main_softc_t *softc, void *arg, iplookupop_t *op)
369 {
370 return (ipf_htable_destroy(softc, arg, op->iplo_unit, op->iplo_name));
371 }
372
373
374 /* ------------------------------------------------------------------------ */
375 /* Function: ipf_htable_destroy */
376 /* Returns: int - 0 = success, else error */
377 /* Parameters: softc(I) - pointer to soft context main structure */
378 /* arg(I) - pointer to local context to use */
379 /* op(I) - pointer to lookup operation data */
380 /* */
381 /* Find the hash table that belongs to the relevant part of ipfilter with a */
382 /* matching name and attempt to destroy it. If it is in use, empty it out */
383 /* and mark it for deletion so that when all the references disappear, it */
384 /* can be removed. */
385 /* ------------------------------------------------------------------------ */
386 static int
ipf_htable_destroy(ipf_main_softc_t * softc,void * arg,int unit,char * name)387 ipf_htable_destroy(ipf_main_softc_t *softc, void *arg, int unit, char *name)
388 {
389 iphtable_t *iph;
390
391 iph = ipf_htable_find(arg, unit, name);
392 if (iph == NULL) {
393 IPFERROR(30007);
394 return (ESRCH);
395 }
396
397 if (iph->iph_unit != unit) {
398 IPFERROR(30008);
399 return (EINVAL);
400 }
401
402 if (iph->iph_ref != 0) {
403 ipf_htable_clear(softc, arg, iph);
404 iph->iph_flags |= IPHASH_DELETE;
405 return (0);
406 }
407
408 ipf_htable_remove(softc, arg, iph);
409
410 return (0);
411 }
412
413
414 /* ------------------------------------------------------------------------ */
415 /* Function: ipf_htable_clear */
416 /* Returns: int - 0 = success, else error */
417 /* Parameters: softc(I) - pointer to soft context main structure */
418 /* arg(I) - pointer to local context to use */
419 /* iph(I) - pointer to hash table to destroy */
420 /* */
421 /* Clean out the hash table by walking the list of entries and removing */
422 /* each one, one by one. */
423 /* ------------------------------------------------------------------------ */
424 static int
ipf_htable_clear(ipf_main_softc_t * softc,void * arg,iphtable_t * iph)425 ipf_htable_clear(ipf_main_softc_t *softc, void *arg, iphtable_t *iph)
426 {
427 iphtent_t *ipe;
428
429 while ((ipe = iph->iph_list) != NULL)
430 if (ipf_htent_remove(softc, arg, iph, ipe) != 0)
431 return (1);
432 return (0);
433 }
434
435
436 /* ------------------------------------------------------------------------ */
437 /* Function: ipf_htable_free */
438 /* Returns: Nil */
439 /* Parameters: arg(I) - pointer to local context to use */
440 /* iph(I) - pointer to hash table to destroy */
441 /* */
442 /* ------------------------------------------------------------------------ */
443 static void
ipf_htable_free(void * arg,iphtable_t * iph)444 ipf_htable_free(void *arg, iphtable_t *iph)
445 {
446 ipf_htable_softc_t *softh = arg;
447
448 if (iph->iph_next != NULL)
449 iph->iph_next->iph_pnext = iph->iph_pnext;
450 if (iph->iph_pnext != NULL)
451 *iph->iph_pnext = iph->iph_next;
452 iph->iph_pnext = NULL;
453 iph->iph_next = NULL;
454
455 softh->ipf_nhtables[iph->iph_unit + 1]--;
456
457 KFREES(iph->iph_table, iph->iph_size * sizeof(*iph->iph_table));
458 KFREE(iph);
459 }
460
461
462 /* ------------------------------------------------------------------------ */
463 /* Function: ipf_htable_remove */
464 /* Returns: int - 0 = success, else error */
465 /* Parameters: softc(I) - pointer to soft context main structure */
466 /* arg(I) - pointer to local context to use */
467 /* iph(I) - pointer to hash table to destroy */
468 /* */
469 /* It is necessary to unlink here as well as free (called by deref) so that */
470 /* the while loop in ipf_htable_flush() functions properly. */
471 /* ------------------------------------------------------------------------ */
472 static int
ipf_htable_remove(ipf_main_softc_t * softc,void * arg,iphtable_t * iph)473 ipf_htable_remove(ipf_main_softc_t *softc, void *arg, iphtable_t *iph)
474 {
475
476 if (ipf_htable_clear(softc, arg, iph) != 0)
477 return (1);
478
479 if (iph->iph_pnext != NULL)
480 *iph->iph_pnext = iph->iph_next;
481 if (iph->iph_next != NULL)
482 iph->iph_next->iph_pnext = iph->iph_pnext;
483 iph->iph_pnext = NULL;
484 iph->iph_next = NULL;
485
486 return (ipf_htable_deref(softc, arg, iph));
487 }
488
489
490 /* ------------------------------------------------------------------------ */
491 /* Function: ipf_htable_node_del */
492 /* Returns: int - 0 = success, else error */
493 /* Parameters: softc(I) - pointer to soft context main structure */
494 /* arg(I) - pointer to local context to use */
495 /* op(I) - pointer to lookup operation data */
496 /* uid(I) - real uid of process doing operation */
497 /* */
498 /* ------------------------------------------------------------------------ */
499 static int
ipf_htable_node_del(ipf_main_softc_t * softc,void * arg,iplookupop_t * op,int uid)500 ipf_htable_node_del(ipf_main_softc_t *softc, void *arg, iplookupop_t *op,
501 int uid)
502 {
503 iphtable_t *iph;
504 iphtent_t hte, *ent;
505 int err;
506
507 if (op->iplo_size != sizeof(hte)) {
508 IPFERROR(30014);
509 return (EINVAL);
510 }
511
512 err = COPYIN(op->iplo_struct, &hte, sizeof(hte));
513 if (err != 0) {
514 IPFERROR(30015);
515 return (EFAULT);
516 }
517
518 iph = ipf_htable_find(arg, op->iplo_unit, op->iplo_name);
519 if (iph == NULL) {
520 IPFERROR(30016);
521 return (ESRCH);
522 }
523
524 ent = ipf_htent_find(iph, &hte);
525 if (ent == NULL) {
526 IPFERROR(30022);
527 return (ESRCH);
528 }
529
530 if ((uid != 0) && (ent->ipe_uid != uid)) {
531 IPFERROR(30023);
532 return (EACCES);
533 }
534
535 err = ipf_htent_remove(softc, arg, iph, ent);
536
537 return (err);
538 }
539
540
541 /* ------------------------------------------------------------------------ */
542 /* Function: ipf_htable_node_del */
543 /* Returns: int - 0 = success, else error */
544 /* Parameters: softc(I) - pointer to soft context main structure */
545 /* arg(I) - pointer to local context to use */
546 /* op(I) - pointer to lookup operation data */
547 /* */
548 /* ------------------------------------------------------------------------ */
549 static int
ipf_htable_table_add(ipf_main_softc_t * softc,void * arg,iplookupop_t * op)550 ipf_htable_table_add(ipf_main_softc_t *softc, void *arg, iplookupop_t *op)
551 {
552 int err;
553
554 if (ipf_htable_find(arg, op->iplo_unit, op->iplo_name) != NULL) {
555 IPFERROR(30017);
556 err = EEXIST;
557 } else {
558 err = ipf_htable_create(softc, arg, op);
559 }
560
561 return (err);
562 }
563
564
565 /* ------------------------------------------------------------------------ */
566 /* Function: ipf_htent_remove */
567 /* Returns: int - 0 = success, else error */
568 /* Parameters: softc(I) - pointer to soft context main structure */
569 /* arg(I) - pointer to local context to use */
570 /* iph(I) - pointer to hash table */
571 /* ipe(I) - pointer to hash table entry to remove */
572 /* */
573 /* Delete an entry from a hash table. */
574 /* ------------------------------------------------------------------------ */
575 static int
ipf_htent_remove(ipf_main_softc_t * softc,void * arg,iphtable_t * iph,iphtent_t * ipe)576 ipf_htent_remove(ipf_main_softc_t *softc, void *arg, iphtable_t *iph,
577 iphtent_t *ipe)
578 {
579
580 if (iph->iph_tail == &ipe->ipe_next)
581 iph->iph_tail = ipe->ipe_pnext;
582
583 if (ipe->ipe_hnext != NULL)
584 ipe->ipe_hnext->ipe_phnext = ipe->ipe_phnext;
585 if (ipe->ipe_phnext != NULL)
586 *ipe->ipe_phnext = ipe->ipe_hnext;
587 ipe->ipe_phnext = NULL;
588 ipe->ipe_hnext = NULL;
589
590 if (ipe->ipe_dnext != NULL)
591 ipe->ipe_dnext->ipe_pdnext = ipe->ipe_pdnext;
592 if (ipe->ipe_pdnext != NULL)
593 *ipe->ipe_pdnext = ipe->ipe_dnext;
594 ipe->ipe_pdnext = NULL;
595 ipe->ipe_dnext = NULL;
596
597 if (ipe->ipe_next != NULL)
598 ipe->ipe_next->ipe_pnext = ipe->ipe_pnext;
599 if (ipe->ipe_pnext != NULL)
600 *ipe->ipe_pnext = ipe->ipe_next;
601 ipe->ipe_pnext = NULL;
602 ipe->ipe_next = NULL;
603
604 switch (iph->iph_type & ~IPHASH_ANON)
605 {
606 case IPHASH_GROUPMAP :
607 if (ipe->ipe_group != NULL)
608 ipf_group_del(softc, ipe->ipe_ptr, NULL);
609 break;
610
611 default :
612 ipe->ipe_ptr = NULL;
613 ipe->ipe_value = 0;
614 break;
615 }
616
617 return (ipf_htent_deref(arg, ipe));
618 }
619
620
621 /* ------------------------------------------------------------------------ */
622 /* Function: ipf_htable_deref */
623 /* Returns: int - 0 = success, else error */
624 /* Parameters: softc(I) - pointer to soft context main structure */
625 /* arg(I) - pointer to local context to use */
626 /* object(I) - pointer to hash table */
627 /* */
628 /* ------------------------------------------------------------------------ */
629 static int
ipf_htable_deref(ipf_main_softc_t * softc,void * arg,void * object)630 ipf_htable_deref(ipf_main_softc_t *softc, void *arg, void *object)
631 {
632 ipf_htable_softc_t *softh = arg;
633 iphtable_t *iph = object;
634 int refs;
635
636 iph->iph_ref--;
637 refs = iph->iph_ref;
638
639 if (iph->iph_ref == 0) {
640 ipf_htable_free(softh, iph);
641 }
642
643 return (refs);
644 }
645
646
647 /* ------------------------------------------------------------------------ */
648 /* Function: ipf_htent_deref */
649 /* Parameters: arg(I) - pointer to local context to use */
650 /* ipe(I) - */
651 /* */
652 /* ------------------------------------------------------------------------ */
653 static int
ipf_htent_deref(void * arg,iphtent_t * ipe)654 ipf_htent_deref(void *arg, iphtent_t *ipe)
655 {
656 ipf_htable_softc_t *softh = arg;
657
658 ipe->ipe_ref--;
659 if (ipe->ipe_ref == 0) {
660 softh->ipf_nhtnodes[ipe->ipe_unit + 1]--;
661 KFREE(ipe);
662
663 return (0);
664 }
665
666 return (ipe->ipe_ref);
667 }
668
669
670 /* ------------------------------------------------------------------------ */
671 /* Function: ipf_htable_exists */
672 /* Parameters: arg(I) - pointer to local context to use */
673 /* */
674 /* ------------------------------------------------------------------------ */
675 static void *
ipf_htable_exists(void * arg,int unit,char * name)676 ipf_htable_exists(void *arg, int unit, char *name)
677 {
678 ipf_htable_softc_t *softh = arg;
679 iphtable_t *iph;
680
681 if (unit == IPL_LOGALL) {
682 int i;
683
684 for (i = 0; i <= LOOKUP_POOL_MAX; i++) {
685 for (iph = softh->ipf_htables[i]; iph != NULL;
686 iph = iph->iph_next) {
687 if (strncmp(iph->iph_name, name,
688 sizeof(iph->iph_name)) == 0)
689 break;
690 }
691 if (iph != NULL)
692 break;
693 }
694 } else {
695 for (iph = softh->ipf_htables[unit + 1]; iph != NULL;
696 iph = iph->iph_next) {
697 if (strncmp(iph->iph_name, name,
698 sizeof(iph->iph_name)) == 0)
699 break;
700 }
701 }
702 return (iph);
703 }
704
705
706 /* ------------------------------------------------------------------------ */
707 /* Function: ipf_htable_select_add_ref */
708 /* Returns: void * - NULL = failure, else pointer to the hash table */
709 /* Parameters: arg(I) - pointer to local context to use */
710 /* unit(I) - ipfilter device to which we are working on */
711 /* name(I) - name of the hash table */
712 /* */
713 /* ------------------------------------------------------------------------ */
714 static void *
ipf_htable_select_add_ref(void * arg,int unit,char * name)715 ipf_htable_select_add_ref(void *arg, int unit, char *name)
716 {
717 iphtable_t *iph;
718
719 iph = ipf_htable_exists(arg, unit, name);
720 if (iph != NULL) {
721 ATOMIC_INC32(iph->iph_ref);
722 }
723 return (iph);
724 }
725
726
727 /* ------------------------------------------------------------------------ */
728 /* Function: ipf_htable_find */
729 /* Returns: void * - NULL = failure, else pointer to the hash table */
730 /* Parameters: arg(I) - pointer to local context to use */
731 /* unit(I) - ipfilter device to which we are working on */
732 /* name(I) - name of the hash table */
733 /* */
734 /* This function is exposed becaues it is used in the group-map feature. */
735 /* ------------------------------------------------------------------------ */
736 iphtable_t *
ipf_htable_find(void * arg,int unit,char * name)737 ipf_htable_find(void *arg, int unit, char *name)
738 {
739 iphtable_t *iph;
740
741 iph = ipf_htable_exists(arg, unit, name);
742 if ((iph != NULL) && (iph->iph_flags & IPHASH_DELETE) == 0)
743 return (iph);
744
745 return (NULL);
746 }
747
748
749 /* ------------------------------------------------------------------------ */
750 /* Function: ipf_htable_flush */
751 /* Returns: size_t - number of entries flushed */
752 /* Parameters: softc(I) - pointer to soft context main structure */
753 /* arg(I) - pointer to local context to use */
754 /* op(I) - pointer to lookup operation data */
755 /* */
756 /* ------------------------------------------------------------------------ */
757 static size_t
ipf_htable_flush(ipf_main_softc_t * softc,void * arg,iplookupflush_t * op)758 ipf_htable_flush(ipf_main_softc_t *softc, void *arg, iplookupflush_t *op)
759 {
760 ipf_htable_softc_t *softh = arg;
761 iphtable_t *iph;
762 size_t freed;
763 int i;
764
765 freed = 0;
766
767 for (i = -1; i <= IPL_LOGMAX; i++) {
768 if (op->iplf_unit == i || op->iplf_unit == IPL_LOGALL) {
769 while ((iph = softh->ipf_htables[i + 1]) != NULL) {
770 if (ipf_htable_remove(softc, arg, iph) == 0) {
771 freed++;
772 } else {
773 iph->iph_flags |= IPHASH_DELETE;
774 }
775 }
776 }
777 }
778
779 return (freed);
780 }
781
782
783 /* ------------------------------------------------------------------------ */
784 /* Function: ipf_htable_node_add */
785 /* Returns: int - 0 = success, else error */
786 /* Parameters: softc(I) - pointer to soft context main structure */
787 /* arg(I) - pointer to local context to use */
788 /* op(I) - pointer to lookup operation data */
789 /* uid(I) - real uid of process doing operation */
790 /* */
791 /* ------------------------------------------------------------------------ */
792 static int
ipf_htable_node_add(ipf_main_softc_t * softc,void * arg,iplookupop_t * op,int uid)793 ipf_htable_node_add(ipf_main_softc_t *softc, void *arg, iplookupop_t *op,
794 int uid)
795 {
796 iphtable_t *iph;
797 iphtent_t hte;
798 int err;
799
800 if (op->iplo_size != sizeof(hte)) {
801 IPFERROR(30018);
802 return (EINVAL);
803 }
804
805 err = COPYIN(op->iplo_struct, &hte, sizeof(hte));
806 if (err != 0) {
807 IPFERROR(30019);
808 return (EFAULT);
809 }
810 hte.ipe_uid = uid;
811
812 iph = ipf_htable_find(arg, op->iplo_unit, op->iplo_name);
813 if (iph == NULL) {
814 IPFERROR(30020);
815 return (ESRCH);
816 }
817
818 if (ipf_htent_find(iph, &hte) != NULL) {
819 IPFERROR(30021);
820 return (EEXIST);
821 }
822
823 err = ipf_htent_insert(softc, arg, iph, &hte);
824
825 return (err);
826 }
827
828
829 /* ------------------------------------------------------------------------ */
830 /* Function: ipf_htent_insert */
831 /* Returns: int - 0 = success, -1 = error */
832 /* Parameters: softc(I) - pointer to soft context main structure */
833 /* arg(I) - pointer to local context to use */
834 /* op(I) - pointer to lookup operation data */
835 /* ipeo(I) - */
836 /* */
837 /* Add an entry to a hash table. */
838 /* ------------------------------------------------------------------------ */
839 static int
ipf_htent_insert(ipf_main_softc_t * softc,void * arg,iphtable_t * iph,iphtent_t * ipeo)840 ipf_htent_insert(ipf_main_softc_t *softc, void *arg, iphtable_t *iph,
841 iphtent_t *ipeo)
842 {
843 ipf_htable_softc_t *softh = arg;
844 iphtent_t *ipe;
845 u_int hv;
846 int bits;
847
848 KMALLOC(ipe, iphtent_t *);
849 if (ipe == NULL)
850 return (-1);
851
852 bcopy((char *)ipeo, (char *)ipe, sizeof(*ipe));
853 ipe->ipe_addr.i6[0] &= ipe->ipe_mask.i6[0];
854 if (ipe->ipe_family == AF_INET) {
855 bits = count4bits(ipe->ipe_mask.in4_addr);
856 ipe->ipe_addr.i6[1] = 0;
857 ipe->ipe_addr.i6[2] = 0;
858 ipe->ipe_addr.i6[3] = 0;
859 ipe->ipe_mask.i6[1] = 0;
860 ipe->ipe_mask.i6[2] = 0;
861 ipe->ipe_mask.i6[3] = 0;
862 hv = IPE_V4_HASH_FN(ipe->ipe_addr.in4_addr,
863 ipe->ipe_mask.in4_addr, iph->iph_size);
864 } else
865 #ifdef USE_INET6
866 if (ipe->ipe_family == AF_INET6) {
867 ipe->ipe_addr.i6[1] &= ipe->ipe_mask.i6[1];
868 ipe->ipe_addr.i6[2] &= ipe->ipe_mask.i6[2];
869 ipe->ipe_addr.i6[3] &= ipe->ipe_mask.i6[3];
870
871 bits = count6bits(ipe->ipe_mask.i6);
872 hv = IPE_V6_HASH_FN(ipe->ipe_addr.i6,
873 ipe->ipe_mask.i6, iph->iph_size);
874 } else
875 #endif
876 {
877 KFREE(ipe);
878 return (-1);
879 }
880
881 ipe->ipe_owner = iph;
882 ipe->ipe_ref = 1;
883 ipe->ipe_hnext = iph->iph_table[hv];
884 ipe->ipe_phnext = iph->iph_table + hv;
885
886 if (iph->iph_table[hv] != NULL)
887 iph->iph_table[hv]->ipe_phnext = &ipe->ipe_hnext;
888 iph->iph_table[hv] = ipe;
889
890 ipe->ipe_pnext = iph->iph_tail;
891 *iph->iph_tail = ipe;
892 iph->iph_tail = &ipe->ipe_next;
893 ipe->ipe_next = NULL;
894
895 if (ipe->ipe_die != 0) {
896 /*
897 * If the new node has a given expiration time, insert it
898 * into the list of expiring nodes with the ones to be
899 * removed first added to the front of the list. The
900 * insertion is O(n) but it is kept sorted for quick scans
901 * at expiration interval checks.
902 */
903 iphtent_t *n;
904
905 ipe->ipe_die = softc->ipf_ticks + IPF_TTLVAL(ipe->ipe_die);
906 for (n = softh->ipf_node_explist; n != NULL; n = n->ipe_dnext) {
907 if (ipe->ipe_die < n->ipe_die)
908 break;
909 if (n->ipe_dnext == NULL) {
910 /*
911 * We've got to the last node and everything
912 * wanted to be expired before this new node,
913 * so we have to tack it on the end...
914 */
915 n->ipe_dnext = ipe;
916 ipe->ipe_pdnext = &n->ipe_dnext;
917 n = NULL;
918 break;
919 }
920 }
921
922 if (softh->ipf_node_explist == NULL) {
923 softh->ipf_node_explist = ipe;
924 ipe->ipe_pdnext = &softh->ipf_node_explist;
925 } else if (n != NULL) {
926 ipe->ipe_dnext = n;
927 ipe->ipe_pdnext = n->ipe_pdnext;
928 n->ipe_pdnext = &ipe->ipe_dnext;
929 }
930 }
931
932 if (ipe->ipe_family == AF_INET) {
933 ipf_inet_mask_add(bits, &iph->iph_v4_masks);
934 }
935 #ifdef USE_INET6
936 else if (ipe->ipe_family == AF_INET6) {
937 ipf_inet6_mask_add(bits, &ipe->ipe_mask, &iph->iph_v6_masks);
938 }
939 #endif
940
941 switch (iph->iph_type & ~IPHASH_ANON)
942 {
943 case IPHASH_GROUPMAP :
944 ipe->ipe_ptr = ipf_group_add(softc, ipe->ipe_group, NULL,
945 iph->iph_flags, IPL_LOGIPF,
946 softc->ipf_active);
947 break;
948
949 default :
950 ipe->ipe_ptr = NULL;
951 ipe->ipe_value = 0;
952 break;
953 }
954
955 ipe->ipe_unit = iph->iph_unit;
956 softh->ipf_nhtnodes[ipe->ipe_unit + 1]++;
957
958 return (0);
959 }
960
961
962 /* ------------------------------------------------------------------------ */
963 /* Function: ipf_htent_find */
964 /* Returns: int - 0 = success, else error */
965 /* Parameters: iph(I) - pointer to table to search */
966 /* ipeo(I) - pointer to entry to find */
967 /* */
968 /* While it isn't absolutely necessary to for the address and mask to be */
969 /* passed in through an iphtent_t structure, one is always present when it */
970 /* is time to call this function, so it is just more convenient. */
971 /* ------------------------------------------------------------------------ */
972 static iphtent_t *
ipf_htent_find(iphtable_t * iph,iphtent_t * ipeo)973 ipf_htent_find(iphtable_t *iph, iphtent_t *ipeo)
974 {
975 iphtent_t ipe, *ent;
976 u_int hv;
977 int bits;
978
979 bcopy((char *)ipeo, (char *)&ipe, sizeof(ipe));
980 ipe.ipe_addr.i6[0] &= ipe.ipe_mask.i6[0];
981 ipe.ipe_addr.i6[1] &= ipe.ipe_mask.i6[1];
982 ipe.ipe_addr.i6[2] &= ipe.ipe_mask.i6[2];
983 ipe.ipe_addr.i6[3] &= ipe.ipe_mask.i6[3];
984 if (ipe.ipe_family == AF_INET) {
985 bits = count4bits(ipe.ipe_mask.in4_addr);
986 ipe.ipe_addr.i6[1] = 0;
987 ipe.ipe_addr.i6[2] = 0;
988 ipe.ipe_addr.i6[3] = 0;
989 ipe.ipe_mask.i6[1] = 0;
990 ipe.ipe_mask.i6[2] = 0;
991 ipe.ipe_mask.i6[3] = 0;
992 hv = IPE_V4_HASH_FN(ipe.ipe_addr.in4_addr,
993 ipe.ipe_mask.in4_addr, iph->iph_size);
994 } else
995 #ifdef USE_INET6
996 if (ipe.ipe_family == AF_INET6) {
997 bits = count6bits(ipe.ipe_mask.i6);
998 hv = IPE_V6_HASH_FN(ipe.ipe_addr.i6,
999 ipe.ipe_mask.i6, iph->iph_size);
1000 } else
1001 #endif
1002 return (NULL);
1003
1004 for (ent = iph->iph_table[hv]; ent != NULL; ent = ent->ipe_hnext) {
1005 if (ent->ipe_family != ipe.ipe_family)
1006 continue;
1007 if (IP6_NEQ(&ipe.ipe_addr, &ent->ipe_addr))
1008 continue;
1009 if (IP6_NEQ(&ipe.ipe_mask, &ent->ipe_mask))
1010 continue;
1011 break;
1012 }
1013
1014 return (ent);
1015 }
1016
1017
1018 /* ------------------------------------------------------------------------ */
1019 /* Function: ipf_iphmfindgroup */
1020 /* Returns: int - 0 = success, else error */
1021 /* Parameters: softc(I) - pointer to soft context main structure */
1022 /* tptr(I) - */
1023 /* aptr(I) - */
1024 /* */
1025 /* Search a hash table for a matching entry and return the pointer stored */
1026 /* in it for use as the next group of rules to search. */
1027 /* */
1028 /* This function is exposed becaues it is used in the group-map feature. */
1029 /* ------------------------------------------------------------------------ */
1030 void *
ipf_iphmfindgroup(ipf_main_softc_t * softc,void * tptr,void * aptr)1031 ipf_iphmfindgroup(ipf_main_softc_t *softc, void *tptr, void *aptr)
1032 {
1033 struct in_addr *addr;
1034 iphtable_t *iph;
1035 iphtent_t *ipe;
1036 void *rval;
1037
1038 READ_ENTER(&softc->ipf_poolrw);
1039 iph = tptr;
1040 addr = aptr;
1041
1042 ipe = ipf_iphmfind(iph, addr);
1043 if (ipe != NULL)
1044 rval = ipe->ipe_ptr;
1045 else
1046 rval = NULL;
1047 RWLOCK_EXIT(&softc->ipf_poolrw);
1048 return (rval);
1049 }
1050
1051
1052 /* ------------------------------------------------------------------------ */
1053 /* Function: ipf_iphmfindip */
1054 /* Returns: int - 0 == +ve match, -1 == error, 1 == -ve/no match */
1055 /* Parameters: softc(I) - pointer to soft context main structure */
1056 /* tptr(I) - pointer to the pool to search */
1057 /* ipversion(I) - IP protocol version (4 or 6) */
1058 /* aptr(I) - pointer to address information */
1059 /* bytes(I) - packet length */
1060 /* */
1061 /* Search the hash table for a given address and return a search result. */
1062 /* ------------------------------------------------------------------------ */
1063 static int
ipf_iphmfindip(ipf_main_softc_t * softc,void * tptr,int ipversion,void * aptr,u_int bytes)1064 ipf_iphmfindip(ipf_main_softc_t *softc, void *tptr, int ipversion, void *aptr,
1065 u_int bytes)
1066 {
1067 struct in_addr *addr;
1068 iphtable_t *iph;
1069 iphtent_t *ipe;
1070 int rval;
1071
1072 if (tptr == NULL || aptr == NULL)
1073 return (-1);
1074
1075 iph = tptr;
1076 addr = aptr;
1077
1078 READ_ENTER(&softc->ipf_poolrw);
1079 if (ipversion == 4) {
1080 ipe = ipf_iphmfind(iph, addr);
1081 #ifdef USE_INET6
1082 } else if (ipversion == 6) {
1083 ipe = ipf_iphmfind6(iph, (i6addr_t *)addr);
1084 #endif
1085 } else {
1086 ipe = NULL;
1087 }
1088
1089 if (ipe != NULL) {
1090 rval = 0;
1091 ipe->ipe_hits++;
1092 ipe->ipe_bytes += bytes;
1093 } else {
1094 rval = 1;
1095 }
1096 RWLOCK_EXIT(&softc->ipf_poolrw);
1097 return (rval);
1098 }
1099
1100
1101 /* ------------------------------------------------------------------------ */
1102 /* Function: ipf_iphmfindip */
1103 /* Parameters: iph(I) - pointer to hash table */
1104 /* addr(I) - pointer to IPv4 address */
1105 /* Locks: ipf_poolrw */
1106 /* */
1107 /* ------------------------------------------------------------------------ */
1108 static iphtent_t *
ipf_iphmfind(iphtable_t * iph,struct in_addr * addr)1109 ipf_iphmfind(iphtable_t *iph, struct in_addr *addr)
1110 {
1111 u_32_t msk, ips;
1112 iphtent_t *ipe;
1113 u_int hv;
1114 int i;
1115
1116 i = 0;
1117 maskloop:
1118 msk = iph->iph_v4_masks.imt4_active[i];
1119 ips = addr->s_addr & msk;
1120 hv = IPE_V4_HASH_FN(ips, msk, iph->iph_size);
1121 for (ipe = iph->iph_table[hv]; (ipe != NULL); ipe = ipe->ipe_hnext) {
1122 if ((ipe->ipe_family != AF_INET) ||
1123 (ipe->ipe_mask.in4_addr != msk) ||
1124 (ipe->ipe_addr.in4_addr != ips)) {
1125 continue;
1126 }
1127 break;
1128 }
1129
1130 if (ipe == NULL) {
1131 i++;
1132 if (i < iph->iph_v4_masks.imt4_max)
1133 goto maskloop;
1134 }
1135 return (ipe);
1136 }
1137
1138
1139 /* ------------------------------------------------------------------------ */
1140 /* Function: ipf_htable_iter_next */
1141 /* Returns: int - 0 = success, else error */
1142 /* Parameters: softc(I) - pointer to soft context main structure */
1143 /* arg(I) - pointer to local context to use */
1144 /* token(I) - */
1145 /* ilp(I) - */
1146 /* */
1147 /* ------------------------------------------------------------------------ */
1148 static int
ipf_htable_iter_next(ipf_main_softc_t * softc,void * arg,ipftoken_t * token,ipflookupiter_t * ilp)1149 ipf_htable_iter_next(ipf_main_softc_t *softc, void *arg, ipftoken_t *token,
1150 ipflookupiter_t *ilp)
1151 {
1152 ipf_htable_softc_t *softh = arg;
1153 iphtent_t *node, zn, *nextnode;
1154 iphtable_t *iph, zp, *nextiph;
1155 void *hnext;
1156 int err;
1157
1158 err = 0;
1159 iph = NULL;
1160 node = NULL;
1161 nextiph = NULL;
1162 nextnode = NULL;
1163
1164 READ_ENTER(&softc->ipf_poolrw);
1165
1166 switch (ilp->ili_otype)
1167 {
1168 case IPFLOOKUPITER_LIST :
1169 iph = token->ipt_data;
1170 if (iph == NULL) {
1171 nextiph = softh->ipf_htables[(int)ilp->ili_unit + 1];
1172 } else {
1173 nextiph = iph->iph_next;
1174 }
1175
1176 if (nextiph != NULL) {
1177 ATOMIC_INC(nextiph->iph_ref);
1178 token->ipt_data = nextiph;
1179 } else {
1180 bzero((char *)&zp, sizeof(zp));
1181 nextiph = &zp;
1182 token->ipt_data = NULL;
1183 }
1184 hnext = nextiph->iph_next;
1185 break;
1186
1187 case IPFLOOKUPITER_NODE :
1188 node = token->ipt_data;
1189 if (node == NULL) {
1190 iph = ipf_htable_find(arg, ilp->ili_unit,
1191 ilp->ili_name);
1192 if (iph == NULL) {
1193 IPFERROR(30009);
1194 err = ESRCH;
1195 } else {
1196 nextnode = iph->iph_list;
1197 }
1198 } else {
1199 nextnode = node->ipe_next;
1200 }
1201
1202 if (nextnode != NULL) {
1203 ATOMIC_INC(nextnode->ipe_ref);
1204 token->ipt_data = nextnode;
1205 } else {
1206 bzero((char *)&zn, sizeof(zn));
1207 nextnode = &zn;
1208 token->ipt_data = NULL;
1209 }
1210 hnext = nextnode->ipe_next;
1211 break;
1212
1213 default :
1214 IPFERROR(30010);
1215 err = EINVAL;
1216 hnext = NULL;
1217 break;
1218 }
1219
1220 RWLOCK_EXIT(&softc->ipf_poolrw);
1221 if (err != 0)
1222 return (err);
1223
1224 switch (ilp->ili_otype)
1225 {
1226 case IPFLOOKUPITER_LIST :
1227 err = COPYOUT(nextiph, ilp->ili_data, sizeof(*nextiph));
1228 if (err != 0) {
1229 IPFERROR(30011);
1230 err = EFAULT;
1231 }
1232 if (iph != NULL) {
1233 WRITE_ENTER(&softc->ipf_poolrw);
1234 ipf_htable_deref(softc, softh, iph);
1235 RWLOCK_EXIT(&softc->ipf_poolrw);
1236 }
1237 break;
1238
1239 case IPFLOOKUPITER_NODE :
1240 err = COPYOUT(nextnode, ilp->ili_data, sizeof(*nextnode));
1241 if (err != 0) {
1242 IPFERROR(30012);
1243 err = EFAULT;
1244 }
1245 if (node != NULL) {
1246 WRITE_ENTER(&softc->ipf_poolrw);
1247 ipf_htent_deref(softc, node);
1248 RWLOCK_EXIT(&softc->ipf_poolrw);
1249 }
1250 break;
1251 }
1252
1253 if (hnext == NULL)
1254 ipf_token_mark_complete(token);
1255
1256 return (err);
1257 }
1258
1259
1260 /* ------------------------------------------------------------------------ */
1261 /* Function: ipf_htable_iter_deref */
1262 /* Returns: int - 0 = success, else error */
1263 /* Parameters: softc(I) - pointer to soft context main structure */
1264 /* arg(I) - pointer to local context to use */
1265 /* otype(I) - which data structure type is being walked */
1266 /* unit(I) - ipfilter device to which we are working on */
1267 /* data(I) - pointer to old data structure */
1268 /* */
1269 /* ------------------------------------------------------------------------ */
1270 static int
ipf_htable_iter_deref(ipf_main_softc_t * softc,void * arg,int otype,int unit,void * data)1271 ipf_htable_iter_deref(ipf_main_softc_t *softc, void *arg, int otype, int unit,
1272 void *data)
1273 {
1274
1275 if (data == NULL)
1276 return (EFAULT);
1277
1278 if (unit < -1 || unit > IPL_LOGMAX)
1279 return (EINVAL);
1280
1281 switch (otype)
1282 {
1283 case IPFLOOKUPITER_LIST :
1284 ipf_htable_deref(softc, arg, (iphtable_t *)data);
1285 break;
1286
1287 case IPFLOOKUPITER_NODE :
1288 ipf_htent_deref(arg, (iphtent_t *)data);
1289 break;
1290 default :
1291 break;
1292 }
1293
1294 return (0);
1295 }
1296
1297
1298 #ifdef USE_INET6
1299 /* ------------------------------------------------------------------------ */
1300 /* Function: ipf_iphmfind6 */
1301 /* Parameters: iph(I) - pointer to hash table */
1302 /* addr(I) - pointer to IPv6 address */
1303 /* Locks: ipf_poolrw */
1304 /* */
1305 /* ------------------------------------------------------------------------ */
1306 static iphtent_t *
ipf_iphmfind6(iphtable_t * iph,i6addr_t * addr)1307 ipf_iphmfind6(iphtable_t *iph, i6addr_t *addr)
1308 {
1309 i6addr_t *msk, ips;
1310 iphtent_t *ipe;
1311 u_int hv;
1312 int i;
1313
1314 i = 0;
1315 maskloop:
1316 msk = iph->iph_v6_masks.imt6_active + i;
1317 ips.i6[0] = addr->i6[0] & msk->i6[0];
1318 ips.i6[1] = addr->i6[1] & msk->i6[1];
1319 ips.i6[2] = addr->i6[2] & msk->i6[2];
1320 ips.i6[3] = addr->i6[3] & msk->i6[3];
1321 hv = IPE_V6_HASH_FN(ips.i6, msk->i6, iph->iph_size);
1322 for (ipe = iph->iph_table[hv]; (ipe != NULL); ipe = ipe->ipe_next) {
1323 if ((ipe->ipe_family != AF_INET6) ||
1324 IP6_NEQ(&ipe->ipe_mask, msk) ||
1325 IP6_NEQ(&ipe->ipe_addr, &ips)) {
1326 continue;
1327 }
1328 break;
1329 }
1330
1331 if (ipe == NULL) {
1332 i++;
1333 if (i < iph->iph_v6_masks.imt6_max)
1334 goto maskloop;
1335 }
1336 return (ipe);
1337 }
1338 #endif
1339
1340
1341 static void
ipf_htable_expire(ipf_main_softc_t * softc,void * arg)1342 ipf_htable_expire(ipf_main_softc_t *softc, void *arg)
1343 {
1344 ipf_htable_softc_t *softh = arg;
1345 iphtent_t *n;
1346
1347 while ((n = softh->ipf_node_explist) != NULL) {
1348 if (n->ipe_die > softc->ipf_ticks)
1349 break;
1350
1351 ipf_htent_remove(softc, softh, n->ipe_owner, n);
1352 }
1353 }
1354
1355
1356 #ifndef _KERNEL
1357
1358 /* ------------------------------------------------------------------------ */
1359 /* */
1360 /* ------------------------------------------------------------------------ */
1361 void
ipf_htable_dump(ipf_main_softc_t * softc,void * arg)1362 ipf_htable_dump(ipf_main_softc_t *softc, void *arg)
1363 {
1364 ipf_htable_softc_t *softh = arg;
1365 iphtable_t *iph;
1366 int i;
1367
1368 printf("List of configured hash tables\n");
1369 for (i = 0; i < IPL_LOGSIZE; i++)
1370 for (iph = softh->ipf_htables[i]; iph != NULL;
1371 iph = iph->iph_next)
1372 printhash(iph, bcopywrap, NULL, opts, NULL);
1373
1374 }
1375 #endif
1376