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