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__ 45struct 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 79static 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 */ 92static int ipf_lookup_addnode(ipf_main_softc_t *, void *, int); 93static int ipf_lookup_delnode(ipf_main_softc_t *, void *, int); 94static int ipf_lookup_addtable(ipf_main_softc_t *, void *); 95static int ipf_lookup_deltable(ipf_main_softc_t *, void *); 96static int ipf_lookup_stats(ipf_main_softc_t *, void *); 97static int ipf_lookup_flush(ipf_main_softc_t *, void *); 98static int ipf_lookup_iterate(ipf_main_softc_t *, void *, int, void *); 99static int ipf_lookup_deltok(ipf_main_softc_t *, void *, int, void *); 100 101#define MAX_BACKENDS 3 102static ipf_lookup_t *backends[MAX_BACKENDS] = { 103 &ipf_pool_backend, 104 &ipf_htable_backend, 105 &ipf_dstlist_backend 106}; 107 108 109typedef 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/* ------------------------------------------------------------------------ */ 121void * 122ipf_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/* ------------------------------------------------------------------------ */ 154int 155ipf_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/* ------------------------------------------------------------------------ */ 179int 180ipf_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/* ------------------------------------------------------------------------ */ 203void 204ipf_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/* ------------------------------------------------------------------------ */ 226void 227ipf_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/* ------------------------------------------------------------------------ */ 258int 259ipf_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/* ------------------------------------------------------------------------ */ 338static int 339ipf_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/* ------------------------------------------------------------------------ */ 388static int 389ipf_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/* ------------------------------------------------------------------------ */ 436static int 437ipf_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/* ------------------------------------------------------------------------ */ 497static int 498ipf_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/* ------------------------------------------------------------------------ */ 544static int 545ipf_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/* ------------------------------------------------------------------------ */ 592static int 593ipf_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/* ------------------------------------------------------------------------ */ 650void 651ipf_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/* ------------------------------------------------------------------------ */ 682static int 683ipf_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/* ------------------------------------------------------------------------ */ 749void 750ipf_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/* ------------------------------------------------------------------------ */ 791int 792ipf_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/* ------------------------------------------------------------------------ */ 821void * 822ipf_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/* ------------------------------------------------------------------------ */ 848void * 849ipf_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/* ------------------------------------------------------------------------ */ 893void * 894ipf_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*/ 925void 926ipf_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 943void 944ipf_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