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