1/* $NetBSD: ip_lookup.c,v 1.5 2016/06/09 04:43:46 pgoyette Exp $ */
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#if defined(__osf__)
15# define _PROTO_NET_H_
16#endif
17#include <sys/param.h>
18#if defined(__NetBSD__)
19# if (NetBSD >= 199905) && !defined(IPFILTER_LKM) && defined(_KERNEL)
20# if (__NetBSD_Version__ >= 799003000)
21# if defined(_KERNEL_OPT)
22# include "opt_ipfilter.h"
23# endif
24# else
25# include "opt_ipfilter.h"
26# endif
27# endif
28#endif
29#include <sys/errno.h>
30#include <sys/types.h>
31#include <sys/time.h>
32#include <sys/file.h>
33#if __FreeBSD_version >= 220000 && defined(_KERNEL)
34# include <sys/fcntl.h>
35# include <sys/filio.h>
36#else
37# include <sys/ioctl.h>
38#endif
39#if !defined(_KERNEL)
40# include <stdio.h>
41# include <string.h>
42# include <stdlib.h>
43# define _KERNEL
44# ifdef __OpenBSD__
45struct file;
46# endif
47# include <sys/uio.h>
48# undef _KERNEL
49#endif
50#include <sys/socket.h>
51#include <net/if.h>
52#if defined(__FreeBSD__)
53# include <sys/cdefs.h>
54# include <sys/proc.h>
55#endif
56#if defined(_KERNEL)
57# include <sys/systm.h>
58# if !defined(__SVR4) && !defined(__svr4__)
59# include <sys/mbuf.h>
60# endif
61#else
62# include "ipf.h"
63#endif
64#include <netinet/in.h>
65
66#include "netinet/ip_compat.h"
67#include "netinet/ip_fil.h"
68#include "netinet/ip_lookup.h"
69#include "netinet/ip_pool.h"
70#include "netinet/ip_htable.h"
71#include "netinet/ip_dstlist.h"
72/* END OF INCLUDES */
73
74#if !defined(lint)
75#if defined(__NetBSD__)
76#include <sys/cdefs.h>
77__KERNEL_RCSID(0, "$NetBSD: ip_lookup.c,v 1.5 2016/06/09 04:43:46 pgoyette Exp $");
78#else
79static const char rcsid[] = "@(#)Id: ip_lookup.c,v 1.1.1.2 2012/07/22 13:45:21 darrenr Exp";
80#endif
81#endif
82
83/*
84 * In this file, ip_pool.c, ip_htable.c and ip_dstlist.c, you will find the
85 * range for unit is [-1,IPL_LOGMAX]. The -1 is considered to be a valid number
86 * and represents a "wildcard" or "all" units (IPL_LOGALL). The reason for not
87 * starting the numbering at 0 is because the numbers [0,IPL_LOGMAX] correspond
88 * to the minor device number for their respective device. Thus where there is
89 * array indexing on the unit, +1 is used to map [-1.IPL_LOGMAX] to
90 * [0.POOL_LOOKUP_MAX].
91 */
92static int ipf_lookup_addnode(ipf_main_softc_t *, void *, int);
93static int ipf_lookup_delnode(ipf_main_softc_t *, void *, int);
94static int ipf_lookup_addtable(ipf_main_softc_t *, void *);
95static int ipf_lookup_deltable(ipf_main_softc_t *, void *);
96static int ipf_lookup_stats(ipf_main_softc_t *, void *);
97static int ipf_lookup_flush(ipf_main_softc_t *, void *);
98static int ipf_lookup_iterate(ipf_main_softc_t *, void *, int, void *);
99static int ipf_lookup_deltok(ipf_main_softc_t *, void *, int, void *);
100
101#define MAX_BACKENDS 3
102static ipf_lookup_t *backends[MAX_BACKENDS] = {
103 &ipf_pool_backend,
104 &ipf_htable_backend,
105 &ipf_dstlist_backend
106};
107
108
109typedef struct ipf_lookup_softc_s {
110 void *ipf_back[MAX_BACKENDS];
111} ipf_lookup_softc_t;
112
113
114/* ------------------------------------------------------------------------ */
115/* Function: ipf_lookup_init */
116/* Returns: int - 0 = success, else error */
117/* Parameters: softc(I) - pointer to soft context main structure */
118/* */
119/* Initialise all of the subcomponents of the lookup infrstructure. */
120/* ------------------------------------------------------------------------ */
121void *
122ipf_lookup_soft_create(ipf_main_softc_t *softc)
123{
124 ipf_lookup_softc_t *softl;
125 ipf_lookup_t **l;
126 int i;
127
128 KMALLOC(softl, ipf_lookup_softc_t *);
129 if (softl == NULL)
130 return NULL;
131
132 bzero((char *)softl, sizeof(*softl));
133
134 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
135 softl->ipf_back[i] = (*(*l)->ipfl_create)(softc);
136 if (softl->ipf_back[i] == NULL) {
137 ipf_lookup_soft_destroy(softc, softl);
138 return NULL;
139 }
140 }
141
142 return softl;
143}
144
145
146/* ------------------------------------------------------------------------ */
147/* Function: ipf_lookup_soft_init */
148/* Returns: int - 0 = success, else error */
149/* Parameters: softc(I) - pointer to soft context main structure */
150/* arg(I) - pointer to local context to use */
151/* */
152/* Initialise all of the subcomponents of the lookup infrstructure. */
153/* ------------------------------------------------------------------------ */
154int
155ipf_lookup_soft_init(ipf_main_softc_t *softc, void *arg)
156{
157 ipf_lookup_softc_t *softl = (ipf_lookup_softc_t *)arg;
158 int err = 0;
159 int i;
160
161 for (i = 0; i < MAX_BACKENDS; i++) {
162 err = (*backends[i]->ipfl_init)(softc, softl->ipf_back[i]);
163 if (err != 0)
164 break;
165 }
166
167 return err;
168}
169
170
171/* ------------------------------------------------------------------------ */
172/* Function: ipf_lookup_soft_fini */
173/* Returns: int - 0 = success, else error */
174/* Parameters: softc(I) - pointer to soft context main structure */
175/* arg(I) - pointer to local context to use */
176/* */
177/* Call the fini function in each backend to cleanup all allocated data. */
178/* ------------------------------------------------------------------------ */
179int
180ipf_lookup_soft_fini(ipf_main_softc_t *softc, void *arg)
181{
182 ipf_lookup_softc_t *softl = (ipf_lookup_softc_t *)arg;
183 int i;
184
185 for (i = 0; i < MAX_BACKENDS; i++) {
186 if (softl->ipf_back[i] != NULL)
187 (*backends[i]->ipfl_fini)(softc,
188 softl->ipf_back[i]);
189 }
190
191 return 0;
192}
193
194
195/* ------------------------------------------------------------------------ */
196/* Function: ipf_lookup_expire */
197/* Returns: Nil */
198/* Parameters: softc(I) - pointer to soft context main structure */
199/* */
200/* Step through each of the backends and call their expire functions, */
201/* allowing them to delete any lifetime limited data. */
202/* ------------------------------------------------------------------------ */
203void
204ipf_lookup_expire(ipf_main_softc_t *softc)
205{
206 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
207 int i;
208
209 WRITE_ENTER(&softc->ipf_poolrw);
210 for (i = 0; i < MAX_BACKENDS; i++)
211 (*backends[i]->ipfl_expire)(softc, softl->ipf_back[i]);
212 RWLOCK_EXIT(&softc->ipf_poolrw);
213}
214
215
216/* ------------------------------------------------------------------------ */
217/* Function: ipf_lookup_softc_destroy */
218/* Returns: int - 0 = success, else error */
219/* Parameters: softc(I) - pointer to soft context main structure */
220/* arg(I) - pointer to local context to use */
221/* */
222/* Free up all pool related memory that has been allocated whilst IPFilter */
223/* has been running. Also, do any other deinitialisation required such */
224/* ipf_lookup_init() can be called again, safely. */
225/* ------------------------------------------------------------------------ */
226void
227ipf_lookup_soft_destroy(ipf_main_softc_t *softc, void *arg)
228{
229 ipf_lookup_softc_t *softl = (ipf_lookup_softc_t *)arg;
230 int i;
231
232 for (i = 0; i < MAX_BACKENDS; i++) {
233 if (softl->ipf_back[i] != NULL)
234 (*backends[i]->ipfl_destroy)(softc,
235 softl->ipf_back[i]);
236 }
237
238 KFREE(softl);
239}
240
241
242/* ------------------------------------------------------------------------ */
243/* Function: ipf_lookup_ioctl */
244/* Returns: int - 0 = success, else error */
245/* Parameters: softc(I) - pointer to soft context main structure */
246/* arg(I) - pointer to local context to use */
247/* data(IO) - pointer to ioctl data to be copied to/from user */
248/* space. */
249/* cmd(I) - ioctl command number */
250/* mode(I) - file mode bits used with open */
251/* uid(I) - uid of process doing ioctl */
252/* ctx(I) - pointer that represents context for uid */
253/* */
254/* Handle ioctl commands sent to the ioctl device. For the most part, this */
255/* involves just calling another function to handle the specifics of each */
256/* command. */
257/* ------------------------------------------------------------------------ */
258int
259ipf_lookup_ioctl(ipf_main_softc_t *softc, void *data, ioctlcmd_t cmd,
260 int mode, int uid, void *ctx)
261{
262 int err;
263 SPL_INT(s);
264
265 mode = mode; /* LINT */
266
267 SPL_NET(s);
268
269 switch (cmd)
270 {
271 case SIOCLOOKUPADDNODE :
272 case SIOCLOOKUPADDNODEW :
273 WRITE_ENTER(&softc->ipf_poolrw);
274 err = ipf_lookup_addnode(softc, data, uid);
275 RWLOCK_EXIT(&softc->ipf_poolrw);
276 break;
277
278 case SIOCLOOKUPDELNODE :
279 case SIOCLOOKUPDELNODEW :
280 WRITE_ENTER(&softc->ipf_poolrw);
281 err = ipf_lookup_delnode(softc, data, uid);
282 RWLOCK_EXIT(&softc->ipf_poolrw);
283 break;
284
285 case SIOCLOOKUPADDTABLE :
286 WRITE_ENTER(&softc->ipf_poolrw);
287 err = ipf_lookup_addtable(softc, data);
288 RWLOCK_EXIT(&softc->ipf_poolrw);
289 break;
290
291 case SIOCLOOKUPDELTABLE :
292 WRITE_ENTER(&softc->ipf_poolrw);
293 err = ipf_lookup_deltable(softc, data);
294 RWLOCK_EXIT(&softc->ipf_poolrw);
295 break;
296
297 case SIOCLOOKUPSTAT :
298 case SIOCLOOKUPSTATW :
299 WRITE_ENTER(&softc->ipf_poolrw);
300 err = ipf_lookup_stats(softc, data);
301 RWLOCK_EXIT(&softc->ipf_poolrw);
302 break;
303
304 case SIOCLOOKUPFLUSH :
305 WRITE_ENTER(&softc->ipf_poolrw);
306 err = ipf_lookup_flush(softc, data);
307 RWLOCK_EXIT(&softc->ipf_poolrw);
308 break;
309
310 case SIOCLOOKUPITER :
311 err = ipf_lookup_iterate(softc, data, uid, ctx);
312 break;
313
314 case SIOCIPFDELTOK :
315 err = ipf_lookup_deltok(softc, data, uid, ctx);
316 break;
317
318 default :
319 IPFERROR(50001);
320 err = EINVAL;
321 break;
322 }
323 SPL_X(s);
324 return err;
325}
326
327
328/* ------------------------------------------------------------------------ */
329/* Function: ipf_lookup_addnode */
330/* Returns: int - 0 = success, else error */
331/* Parameters: softc(I) - pointer to soft context main structure */
332/* data(I) - pointer to data from ioctl call */
333/* */
334/* Add a new data node to a lookup structure. First, check to see if the */
335/* parent structure refered to by name exists and if it does, then go on to */
336/* add a node to it. */
337/* ------------------------------------------------------------------------ */
338static int
339ipf_lookup_addnode(ipf_main_softc_t *softc, void *data, int uid)
340{
341 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
342 iplookupop_t op;
343 ipf_lookup_t **l;
344 int err;
345 int i;
346
347 err = BCOPYIN(data, &op, sizeof(op));
348 if (err != 0) {
349 IPFERROR(50002);
350 return EFAULT;
351 }
352
353 if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) &&
354 (op.iplo_unit != IPLT_ALL)) {
355 IPFERROR(50003);
356 return EINVAL;
357 }
358
359 op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
360
361 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
362 if (op.iplo_type == (*l)->ipfl_type) {
363 err = (*(*l)->ipfl_node_add)(softc,
364 softl->ipf_back[i],
365 &op, uid);
366 break;
367 }
368 }
369
370 if (i == MAX_BACKENDS) {
371 IPFERROR(50012);
372 err = EINVAL;
373 }
374
375 return err;
376}
377
378
379/* ------------------------------------------------------------------------ */
380/* Function: ipf_lookup_delnode */
381/* Returns: int - 0 = success, else error */
382/* Parameters: softc(I) - pointer to soft context main structure */
383/* data(I) - pointer to data from ioctl call */
384/* */
385/* Delete a node from a lookup table by first looking for the table it is */
386/* in and then deleting the entry that gets found. */
387/* ------------------------------------------------------------------------ */
388static int
389ipf_lookup_delnode(ipf_main_softc_t *softc, void *data, int uid)
390{
391 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
392 iplookupop_t op;
393 ipf_lookup_t **l;
394 int err;
395 int i;
396
397 err = BCOPYIN(data, &op, sizeof(op));
398 if (err != 0) {
399 IPFERROR(50042);
400 return EFAULT;
401 }
402
403 if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) &&
404 (op.iplo_unit != IPLT_ALL)) {
405 IPFERROR(50013);
406 return EINVAL;
407 }
408
409 op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
410
411 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
412 if (op.iplo_type == (*l)->ipfl_type) {
413 err = (*(*l)->ipfl_node_del)(softc, softl->ipf_back[i],
414 &op, uid);
415 break;
416 }
417 }
418
419 if (i == MAX_BACKENDS) {
420 IPFERROR(50021);
421 err = EINVAL;
422 }
423 return err;
424}
425
426
427/* ------------------------------------------------------------------------ */
428/* Function: ipf_lookup_addtable */
429/* Returns: int - 0 = success, else error */
430/* Parameters: softc(I) - pointer to soft context main structure */
431/* data(I) - pointer to data from ioctl call */
432/* */
433/* Create a new lookup table, if one doesn't already exist using the name */
434/* for this one. */
435/* ------------------------------------------------------------------------ */
436static int
437ipf_lookup_addtable(ipf_main_softc_t *softc, void *data)
438{
439 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
440 iplookupop_t op;
441 ipf_lookup_t **l;
442 int err, i;
443
444 err = BCOPYIN(data, &op, sizeof(op));
445 if (err != 0) {
446 IPFERROR(50022);
447 return EFAULT;
448 }
449
450 if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) &&
451 (op.iplo_unit != IPLT_ALL)) {
452 IPFERROR(50023);
453 return EINVAL;
454 }
455
456 op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
457
458 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
459 if (op.iplo_type == (*l)->ipfl_type) {
460 err = (*(*l)->ipfl_table_add)(softc,
461 softl->ipf_back[i],
462 &op);
463 break;
464 }
465 }
466
467 if (i == MAX_BACKENDS) {
468 IPFERROR(50026);
469 err = EINVAL;
470 }
471
472 /*
473 * For anonymous pools, copy back the operation struct because in the
474 * case of success it will contain the new table's name.
475 */
476 if ((err == 0) && ((op.iplo_arg & LOOKUP_ANON) != 0)) {
477 err = BCOPYOUT(&op, data, sizeof(op));
478 if (err != 0) {
479 IPFERROR(50027);
480 err = EFAULT;
481 }
482 }
483
484 return err;
485}
486
487
488/* ------------------------------------------------------------------------ */
489/* Function: ipf_lookup_deltable */
490/* Returns: int - 0 = success, else error */
491/* Parameters: softc(I) - pointer to soft context main structure */
492/* data(I) - pointer to data from ioctl call */
493/* */
494/* Decodes ioctl request to remove a particular hash table or pool and */
495/* calls the relevant function to do the cleanup. */
496/* ------------------------------------------------------------------------ */
497static int
498ipf_lookup_deltable(ipf_main_softc_t *softc, void *data)
499{
500 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
501 iplookupop_t op;
502 ipf_lookup_t **l;
503 int err, i;
504
505 err = BCOPYIN(data, &op, sizeof(op));
506 if (err != 0) {
507 IPFERROR(50028);
508 return EFAULT;
509 }
510
511 if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) &&
512 (op.iplo_unit != IPLT_ALL)) {
513 IPFERROR(50029);
514 return EINVAL;
515 }
516
517 op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
518
519 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
520 if (op.iplo_type == (*l)->ipfl_type) {
521 err = (*(*l)->ipfl_table_del)(softc,
522 softl->ipf_back[i],
523 &op);
524 break;
525 }
526 }
527
528 if (i == MAX_BACKENDS) {
529 IPFERROR(50030);
530 err = EINVAL;
531 }
532 return err;
533}
534
535
536/* ------------------------------------------------------------------------ */
537/* Function: ipf_lookup_stats */
538/* Returns: int - 0 = success, else error */
539/* Parameters: softc(I) - pointer to soft context main structure */
540/* data(I) - pointer to data from ioctl call */
541/* */
542/* Copy statistical information from inside the kernel back to user space. */
543/* ------------------------------------------------------------------------ */
544static int
545ipf_lookup_stats(ipf_main_softc_t *softc, void *data)
546{
547 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
548 iplookupop_t op;
549 ipf_lookup_t **l;
550 int err;
551 int i;
552
553 err = BCOPYIN(data, &op, sizeof(op));
554 if (err != 0) {
555 IPFERROR(50031);
556 return EFAULT;
557 }
558
559 if ((op.iplo_unit < 0 || op.iplo_unit > IPL_LOGMAX) &&
560 (op.iplo_unit != IPLT_ALL)) {
561 IPFERROR(50032);
562 return EINVAL;
563 }
564
565 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
566 if (op.iplo_type == (*l)->ipfl_type) {
567 err = (*(*l)->ipfl_stats_get)(softc,
568 softl->ipf_back[i],
569 &op);
570 break;
571 }
572 }
573
574 if (i == MAX_BACKENDS) {
575 IPFERROR(50033);
576 err = EINVAL;
577 }
578
579 return err;
580}
581
582
583/* ------------------------------------------------------------------------ */
584/* Function: ipf_lookup_flush */
585/* Returns: int - 0 = success, else error */
586/* Parameters: softc(I) - pointer to soft context main structure */
587/* data(I) - pointer to data from ioctl call */
588/* */
589/* A flush is called when we want to flush all the nodes from a particular */
590/* entry in the hash table/pool or want to remove all groups from those. */
591/* ------------------------------------------------------------------------ */
592static int
593ipf_lookup_flush(ipf_main_softc_t *softc, void *data)
594{
595 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
596 int err, unit, num, type, i;
597 iplookupflush_t flush;
598 ipf_lookup_t **l;
599
600 err = BCOPYIN(data, &flush, sizeof(flush));
601 if (err != 0) {
602 IPFERROR(50034);
603 return EFAULT;
604 }
605
606 unit = flush.iplf_unit;
607 if ((unit < 0 || unit > IPL_LOGMAX) && (unit != IPLT_ALL)) {
608 IPFERROR(50035);
609 return EINVAL;
610 }
611
612 flush.iplf_name[sizeof(flush.iplf_name) - 1] = '\0';
613
614 type = flush.iplf_type;
615 IPFERROR(50036);
616 err = EINVAL;
617 num = 0;
618
619 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
620 if (type == (*l)->ipfl_type || type == IPLT_ALL) {
621 err = 0;
622 num += (*(*l)->ipfl_flush)(softc,
623 softl->ipf_back[i],
624 &flush);
625 }
626 }
627
628 if (err == 0) {
629 flush.iplf_count = num;
630 err = BCOPYOUT(&flush, data, sizeof(flush));
631 if (err != 0) {
632 IPFERROR(50037);
633 err = EFAULT;
634 }
635 }
636 return err;
637}
638
639
640/* ------------------------------------------------------------------------ */
641/* Function: ipf_lookup_delref */
642/* Returns: void */
643/* Parameters: softc(I) - pointer to soft context main structure */
644/* type(I) - table type to operate on */
645/* ptr(I) - pointer to object to remove reference for */
646/* */
647/* This function organises calling the correct deref function for a given */
648/* type of object being passed into it. */
649/* ------------------------------------------------------------------------ */
650void
651ipf_lookup_deref(ipf_main_softc_t *softc, int type, void *ptr)
652{
653 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
654 int i;
655
656 if (ptr == NULL)
657 return;
658
659 for (i = 0; i < MAX_BACKENDS; i++) {
660 if (type == backends[i]->ipfl_type) {
661 WRITE_ENTER(&softc->ipf_poolrw);
662 (*backends[i]->ipfl_table_deref)(softc,
663 softl->ipf_back[i],
664 ptr);
665 RWLOCK_EXIT(&softc->ipf_poolrw);
666 break;
667 }
668 }
669}
670
671
672/* ------------------------------------------------------------------------ */
673/* Function: ipf_lookup_iterate */
674/* Returns: int - 0 = success, else error */
675/* Parameters: softc(I) - pointer to soft context main structure */
676/* data(I) - pointer to data from ioctl call */
677/* uid(I) - uid of caller */
678/* ctx(I) - pointer to give the uid context */
679/* */
680/* Decodes ioctl request to step through either hash tables or pools. */
681/* ------------------------------------------------------------------------ */
682static int
683ipf_lookup_iterate(ipf_main_softc_t *softc, void *data, int uid, void *ctx)
684{
685 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
686 ipflookupiter_t iter;
687 ipftoken_t *token;
688 int err, i;
689 SPL_INT(s);
690
691 err = ipf_inobj(softc, data, NULL, &iter, IPFOBJ_LOOKUPITER);
692 if (err != 0)
693 return err;
694
695 if (iter.ili_unit < IPL_LOGALL && iter.ili_unit > IPL_LOGMAX) {
696 IPFERROR(50038);
697 return EINVAL;
698 }
699
700 if (iter.ili_ival != IPFGENITER_LOOKUP) {
701 IPFERROR(50039);
702 return EINVAL;
703 }
704
705 SPL_SCHED(s);
706 token = ipf_token_find(softc, iter.ili_key, uid, ctx);
707 if (token == NULL) {
708 SPL_X(s);
709 IPFERROR(50040);
710 return ESRCH;
711 }
712
713 for (i = 0; i < MAX_BACKENDS; i++) {
714 if (iter.ili_type == backends[i]->ipfl_type) {
715 err = (*backends[i]->ipfl_iter_next)(softc,
716 softl->ipf_back[i],
717 token, &iter);
718 break;
719 }
720 }
721 SPL_X(s);
722
723 if (i == MAX_BACKENDS) {
724 IPFERROR(50041);
725 err = EINVAL;
726 }
727
728 WRITE_ENTER(&softc->ipf_tokens);
729 ipf_token_deref(softc, token);
730 RWLOCK_EXIT(&softc->ipf_tokens);
731
732 return err;
733}
734
735
736/* ------------------------------------------------------------------------ */
737/* Function: ipf_lookup_iterderef */
738/* Returns: void */
739/* Parameters: softc(I) - pointer to soft context main structure */
740/* type(I) - backend type to iterate through */
741/* data(I) - pointer to data from ioctl call */
742/* */
743/* Decodes ioctl request to remove a particular hash table or pool and */
744/* calls the relevant function to do the cleanup. */
745/* Because each of the backend types has a different data structure, */
746/* iteration is limited to one type at a time (i.e. it is not permitted to */
747/* go on from pool types to hash types as part of the "get next".) */
748/* ------------------------------------------------------------------------ */
749void
750ipf_lookup_iterderef(ipf_main_softc_t *softc, u_32_t type, void *data)
751{
752 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
753 struct iplookupiterkey *lkey;
754 iplookupiterkey_t key;
755 int i;
756
757 key.ilik_key = type;
758 lkey = &key.ilik_unstr;
759
760 if (lkey->ilik_ival != IPFGENITER_LOOKUP)
761 return;
762
763 WRITE_ENTER(&softc->ipf_poolrw);
764
765 for (i = 0; i < MAX_BACKENDS; i++) {
766 if (lkey->ilik_type == backends[i]->ipfl_type) {
767 (*backends[i]->ipfl_iter_deref)(softc,
768 softl->ipf_back[i],
769 lkey->ilik_otype,
770 lkey->ilik_unit,
771 data);
772 break;
773 }
774 }
775 RWLOCK_EXIT(&softc->ipf_poolrw);
776}
777
778
779/* ------------------------------------------------------------------------ */
780/* Function: ipf_lookup_deltok */
781/* Returns: int - 0 = success, else error */
782/* Parameters: softc(I) - pointer to soft context main structure */
783/* data(I) - pointer to data from ioctl call */
784/* uid(I) - uid of caller */
785/* ctx(I) - pointer to give the uid context */
786/* */
787/* Deletes the token identified by the combination of (type,uid,ctx) */
788/* "key" is a combination of the table type, iterator type and the unit for */
789/* which the token was being used. */
790/* ------------------------------------------------------------------------ */
791int
792ipf_lookup_deltok(ipf_main_softc_t *softc, void *data, int uid, void *ctx)
793{
794 int error, key;
795 SPL_INT(s);
796
797 SPL_SCHED(s);
798 error = BCOPYIN(data, &key, sizeof(key));
799 if (error == 0)
800 error = ipf_token_del(softc, key, uid, ctx);
801 SPL_X(s);
802 return error;
803}
804
805
806/* ------------------------------------------------------------------------ */
807/* Function: ipf_lookup_res_num */
808/* Returns: void * - NULL = failure, else success. */
809/* Parameters: softc(I) - pointer to soft context main structure */
810/* unit(I) - device for which this is for */
811/* type(I) - type of lookup these parameters are for. */
812/* number(I) - table number to use when searching */
813/* funcptr(IO) - pointer to pointer for storing IP address */
814/* searching function. */
815/* */
816/* Search for the "table" number passed in amongst those configured for */
817/* that particular type. If the type is recognised then the function to */
818/* call to do the IP address search will be change, regardless of whether */
819/* or not the "table" number exists. */
820/* ------------------------------------------------------------------------ */
821void *
822ipf_lookup_res_num(ipf_main_softc_t *softc, int unit, u_int type, u_int number,
823 lookupfunc_t *funcptr)
824{
825 char name[FR_GROUPLEN];
826
827 snprintf(name, sizeof(name), "%u", number);
828
829 return ipf_lookup_res_name(softc, unit, type, name, funcptr);
830}
831
832
833/* ------------------------------------------------------------------------ */
834/* Function: ipf_lookup_res_name */
835/* Returns: void * - NULL = failure, else success. */
836/* Parameters: softc(I) - pointer to soft context main structure */
837/* unit(I) - device for which this is for */
838/* type(I) - type of lookup these parameters are for. */
839/* name(I) - table name to use when searching */
840/* funcptr(IO) - pointer to pointer for storing IP address */
841/* searching function. */
842/* */
843/* Search for the "table" number passed in amongst those configured for */
844/* that particular type. If the type is recognised then the function to */
845/* call to do the IP address search will be changed, regardless of whether */
846/* or not the "table" number exists. */
847/* ------------------------------------------------------------------------ */
848void *
849ipf_lookup_res_name(ipf_main_softc_t *softc, int unit, u_int type, char *name,
850 lookupfunc_t *funcptr)
851{
852 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
853 ipf_lookup_t **l;
854 void *ptr = NULL;
855 int i;
856
857 READ_ENTER(&softc->ipf_poolrw);
858
859 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) {
860 if (type == (*l)->ipfl_type) {
861 ptr = (*(*l)->ipfl_select_add_ref)(softl->ipf_back[i],
862 unit, name);
863 if (ptr != NULL && funcptr != NULL) {
864 *funcptr = (*l)->ipfl_addr_find;
865 }
866 break;
867 }
868 }
869
870 if (i == MAX_BACKENDS) {
871 ptr = NULL;
872 if (funcptr != NULL)
873 *funcptr = NULL;
874 }
875
876 RWLOCK_EXIT(&softc->ipf_poolrw);
877
878 return ptr;
879}
880
881
882/* ------------------------------------------------------------------------ */
883/* Function: ipf_lookup_find_htable */
884/* Returns: void * - NULL = failure, else success. */
885/* Parameters: softc(I) - pointer to soft context main structure */
886/* unit(I) - device for which this is for */
887/* name(I) - table name to use when searching */
888/* */
889/* To support the group-map feature, where a hash table maps address */
890/* networks to rule group numbers, we need to expose a function that uses */
891/* only the hash table backend. */
892/* ------------------------------------------------------------------------ */
893void *
894ipf_lookup_find_htable(ipf_main_softc_t *softc, int unit, char *name)
895{
896 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
897 ipf_lookup_t **l;
898 void *tab = NULL;
899 int i;
900
901 READ_ENTER(&softc->ipf_poolrw);
902
903 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++)
904 if (IPLT_HASH == (*l)->ipfl_type) {
905 tab = ipf_htable_find(softl->ipf_back[i], unit, name);
906 break;
907 }
908
909 RWLOCK_EXIT(&softc->ipf_poolrw);
910
911 return tab;
912}
913
914
915/* ------------------------------------------------------------------------ */
916/* Function: ipf_lookup_sync */
917/* Returns: void */
918/* Parameters: softc(I) - pointer to soft context main structure */
919/* */
920/* This function is the interface that the machine dependent sync functions */
921/* call when a network interface name change occurs. It then calls the sync */
922/* functions of the lookup implementations - if they have one. */
923/* ------------------------------------------------------------------------ */
924/*ARGSUSED*/
925void
926ipf_lookup_sync(ipf_main_softc_t *softc, void *ifp)
927{
928 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
929 ipf_lookup_t **l;
930 int i;
931
932 READ_ENTER(&softc->ipf_poolrw);
933
934 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++)
935 if ((*l)->ipfl_sync != NULL)
936 (*(*l)->ipfl_sync)(softc, softl->ipf_back[i]);
937
938 RWLOCK_EXIT(&softc->ipf_poolrw);
939}
940
941
942#ifndef _KERNEL
943void
944ipf_lookup_dump(softc, arg)
945 ipf_main_softc_t *softc;
946 void *arg;
947{
948 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft;
949 ipf_lookup_t **l;
950 int i;
951
952 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++)
953 if (IPLT_POOL == (*l)->ipfl_type) {
954 ipf_pool_dump(softc, softl->ipf_back[i]);
955 break;
956 }
957
958 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++)
959 if (IPLT_HASH == (*l)->ipfl_type) {
960 ipf_htable_dump(softc, softl->ipf_back[i]);
961 break;
962 }
963}
964#endif
965