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