1 /* $NetBSD: ip_lookup.c,v 1.4 2014/03/20 20:43:12 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2012 by Darren Reed. 5 * 6 * See the IPFILTER.LICENCE file for details on licencing. 7 */ 8 #if defined(KERNEL) || defined(_KERNEL) 9 # undef KERNEL 10 # undef _KERNEL 11 # define KERNEL 1 12 # define _KERNEL 1 13 #endif 14 #if defined(__osf__) 15 # define _PROTO_NET_H_ 16 #endif 17 #include <sys/param.h> 18 #if defined(__NetBSD__) 19 # if (NetBSD >= 199905) && !defined(IPFILTER_LKM) && defined(_KERNEL) 20 # 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.4 2014/03/20 20:43:12 christos Exp $"); 72 #else 73 static const char rcsid[] = "@(#)Id: ip_lookup.c,v 1.1.1.2 2012/07/22 13:45:21 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 (lkey->ilik_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 snprintf(name, sizeof(name), "%u", number); 822 823 return ipf_lookup_res_name(softc, unit, type, name, funcptr); 824 } 825 826 827 /* ------------------------------------------------------------------------ */ 828 /* Function: ipf_lookup_res_name */ 829 /* Returns: void * - NULL = failure, else success. */ 830 /* Parameters: softc(I) - pointer to soft context main structure */ 831 /* unit(I) - device for which this is for */ 832 /* type(I) - type of lookup these parameters are for. */ 833 /* name(I) - table name to use when searching */ 834 /* funcptr(IO) - pointer to pointer for storing IP address */ 835 /* searching function. */ 836 /* */ 837 /* Search for the "table" number passed in amongst those configured for */ 838 /* that particular type. If the type is recognised then the function to */ 839 /* call to do the IP address search will be changed, regardless of whether */ 840 /* or not the "table" number exists. */ 841 /* ------------------------------------------------------------------------ */ 842 void * 843 ipf_lookup_res_name(ipf_main_softc_t *softc, int unit, u_int type, char *name, 844 lookupfunc_t *funcptr) 845 { 846 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; 847 ipf_lookup_t **l; 848 void *ptr = NULL; 849 int i; 850 851 READ_ENTER(&softc->ipf_poolrw); 852 853 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) { 854 if (type == (*l)->ipfl_type) { 855 ptr = (*(*l)->ipfl_select_add_ref)(softl->ipf_back[i], 856 unit, name); 857 if (ptr != NULL && funcptr != NULL) { 858 *funcptr = (*l)->ipfl_addr_find; 859 } 860 break; 861 } 862 } 863 864 if (i == MAX_BACKENDS) { 865 ptr = NULL; 866 if (funcptr != NULL) 867 *funcptr = NULL; 868 } 869 870 RWLOCK_EXIT(&softc->ipf_poolrw); 871 872 return ptr; 873 } 874 875 876 /* ------------------------------------------------------------------------ */ 877 /* Function: ipf_lookup_find_htable */ 878 /* Returns: void * - NULL = failure, else success. */ 879 /* Parameters: softc(I) - pointer to soft context main structure */ 880 /* unit(I) - device for which this is for */ 881 /* name(I) - table name to use when searching */ 882 /* */ 883 /* To support the group-map feature, where a hash table maps address */ 884 /* networks to rule group numbers, we need to expose a function that uses */ 885 /* only the hash table backend. */ 886 /* ------------------------------------------------------------------------ */ 887 void * 888 ipf_lookup_find_htable(ipf_main_softc_t *softc, int unit, char *name) 889 { 890 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; 891 ipf_lookup_t **l; 892 void *tab = NULL; 893 int i; 894 895 READ_ENTER(&softc->ipf_poolrw); 896 897 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) 898 if (IPLT_HASH == (*l)->ipfl_type) { 899 tab = ipf_htable_find(softl->ipf_back[i], unit, name); 900 break; 901 } 902 903 RWLOCK_EXIT(&softc->ipf_poolrw); 904 905 return tab; 906 } 907 908 909 /* ------------------------------------------------------------------------ */ 910 /* Function: ipf_lookup_sync */ 911 /* Returns: void */ 912 /* Parameters: softc(I) - pointer to soft context main structure */ 913 /* */ 914 /* This function is the interface that the machine dependent sync functions */ 915 /* call when a network interface name change occurs. It then calls the sync */ 916 /* functions of the lookup implementations - if they have one. */ 917 /* ------------------------------------------------------------------------ */ 918 /*ARGSUSED*/ 919 void 920 ipf_lookup_sync(ipf_main_softc_t *softc, void *ifp) 921 { 922 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; 923 ipf_lookup_t **l; 924 int i; 925 926 READ_ENTER(&softc->ipf_poolrw); 927 928 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) 929 if ((*l)->ipfl_sync != NULL) 930 (*(*l)->ipfl_sync)(softc, softl->ipf_back[i]); 931 932 RWLOCK_EXIT(&softc->ipf_poolrw); 933 } 934 935 936 #ifndef _KERNEL 937 void 938 ipf_lookup_dump(softc, arg) 939 ipf_main_softc_t *softc; 940 void *arg; 941 { 942 ipf_lookup_softc_t *softl = softc->ipf_lookup_soft; 943 ipf_lookup_t **l; 944 int i; 945 946 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) 947 if (IPLT_POOL == (*l)->ipfl_type) { 948 ipf_pool_dump(softc, softl->ipf_back[i]); 949 break; 950 } 951 952 for (i = 0, l = backends; i < MAX_BACKENDS; i++, l++) 953 if (IPLT_HASH == (*l)->ipfl_type) { 954 ipf_htable_dump(softc, softl->ipf_back[i]); 955 break; 956 } 957 } 958 #endif 959