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