ip_lookup.c revision 1.1
1/* $NetBSD: ip_lookup.c,v 1.1 2012/03/23 21:19:56 christos Exp $ */ 2 3/* 4 * Copyright (C) 2010 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__ 34struct 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) 64static const char rcsid[] = "@(#)Id"; 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 */ 76static int ipf_lookup_addnode __P((ipf_main_softc_t *, caddr_t, int)); 77static int ipf_lookup_delnode __P((ipf_main_softc_t *, caddr_t, int)); 78static int ipf_lookup_addtable __P((ipf_main_softc_t *, caddr_t)); 79static int ipf_lookup_deltable __P((ipf_main_softc_t *, caddr_t)); 80static int ipf_lookup_stats __P((ipf_main_softc_t *, caddr_t)); 81static int ipf_lookup_flush __P((ipf_main_softc_t *, caddr_t)); 82static int ipf_lookup_iterate __P((ipf_main_softc_t *, void *, int, void *)); 83static int ipf_lookup_deltok __P((ipf_main_softc_t *, void *, int, void *)); 84 85#define MAX_BACKENDS 3 86static ipf_lookup_t *backends[MAX_BACKENDS] = { 87 &ipf_pool_backend, 88 &ipf_htable_backend, 89 &ipf_dstlist_backend 90}; 91 92 93typedef 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/* ------------------------------------------------------------------------ */ 105void * 106ipf_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/* ------------------------------------------------------------------------ */ 139int 140ipf_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/* ------------------------------------------------------------------------ */ 166int 167ipf_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/* ------------------------------------------------------------------------ */ 192void 193ipf_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/* ------------------------------------------------------------------------ */ 216void 217ipf_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/* ------------------------------------------------------------------------ */ 250int 251ipf_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/* ------------------------------------------------------------------------ */ 334static int 335ipf_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/* ------------------------------------------------------------------------ */ 387static int 388ipf_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/* ------------------------------------------------------------------------ */ 438static int 439ipf_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/* ------------------------------------------------------------------------ */ 501static int 502ipf_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/* ------------------------------------------------------------------------ */ 550static int 551ipf_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/* ------------------------------------------------------------------------ */ 600static int 601ipf_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/* ------------------------------------------------------------------------ */ 660void 661ipf_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/* ------------------------------------------------------------------------ */ 695static int 696ipf_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/* ------------------------------------------------------------------------ */ 766void 767ipf_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 (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/* ------------------------------------------------------------------------ */ 811int 812ipf_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/* ------------------------------------------------------------------------ */ 845void * 846ipf_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 change, regardless of whether */ 878/* or not the "table" number exists. */ 879/* ------------------------------------------------------------------------ */ 880void * 881ipf_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/* ------------------------------------------------------------------------ */ 929void * 930ipf_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*/ 964void 965ipf_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 984void 985ipf_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