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