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