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