1255332Scy/* $FreeBSD$ */
2145516Sdarrenr/*
3255332Scy * Copyright (C) 2012 by Darren Reed.
4145516Sdarrenr *
5145516Sdarrenr * See the IPFILTER.LICENCE file for details on licencing.
6145516Sdarrenr */
7145516Sdarrenr#if defined(KERNEL) || defined(_KERNEL)
8145516Sdarrenr# undef KERNEL
9145516Sdarrenr# undef _KERNEL
10145516Sdarrenr# define        KERNEL	1
11145516Sdarrenr# define        _KERNEL	1
12145516Sdarrenr#endif
13145516Sdarrenr#if defined(__osf__)
14145516Sdarrenr# define _PROTO_NET_H_
15145516Sdarrenr#endif
16145516Sdarrenr#include <sys/param.h>
17145516Sdarrenr#include <sys/errno.h>
18145516Sdarrenr#include <sys/types.h>
19145516Sdarrenr#include <sys/time.h>
20145516Sdarrenr#include <sys/file.h>
21145516Sdarrenr#if __FreeBSD_version >= 220000 && defined(_KERNEL)
22145516Sdarrenr# include <sys/fcntl.h>
23145516Sdarrenr# include <sys/filio.h>
24145516Sdarrenr#else
25145516Sdarrenr# include <sys/ioctl.h>
26145516Sdarrenr#endif
27145516Sdarrenr#if !defined(_KERNEL)
28255332Scy# include <stdio.h>
29145516Sdarrenr# include <string.h>
30255332Scy# include <stdlib.h>
31145516Sdarrenr# define _KERNEL
32145516Sdarrenr# ifdef __OpenBSD__
33145516Sdarrenrstruct file;
34145516Sdarrenr# endif
35145516Sdarrenr# include <sys/uio.h>
36145516Sdarrenr# undef _KERNEL
37145516Sdarrenr#endif
38145516Sdarrenr#include <sys/socket.h>
39145516Sdarrenr#include <net/if.h>
40145516Sdarrenr#if defined(__FreeBSD__)
41255332Scy# include <sys/cdefs.h>
42255332Scy# include <sys/proc.h>
43145516Sdarrenr#endif
44145516Sdarrenr#if defined(_KERNEL)
45145516Sdarrenr# include <sys/systm.h>
46145516Sdarrenr# if !defined(__SVR4) && !defined(__svr4__)
47145516Sdarrenr#  include <sys/mbuf.h>
48145516Sdarrenr# endif
49255332Scy#else
50255332Scy# include "ipf.h"
51145516Sdarrenr#endif
52145516Sdarrenr#include <netinet/in.h>
53145516Sdarrenr
54145516Sdarrenr#include "netinet/ip_compat.h"
55145516Sdarrenr#include "netinet/ip_fil.h"
56255332Scy#include "netinet/ip_lookup.h"
57145516Sdarrenr#include "netinet/ip_pool.h"
58145516Sdarrenr#include "netinet/ip_htable.h"
59255332Scy#include "netinet/ip_dstlist.h"
60145516Sdarrenr/* END OF INCLUDES */
61145516Sdarrenr
62145516Sdarrenr#if !defined(lint)
63255332Scystatic const char rcsid[] = "@(#)$Id$";
64145516Sdarrenr#endif
65145516Sdarrenr
66255332Scy/*
67255332Scy * In this file, ip_pool.c, ip_htable.c and ip_dstlist.c, you will find the
68255332Scy * range for unit is [-1,IPL_LOGMAX]. The -1 is considered to be a valid number
69255332Scy * and represents a "wildcard" or "all" units (IPL_LOGALL). The reason for not
70255332Scy * starting the numbering at 0 is because the numbers [0,IPL_LOGMAX] correspond
71255332Scy * to the minor device number for their respective device. Thus where there is
72255332Scy * array indexing on the unit, +1 is used to map [-1.IPL_LOGMAX] to
73255332Scy * [0.POOL_LOOKUP_MAX].
74255332Scy */
75255332Scystatic int ipf_lookup_addnode __P((ipf_main_softc_t *, caddr_t, int));
76255332Scystatic int ipf_lookup_delnode __P((ipf_main_softc_t *, caddr_t, int));
77255332Scystatic int ipf_lookup_addtable __P((ipf_main_softc_t *, caddr_t));
78255332Scystatic int ipf_lookup_deltable __P((ipf_main_softc_t *, caddr_t));
79255332Scystatic int ipf_lookup_stats __P((ipf_main_softc_t *, caddr_t));
80255332Scystatic int ipf_lookup_flush __P((ipf_main_softc_t *, caddr_t));
81255332Scystatic int ipf_lookup_iterate __P((ipf_main_softc_t *, void *, int, void *));
82255332Scystatic int ipf_lookup_deltok __P((ipf_main_softc_t *, void *, int, void *));
83145516Sdarrenr
84255332Scy#define	MAX_BACKENDS	3
85255332Scystatic ipf_lookup_t *backends[MAX_BACKENDS] = {
86255332Scy	&ipf_pool_backend,
87255332Scy	&ipf_htable_backend,
88255332Scy	&ipf_dstlist_backend
89255332Scy};
90145516Sdarrenr
91145516Sdarrenr
92255332Scytypedef struct ipf_lookup_softc_s {
93255332Scy	void		*ipf_back[MAX_BACKENDS];
94255332Scy} ipf_lookup_softc_t;
95255332Scy
96255332Scy
97145516Sdarrenr/* ------------------------------------------------------------------------ */
98255332Scy/* Function:    ipf_lookup_init                                             */
99255332Scy/* Returns:     int      - 0 = success, else error                          */
100255332Scy/* Parameters:  softc(I) - pointer to soft context main structure           */
101145516Sdarrenr/*                                                                          */
102145516Sdarrenr/* Initialise all of the subcomponents of the lookup infrstructure.         */
103145516Sdarrenr/* ------------------------------------------------------------------------ */
104255332Scyvoid *
105255332Scyipf_lookup_soft_create(softc)
106255332Scy	ipf_main_softc_t *softc;
107145516Sdarrenr{
108255332Scy	ipf_lookup_softc_t *softl;
109255332Scy	ipf_lookup_t **l;
110255332Scy	int i;
111145516Sdarrenr
112255332Scy	KMALLOC(softl, ipf_lookup_softc_t *);
113255332Scy	if (softl == NULL)
114255332Scy		return NULL;
115145516Sdarrenr
116255332Scy	bzero((char *)softl, sizeof(*softl));
117145516Sdarrenr
118255332Scy	for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
119255332Scy		softl->ipf_back[i] = (*(*l)->ipfl_create)(softc);
120255332Scy		if (softl->ipf_back[i] == NULL) {
121255332Scy			ipf_lookup_soft_destroy(softc, softl);
122255332Scy			return NULL;
123255332Scy		}
124255332Scy	}
125145516Sdarrenr
126255332Scy	return softl;
127255332Scy}
128255332Scy
129255332Scy
130255332Scy/* ------------------------------------------------------------------------ */
131255332Scy/* Function:    ipf_lookup_soft_init                                        */
132255332Scy/* Returns:     int      - 0 = success, else error                          */
133255332Scy/* Parameters:  softc(I) - pointer to soft context main structure           */
134255332Scy/*              arg(I)   - pointer to local context to use                  */
135255332Scy/*                                                                          */
136255332Scy/* Initialise all of the subcomponents of the lookup infrstructure.         */
137255332Scy/* ------------------------------------------------------------------------ */
138255332Scyint
139255332Scyipf_lookup_soft_init(softc, arg)
140255332Scy	ipf_main_softc_t *softc;
141255332Scy	void *arg;
142255332Scy{
143255332Scy	ipf_lookup_softc_t *softl = (ipf_lookup_softc_t *)arg;
144255332Scy	int err = 0;
145255332Scy	int i;
146255332Scy
147255332Scy	for (i = 0; i < MAX_BACKENDS; i++) {
148255332Scy		err = (*backends[i]->ipfl_init)(softc, softl->ipf_back[i]);
149255332Scy		if (err != 0)
150255332Scy			break;
151255332Scy	}
152255332Scy
153255332Scy	return err;
154255332Scy}
155255332Scy
156255332Scy
157255332Scy/* ------------------------------------------------------------------------ */
158255332Scy/* Function:    ipf_lookup_soft_fini                                        */
159255332Scy/* Returns:     int      - 0 = success, else error                          */
160255332Scy/* Parameters:  softc(I) - pointer to soft context main structure           */
161255332Scy/*              arg(I)   - pointer to local context to use                  */
162255332Scy/*                                                                          */
163255332Scy/* Call the fini function in each backend to cleanup all allocated data.    */
164255332Scy/* ------------------------------------------------------------------------ */
165255332Scyint
166255332Scyipf_lookup_soft_fini(softc, arg)
167255332Scy	ipf_main_softc_t *softc;
168255332Scy	void *arg;
169255332Scy{
170255332Scy	ipf_lookup_softc_t *softl = (ipf_lookup_softc_t *)arg;
171255332Scy	int i;
172255332Scy
173255332Scy	for (i = 0; i < MAX_BACKENDS; i++) {
174255332Scy		if (softl->ipf_back[i] != NULL)
175255332Scy			(*backends[i]->ipfl_fini)(softc,
176255332Scy						  softl->ipf_back[i]);
177255332Scy	}
178255332Scy
179145516Sdarrenr	return 0;
180145516Sdarrenr}
181145516Sdarrenr
182145516Sdarrenr
183145516Sdarrenr/* ------------------------------------------------------------------------ */
184255332Scy/* Function:    ipf_lookup_expire                                           */
185255332Scy/* Returns:     Nil                                                         */
186255332Scy/* Parameters:  softc(I) - pointer to soft context main structure           */
187255332Scy/*                                                                          */
188255332Scy/* Step through each of the backends and call their expire functions,       */
189255332Scy/* allowing them to delete any lifetime limited data.                       */
190255332Scy/* ------------------------------------------------------------------------ */
191255332Scyvoid
192255332Scyipf_lookup_expire(softc)
193255332Scy	ipf_main_softc_t *softc;
194255332Scy{
195255332Scy	ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
196255332Scy	int i;
197255332Scy
198255332Scy	WRITE_ENTER(&softc->ipf_poolrw);
199255332Scy	for (i = 0; i < MAX_BACKENDS; i++)
200255332Scy		(*backends[i]->ipfl_expire)(softc, softl->ipf_back[i]);
201255332Scy	RWLOCK_EXIT(&softc->ipf_poolrw);
202255332Scy}
203255332Scy
204255332Scy
205255332Scy/* ------------------------------------------------------------------------ */
206255332Scy/* Function:    ipf_lookup_softc_destroy                                    */
207145516Sdarrenr/* Returns:     int     - 0 = success, else error                           */
208255332Scy/* Parameters:  softc(I) - pointer to soft context main structure           */
209255332Scy/*              arg(I)   - pointer to local context to use                  */
210145516Sdarrenr/*                                                                          */
211145516Sdarrenr/* Free up all pool related memory that has been allocated whilst IPFilter  */
212145516Sdarrenr/* has been running.  Also, do any other deinitialisation required such     */
213255332Scy/* ipf_lookup_init() can be called again, safely.                           */
214145516Sdarrenr/* ------------------------------------------------------------------------ */
215255332Scyvoid
216255332Scyipf_lookup_soft_destroy(softc, arg)
217255332Scy	ipf_main_softc_t *softc;
218255332Scy	void *arg;
219145516Sdarrenr{
220255332Scy	ipf_lookup_softc_t *softl = (ipf_lookup_softc_t *)arg;
221255332Scy	int i;
222145516Sdarrenr
223255332Scy	for (i = 0; i < MAX_BACKENDS; i++) {
224255332Scy		if (softl->ipf_back[i] != NULL)
225255332Scy			(*backends[i]->ipfl_destroy)(softc,
226255332Scy						     softl->ipf_back[i]);
227145516Sdarrenr	}
228255332Scy
229255332Scy	KFREE(softl);
230145516Sdarrenr}
231145516Sdarrenr
232145516Sdarrenr
233145516Sdarrenr/* ------------------------------------------------------------------------ */
234255332Scy/* Function:    ipf_lookup_ioctl                                            */
235145516Sdarrenr/* Returns:     int      - 0 = success, else error                          */
236255332Scy/* Parameters:  softc(I) - pointer to soft context main structure           */
237255332Scy/*              arg(I)   - pointer to local context to use                  */
238255332Scy/*              data(IO) - pointer to ioctl data to be copied to/from user  */
239145516Sdarrenr/*                         space.                                           */
240145516Sdarrenr/*              cmd(I)   - ioctl command number                             */
241145516Sdarrenr/*              mode(I)  - file mode bits used with open                    */
242255332Scy/*              uid(I)   - uid of process doing ioctl                       */
243255332Scy/*              ctx(I)   - pointer that represents context for uid          */
244145516Sdarrenr/*                                                                          */
245145516Sdarrenr/* Handle ioctl commands sent to the ioctl device.  For the most part, this */
246145516Sdarrenr/* involves just calling another function to handle the specifics of each   */
247145516Sdarrenr/* command.                                                                 */
248145516Sdarrenr/* ------------------------------------------------------------------------ */
249255332Scyint
250255332Scyipf_lookup_ioctl(softc, data, cmd, mode, uid, ctx)
251255332Scy	ipf_main_softc_t *softc;
252255332Scy	caddr_t data;
253255332Scy	ioctlcmd_t cmd;
254255332Scy	int mode, uid;
255255332Scy	void *ctx;
256145516Sdarrenr{
257145516Sdarrenr	int err;
258153872Sguido	SPL_INT(s);
259145516Sdarrenr
260145516Sdarrenr	mode = mode;	/* LINT */
261145516Sdarrenr
262145516Sdarrenr	SPL_NET(s);
263145516Sdarrenr
264145516Sdarrenr	switch (cmd)
265145516Sdarrenr	{
266145516Sdarrenr	case SIOCLOOKUPADDNODE :
267145516Sdarrenr	case SIOCLOOKUPADDNODEW :
268255332Scy		WRITE_ENTER(&softc->ipf_poolrw);
269255332Scy		err = ipf_lookup_addnode(softc, data, uid);
270255332Scy		RWLOCK_EXIT(&softc->ipf_poolrw);
271145516Sdarrenr		break;
272145516Sdarrenr
273145516Sdarrenr	case SIOCLOOKUPDELNODE :
274145516Sdarrenr	case SIOCLOOKUPDELNODEW :
275255332Scy		WRITE_ENTER(&softc->ipf_poolrw);
276255332Scy		err = ipf_lookup_delnode(softc, data, uid);
277255332Scy		RWLOCK_EXIT(&softc->ipf_poolrw);
278145516Sdarrenr		break;
279145516Sdarrenr
280145516Sdarrenr	case SIOCLOOKUPADDTABLE :
281255332Scy		WRITE_ENTER(&softc->ipf_poolrw);
282255332Scy		err = ipf_lookup_addtable(softc, data);
283255332Scy		RWLOCK_EXIT(&softc->ipf_poolrw);
284145516Sdarrenr		break;
285145516Sdarrenr
286145516Sdarrenr	case SIOCLOOKUPDELTABLE :
287255332Scy		WRITE_ENTER(&softc->ipf_poolrw);
288255332Scy		err = ipf_lookup_deltable(softc, data);
289255332Scy		RWLOCK_EXIT(&softc->ipf_poolrw);
290145516Sdarrenr		break;
291145516Sdarrenr
292145516Sdarrenr	case SIOCLOOKUPSTAT :
293145516Sdarrenr	case SIOCLOOKUPSTATW :
294255332Scy		WRITE_ENTER(&softc->ipf_poolrw);
295255332Scy		err = ipf_lookup_stats(softc, data);
296255332Scy		RWLOCK_EXIT(&softc->ipf_poolrw);
297145516Sdarrenr		break;
298145516Sdarrenr
299145516Sdarrenr	case SIOCLOOKUPFLUSH :
300255332Scy		WRITE_ENTER(&softc->ipf_poolrw);
301255332Scy		err = ipf_lookup_flush(softc, data);
302255332Scy		RWLOCK_EXIT(&softc->ipf_poolrw);
303145516Sdarrenr		break;
304145516Sdarrenr
305170263Sdarrenr	case SIOCLOOKUPITER :
306255332Scy		err = ipf_lookup_iterate(softc, data, uid, ctx);
307170263Sdarrenr		break;
308170263Sdarrenr
309172771Sdarrenr	case SIOCIPFDELTOK :
310255332Scy		err = ipf_lookup_deltok(softc, data, uid, ctx);
311172771Sdarrenr		break;
312172771Sdarrenr
313145516Sdarrenr	default :
314255332Scy		IPFERROR(50001);
315145516Sdarrenr		err = EINVAL;
316145516Sdarrenr		break;
317145516Sdarrenr	}
318145516Sdarrenr	SPL_X(s);
319145516Sdarrenr	return err;
320145516Sdarrenr}
321145516Sdarrenr
322145516Sdarrenr
323145516Sdarrenr/* ------------------------------------------------------------------------ */
324255332Scy/* Function:    ipf_lookup_addnode                                          */
325145516Sdarrenr/* Returns:     int     - 0 = success, else error                           */
326255332Scy/* Parameters:  softc(I) - pointer to soft context main structure           */
327255332Scy/*              data(I) - pointer to data from ioctl call                   */
328145516Sdarrenr/*                                                                          */
329145516Sdarrenr/* Add a new data node to a lookup structure.  First, check to see if the   */
330145516Sdarrenr/* parent structure refered to by name exists and if it does, then go on to */
331145516Sdarrenr/* add a node to it.                                                        */
332145516Sdarrenr/* ------------------------------------------------------------------------ */
333255332Scystatic int
334255332Scyipf_lookup_addnode(softc, data, uid)
335255332Scy	ipf_main_softc_t *softc;
336255332Scy	caddr_t data;
337255332Scy	int uid;
338145516Sdarrenr{
339255332Scy	ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
340145516Sdarrenr	iplookupop_t op;
341255332Scy	ipf_lookup_t **l;
342145516Sdarrenr	int err;
343255332Scy	int i;
344145516Sdarrenr
345170263Sdarrenr	err = BCOPYIN(data, &op, sizeof(op));
346255332Scy	if (err != 0) {
347255332Scy		IPFERROR(50002);
348170263Sdarrenr		return EFAULT;
349255332Scy	}
350170263Sdarrenr
351255332Scy	if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) &&
352255332Scy	    (op.iplo_unit != IPLT_ALL)) {
353255332Scy		IPFERROR(50003);
354170263Sdarrenr		return EINVAL;
355255332Scy	}
356170263Sdarrenr
357145516Sdarrenr	op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
358145516Sdarrenr
359255332Scy	for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
360255332Scy		if (op.iplo_type == (*l)->ipfl_type) {
361255332Scy			err = (*(*l)->ipfl_node_add)(softc,
362255332Scy						     softl->ipf_back[i],
363255332Scy						     &op, uid);
364255332Scy			break;
365255332Scy		}
366255332Scy	}
367145516Sdarrenr
368255332Scy	if (i == MAX_BACKENDS) {
369255332Scy		IPFERROR(50012);
370145516Sdarrenr		err = EINVAL;
371145516Sdarrenr	}
372255332Scy
373145516Sdarrenr	return err;
374145516Sdarrenr}
375145516Sdarrenr
376145516Sdarrenr
377145516Sdarrenr/* ------------------------------------------------------------------------ */
378255332Scy/* Function:    ipf_lookup_delnode                                          */
379145516Sdarrenr/* Returns:     int     - 0 = success, else error                           */
380255332Scy/* Parameters:  softc(I) - pointer to soft context main structure           */
381255332Scy/*              data(I) - pointer to data from ioctl call                   */
382145516Sdarrenr/*                                                                          */
383145516Sdarrenr/* Delete a node from a lookup table by first looking for the table it is   */
384145516Sdarrenr/* in and then deleting the entry that gets found.                          */
385145516Sdarrenr/* ------------------------------------------------------------------------ */
386255332Scystatic int
387255332Scyipf_lookup_delnode(softc, data, uid)
388255332Scy	ipf_main_softc_t *softc;
389255332Scy	caddr_t data;
390255332Scy	int uid;
391145516Sdarrenr{
392255332Scy	ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
393145516Sdarrenr	iplookupop_t op;
394255332Scy	ipf_lookup_t **l;
395145516Sdarrenr	int err;
396255332Scy	int i;
397145516Sdarrenr
398172771Sdarrenr	err = BCOPYIN(data, &op, sizeof(op));
399255332Scy	if (err != 0) {
400255332Scy		IPFERROR(50042);
401172771Sdarrenr		return EFAULT;
402255332Scy	}
403145516Sdarrenr
404255332Scy	if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) &&
405255332Scy	    (op.iplo_unit != IPLT_ALL)) {
406255332Scy		IPFERROR(50013);
407170263Sdarrenr		return EINVAL;
408255332Scy	}
409170263Sdarrenr
410145516Sdarrenr	op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
411145516Sdarrenr
412255332Scy	for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
413255332Scy		if (op.iplo_type == (*l)->ipfl_type) {
414255332Scy			err = (*(*l)->ipfl_node_del)(softc, softl->ipf_back[i],
415255332Scy						     &op, uid);
416255332Scy			break;
417255332Scy		}
418255332Scy	}
419145516Sdarrenr
420255332Scy	if (i == MAX_BACKENDS) {
421255332Scy		IPFERROR(50021);
422145516Sdarrenr		err = EINVAL;
423145516Sdarrenr	}
424145516Sdarrenr	return err;
425145516Sdarrenr}
426145516Sdarrenr
427145516Sdarrenr
428145516Sdarrenr/* ------------------------------------------------------------------------ */
429255332Scy/* Function:    ipf_lookup_addtable                                         */
430145516Sdarrenr/* Returns:     int     - 0 = success, else error                           */
431255332Scy/* Parameters:  softc(I) - pointer to soft context main structure           */
432255332Scy/*              data(I) - pointer to data from ioctl call                   */
433145516Sdarrenr/*                                                                          */
434145516Sdarrenr/* Create a new lookup table, if one doesn't already exist using the name   */
435145516Sdarrenr/* for this one.                                                            */
436145516Sdarrenr/* ------------------------------------------------------------------------ */
437255332Scystatic int
438255332Scyipf_lookup_addtable(softc, data)
439255332Scy	ipf_main_softc_t *softc;
440255332Scy	caddr_t data;
441145516Sdarrenr{
442255332Scy	ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
443145516Sdarrenr	iplookupop_t op;
444255332Scy	ipf_lookup_t **l;
445255332Scy	int err, i;
446145516Sdarrenr
447170263Sdarrenr	err = BCOPYIN(data, &op, sizeof(op));
448255332Scy	if (err != 0) {
449255332Scy		IPFERROR(50022);
450170263Sdarrenr		return EFAULT;
451255332Scy	}
452145516Sdarrenr
453255332Scy	if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) &&
454255332Scy	    (op.iplo_unit != IPLT_ALL)) {
455255332Scy		IPFERROR(50023);
456170263Sdarrenr		return EINVAL;
457255332Scy	}
458170263Sdarrenr
459145516Sdarrenr	op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
460145516Sdarrenr
461255332Scy	for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
462255332Scy		if (op.iplo_type == (*l)->ipfl_type) {
463255332Scy			err = (*(*l)->ipfl_table_add)(softc,
464255332Scy						      softl->ipf_back[i],
465255332Scy						      &op);
466255332Scy			break;
467255332Scy		}
468255332Scy	}
469145516Sdarrenr
470255332Scy	if (i == MAX_BACKENDS) {
471255332Scy		IPFERROR(50026);
472145516Sdarrenr		err = EINVAL;
473145516Sdarrenr	}
474153872Sguido
475153872Sguido	/*
476153872Sguido	 * For anonymous pools, copy back the operation struct because in the
477153872Sguido	 * case of success it will contain the new table's name.
478153872Sguido	 */
479170263Sdarrenr	if ((err == 0) && ((op.iplo_arg & LOOKUP_ANON) != 0)) {
480170263Sdarrenr		err = BCOPYOUT(&op, data, sizeof(op));
481255332Scy		if (err != 0) {
482255332Scy			IPFERROR(50027);
483170263Sdarrenr			err = EFAULT;
484255332Scy		}
485153872Sguido	}
486153872Sguido
487145516Sdarrenr	return err;
488145516Sdarrenr}
489145516Sdarrenr
490145516Sdarrenr
491145516Sdarrenr/* ------------------------------------------------------------------------ */
492255332Scy/* Function:    ipf_lookup_deltable                                         */
493145516Sdarrenr/* Returns:     int     - 0 = success, else error                           */
494255332Scy/* Parameters:  softc(I) - pointer to soft context main structure           */
495255332Scy/*              data(I) - pointer to data from ioctl call                   */
496145516Sdarrenr/*                                                                          */
497145516Sdarrenr/* Decodes ioctl request to remove a particular hash table or pool and      */
498145516Sdarrenr/* calls the relevant function to do the cleanup.                           */
499145516Sdarrenr/* ------------------------------------------------------------------------ */
500255332Scystatic int
501255332Scyipf_lookup_deltable(softc, data)
502255332Scy	ipf_main_softc_t *softc;
503255332Scy	caddr_t data;
504145516Sdarrenr{
505255332Scy	ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
506145516Sdarrenr	iplookupop_t op;
507255332Scy	ipf_lookup_t **l;
508255332Scy	int err, i;
509145516Sdarrenr
510170263Sdarrenr	err = BCOPYIN(data, &op, sizeof(op));
511255332Scy	if (err != 0) {
512255332Scy		IPFERROR(50028);
513170263Sdarrenr		return EFAULT;
514255332Scy	}
515170263Sdarrenr
516255332Scy	if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) &&
517255332Scy	    (op.iplo_unit != IPLT_ALL)) {
518255332Scy		IPFERROR(50029);
519170263Sdarrenr		return EINVAL;
520255332Scy	}
521170263Sdarrenr
522145516Sdarrenr	op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
523145516Sdarrenr
524255332Scy	for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
525255332Scy		if (op.iplo_type == (*l)->ipfl_type) {
526255332Scy			err = (*(*l)->ipfl_table_del)(softc,
527255332Scy						      softl->ipf_back[i],
528255332Scy						      &op);
529255332Scy			break;
530255332Scy		}
531255332Scy	}
532145516Sdarrenr
533255332Scy	if (i == MAX_BACKENDS) {
534255332Scy		IPFERROR(50030);
535145516Sdarrenr		err = EINVAL;
536145516Sdarrenr	}
537145516Sdarrenr	return err;
538145516Sdarrenr}
539145516Sdarrenr
540145516Sdarrenr
541145516Sdarrenr/* ------------------------------------------------------------------------ */
542255332Scy/* Function:    ipf_lookup_stats                                            */
543145516Sdarrenr/* Returns:     int     - 0 = success, else error                           */
544255332Scy/* Parameters:  softc(I) - pointer to soft context main structure           */
545255332Scy/*              data(I) - pointer to data from ioctl call                   */
546145516Sdarrenr/*                                                                          */
547145516Sdarrenr/* Copy statistical information from inside the kernel back to user space.  */
548145516Sdarrenr/* ------------------------------------------------------------------------ */
549255332Scystatic int
550255332Scyipf_lookup_stats(softc, data)
551255332Scy	ipf_main_softc_t *softc;
552255332Scy	caddr_t data;
553145516Sdarrenr{
554255332Scy	ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
555145516Sdarrenr	iplookupop_t op;
556255332Scy	ipf_lookup_t **l;
557145516Sdarrenr	int err;
558255332Scy	int i;
559145516Sdarrenr
560170263Sdarrenr	err = BCOPYIN(data, &op, sizeof(op));
561255332Scy	if (err != 0) {
562255332Scy		IPFERROR(50031);
563170263Sdarrenr		return EFAULT;
564255332Scy	}
565145516Sdarrenr
566255332Scy	if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) &&
567255332Scy	    (op.iplo_unit != IPLT_ALL)) {
568255332Scy		IPFERROR(50032);
569170263Sdarrenr		return EINVAL;
570255332Scy	}
571170263Sdarrenr
572255332Scy	for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
573255332Scy		if (op.iplo_type == (*l)->ipfl_type) {
574255332Scy			err = (*(*l)->ipfl_stats_get)(softc,
575255332Scy						      softl->ipf_back[i],
576255332Scy						      &op);
577255332Scy			break;
578255332Scy		}
579255332Scy	}
580145516Sdarrenr
581255332Scy	if (i == MAX_BACKENDS) {
582255332Scy		IPFERROR(50033);
583145516Sdarrenr		err = EINVAL;
584145516Sdarrenr	}
585255332Scy
586145516Sdarrenr	return err;
587145516Sdarrenr}
588145516Sdarrenr
589145516Sdarrenr
590145516Sdarrenr/* ------------------------------------------------------------------------ */
591255332Scy/* Function:    ipf_lookup_flush                                            */
592145516Sdarrenr/* Returns:     int     - 0 = success, else error                           */
593255332Scy/* Parameters:  softc(I) - pointer to soft context main structure           */
594255332Scy/*              data(I) - pointer to data from ioctl call                   */
595145516Sdarrenr/*                                                                          */
596145516Sdarrenr/* A flush is called when we want to flush all the nodes from a particular  */
597145516Sdarrenr/* entry in the hash table/pool or want to remove all groups from those.    */
598145516Sdarrenr/* ------------------------------------------------------------------------ */
599255332Scystatic int
600255332Scyipf_lookup_flush(softc, data)
601255332Scy	ipf_main_softc_t *softc;
602255332Scy	caddr_t data;
603145516Sdarrenr{
604255332Scy	ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
605255332Scy	int err, unit, num, type, i;
606145516Sdarrenr	iplookupflush_t flush;
607255332Scy	ipf_lookup_t **l;
608145516Sdarrenr
609170263Sdarrenr	err = BCOPYIN(data, &flush, sizeof(flush));
610255332Scy	if (err != 0) {
611255332Scy		IPFERROR(50034);
612170263Sdarrenr		return EFAULT;
613255332Scy	}
614145516Sdarrenr
615145516Sdarrenr	unit = flush.iplf_unit;
616255332Scy	if ((unit < 0 || unit > IPL_LOGMAX) && (unit != IPLT_ALL)) {
617255332Scy		IPFERROR(50035);
618145516Sdarrenr		return EINVAL;
619255332Scy	}
620145516Sdarrenr
621170263Sdarrenr	flush.iplf_name[sizeof(flush.iplf_name) - 1] = '\0';
622170263Sdarrenr
623145516Sdarrenr	type = flush.iplf_type;
624255332Scy	IPFERROR(50036);
625145516Sdarrenr	err = EINVAL;
626145516Sdarrenr	num = 0;
627145516Sdarrenr
628255332Scy	for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
629255332Scy		if (type == (*l)->ipfl_type || type == IPLT_ALL) {
630255332Scy			err = 0;
631255332Scy			num += (*(*l)->ipfl_flush)(softc,
632255332Scy						   softl->ipf_back[i],
633255332Scy						   &flush);
634255332Scy		}
635145516Sdarrenr	}
636145516Sdarrenr
637145516Sdarrenr	if (err == 0) {
638145516Sdarrenr		flush.iplf_count = num;
639170263Sdarrenr		err = BCOPYOUT(&flush, data, sizeof(flush));
640255332Scy		if (err != 0) {
641255332Scy			IPFERROR(50037);
642170263Sdarrenr			err = EFAULT;
643255332Scy		}
644145516Sdarrenr	}
645145516Sdarrenr	return err;
646145516Sdarrenr}
647145516Sdarrenr
648145516Sdarrenr
649170263Sdarrenr/* ------------------------------------------------------------------------ */
650255332Scy/* Function:    ipf_lookup_delref                                           */
651170263Sdarrenr/* Returns:     void                                                        */
652255332Scy/* Parameters:  softc(I) - pointer to soft context main structure           */
653255332Scy/*              type(I) - table type to operate on                          */
654170263Sdarrenr/*              ptr(I)  - pointer to object to remove reference for         */
655170263Sdarrenr/*                                                                          */
656170263Sdarrenr/* This function organises calling the correct deref function for a given   */
657170263Sdarrenr/* type of object being passed into it.                                     */
658170263Sdarrenr/* ------------------------------------------------------------------------ */
659255332Scyvoid
660255332Scyipf_lookup_deref(softc, type, ptr)
661255332Scy	ipf_main_softc_t *softc;
662255332Scy	int type;
663255332Scy	void *ptr;
664145516Sdarrenr{
665255332Scy	ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
666255332Scy	int i;
667255332Scy
668145516Sdarrenr	if (ptr == NULL)
669145516Sdarrenr		return;
670145516Sdarrenr
671255332Scy	for (i = 0; i < MAX_BACKENDS; i++) {
672255332Scy		if (type == backends[i]->ipfl_type) {
673255332Scy			WRITE_ENTER(&softc->ipf_poolrw);
674255332Scy			(*backends[i]->ipfl_table_deref)(softc,
675255332Scy							 softl->ipf_back[i],
676255332Scy							 ptr);
677255332Scy			RWLOCK_EXIT(&softc->ipf_poolrw);
678255332Scy			break;
679255332Scy		}
680145516Sdarrenr	}
681145516Sdarrenr}
682145516Sdarrenr
683145516Sdarrenr
684170263Sdarrenr/* ------------------------------------------------------------------------ */
685255332Scy/* Function:    ipf_lookup_iterate                                          */
686170263Sdarrenr/* Returns:     int     - 0 = success, else error                           */
687255332Scy/* Parameters:  softc(I) - pointer to soft context main structure           */
688255332Scy/*              data(I) - pointer to data from ioctl call                   */
689172771Sdarrenr/*              uid(I)  - uid of caller                                     */
690172771Sdarrenr/*              ctx(I)  - pointer to give the uid context                   */
691170263Sdarrenr/*                                                                          */
692170263Sdarrenr/* Decodes ioctl request to step through either hash tables or pools.       */
693170263Sdarrenr/* ------------------------------------------------------------------------ */
694255332Scystatic int
695255332Scyipf_lookup_iterate(softc, data, uid, ctx)
696255332Scy	ipf_main_softc_t *softc;
697255332Scy	void *data;
698255332Scy	int uid;
699255332Scy	void *ctx;
700170263Sdarrenr{
701255332Scy	ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
702170263Sdarrenr	ipflookupiter_t iter;
703170263Sdarrenr	ipftoken_t *token;
704255332Scy	int err, i;
705170263Sdarrenr	SPL_INT(s);
706170263Sdarrenr
707255332Scy	err = ipf_inobj(softc, data, NULL, &iter, IPFOBJ_LOOKUPITER);
708170263Sdarrenr	if (err != 0)
709170263Sdarrenr		return err;
710170263Sdarrenr
711255332Scy	if (iter.ili_unit < IPL_LOGALL && iter.ili_unit > IPL_LOGMAX) {
712255332Scy		IPFERROR(50038);
713170263Sdarrenr		return EINVAL;
714255332Scy	}
715170263Sdarrenr
716255332Scy	if (iter.ili_ival != IPFGENITER_LOOKUP) {
717255332Scy		IPFERROR(50039);
718170263Sdarrenr		return EINVAL;
719255332Scy	}
720170263Sdarrenr
721170263Sdarrenr	SPL_SCHED(s);
722255332Scy	token = ipf_token_find(softc, iter.ili_key, uid, ctx);
723170263Sdarrenr	if (token == NULL) {
724170263Sdarrenr		SPL_X(s);
725255332Scy		IPFERROR(50040);
726170263Sdarrenr		return ESRCH;
727170263Sdarrenr	}
728170263Sdarrenr
729255332Scy	for (i = 0; i < MAX_BACKENDS; i++) {
730255332Scy		if (iter.ili_type == backends[i]->ipfl_type) {
731255332Scy			err = (*backends[i]->ipfl_iter_next)(softc,
732255332Scy							     softl->ipf_back[i],
733255332Scy							     token, &iter);
734255332Scy			break;
735255332Scy		}
736170263Sdarrenr	}
737170263Sdarrenr	SPL_X(s);
738170263Sdarrenr
739255332Scy	if (i == MAX_BACKENDS) {
740255332Scy		IPFERROR(50041);
741255332Scy		err = EINVAL;
742255332Scy	}
743255332Scy
744255332Scy	WRITE_ENTER(&softc->ipf_tokens);
745255332Scy	ipf_token_deref(softc, token);
746255332Scy	RWLOCK_EXIT(&softc->ipf_tokens);
747255332Scy
748170263Sdarrenr	return err;
749170263Sdarrenr}
750170263Sdarrenr
751170263Sdarrenr
752170263Sdarrenr/* ------------------------------------------------------------------------ */
753255332Scy/* Function:    ipf_lookup_iterderef                                        */
754255332Scy/* Returns:     void                                                        */
755255332Scy/* Parameters:  softc(I) - pointer to soft context main structure           */
756255332Scy/*              type(I)  - backend type to iterate through                  */
757255332Scy/*              data(I)  - pointer to data from ioctl call                  */
758170263Sdarrenr/*                                                                          */
759170263Sdarrenr/* Decodes ioctl request to remove a particular hash table or pool and      */
760170263Sdarrenr/* calls the relevant function to do the cleanup.                           */
761255332Scy/* Because each of the backend types has a different data structure,        */
762255332Scy/* iteration is limited to one type at a time (i.e. it is not permitted to  */
763255332Scy/* go on from pool types to hash types as part of the "get next".)          */
764170263Sdarrenr/* ------------------------------------------------------------------------ */
765255332Scyvoid
766255332Scyipf_lookup_iterderef(softc, type, data)
767255332Scy	ipf_main_softc_t *softc;
768255332Scy	u_32_t type;
769255332Scy	void *data;
770170263Sdarrenr{
771255332Scy	ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
772255332Scy	struct iplookupiterkey *lkey;
773255332Scy	iplookupiterkey_t key;
774255332Scy	int i;
775170263Sdarrenr
776170263Sdarrenr	key.ilik_key = type;
777255332Scy	lkey = &key.ilik_unstr;
778170263Sdarrenr
779255332Scy	if (lkey->ilik_ival != IPFGENITER_LOOKUP)
780170263Sdarrenr		return;
781170263Sdarrenr
782255332Scy	WRITE_ENTER(&softc->ipf_poolrw);
783255332Scy
784255332Scy	for (i = 0; i < MAX_BACKENDS; i++) {
785255332Scy		if (lkey->ilik_type == backends[i]->ipfl_type) {
786255332Scy			(*backends[i]->ipfl_iter_deref)(softc,
787255332Scy							softl->ipf_back[i],
788255332Scy							lkey->ilik_otype,
789255332Scy							lkey->ilik_unit,
790255332Scy							data);
791255332Scy			break;
792255332Scy		}
793170263Sdarrenr	}
794255332Scy	RWLOCK_EXIT(&softc->ipf_poolrw);
795170263Sdarrenr}
796170263Sdarrenr
797170263Sdarrenr
798172771Sdarrenr/* ------------------------------------------------------------------------ */
799255332Scy/* Function:    ipf_lookup_deltok                                           */
800172771Sdarrenr/* Returns:     int     - 0 = success, else error                           */
801255332Scy/* Parameters:  softc(I) - pointer to soft context main structure           */
802255332Scy/*              data(I) - pointer to data from ioctl call                   */
803172771Sdarrenr/*              uid(I)  - uid of caller                                     */
804172771Sdarrenr/*              ctx(I)  - pointer to give the uid context                   */
805172771Sdarrenr/*                                                                          */
806172771Sdarrenr/* Deletes the token identified by the combination of (type,uid,ctx)        */
807172771Sdarrenr/* "key" is a combination of the table type, iterator type and the unit for */
808172771Sdarrenr/* which the token was being used.                                          */
809172771Sdarrenr/* ------------------------------------------------------------------------ */
810255332Scyint
811255332Scyipf_lookup_deltok(softc, data, uid, ctx)
812255332Scy	ipf_main_softc_t *softc;
813255332Scy	void *data;
814255332Scy	int uid;
815255332Scy	void *ctx;
816172771Sdarrenr{
817172771Sdarrenr	int error, key;
818172771Sdarrenr	SPL_INT(s);
819170263Sdarrenr
820172771Sdarrenr	SPL_SCHED(s);
821255332Scy	error = BCOPYIN(data, &key, sizeof(key));
822172771Sdarrenr	if (error == 0)
823255332Scy		error = ipf_token_del(softc, key, uid, ctx);
824172771Sdarrenr	SPL_X(s);
825172771Sdarrenr	return error;
826172771Sdarrenr}
827172771Sdarrenr
828172771Sdarrenr
829255332Scy/* ------------------------------------------------------------------------ */
830255332Scy/* Function:    ipf_lookup_res_num                                          */
831255332Scy/* Returns:     void * - NULL = failure, else success.                      */
832255332Scy/* Parameters:  softc(I) - pointer to soft context main structure           */
833255332Scy/*              unit(I)     - device for which this is for                  */
834255332Scy/*              type(I)     - type of lookup these parameters are for.      */
835255332Scy/*              number(I)   - table number to use when searching            */
836255332Scy/*              funcptr(IO) - pointer to pointer for storing IP address     */
837255332Scy/*                            searching function.                           */
838255332Scy/*                                                                          */
839255332Scy/* Search for the "table" number passed in amongst those configured for     */
840255332Scy/* that particular type.  If the type is recognised then the function to    */
841255332Scy/* call to do the IP address search will be change, regardless of whether   */
842255332Scy/* or not the "table" number exists.                                        */
843255332Scy/* ------------------------------------------------------------------------ */
844255332Scyvoid *
845255332Scyipf_lookup_res_num(softc, unit, type, number, funcptr)
846255332Scy	ipf_main_softc_t *softc;
847255332Scy	int unit;
848255332Scy	u_int type;
849255332Scy	u_int number;
850255332Scy	lookupfunc_t *funcptr;
851255332Scy{
852255332Scy	char name[FR_GROUPLEN];
853145516Sdarrenr
854255332Scy#if defined(SNPRINTF) && defined(_KERNEL)
855255332Scy	SNPRINTF(name, sizeof(name), "%u", number);
856255332Scy#else
857255332Scy	(void) sprintf(name, "%u", number);
858255332Scy#endif
859255332Scy
860255332Scy	return ipf_lookup_res_name(softc, unit, type, name, funcptr);
861255332Scy}
862255332Scy
863255332Scy
864255332Scy/* ------------------------------------------------------------------------ */
865255332Scy/* Function:    ipf_lookup_res_name                                         */
866255332Scy/* Returns:     void * - NULL = failure, else success.                      */
867255332Scy/* Parameters:  softc(I) - pointer to soft context main structure           */
868255332Scy/*              unit(I)     - device for which this is for                  */
869255332Scy/*              type(I)     - type of lookup these parameters are for.      */
870255332Scy/*              name(I)     - table name to use when searching              */
871255332Scy/*              funcptr(IO) - pointer to pointer for storing IP address     */
872255332Scy/*                            searching function.                           */
873255332Scy/*                                                                          */
874255332Scy/* Search for the "table" number passed in amongst those configured for     */
875255332Scy/* that particular type.  If the type is recognised then the function to    */
876255332Scy/* call to do the IP address search will be changed, regardless of whether  */
877255332Scy/* or not the "table" number exists.                                        */
878255332Scy/* ------------------------------------------------------------------------ */
879255332Scyvoid *
880255332Scyipf_lookup_res_name(softc, unit, type, name, funcptr)
881255332Scy	ipf_main_softc_t *softc;
882255332Scy	int unit;
883255332Scy	u_int type;
884255332Scy	char *name;
885255332Scy	lookupfunc_t *funcptr;
886255332Scy{
887255332Scy	ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
888255332Scy	ipf_lookup_t **l;
889255332Scy	void *ptr = NULL;
890255332Scy	int i;
891255332Scy
892255332Scy	READ_ENTER(&softc->ipf_poolrw);
893255332Scy
894255332Scy	for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
895255332Scy		if (type == (*l)->ipfl_type) {
896255332Scy			ptr = (*(*l)->ipfl_select_add_ref)(softl->ipf_back[i],
897255332Scy							   unit, name);
898255332Scy			if (ptr != NULL && funcptr != NULL) {
899255332Scy				*funcptr = (*l)->ipfl_addr_find;
900255332Scy			}
901255332Scy			break;
902255332Scy		}
903255332Scy	}
904255332Scy
905255332Scy	if (i == MAX_BACKENDS) {
906255332Scy		ptr = NULL;
907255332Scy		if (funcptr != NULL)
908255332Scy			*funcptr = NULL;
909255332Scy	}
910255332Scy
911255332Scy	RWLOCK_EXIT(&softc->ipf_poolrw);
912255332Scy
913255332Scy	return ptr;
914255332Scy}
915255332Scy
916255332Scy
917255332Scy/* ------------------------------------------------------------------------ */
918255332Scy/* Function:    ipf_lookup_find_htable                                      */
919255332Scy/* Returns:     void * - NULL = failure, else success.                      */
920255332Scy/* Parameters:  softc(I) - pointer to soft context main structure           */
921255332Scy/*              unit(I)     - device for which this is for                  */
922255332Scy/*              name(I)     - table name to use when searching              */
923255332Scy/*                                                                          */
924255332Scy/* To support the group-map feature, where a hash table maps address        */
925255332Scy/* networks to rule group numbers, we need to expose a function that uses   */
926255332Scy/* only the hash table backend.                                             */
927255332Scy/* ------------------------------------------------------------------------ */
928255332Scyvoid *
929255332Scyipf_lookup_find_htable(softc, unit, name)
930255332Scy	ipf_main_softc_t *softc;
931255332Scy	int unit;
932255332Scy	char *name;
933255332Scy{
934255332Scy	ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
935255332Scy	ipf_lookup_t **l;
936255332Scy	void *tab = NULL;
937255332Scy	int i;
938255332Scy
939255332Scy	READ_ENTER(&softc->ipf_poolrw);
940255332Scy
941255332Scy	for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++)
942255332Scy		if (IPLT_HASH == (*l)->ipfl_type) {
943255332Scy			tab = ipf_htable_find(softl->ipf_back[i], unit, name);
944255332Scy			break;
945255332Scy		}
946255332Scy
947255332Scy	RWLOCK_EXIT(&softc->ipf_poolrw);
948255332Scy
949255332Scy	return tab;
950255332Scy}
951255332Scy
952255332Scy
953255332Scy/* ------------------------------------------------------------------------ */
954255332Scy/* Function:    ipf_lookup_sync                                             */
955255332Scy/* Returns:     void                                                        */
956255332Scy/* Parameters:  softc(I) - pointer to soft context main structure           */
957255332Scy/*                                                                          */
958255332Scy/* This function is the interface that the machine dependent sync functions */
959255332Scy/* call when a network interface name change occurs. It then calls the sync */
960255332Scy/* functions of the lookup implementations - if they have one.              */
961255332Scy/* ------------------------------------------------------------------------ */
962145516Sdarrenr/*ARGSUSED*/
963255332Scyvoid
964255332Scyipf_lookup_sync(softc, ifp)
965255332Scy	ipf_main_softc_t *softc;
966255332Scy	void *ifp;
967145516Sdarrenr{
968255332Scy	ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
969255332Scy	ipf_lookup_t **l;
970255332Scy	int i;
971255332Scy
972255332Scy	READ_ENTER(&softc->ipf_poolrw);
973255332Scy
974255332Scy	for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++)
975255332Scy		if ((*l)->ipfl_sync != NULL)
976255332Scy			(*(*l)->ipfl_sync)(softc, softl->ipf_back[i]);
977255332Scy
978255332Scy	RWLOCK_EXIT(&softc->ipf_poolrw);
979145516Sdarrenr}
980255332Scy
981255332Scy
982255332Scy#ifndef _KERNEL
983255332Scyvoid
984255332Scyipf_lookup_dump(softc, arg)
985255332Scy	ipf_main_softc_t *softc;
986255332Scy	void *arg;
987255332Scy{
988255332Scy	ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
989255332Scy	ipf_lookup_t **l;
990255332Scy	int i;
991255332Scy
992255332Scy	for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++)
993255332Scy		if (IPLT_POOL == (*l)->ipfl_type) {
994255332Scy			ipf_pool_dump(softc, softl->ipf_back[i]);
995255332Scy			break;
996255332Scy		}
997255332Scy
998255332Scy	for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++)
999255332Scy		if (IPLT_HASH == (*l)->ipfl_type) {
1000255332Scy			ipf_htable_dump(softc, softl->ipf_back[i]);
1001255332Scy			break;
1002255332Scy		}
1003255332Scy}
1004255332Scy#endif
1005