libiptc.c revision a9c79c7ba494b39bad959a0c833e58a343686272
1/* Library which manipulates firewall rules. Version $Revision$ */ 2 3/* Architecture of firewall rules is as follows: 4 * 5 * Chains go INPUT, FORWARD, OUTPUT then user chains. 6 * Each user chain starts with an ERROR node. 7 * Every chain ends with an unconditional jump: a RETURN for user chains, 8 * and a POLICY for built-ins. 9 */ 10 11/* (C) 1999 Paul ``Rusty'' Russell - Placed under the GNU GPL (See 12 * COPYING for details). 13 * (C) 2000-2004 by the Netfilter Core Team <coreteam@netfilter.org> 14 * 15 * 2003-Jun-20: Harald Welte <laforge@netfilter.org>: 16 * - Reimplementation of chain cache to use offsets instead of entries 17 * 2003-Jun-23: Harald Welte <laforge@netfilter.org>: 18 * - performance optimization, sponsored by Astaro AG (http://www.astaro.com/) 19 * don't rebuild the chain cache after every operation, instead fix it 20 * up after a ruleset change. 21 * 2004-Aug-18: Harald Welte <laforge@netfilter.org>: 22 * - further performance work: total reimplementation of libiptc. 23 * - libiptc now has a real internal (linked-list) represntation of the 24 * ruleset and a parser/compiler from/to this internal representation 25 * - again sponsored by Astaro AG (http://www.astaro.com/) 26 * 27 * 2008-Jan+Jul: Jesper Dangaard Brouer <hawk@comx.dk> 28 * - performance work: speedup chain list "name" searching. 29 * - performance work: speedup initial ruleset parsing. 30 * - sponsored by ComX Networks A/S (http://www.comx.dk/) 31 */ 32#include <sys/types.h> 33#include <sys/socket.h> 34#include <xtables.h> 35 36#include "linux_list.h" 37 38//#define IPTC_DEBUG2 1 39 40#ifdef IPTC_DEBUG2 41#include <fcntl.h> 42#define DEBUGP(x, args...) fprintf(stderr, "%s: " x, __FUNCTION__, ## args) 43#define DEBUGP_C(x, args...) fprintf(stderr, x, ## args) 44#else 45#define DEBUGP(x, args...) 46#define DEBUGP_C(x, args...) 47#endif 48 49#ifdef DEBUG 50#define debug(x, args...) fprintf(stderr, x, ## args) 51#else 52#define debug(x, args...) 53#endif 54 55static void *iptc_fn = NULL; 56 57static const char *hooknames[] = { 58 [HOOK_PRE_ROUTING] = "PREROUTING", 59 [HOOK_LOCAL_IN] = "INPUT", 60 [HOOK_FORWARD] = "FORWARD", 61 [HOOK_LOCAL_OUT] = "OUTPUT", 62 [HOOK_POST_ROUTING] = "POSTROUTING", 63#ifdef HOOK_DROPPING 64 [HOOK_DROPPING] = "DROPPING" 65#endif 66}; 67 68/* Convenience structures */ 69struct ipt_error_target 70{ 71 STRUCT_ENTRY_TARGET t; 72 char error[TABLE_MAXNAMELEN]; 73}; 74 75struct chain_head; 76struct rule_head; 77 78struct counter_map 79{ 80 enum { 81 COUNTER_MAP_NOMAP, 82 COUNTER_MAP_NORMAL_MAP, 83 COUNTER_MAP_ZEROED, 84 COUNTER_MAP_SET 85 } maptype; 86 unsigned int mappos; 87}; 88 89enum iptcc_rule_type { 90 IPTCC_R_STANDARD, /* standard target (ACCEPT, ...) */ 91 IPTCC_R_MODULE, /* extension module (SNAT, ...) */ 92 IPTCC_R_FALLTHROUGH, /* fallthrough rule */ 93 IPTCC_R_JUMP, /* jump to other chain */ 94}; 95 96struct rule_head 97{ 98 struct list_head list; 99 struct chain_head *chain; 100 struct counter_map counter_map; 101 102 unsigned int index; /* index (needed for counter_map) */ 103 unsigned int offset; /* offset in rule blob */ 104 105 enum iptcc_rule_type type; 106 struct chain_head *jump; /* jump target, if IPTCC_R_JUMP */ 107 108 unsigned int size; /* size of entry data */ 109 STRUCT_ENTRY entry[0]; 110}; 111 112struct chain_head 113{ 114 struct list_head list; 115 char name[TABLE_MAXNAMELEN]; 116 unsigned int hooknum; /* hook number+1 if builtin */ 117 unsigned int references; /* how many jumps reference us */ 118 int verdict; /* verdict if builtin */ 119 120 STRUCT_COUNTERS counters; /* per-chain counters */ 121 struct counter_map counter_map; 122 123 unsigned int num_rules; /* number of rules in list */ 124 struct list_head rules; /* list of rules */ 125 126 unsigned int index; /* index (needed for jump resolval) */ 127 unsigned int head_offset; /* offset in rule blob */ 128 unsigned int foot_index; /* index (needed for counter_map) */ 129 unsigned int foot_offset; /* offset in rule blob */ 130}; 131 132STRUCT_TC_HANDLE 133{ 134 int sockfd; 135 int changed; /* Have changes been made? */ 136 137 struct list_head chains; 138 139 struct chain_head *chain_iterator_cur; 140 struct rule_head *rule_iterator_cur; 141 142 unsigned int num_chains; /* number of user defined chains */ 143 144 struct chain_head **chain_index; /* array for fast chain list access*/ 145 unsigned int chain_index_sz;/* size of chain index array */ 146 147 int sorted_offsets; /* if chains are received sorted from kernel, 148 * then the offsets are also sorted. Says if its 149 * possible to bsearch offsets using chain_index. 150 */ 151 152 STRUCT_GETINFO info; 153 STRUCT_GET_ENTRIES *entries; 154}; 155 156enum bsearch_type { 157 BSEARCH_NAME, /* Binary search after chain name */ 158 BSEARCH_OFFSET, /* Binary search based on offset */ 159}; 160 161/* allocate a new chain head for the cache */ 162static struct chain_head *iptcc_alloc_chain_head(const char *name, int hooknum) 163{ 164 struct chain_head *c = malloc(sizeof(*c)); 165 if (!c) 166 return NULL; 167 memset(c, 0, sizeof(*c)); 168 169 strncpy(c->name, name, TABLE_MAXNAMELEN); 170 c->hooknum = hooknum; 171 INIT_LIST_HEAD(&c->rules); 172 173 return c; 174} 175 176/* allocate and initialize a new rule for the cache */ 177static struct rule_head *iptcc_alloc_rule(struct chain_head *c, unsigned int size) 178{ 179 struct rule_head *r = malloc(sizeof(*r)+size); 180 if (!r) 181 return NULL; 182 memset(r, 0, sizeof(*r)); 183 184 r->chain = c; 185 r->size = size; 186 187 return r; 188} 189 190/* notify us that the ruleset has been modified by the user */ 191static inline void 192set_changed(struct xtc_handle *h) 193{ 194 h->changed = 1; 195} 196 197#ifdef IPTC_DEBUG 198static void do_check(struct xtc_handle *h, unsigned int line); 199#define CHECK(h) do { if (!getenv("IPTC_NO_CHECK")) do_check((h), __LINE__); } while(0) 200#else 201#define CHECK(h) 202#endif 203 204 205/********************************************************************** 206 * iptc blob utility functions (iptcb_*) 207 **********************************************************************/ 208 209static inline int 210iptcb_get_number(const STRUCT_ENTRY *i, 211 const STRUCT_ENTRY *seek, 212 unsigned int *pos) 213{ 214 if (i == seek) 215 return 1; 216 (*pos)++; 217 return 0; 218} 219 220static inline int 221iptcb_get_entry_n(STRUCT_ENTRY *i, 222 unsigned int number, 223 unsigned int *pos, 224 STRUCT_ENTRY **pe) 225{ 226 if (*pos == number) { 227 *pe = i; 228 return 1; 229 } 230 (*pos)++; 231 return 0; 232} 233 234static inline STRUCT_ENTRY * 235iptcb_get_entry(struct xtc_handle *h, unsigned int offset) 236{ 237 return (STRUCT_ENTRY *)((char *)h->entries->entrytable + offset); 238} 239 240static unsigned int 241iptcb_entry2index(struct xtc_handle *const h, const STRUCT_ENTRY *seek) 242{ 243 unsigned int pos = 0; 244 245 if (ENTRY_ITERATE(h->entries->entrytable, h->entries->size, 246 iptcb_get_number, seek, &pos) == 0) { 247 fprintf(stderr, "ERROR: offset %u not an entry!\n", 248 (unsigned int)((char *)seek - (char *)h->entries->entrytable)); 249 abort(); 250 } 251 return pos; 252} 253 254static inline STRUCT_ENTRY * 255iptcb_offset2entry(struct xtc_handle *h, unsigned int offset) 256{ 257 return (STRUCT_ENTRY *) ((void *)h->entries->entrytable+offset); 258} 259 260 261static inline unsigned long 262iptcb_entry2offset(struct xtc_handle *const h, const STRUCT_ENTRY *e) 263{ 264 return (void *)e - (void *)h->entries->entrytable; 265} 266 267static inline unsigned int 268iptcb_offset2index(struct xtc_handle *const h, unsigned int offset) 269{ 270 return iptcb_entry2index(h, iptcb_offset2entry(h, offset)); 271} 272 273/* Returns 0 if not hook entry, else hooknumber + 1 */ 274static inline unsigned int 275iptcb_ent_is_hook_entry(STRUCT_ENTRY *e, struct xtc_handle *h) 276{ 277 unsigned int i; 278 279 for (i = 0; i < NUMHOOKS; i++) { 280 if ((h->info.valid_hooks & (1 << i)) 281 && iptcb_get_entry(h, h->info.hook_entry[i]) == e) 282 return i+1; 283 } 284 return 0; 285} 286 287 288/********************************************************************** 289 * Chain index (cache utility) functions 290 ********************************************************************** 291 * The chain index is an array with pointers into the chain list, with 292 * CHAIN_INDEX_BUCKET_LEN spacing. This facilitates the ability to 293 * speedup chain list searching, by find a more optimal starting 294 * points when searching the linked list. 295 * 296 * The starting point can be found fast by using a binary search of 297 * the chain index. Thus, reducing the previous search complexity of 298 * O(n) to O(log(n/k) + k) where k is CHAIN_INDEX_BUCKET_LEN. 299 * 300 * A nice property of the chain index, is that the "bucket" list 301 * length is max CHAIN_INDEX_BUCKET_LEN (when just build, inserts will 302 * change this). Oppose to hashing, where the "bucket" list length can 303 * vary a lot. 304 */ 305#ifndef CHAIN_INDEX_BUCKET_LEN 306#define CHAIN_INDEX_BUCKET_LEN 40 307#endif 308 309/* Another nice property of the chain index is that inserting/creating 310 * chains in chain list don't change the correctness of the chain 311 * index, it only causes longer lists in the buckets. 312 * 313 * To mitigate the performance penalty of longer bucket lists and the 314 * penalty of rebuilding, the chain index is rebuild only when 315 * CHAIN_INDEX_INSERT_MAX chains has been added. 316 */ 317#ifndef CHAIN_INDEX_INSERT_MAX 318#define CHAIN_INDEX_INSERT_MAX 355 319#endif 320 321static inline unsigned int iptcc_is_builtin(struct chain_head *c); 322 323/* Use binary search in the chain index array, to find a chain_head 324 * pointer closest to the place of the searched name element. 325 * 326 * Notes that, binary search (obviously) requires that the chain list 327 * is sorted by name. 328 * 329 * The not so obvious: The chain index array, is actually both sorted 330 * by name and offset, at the same time!. This is only true because, 331 * chain are stored sorted in the kernel (as we pushed it in sorted). 332 * 333 */ 334static struct list_head * 335__iptcc_bsearch_chain_index(const char *name, unsigned int offset, 336 unsigned int *idx, struct xtc_handle *handle, 337 enum bsearch_type type) 338{ 339 unsigned int pos, end; 340 int res; 341 342 struct list_head *list_pos; 343 list_pos=&handle->chains; 344 345 /* Check for empty array, e.g. no user defined chains */ 346 if (handle->chain_index_sz == 0) { 347 debug("WARNING: handle->chain_index_sz == 0\n"); 348 return list_pos; 349 } 350 351 /* Init */ 352 end = handle->chain_index_sz; 353 pos = end / 2; 354 355 debug("bsearch Find chain:%s (pos:%d end:%d) (offset:%d)\n", 356 name, pos, end, offset); 357 358 /* Loop */ 359 loop: 360 if (!handle->chain_index[pos]) { 361 fprintf(stderr, "ERROR: NULL pointer chain_index[%d]\n", pos); 362 return &handle->chains; /* Be safe, return orig start pos */ 363 } 364 365 debug("bsearch Index[%d] name:%s ", 366 pos, handle->chain_index[pos]->name); 367 368 /* Support for different compare functions */ 369 switch (type) { 370 case BSEARCH_NAME: 371 res = strcmp(name, handle->chain_index[pos]->name); 372 break; 373 case BSEARCH_OFFSET: 374 debug("head_offset:[%d] foot_offset:[%d] ", 375 handle->chain_index[pos]->head_offset, 376 handle->chain_index[pos]->foot_offset); 377 res = offset - handle->chain_index[pos]->head_offset; 378 break; 379 default: 380 fprintf(stderr, "ERROR: %d not a valid bsearch type\n", 381 type); 382 abort(); 383 break; 384 } 385 debug("res:%d ", res); 386 387 388 list_pos = &handle->chain_index[pos]->list; 389 *idx = pos; 390 391 if (res == 0) { /* Found element, by direct hit */ 392 debug("[found] Direct hit pos:%d end:%d\n", pos, end); 393 return list_pos; 394 } else if (res < 0) { /* Too far, jump back */ 395 end = pos; 396 pos = pos / 2; 397 398 /* Exit case: First element of array */ 399 if (end == 0) { 400 debug("[found] Reached first array elem (end%d)\n",end); 401 return list_pos; 402 } 403 debug("jump back to pos:%d (end:%d)\n", pos, end); 404 goto loop; 405 } else if (res > 0 ){ /* Not far enough, jump forward */ 406 407 /* Exit case: Last element of array */ 408 if (pos == handle->chain_index_sz-1) { 409 debug("[found] Last array elem (end:%d)\n", end); 410 return list_pos; 411 } 412 413 /* Exit case: Next index less, thus elem in this list section */ 414 switch (type) { 415 case BSEARCH_NAME: 416 res = strcmp(name, handle->chain_index[pos+1]->name); 417 break; 418 case BSEARCH_OFFSET: 419 res = offset - handle->chain_index[pos+1]->head_offset; 420 break; 421 } 422 423 if (res < 0) { 424 debug("[found] closest list (end:%d)\n", end); 425 return list_pos; 426 } 427 428 pos = (pos+end)/2; 429 debug("jump forward to pos:%d (end:%d)\n", pos, end); 430 goto loop; 431 } 432 433 return list_pos; 434} 435 436/* Wrapper for string chain name based bsearch */ 437static struct list_head * 438iptcc_bsearch_chain_index(const char *name, unsigned int *idx, 439 struct xtc_handle *handle) 440{ 441 return __iptcc_bsearch_chain_index(name, 0, idx, handle, BSEARCH_NAME); 442} 443 444 445/* Wrapper for offset chain based bsearch */ 446static struct list_head * 447iptcc_bsearch_chain_offset(unsigned int offset, unsigned int *idx, 448 struct xtc_handle *handle) 449{ 450 struct list_head *pos; 451 452 /* If chains were not received sorted from kernel, then the 453 * offset bsearch is not possible. 454 */ 455 if (!handle->sorted_offsets) 456 pos = handle->chains.next; 457 else 458 pos = __iptcc_bsearch_chain_index(NULL, offset, idx, handle, 459 BSEARCH_OFFSET); 460 return pos; 461} 462 463 464#ifdef DEBUG 465/* Trivial linear search of chain index. Function used for verifying 466 the output of bsearch function */ 467static struct list_head * 468iptcc_linearly_search_chain_index(const char *name, struct xtc_handle *handle) 469{ 470 unsigned int i=0; 471 int res=0; 472 473 struct list_head *list_pos; 474 list_pos = &handle->chains; 475 476 if (handle->chain_index_sz) 477 list_pos = &handle->chain_index[0]->list; 478 479 /* Linearly walk of chain index array */ 480 481 for (i=0; i < handle->chain_index_sz; i++) { 482 if (handle->chain_index[i]) { 483 res = strcmp(handle->chain_index[i]->name, name); 484 if (res > 0) 485 break; // One step too far 486 list_pos = &handle->chain_index[i]->list; 487 if (res == 0) 488 break; // Direct hit 489 } 490 } 491 492 return list_pos; 493} 494#endif 495 496static int iptcc_chain_index_alloc(struct xtc_handle *h) 497{ 498 unsigned int list_length = CHAIN_INDEX_BUCKET_LEN; 499 unsigned int array_elems; 500 unsigned int array_mem; 501 502 /* Allocate memory for the chain index array */ 503 array_elems = (h->num_chains / list_length) + 504 (h->num_chains % list_length ? 1 : 0); 505 array_mem = sizeof(h->chain_index) * array_elems; 506 507 debug("Alloc Chain index, elems:%d mem:%d bytes\n", 508 array_elems, array_mem); 509 510 h->chain_index = malloc(array_mem); 511 if (h->chain_index == NULL && array_mem > 0) { 512 h->chain_index_sz = 0; 513 return -ENOMEM; 514 } 515 memset(h->chain_index, 0, array_mem); 516 h->chain_index_sz = array_elems; 517 518 return 1; 519} 520 521static void iptcc_chain_index_free(struct xtc_handle *h) 522{ 523 h->chain_index_sz = 0; 524 free(h->chain_index); 525} 526 527 528#ifdef DEBUG 529static void iptcc_chain_index_dump(struct xtc_handle *h) 530{ 531 unsigned int i = 0; 532 533 /* Dump: contents of chain index array */ 534 for (i=0; i < h->chain_index_sz; i++) { 535 if (h->chain_index[i]) { 536 fprintf(stderr, "Chain index[%d].name: %s\n", 537 i, h->chain_index[i]->name); 538 } 539 } 540} 541#endif 542 543/* Build the chain index */ 544static int iptcc_chain_index_build(struct xtc_handle *h) 545{ 546 unsigned int list_length = CHAIN_INDEX_BUCKET_LEN; 547 unsigned int chains = 0; 548 unsigned int cindex = 0; 549 struct chain_head *c; 550 551 /* Build up the chain index array here */ 552 debug("Building chain index\n"); 553 554 debug("Number of user defined chains:%d bucket_sz:%d array_sz:%d\n", 555 h->num_chains, list_length, h->chain_index_sz); 556 557 if (h->chain_index_sz == 0) 558 return 0; 559 560 list_for_each_entry(c, &h->chains, list) { 561 562 /* Issue: The index array needs to start after the 563 * builtin chains, as they are not sorted */ 564 if (!iptcc_is_builtin(c)) { 565 cindex=chains / list_length; 566 567 /* Safe guard, break out on array limit, this 568 * is useful if chains are added and array is 569 * rebuild, without realloc of memory. */ 570 if (cindex >= h->chain_index_sz) 571 break; 572 573 if ((chains % list_length)== 0) { 574 debug("\nIndex[%d] Chains:", cindex); 575 h->chain_index[cindex] = c; 576 } 577 chains++; 578 } 579 debug("%s, ", c->name); 580 } 581 debug("\n"); 582 583 return 1; 584} 585 586static int iptcc_chain_index_rebuild(struct xtc_handle *h) 587{ 588 debug("REBUILD chain index array\n"); 589 iptcc_chain_index_free(h); 590 if ((iptcc_chain_index_alloc(h)) < 0) 591 return -ENOMEM; 592 iptcc_chain_index_build(h); 593 return 1; 594} 595 596/* Delete chain (pointer) from index array. Removing an element from 597 * the chain list only affects the chain index array, if the chain 598 * index points-to/uses that list pointer. 599 * 600 * There are different strategies, the simple and safe is to rebuild 601 * the chain index every time. The more advanced is to update the 602 * array index to point to the next element, but that requires some 603 * house keeping and boundry checks. The advanced is implemented, as 604 * the simple approach behaves badly when all chains are deleted 605 * because list_for_each processing will always hit the first chain 606 * index, thus causing a rebuild for every chain. 607 */ 608static int iptcc_chain_index_delete_chain(struct chain_head *c, struct xtc_handle *h) 609{ 610 struct list_head *index_ptr, *index_ptr2, *next; 611 struct chain_head *c2; 612 unsigned int idx, idx2; 613 614 index_ptr = iptcc_bsearch_chain_index(c->name, &idx, h); 615 616 debug("Del chain[%s] c->list:%p index_ptr:%p\n", 617 c->name, &c->list, index_ptr); 618 619 /* Save the next pointer */ 620 next = c->list.next; 621 list_del(&c->list); 622 623 if (index_ptr == &c->list) { /* Chain used as index ptr */ 624 625 /* See if its possible to avoid a rebuild, by shifting 626 * to next pointer. Its possible if the next pointer 627 * is located in the same index bucket. 628 */ 629 c2 = list_entry(next, struct chain_head, list); 630 index_ptr2 = iptcc_bsearch_chain_index(c2->name, &idx2, h); 631 if (idx != idx2) { 632 /* Rebuild needed */ 633 return iptcc_chain_index_rebuild(h); 634 } else { 635 /* Avoiding rebuild */ 636 debug("Update cindex[%d] with next ptr name:[%s]\n", 637 idx, c2->name); 638 h->chain_index[idx]=c2; 639 return 0; 640 } 641 } 642 return 0; 643} 644 645 646/********************************************************************** 647 * iptc cache utility functions (iptcc_*) 648 **********************************************************************/ 649 650/* Is the given chain builtin (1) or user-defined (0) */ 651static inline unsigned int iptcc_is_builtin(struct chain_head *c) 652{ 653 return (c->hooknum ? 1 : 0); 654} 655 656/* Get a specific rule within a chain */ 657static struct rule_head *iptcc_get_rule_num(struct chain_head *c, 658 unsigned int rulenum) 659{ 660 struct rule_head *r; 661 unsigned int num = 0; 662 663 list_for_each_entry(r, &c->rules, list) { 664 num++; 665 if (num == rulenum) 666 return r; 667 } 668 return NULL; 669} 670 671/* Get a specific rule within a chain backwards */ 672static struct rule_head *iptcc_get_rule_num_reverse(struct chain_head *c, 673 unsigned int rulenum) 674{ 675 struct rule_head *r; 676 unsigned int num = 0; 677 678 list_for_each_entry_reverse(r, &c->rules, list) { 679 num++; 680 if (num == rulenum) 681 return r; 682 } 683 return NULL; 684} 685 686/* Returns chain head if found, otherwise NULL. */ 687static struct chain_head * 688iptcc_find_chain_by_offset(struct xtc_handle *handle, unsigned int offset) 689{ 690 struct list_head *pos; 691 struct list_head *list_start_pos; 692 unsigned int i; 693 694 if (list_empty(&handle->chains)) 695 return NULL; 696 697 /* Find a smart place to start the search */ 698 list_start_pos = iptcc_bsearch_chain_offset(offset, &i, handle); 699 700 /* Note that iptcc_bsearch_chain_offset() skips builtin 701 * chains, but this function is only used for finding jump 702 * targets, and a buildin chain is not a valid jump target */ 703 704 debug("Offset:[%u] starting search at index:[%u]\n", offset, i); 705// list_for_each(pos, &handle->chains) { 706 list_for_each(pos, list_start_pos->prev) { 707 struct chain_head *c = list_entry(pos, struct chain_head, list); 708 debug("."); 709 if (offset >= c->head_offset && offset <= c->foot_offset) { 710 debug("Offset search found chain:[%s]\n", c->name); 711 return c; 712 } 713 } 714 715 return NULL; 716} 717 718/* Returns chain head if found, otherwise NULL. */ 719static struct chain_head * 720iptcc_find_label(const char *name, struct xtc_handle *handle) 721{ 722 struct list_head *pos; 723 struct list_head *list_start_pos; 724 unsigned int i=0; 725 int res; 726 727 if (list_empty(&handle->chains)) 728 return NULL; 729 730 /* First look at builtin chains */ 731 list_for_each(pos, &handle->chains) { 732 struct chain_head *c = list_entry(pos, struct chain_head, list); 733 if (!iptcc_is_builtin(c)) 734 break; 735 if (!strcmp(c->name, name)) 736 return c; 737 } 738 739 /* Find a smart place to start the search via chain index */ 740 //list_start_pos = iptcc_linearly_search_chain_index(name, handle); 741 list_start_pos = iptcc_bsearch_chain_index(name, &i, handle); 742 743 /* Handel if bsearch bails out early */ 744 if (list_start_pos == &handle->chains) { 745 list_start_pos = pos; 746 } 747#ifdef DEBUG 748 else { 749 /* Verify result of bsearch against linearly index search */ 750 struct list_head *test_pos; 751 struct chain_head *test_c, *tmp_c; 752 test_pos = iptcc_linearly_search_chain_index(name, handle); 753 if (list_start_pos != test_pos) { 754 debug("BUG in chain_index search\n"); 755 test_c=list_entry(test_pos, struct chain_head,list); 756 tmp_c =list_entry(list_start_pos,struct chain_head,list); 757 debug("Verify search found:\n"); 758 debug(" Chain:%s\n", test_c->name); 759 debug("BSearch found:\n"); 760 debug(" Chain:%s\n", tmp_c->name); 761 exit(42); 762 } 763 } 764#endif 765 766 /* Initial/special case, no user defined chains */ 767 if (handle->num_chains == 0) 768 return NULL; 769 770 /* Start searching through the chain list */ 771 list_for_each(pos, list_start_pos->prev) { 772 struct chain_head *c = list_entry(pos, struct chain_head, list); 773 res = strcmp(c->name, name); 774 debug("List search name:%s == %s res:%d\n", name, c->name, res); 775 if (res==0) 776 return c; 777 778 /* We can stop earlier as we know list is sorted */ 779 if (res>0 && !iptcc_is_builtin(c)) { /* Walked too far*/ 780 debug(" Not in list, walked too far, sorted list\n"); 781 return NULL; 782 } 783 784 /* Stop on wrap around, if list head is reached */ 785 if (pos == &handle->chains) { 786 debug("Stop, list head reached\n"); 787 return NULL; 788 } 789 } 790 791 debug("List search NOT found name:%s\n", name); 792 return NULL; 793} 794 795/* called when rule is to be removed from cache */ 796static void iptcc_delete_rule(struct rule_head *r) 797{ 798 DEBUGP("deleting rule %p (offset %u)\n", r, r->offset); 799 /* clean up reference count of called chain */ 800 if (r->type == IPTCC_R_JUMP 801 && r->jump) 802 r->jump->references--; 803 804 list_del(&r->list); 805 free(r); 806} 807 808 809/********************************************************************** 810 * RULESET PARSER (blob -> cache) 811 **********************************************************************/ 812 813/* Delete policy rule of previous chain, since cache doesn't contain 814 * chain policy rules. 815 * WARNING: This function has ugly design and relies on a lot of context, only 816 * to be called from specific places within the parser */ 817static int __iptcc_p_del_policy(struct xtc_handle *h, unsigned int num) 818{ 819 if (h->chain_iterator_cur) { 820 /* policy rule is last rule */ 821 struct rule_head *pr = (struct rule_head *) 822 h->chain_iterator_cur->rules.prev; 823 824 /* save verdict */ 825 h->chain_iterator_cur->verdict = 826 *(int *)GET_TARGET(pr->entry)->data; 827 828 /* save counter and counter_map information */ 829 h->chain_iterator_cur->counter_map.maptype = 830 COUNTER_MAP_NORMAL_MAP; 831 h->chain_iterator_cur->counter_map.mappos = num-1; 832 memcpy(&h->chain_iterator_cur->counters, &pr->entry->counters, 833 sizeof(h->chain_iterator_cur->counters)); 834 835 /* foot_offset points to verdict rule */ 836 h->chain_iterator_cur->foot_index = num; 837 h->chain_iterator_cur->foot_offset = pr->offset; 838 839 /* delete rule from cache */ 840 iptcc_delete_rule(pr); 841 h->chain_iterator_cur->num_rules--; 842 843 return 1; 844 } 845 return 0; 846} 847 848/* alphabetically insert a chain into the list */ 849static void iptc_insert_chain(struct xtc_handle *h, struct chain_head *c) 850{ 851 struct chain_head *tmp; 852 struct list_head *list_start_pos; 853 unsigned int i=1; 854 855 /* Find a smart place to start the insert search */ 856 list_start_pos = iptcc_bsearch_chain_index(c->name, &i, h); 857 858 /* Handle the case, where chain.name is smaller than index[0] */ 859 if (i==0 && strcmp(c->name, h->chain_index[0]->name) <= 0) { 860 h->chain_index[0] = c; /* Update chain index head */ 861 list_start_pos = h->chains.next; 862 debug("Update chain_index[0] with %s\n", c->name); 863 } 864 865 /* Handel if bsearch bails out early */ 866 if (list_start_pos == &h->chains) { 867 list_start_pos = h->chains.next; 868 } 869 870 /* sort only user defined chains */ 871 if (!c->hooknum) { 872 list_for_each_entry(tmp, list_start_pos->prev, list) { 873 if (!tmp->hooknum && strcmp(c->name, tmp->name) <= 0) { 874 list_add(&c->list, tmp->list.prev); 875 return; 876 } 877 878 /* Stop if list head is reached */ 879 if (&tmp->list == &h->chains) { 880 debug("Insert, list head reached add to tail\n"); 881 break; 882 } 883 } 884 } 885 886 /* survived till end of list: add at tail */ 887 list_add_tail(&c->list, &h->chains); 888} 889 890/* Another ugly helper function split out of cache_add_entry to make it less 891 * spaghetti code */ 892static void __iptcc_p_add_chain(struct xtc_handle *h, struct chain_head *c, 893 unsigned int offset, unsigned int *num) 894{ 895 struct list_head *tail = h->chains.prev; 896 struct chain_head *ctail; 897 898 __iptcc_p_del_policy(h, *num); 899 900 c->head_offset = offset; 901 c->index = *num; 902 903 /* Chains from kernel are already sorted, as they are inserted 904 * sorted. But there exists an issue when shifting to 1.4.0 905 * from an older version, as old versions allow last created 906 * chain to be unsorted. 907 */ 908 if (iptcc_is_builtin(c)) /* Only user defined chains are sorted*/ 909 list_add_tail(&c->list, &h->chains); 910 else { 911 ctail = list_entry(tail, struct chain_head, list); 912 913 if (strcmp(c->name, ctail->name) > 0 || 914 iptcc_is_builtin(ctail)) 915 list_add_tail(&c->list, &h->chains);/* Already sorted*/ 916 else { 917 iptc_insert_chain(h, c);/* Was not sorted */ 918 919 /* Notice, if chains were not received sorted 920 * from kernel, then an offset bsearch is no 921 * longer valid. 922 */ 923 h->sorted_offsets = 0; 924 925 debug("NOTICE: chain:[%s] was NOT sorted(ctail:%s)\n", 926 c->name, ctail->name); 927 } 928 } 929 930 h->chain_iterator_cur = c; 931} 932 933/* main parser function: add an entry from the blob to the cache */ 934static int cache_add_entry(STRUCT_ENTRY *e, 935 struct xtc_handle *h, 936 STRUCT_ENTRY **prev, 937 unsigned int *num) 938{ 939 unsigned int builtin; 940 unsigned int offset = (char *)e - (char *)h->entries->entrytable; 941 942 DEBUGP("entering..."); 943 944 /* Last entry ("policy rule"). End it.*/ 945 if (iptcb_entry2offset(h,e) + e->next_offset == h->entries->size) { 946 /* This is the ERROR node at the end of the chain */ 947 DEBUGP_C("%u:%u: end of table:\n", *num, offset); 948 949 __iptcc_p_del_policy(h, *num); 950 951 h->chain_iterator_cur = NULL; 952 goto out_inc; 953 } 954 955 /* We know this is the start of a new chain if it's an ERROR 956 * target, or a hook entry point */ 957 958 if (strcmp(GET_TARGET(e)->u.user.name, ERROR_TARGET) == 0) { 959 struct chain_head *c = 960 iptcc_alloc_chain_head((const char *)GET_TARGET(e)->data, 0); 961 DEBUGP_C("%u:%u:new userdefined chain %s: %p\n", *num, offset, 962 (char *)c->name, c); 963 if (!c) { 964 errno = -ENOMEM; 965 return -1; 966 } 967 h->num_chains++; /* New user defined chain */ 968 969 __iptcc_p_add_chain(h, c, offset, num); 970 971 } else if ((builtin = iptcb_ent_is_hook_entry(e, h)) != 0) { 972 struct chain_head *c = 973 iptcc_alloc_chain_head((char *)hooknames[builtin-1], 974 builtin); 975 DEBUGP_C("%u:%u new builtin chain: %p (rules=%p)\n", 976 *num, offset, c, &c->rules); 977 if (!c) { 978 errno = -ENOMEM; 979 return -1; 980 } 981 982 c->hooknum = builtin; 983 984 __iptcc_p_add_chain(h, c, offset, num); 985 986 /* FIXME: this is ugly. */ 987 goto new_rule; 988 } else { 989 /* has to be normal rule */ 990 struct rule_head *r; 991new_rule: 992 993 if (!(r = iptcc_alloc_rule(h->chain_iterator_cur, 994 e->next_offset))) { 995 errno = ENOMEM; 996 return -1; 997 } 998 DEBUGP_C("%u:%u normal rule: %p: ", *num, offset, r); 999 1000 r->index = *num; 1001 r->offset = offset; 1002 memcpy(r->entry, e, e->next_offset); 1003 r->counter_map.maptype = COUNTER_MAP_NORMAL_MAP; 1004 r->counter_map.mappos = r->index; 1005 1006 /* handling of jumps, etc. */ 1007 if (!strcmp(GET_TARGET(e)->u.user.name, STANDARD_TARGET)) { 1008 STRUCT_STANDARD_TARGET *t; 1009 1010 t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e); 1011 if (t->target.u.target_size 1012 != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) { 1013 errno = EINVAL; 1014 return -1; 1015 } 1016 1017 if (t->verdict < 0) { 1018 DEBUGP_C("standard, verdict=%d\n", t->verdict); 1019 r->type = IPTCC_R_STANDARD; 1020 } else if (t->verdict == r->offset+e->next_offset) { 1021 DEBUGP_C("fallthrough\n"); 1022 r->type = IPTCC_R_FALLTHROUGH; 1023 } else { 1024 DEBUGP_C("jump, target=%u\n", t->verdict); 1025 r->type = IPTCC_R_JUMP; 1026 /* Jump target fixup has to be deferred 1027 * until second pass, since we migh not 1028 * yet have parsed the target */ 1029 } 1030 } else { 1031 DEBUGP_C("module, target=%s\n", GET_TARGET(e)->u.user.name); 1032 r->type = IPTCC_R_MODULE; 1033 } 1034 1035 list_add_tail(&r->list, &h->chain_iterator_cur->rules); 1036 h->chain_iterator_cur->num_rules++; 1037 } 1038out_inc: 1039 (*num)++; 1040 return 0; 1041} 1042 1043 1044/* parse an iptables blob into it's pieces */ 1045static int parse_table(struct xtc_handle *h) 1046{ 1047 STRUCT_ENTRY *prev; 1048 unsigned int num = 0; 1049 struct chain_head *c; 1050 1051 /* Assume that chains offsets are sorted, this verified during 1052 parsing of ruleset (in __iptcc_p_add_chain())*/ 1053 h->sorted_offsets = 1; 1054 1055 /* First pass: over ruleset blob */ 1056 ENTRY_ITERATE(h->entries->entrytable, h->entries->size, 1057 cache_add_entry, h, &prev, &num); 1058 1059 /* Build the chain index, used for chain list search speedup */ 1060 if ((iptcc_chain_index_alloc(h)) < 0) 1061 return -ENOMEM; 1062 iptcc_chain_index_build(h); 1063 1064 /* Second pass: fixup parsed data from first pass */ 1065 list_for_each_entry(c, &h->chains, list) { 1066 struct rule_head *r; 1067 list_for_each_entry(r, &c->rules, list) { 1068 struct chain_head *lc; 1069 STRUCT_STANDARD_TARGET *t; 1070 1071 if (r->type != IPTCC_R_JUMP) 1072 continue; 1073 1074 t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry); 1075 lc = iptcc_find_chain_by_offset(h, t->verdict); 1076 if (!lc) 1077 return -1; 1078 r->jump = lc; 1079 lc->references++; 1080 } 1081 } 1082 1083 return 1; 1084} 1085 1086 1087/********************************************************************** 1088 * RULESET COMPILATION (cache -> blob) 1089 **********************************************************************/ 1090 1091/* Convenience structures */ 1092struct iptcb_chain_start{ 1093 STRUCT_ENTRY e; 1094 struct ipt_error_target name; 1095}; 1096#define IPTCB_CHAIN_START_SIZE (sizeof(STRUCT_ENTRY) + \ 1097 ALIGN(sizeof(struct ipt_error_target))) 1098 1099struct iptcb_chain_foot { 1100 STRUCT_ENTRY e; 1101 STRUCT_STANDARD_TARGET target; 1102}; 1103#define IPTCB_CHAIN_FOOT_SIZE (sizeof(STRUCT_ENTRY) + \ 1104 ALIGN(sizeof(STRUCT_STANDARD_TARGET))) 1105 1106struct iptcb_chain_error { 1107 STRUCT_ENTRY entry; 1108 struct ipt_error_target target; 1109}; 1110#define IPTCB_CHAIN_ERROR_SIZE (sizeof(STRUCT_ENTRY) + \ 1111 ALIGN(sizeof(struct ipt_error_target))) 1112 1113 1114 1115/* compile rule from cache into blob */ 1116static inline int iptcc_compile_rule (struct xtc_handle *h, STRUCT_REPLACE *repl, struct rule_head *r) 1117{ 1118 /* handle jumps */ 1119 if (r->type == IPTCC_R_JUMP) { 1120 STRUCT_STANDARD_TARGET *t; 1121 t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry); 1122 /* memset for memcmp convenience on delete/replace */ 1123 memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN); 1124 strcpy(t->target.u.user.name, STANDARD_TARGET); 1125 /* Jumps can only happen to builtin chains, so we 1126 * can safely assume that they always have a header */ 1127 t->verdict = r->jump->head_offset + IPTCB_CHAIN_START_SIZE; 1128 } else if (r->type == IPTCC_R_FALLTHROUGH) { 1129 STRUCT_STANDARD_TARGET *t; 1130 t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry); 1131 t->verdict = r->offset + r->size; 1132 } 1133 1134 /* copy entry from cache to blob */ 1135 memcpy((char *)repl->entries+r->offset, r->entry, r->size); 1136 1137 return 1; 1138} 1139 1140/* compile chain from cache into blob */ 1141static int iptcc_compile_chain(struct xtc_handle *h, STRUCT_REPLACE *repl, struct chain_head *c) 1142{ 1143 int ret; 1144 struct rule_head *r; 1145 struct iptcb_chain_start *head; 1146 struct iptcb_chain_foot *foot; 1147 1148 /* only user-defined chains have heaer */ 1149 if (!iptcc_is_builtin(c)) { 1150 /* put chain header in place */ 1151 head = (void *)repl->entries + c->head_offset; 1152 head->e.target_offset = sizeof(STRUCT_ENTRY); 1153 head->e.next_offset = IPTCB_CHAIN_START_SIZE; 1154 strcpy(head->name.t.u.user.name, ERROR_TARGET); 1155 head->name.t.u.target_size = 1156 ALIGN(sizeof(struct ipt_error_target)); 1157 strcpy(head->name.error, c->name); 1158 } else { 1159 repl->hook_entry[c->hooknum-1] = c->head_offset; 1160 repl->underflow[c->hooknum-1] = c->foot_offset; 1161 } 1162 1163 /* iterate over rules */ 1164 list_for_each_entry(r, &c->rules, list) { 1165 ret = iptcc_compile_rule(h, repl, r); 1166 if (ret < 0) 1167 return ret; 1168 } 1169 1170 /* put chain footer in place */ 1171 foot = (void *)repl->entries + c->foot_offset; 1172 foot->e.target_offset = sizeof(STRUCT_ENTRY); 1173 foot->e.next_offset = IPTCB_CHAIN_FOOT_SIZE; 1174 strcpy(foot->target.target.u.user.name, STANDARD_TARGET); 1175 foot->target.target.u.target_size = 1176 ALIGN(sizeof(STRUCT_STANDARD_TARGET)); 1177 /* builtin targets have verdict, others return */ 1178 if (iptcc_is_builtin(c)) 1179 foot->target.verdict = c->verdict; 1180 else 1181 foot->target.verdict = RETURN; 1182 /* set policy-counters */ 1183 memcpy(&foot->e.counters, &c->counters, sizeof(STRUCT_COUNTERS)); 1184 1185 return 0; 1186} 1187 1188/* calculate offset and number for every rule in the cache */ 1189static int iptcc_compile_chain_offsets(struct xtc_handle *h, struct chain_head *c, 1190 unsigned int *offset, unsigned int *num) 1191{ 1192 struct rule_head *r; 1193 1194 c->head_offset = *offset; 1195 DEBUGP("%s: chain_head %u, offset=%u\n", c->name, *num, *offset); 1196 1197 if (!iptcc_is_builtin(c)) { 1198 /* Chain has header */ 1199 *offset += sizeof(STRUCT_ENTRY) 1200 + ALIGN(sizeof(struct ipt_error_target)); 1201 (*num)++; 1202 } 1203 1204 list_for_each_entry(r, &c->rules, list) { 1205 DEBUGP("rule %u, offset=%u, index=%u\n", *num, *offset, *num); 1206 r->offset = *offset; 1207 r->index = *num; 1208 *offset += r->size; 1209 (*num)++; 1210 } 1211 1212 DEBUGP("%s; chain_foot %u, offset=%u, index=%u\n", c->name, *num, 1213 *offset, *num); 1214 c->foot_offset = *offset; 1215 c->foot_index = *num; 1216 *offset += sizeof(STRUCT_ENTRY) 1217 + ALIGN(sizeof(STRUCT_STANDARD_TARGET)); 1218 (*num)++; 1219 1220 return 1; 1221} 1222 1223/* put the pieces back together again */ 1224static int iptcc_compile_table_prep(struct xtc_handle *h, unsigned int *size) 1225{ 1226 struct chain_head *c; 1227 unsigned int offset = 0, num = 0; 1228 int ret = 0; 1229 1230 /* First pass: calculate offset for every rule */ 1231 list_for_each_entry(c, &h->chains, list) { 1232 ret = iptcc_compile_chain_offsets(h, c, &offset, &num); 1233 if (ret < 0) 1234 return ret; 1235 } 1236 1237 /* Append one error rule at end of chain */ 1238 num++; 1239 offset += sizeof(STRUCT_ENTRY) 1240 + ALIGN(sizeof(struct ipt_error_target)); 1241 1242 /* ruleset size is now in offset */ 1243 *size = offset; 1244 return num; 1245} 1246 1247static int iptcc_compile_table(struct xtc_handle *h, STRUCT_REPLACE *repl) 1248{ 1249 struct chain_head *c; 1250 struct iptcb_chain_error *error; 1251 1252 /* Second pass: copy from cache to offsets, fill in jumps */ 1253 list_for_each_entry(c, &h->chains, list) { 1254 int ret = iptcc_compile_chain(h, repl, c); 1255 if (ret < 0) 1256 return ret; 1257 } 1258 1259 /* Append error rule at end of chain */ 1260 error = (void *)repl->entries + repl->size - IPTCB_CHAIN_ERROR_SIZE; 1261 error->entry.target_offset = sizeof(STRUCT_ENTRY); 1262 error->entry.next_offset = IPTCB_CHAIN_ERROR_SIZE; 1263 error->target.t.u.user.target_size = 1264 ALIGN(sizeof(struct ipt_error_target)); 1265 strcpy((char *)&error->target.t.u.user.name, ERROR_TARGET); 1266 strcpy((char *)&error->target.error, "ERROR"); 1267 1268 return 1; 1269} 1270 1271/********************************************************************** 1272 * EXTERNAL API (operates on cache only) 1273 **********************************************************************/ 1274 1275/* Allocate handle of given size */ 1276static struct xtc_handle * 1277alloc_handle(const char *tablename, unsigned int size, unsigned int num_rules) 1278{ 1279 size_t len; 1280 struct xtc_handle *h; 1281 1282 len = sizeof(STRUCT_TC_HANDLE) + size; 1283 1284 h = malloc(sizeof(STRUCT_TC_HANDLE)); 1285 if (!h) { 1286 errno = ENOMEM; 1287 return NULL; 1288 } 1289 memset(h, 0, sizeof(*h)); 1290 INIT_LIST_HEAD(&h->chains); 1291 strcpy(h->info.name, tablename); 1292 1293 h->entries = malloc(sizeof(STRUCT_GET_ENTRIES) + size); 1294 if (!h->entries) 1295 goto out_free_handle; 1296 1297 strcpy(h->entries->name, tablename); 1298 h->entries->size = size; 1299 1300 return h; 1301 1302out_free_handle: 1303 free(h); 1304 1305 return NULL; 1306} 1307 1308 1309struct xtc_handle * 1310TC_INIT(const char *tablename) 1311{ 1312 struct xtc_handle *h; 1313 STRUCT_GETINFO info; 1314 unsigned int tmp; 1315 socklen_t s; 1316 int sockfd; 1317 1318 iptc_fn = TC_INIT; 1319 1320 if (strlen(tablename) >= TABLE_MAXNAMELEN) { 1321 errno = EINVAL; 1322 return NULL; 1323 } 1324 1325 sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW); 1326 if (sockfd < 0) 1327 return NULL; 1328 1329retry: 1330 s = sizeof(info); 1331 1332 strcpy(info.name, tablename); 1333 if (getsockopt(sockfd, TC_IPPROTO, SO_GET_INFO, &info, &s) < 0) { 1334 close(sockfd); 1335 return NULL; 1336 } 1337 1338 DEBUGP("valid_hooks=0x%08x, num_entries=%u, size=%u\n", 1339 info.valid_hooks, info.num_entries, info.size); 1340 1341 if ((h = alloc_handle(info.name, info.size, info.num_entries)) 1342 == NULL) { 1343 close(sockfd); 1344 return NULL; 1345 } 1346 1347 /* Initialize current state */ 1348 h->sockfd = sockfd; 1349 h->info = info; 1350 1351 h->entries->size = h->info.size; 1352 1353 tmp = sizeof(STRUCT_GET_ENTRIES) + h->info.size; 1354 1355 if (getsockopt(h->sockfd, TC_IPPROTO, SO_GET_ENTRIES, h->entries, 1356 &tmp) < 0) 1357 goto error; 1358 1359#ifdef IPTC_DEBUG2 1360 { 1361 int fd = open("/tmp/libiptc-so_get_entries.blob", 1362 O_CREAT|O_WRONLY); 1363 if (fd >= 0) { 1364 write(fd, h->entries, tmp); 1365 close(fd); 1366 } 1367 } 1368#endif 1369 1370 if (parse_table(h) < 0) 1371 goto error; 1372 1373 CHECK(h); 1374 return h; 1375error: 1376 TC_FREE(h); 1377 /* A different process changed the ruleset size, retry */ 1378 if (errno == EAGAIN) 1379 goto retry; 1380 return NULL; 1381} 1382 1383void 1384TC_FREE(struct xtc_handle *h) 1385{ 1386 struct chain_head *c, *tmp; 1387 1388 iptc_fn = TC_FREE; 1389 close(h->sockfd); 1390 1391 list_for_each_entry_safe(c, tmp, &h->chains, list) { 1392 struct rule_head *r, *rtmp; 1393 1394 list_for_each_entry_safe(r, rtmp, &c->rules, list) { 1395 free(r); 1396 } 1397 1398 free(c); 1399 } 1400 1401 iptcc_chain_index_free(h); 1402 1403 free(h->entries); 1404 free(h); 1405} 1406 1407static inline int 1408print_match(const STRUCT_ENTRY_MATCH *m) 1409{ 1410 printf("Match name: `%s'\n", m->u.user.name); 1411 return 0; 1412} 1413 1414static int dump_entry(STRUCT_ENTRY *e, struct xtc_handle *const handle); 1415 1416void 1417TC_DUMP_ENTRIES(struct xtc_handle *const handle) 1418{ 1419 iptc_fn = TC_DUMP_ENTRIES; 1420 CHECK(handle); 1421 1422 printf("libiptc v%s. %u bytes.\n", 1423 XTABLES_VERSION, handle->entries->size); 1424 printf("Table `%s'\n", handle->info.name); 1425 printf("Hooks: pre/in/fwd/out/post = %x/%x/%x/%x/%x\n", 1426 handle->info.hook_entry[HOOK_PRE_ROUTING], 1427 handle->info.hook_entry[HOOK_LOCAL_IN], 1428 handle->info.hook_entry[HOOK_FORWARD], 1429 handle->info.hook_entry[HOOK_LOCAL_OUT], 1430 handle->info.hook_entry[HOOK_POST_ROUTING]); 1431 printf("Underflows: pre/in/fwd/out/post = %x/%x/%x/%x/%x\n", 1432 handle->info.underflow[HOOK_PRE_ROUTING], 1433 handle->info.underflow[HOOK_LOCAL_IN], 1434 handle->info.underflow[HOOK_FORWARD], 1435 handle->info.underflow[HOOK_LOCAL_OUT], 1436 handle->info.underflow[HOOK_POST_ROUTING]); 1437 1438 ENTRY_ITERATE(handle->entries->entrytable, handle->entries->size, 1439 dump_entry, handle); 1440} 1441 1442/* Does this chain exist? */ 1443int TC_IS_CHAIN(const char *chain, struct xtc_handle *const handle) 1444{ 1445 iptc_fn = TC_IS_CHAIN; 1446 return iptcc_find_label(chain, handle) != NULL; 1447} 1448 1449static void iptcc_chain_iterator_advance(struct xtc_handle *handle) 1450{ 1451 struct chain_head *c = handle->chain_iterator_cur; 1452 1453 if (c->list.next == &handle->chains) 1454 handle->chain_iterator_cur = NULL; 1455 else 1456 handle->chain_iterator_cur = 1457 list_entry(c->list.next, struct chain_head, list); 1458} 1459 1460/* Iterator functions to run through the chains. */ 1461const char * 1462TC_FIRST_CHAIN(struct xtc_handle *handle) 1463{ 1464 struct chain_head *c = list_entry(handle->chains.next, 1465 struct chain_head, list); 1466 1467 iptc_fn = TC_FIRST_CHAIN; 1468 1469 1470 if (list_empty(&handle->chains)) { 1471 DEBUGP(": no chains\n"); 1472 return NULL; 1473 } 1474 1475 handle->chain_iterator_cur = c; 1476 iptcc_chain_iterator_advance(handle); 1477 1478 DEBUGP(": returning `%s'\n", c->name); 1479 return c->name; 1480} 1481 1482/* Iterator functions to run through the chains. Returns NULL at end. */ 1483const char * 1484TC_NEXT_CHAIN(struct xtc_handle *handle) 1485{ 1486 struct chain_head *c = handle->chain_iterator_cur; 1487 1488 iptc_fn = TC_NEXT_CHAIN; 1489 1490 if (!c) { 1491 DEBUGP(": no more chains\n"); 1492 return NULL; 1493 } 1494 1495 iptcc_chain_iterator_advance(handle); 1496 1497 DEBUGP(": returning `%s'\n", c->name); 1498 return c->name; 1499} 1500 1501/* Get first rule in the given chain: NULL for empty chain. */ 1502const STRUCT_ENTRY * 1503TC_FIRST_RULE(const char *chain, struct xtc_handle *handle) 1504{ 1505 struct chain_head *c; 1506 struct rule_head *r; 1507 1508 iptc_fn = TC_FIRST_RULE; 1509 1510 DEBUGP("first rule(%s): ", chain); 1511 1512 c = iptcc_find_label(chain, handle); 1513 if (!c) { 1514 errno = ENOENT; 1515 return NULL; 1516 } 1517 1518 /* Empty chain: single return/policy rule */ 1519 if (list_empty(&c->rules)) { 1520 DEBUGP_C("no rules, returning NULL\n"); 1521 return NULL; 1522 } 1523 1524 r = list_entry(c->rules.next, struct rule_head, list); 1525 handle->rule_iterator_cur = r; 1526 DEBUGP_C("%p\n", r); 1527 1528 return r->entry; 1529} 1530 1531/* Returns NULL when rules run out. */ 1532const STRUCT_ENTRY * 1533TC_NEXT_RULE(const STRUCT_ENTRY *prev, struct xtc_handle *handle) 1534{ 1535 struct rule_head *r; 1536 1537 iptc_fn = TC_NEXT_RULE; 1538 DEBUGP("rule_iterator_cur=%p...", handle->rule_iterator_cur); 1539 1540 if (handle->rule_iterator_cur == NULL) { 1541 DEBUGP_C("returning NULL\n"); 1542 return NULL; 1543 } 1544 1545 r = list_entry(handle->rule_iterator_cur->list.next, 1546 struct rule_head, list); 1547 1548 iptc_fn = TC_NEXT_RULE; 1549 1550 DEBUGP_C("next=%p, head=%p...", &r->list, 1551 &handle->rule_iterator_cur->chain->rules); 1552 1553 if (&r->list == &handle->rule_iterator_cur->chain->rules) { 1554 handle->rule_iterator_cur = NULL; 1555 DEBUGP_C("finished, returning NULL\n"); 1556 return NULL; 1557 } 1558 1559 handle->rule_iterator_cur = r; 1560 1561 /* NOTE: prev is without any influence ! */ 1562 DEBUGP_C("returning rule %p\n", r); 1563 return r->entry; 1564} 1565 1566/* Returns a pointer to the target name of this position. */ 1567static const char *standard_target_map(int verdict) 1568{ 1569 switch (verdict) { 1570 case RETURN: 1571 return LABEL_RETURN; 1572 break; 1573 case -NF_ACCEPT-1: 1574 return LABEL_ACCEPT; 1575 break; 1576 case -NF_DROP-1: 1577 return LABEL_DROP; 1578 break; 1579 case -NF_QUEUE-1: 1580 return LABEL_QUEUE; 1581 break; 1582 default: 1583 fprintf(stderr, "ERROR: %d not a valid target)\n", 1584 verdict); 1585 abort(); 1586 break; 1587 } 1588 /* not reached */ 1589 return NULL; 1590} 1591 1592/* Returns a pointer to the target name of this position. */ 1593const char *TC_GET_TARGET(const STRUCT_ENTRY *ce, 1594 struct xtc_handle *handle) 1595{ 1596 STRUCT_ENTRY *e = (STRUCT_ENTRY *)ce; 1597 struct rule_head *r = container_of(e, struct rule_head, entry[0]); 1598 1599 iptc_fn = TC_GET_TARGET; 1600 1601 switch(r->type) { 1602 int spos; 1603 case IPTCC_R_FALLTHROUGH: 1604 return ""; 1605 break; 1606 case IPTCC_R_JUMP: 1607 DEBUGP("r=%p, jump=%p, name=`%s'\n", r, r->jump, r->jump->name); 1608 return r->jump->name; 1609 break; 1610 case IPTCC_R_STANDARD: 1611 spos = *(int *)GET_TARGET(e)->data; 1612 DEBUGP("r=%p, spos=%d'\n", r, spos); 1613 return standard_target_map(spos); 1614 break; 1615 case IPTCC_R_MODULE: 1616 return GET_TARGET(e)->u.user.name; 1617 break; 1618 } 1619 return NULL; 1620} 1621/* Is this a built-in chain? Actually returns hook + 1. */ 1622int 1623TC_BUILTIN(const char *chain, struct xtc_handle *const handle) 1624{ 1625 struct chain_head *c; 1626 1627 iptc_fn = TC_BUILTIN; 1628 1629 c = iptcc_find_label(chain, handle); 1630 if (!c) { 1631 errno = ENOENT; 1632 return 0; 1633 } 1634 1635 return iptcc_is_builtin(c); 1636} 1637 1638/* Get the policy of a given built-in chain */ 1639const char * 1640TC_GET_POLICY(const char *chain, 1641 STRUCT_COUNTERS *counters, 1642 struct xtc_handle *handle) 1643{ 1644 struct chain_head *c; 1645 1646 iptc_fn = TC_GET_POLICY; 1647 1648 DEBUGP("called for chain %s\n", chain); 1649 1650 c = iptcc_find_label(chain, handle); 1651 if (!c) { 1652 errno = ENOENT; 1653 return NULL; 1654 } 1655 1656 if (!iptcc_is_builtin(c)) 1657 return NULL; 1658 1659 *counters = c->counters; 1660 1661 return standard_target_map(c->verdict); 1662} 1663 1664static int 1665iptcc_standard_map(struct rule_head *r, int verdict) 1666{ 1667 STRUCT_ENTRY *e = r->entry; 1668 STRUCT_STANDARD_TARGET *t; 1669 1670 t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e); 1671 1672 if (t->target.u.target_size 1673 != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) { 1674 errno = EINVAL; 1675 return 0; 1676 } 1677 /* memset for memcmp convenience on delete/replace */ 1678 memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN); 1679 strcpy(t->target.u.user.name, STANDARD_TARGET); 1680 t->verdict = verdict; 1681 1682 r->type = IPTCC_R_STANDARD; 1683 1684 return 1; 1685} 1686 1687static int 1688iptcc_map_target(struct xtc_handle *const handle, 1689 struct rule_head *r) 1690{ 1691 STRUCT_ENTRY *e = r->entry; 1692 STRUCT_ENTRY_TARGET *t = GET_TARGET(e); 1693 1694 /* Maybe it's empty (=> fall through) */ 1695 if (strcmp(t->u.user.name, "") == 0) { 1696 r->type = IPTCC_R_FALLTHROUGH; 1697 return 1; 1698 } 1699 /* Maybe it's a standard target name... */ 1700 else if (strcmp(t->u.user.name, LABEL_ACCEPT) == 0) 1701 return iptcc_standard_map(r, -NF_ACCEPT - 1); 1702 else if (strcmp(t->u.user.name, LABEL_DROP) == 0) 1703 return iptcc_standard_map(r, -NF_DROP - 1); 1704 else if (strcmp(t->u.user.name, LABEL_QUEUE) == 0) 1705 return iptcc_standard_map(r, -NF_QUEUE - 1); 1706 else if (strcmp(t->u.user.name, LABEL_RETURN) == 0) 1707 return iptcc_standard_map(r, RETURN); 1708 else if (TC_BUILTIN(t->u.user.name, handle)) { 1709 /* Can't jump to builtins. */ 1710 errno = EINVAL; 1711 return 0; 1712 } else { 1713 /* Maybe it's an existing chain name. */ 1714 struct chain_head *c; 1715 DEBUGP("trying to find chain `%s': ", t->u.user.name); 1716 1717 c = iptcc_find_label(t->u.user.name, handle); 1718 if (c) { 1719 DEBUGP_C("found!\n"); 1720 r->type = IPTCC_R_JUMP; 1721 r->jump = c; 1722 c->references++; 1723 return 1; 1724 } 1725 DEBUGP_C("not found :(\n"); 1726 } 1727 1728 /* Must be a module? If not, kernel will reject... */ 1729 /* memset to all 0 for your memcmp convenience: don't clear version */ 1730 memset(t->u.user.name + strlen(t->u.user.name), 1731 0, 1732 FUNCTION_MAXNAMELEN - 1 - strlen(t->u.user.name)); 1733 r->type = IPTCC_R_MODULE; 1734 set_changed(handle); 1735 return 1; 1736} 1737 1738/* Insert the entry `fw' in chain `chain' into position `rulenum'. */ 1739int 1740TC_INSERT_ENTRY(const IPT_CHAINLABEL chain, 1741 const STRUCT_ENTRY *e, 1742 unsigned int rulenum, 1743 struct xtc_handle *handle) 1744{ 1745 struct chain_head *c; 1746 struct rule_head *r; 1747 struct list_head *prev; 1748 1749 iptc_fn = TC_INSERT_ENTRY; 1750 1751 if (!(c = iptcc_find_label(chain, handle))) { 1752 errno = ENOENT; 1753 return 0; 1754 } 1755 1756 /* first rulenum index = 0 1757 first c->num_rules index = 1 */ 1758 if (rulenum > c->num_rules) { 1759 errno = E2BIG; 1760 return 0; 1761 } 1762 1763 /* If we are inserting at the end just take advantage of the 1764 double linked list, insert will happen before the entry 1765 prev points to. */ 1766 if (rulenum == c->num_rules) { 1767 prev = &c->rules; 1768 } else if (rulenum + 1 <= c->num_rules/2) { 1769 r = iptcc_get_rule_num(c, rulenum + 1); 1770 prev = &r->list; 1771 } else { 1772 r = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum); 1773 prev = &r->list; 1774 } 1775 1776 if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1777 errno = ENOMEM; 1778 return 0; 1779 } 1780 1781 memcpy(r->entry, e, e->next_offset); 1782 r->counter_map.maptype = COUNTER_MAP_SET; 1783 1784 if (!iptcc_map_target(handle, r)) { 1785 free(r); 1786 return 0; 1787 } 1788 1789 list_add_tail(&r->list, prev); 1790 c->num_rules++; 1791 1792 set_changed(handle); 1793 1794 return 1; 1795} 1796 1797/* Atomically replace rule `rulenum' in `chain' with `fw'. */ 1798int 1799TC_REPLACE_ENTRY(const IPT_CHAINLABEL chain, 1800 const STRUCT_ENTRY *e, 1801 unsigned int rulenum, 1802 struct xtc_handle *handle) 1803{ 1804 struct chain_head *c; 1805 struct rule_head *r, *old; 1806 1807 iptc_fn = TC_REPLACE_ENTRY; 1808 1809 if (!(c = iptcc_find_label(chain, handle))) { 1810 errno = ENOENT; 1811 return 0; 1812 } 1813 1814 if (rulenum >= c->num_rules) { 1815 errno = E2BIG; 1816 return 0; 1817 } 1818 1819 /* Take advantage of the double linked list if possible. */ 1820 if (rulenum + 1 <= c->num_rules/2) { 1821 old = iptcc_get_rule_num(c, rulenum + 1); 1822 } else { 1823 old = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum); 1824 } 1825 1826 if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1827 errno = ENOMEM; 1828 return 0; 1829 } 1830 1831 memcpy(r->entry, e, e->next_offset); 1832 r->counter_map.maptype = COUNTER_MAP_SET; 1833 1834 if (!iptcc_map_target(handle, r)) { 1835 free(r); 1836 return 0; 1837 } 1838 1839 list_add(&r->list, &old->list); 1840 iptcc_delete_rule(old); 1841 1842 set_changed(handle); 1843 1844 return 1; 1845} 1846 1847/* Append entry `fw' to chain `chain'. Equivalent to insert with 1848 rulenum = length of chain. */ 1849int 1850TC_APPEND_ENTRY(const IPT_CHAINLABEL chain, 1851 const STRUCT_ENTRY *e, 1852 struct xtc_handle *handle) 1853{ 1854 struct chain_head *c; 1855 struct rule_head *r; 1856 1857 iptc_fn = TC_APPEND_ENTRY; 1858 if (!(c = iptcc_find_label(chain, handle))) { 1859 DEBUGP("unable to find chain `%s'\n", chain); 1860 errno = ENOENT; 1861 return 0; 1862 } 1863 1864 if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1865 DEBUGP("unable to allocate rule for chain `%s'\n", chain); 1866 errno = ENOMEM; 1867 return 0; 1868 } 1869 1870 memcpy(r->entry, e, e->next_offset); 1871 r->counter_map.maptype = COUNTER_MAP_SET; 1872 1873 if (!iptcc_map_target(handle, r)) { 1874 DEBUGP("unable to map target of rule for chain `%s'\n", chain); 1875 free(r); 1876 return 0; 1877 } 1878 1879 list_add_tail(&r->list, &c->rules); 1880 c->num_rules++; 1881 1882 set_changed(handle); 1883 1884 return 1; 1885} 1886 1887static inline int 1888match_different(const STRUCT_ENTRY_MATCH *a, 1889 const unsigned char *a_elems, 1890 const unsigned char *b_elems, 1891 unsigned char **maskptr) 1892{ 1893 const STRUCT_ENTRY_MATCH *b; 1894 unsigned int i; 1895 1896 /* Offset of b is the same as a. */ 1897 b = (void *)b_elems + ((unsigned char *)a - a_elems); 1898 1899 if (a->u.match_size != b->u.match_size) 1900 return 1; 1901 1902 if (strcmp(a->u.user.name, b->u.user.name) != 0) 1903 return 1; 1904 1905 *maskptr += ALIGN(sizeof(*a)); 1906 1907 for (i = 0; i < a->u.match_size - ALIGN(sizeof(*a)); i++) 1908 if (((a->data[i] ^ b->data[i]) & (*maskptr)[i]) != 0) 1909 return 1; 1910 *maskptr += i; 1911 return 0; 1912} 1913 1914static inline int 1915target_same(struct rule_head *a, struct rule_head *b,const unsigned char *mask) 1916{ 1917 unsigned int i; 1918 STRUCT_ENTRY_TARGET *ta, *tb; 1919 1920 if (a->type != b->type) 1921 return 0; 1922 1923 ta = GET_TARGET(a->entry); 1924 tb = GET_TARGET(b->entry); 1925 1926 switch (a->type) { 1927 case IPTCC_R_FALLTHROUGH: 1928 return 1; 1929 case IPTCC_R_JUMP: 1930 return a->jump == b->jump; 1931 case IPTCC_R_STANDARD: 1932 return ((STRUCT_STANDARD_TARGET *)ta)->verdict 1933 == ((STRUCT_STANDARD_TARGET *)tb)->verdict; 1934 case IPTCC_R_MODULE: 1935 if (ta->u.target_size != tb->u.target_size) 1936 return 0; 1937 if (strcmp(ta->u.user.name, tb->u.user.name) != 0) 1938 return 0; 1939 1940 for (i = 0; i < ta->u.target_size - sizeof(*ta); i++) 1941 if (((ta->data[i] ^ tb->data[i]) & mask[i]) != 0) 1942 return 0; 1943 return 1; 1944 default: 1945 fprintf(stderr, "ERROR: bad type %i\n", a->type); 1946 abort(); 1947 } 1948} 1949 1950static unsigned char * 1951is_same(const STRUCT_ENTRY *a, 1952 const STRUCT_ENTRY *b, 1953 unsigned char *matchmask); 1954 1955/* Delete the first rule in `chain' which matches `fw'. */ 1956int 1957TC_DELETE_ENTRY(const IPT_CHAINLABEL chain, 1958 const STRUCT_ENTRY *origfw, 1959 unsigned char *matchmask, 1960 struct xtc_handle *handle) 1961{ 1962 struct chain_head *c; 1963 struct rule_head *r, *i; 1964 1965 iptc_fn = TC_DELETE_ENTRY; 1966 if (!(c = iptcc_find_label(chain, handle))) { 1967 errno = ENOENT; 1968 return 0; 1969 } 1970 1971 /* Create a rule_head from origfw. */ 1972 r = iptcc_alloc_rule(c, origfw->next_offset); 1973 if (!r) { 1974 errno = ENOMEM; 1975 return 0; 1976 } 1977 1978 memcpy(r->entry, origfw, origfw->next_offset); 1979 r->counter_map.maptype = COUNTER_MAP_NOMAP; 1980 if (!iptcc_map_target(handle, r)) { 1981 DEBUGP("unable to map target of rule for chain `%s'\n", chain); 1982 free(r); 1983 return 0; 1984 } else { 1985 /* iptcc_map_target increment target chain references 1986 * since this is a fake rule only used for matching 1987 * the chain references count is decremented again. 1988 */ 1989 if (r->type == IPTCC_R_JUMP 1990 && r->jump) 1991 r->jump->references--; 1992 } 1993 1994 list_for_each_entry(i, &c->rules, list) { 1995 unsigned char *mask; 1996 1997 mask = is_same(r->entry, i->entry, matchmask); 1998 if (!mask) 1999 continue; 2000 2001 if (!target_same(r, i, mask)) 2002 continue; 2003 2004 /* If we are about to delete the rule that is the 2005 * current iterator, move rule iterator back. next 2006 * pointer will then point to real next node */ 2007 if (i == handle->rule_iterator_cur) { 2008 handle->rule_iterator_cur = 2009 list_entry(handle->rule_iterator_cur->list.prev, 2010 struct rule_head, list); 2011 } 2012 2013 c->num_rules--; 2014 iptcc_delete_rule(i); 2015 2016 set_changed(handle); 2017 free(r); 2018 return 1; 2019 } 2020 2021 free(r); 2022 errno = ENOENT; 2023 return 0; 2024} 2025 2026 2027/* Delete the rule in position `rulenum' in `chain'. */ 2028int 2029TC_DELETE_NUM_ENTRY(const IPT_CHAINLABEL chain, 2030 unsigned int rulenum, 2031 struct xtc_handle *handle) 2032{ 2033 struct chain_head *c; 2034 struct rule_head *r; 2035 2036 iptc_fn = TC_DELETE_NUM_ENTRY; 2037 2038 if (!(c = iptcc_find_label(chain, handle))) { 2039 errno = ENOENT; 2040 return 0; 2041 } 2042 2043 if (rulenum >= c->num_rules) { 2044 errno = E2BIG; 2045 return 0; 2046 } 2047 2048 /* Take advantage of the double linked list if possible. */ 2049 if (rulenum + 1 <= c->num_rules/2) { 2050 r = iptcc_get_rule_num(c, rulenum + 1); 2051 } else { 2052 r = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum); 2053 } 2054 2055 /* If we are about to delete the rule that is the current 2056 * iterator, move rule iterator back. next pointer will then 2057 * point to real next node */ 2058 if (r == handle->rule_iterator_cur) { 2059 handle->rule_iterator_cur = 2060 list_entry(handle->rule_iterator_cur->list.prev, 2061 struct rule_head, list); 2062 } 2063 2064 c->num_rules--; 2065 iptcc_delete_rule(r); 2066 2067 set_changed(handle); 2068 2069 return 1; 2070} 2071 2072/* Flushes the entries in the given chain (ie. empties chain). */ 2073int 2074TC_FLUSH_ENTRIES(const IPT_CHAINLABEL chain, struct xtc_handle *handle) 2075{ 2076 struct chain_head *c; 2077 struct rule_head *r, *tmp; 2078 2079 iptc_fn = TC_FLUSH_ENTRIES; 2080 if (!(c = iptcc_find_label(chain, handle))) { 2081 errno = ENOENT; 2082 return 0; 2083 } 2084 2085 list_for_each_entry_safe(r, tmp, &c->rules, list) { 2086 iptcc_delete_rule(r); 2087 } 2088 2089 c->num_rules = 0; 2090 2091 set_changed(handle); 2092 2093 return 1; 2094} 2095 2096/* Zeroes the counters in a chain. */ 2097int 2098TC_ZERO_ENTRIES(const IPT_CHAINLABEL chain, struct xtc_handle *handle) 2099{ 2100 struct chain_head *c; 2101 struct rule_head *r; 2102 2103 iptc_fn = TC_ZERO_ENTRIES; 2104 if (!(c = iptcc_find_label(chain, handle))) { 2105 errno = ENOENT; 2106 return 0; 2107 } 2108 2109 if (c->counter_map.maptype == COUNTER_MAP_NORMAL_MAP) 2110 c->counter_map.maptype = COUNTER_MAP_ZEROED; 2111 2112 list_for_each_entry(r, &c->rules, list) { 2113 if (r->counter_map.maptype == COUNTER_MAP_NORMAL_MAP) 2114 r->counter_map.maptype = COUNTER_MAP_ZEROED; 2115 } 2116 2117 set_changed(handle); 2118 2119 return 1; 2120} 2121 2122STRUCT_COUNTERS * 2123TC_READ_COUNTER(const IPT_CHAINLABEL chain, 2124 unsigned int rulenum, 2125 struct xtc_handle *handle) 2126{ 2127 struct chain_head *c; 2128 struct rule_head *r; 2129 2130 iptc_fn = TC_READ_COUNTER; 2131 CHECK(*handle); 2132 2133 if (!(c = iptcc_find_label(chain, handle))) { 2134 errno = ENOENT; 2135 return NULL; 2136 } 2137 2138 if (!(r = iptcc_get_rule_num(c, rulenum))) { 2139 errno = E2BIG; 2140 return NULL; 2141 } 2142 2143 return &r->entry[0].counters; 2144} 2145 2146int 2147TC_ZERO_COUNTER(const IPT_CHAINLABEL chain, 2148 unsigned int rulenum, 2149 struct xtc_handle *handle) 2150{ 2151 struct chain_head *c; 2152 struct rule_head *r; 2153 2154 iptc_fn = TC_ZERO_COUNTER; 2155 CHECK(handle); 2156 2157 if (!(c = iptcc_find_label(chain, handle))) { 2158 errno = ENOENT; 2159 return 0; 2160 } 2161 2162 if (!(r = iptcc_get_rule_num(c, rulenum))) { 2163 errno = E2BIG; 2164 return 0; 2165 } 2166 2167 if (r->counter_map.maptype == COUNTER_MAP_NORMAL_MAP) 2168 r->counter_map.maptype = COUNTER_MAP_ZEROED; 2169 2170 set_changed(handle); 2171 2172 return 1; 2173} 2174 2175int 2176TC_SET_COUNTER(const IPT_CHAINLABEL chain, 2177 unsigned int rulenum, 2178 STRUCT_COUNTERS *counters, 2179 struct xtc_handle *handle) 2180{ 2181 struct chain_head *c; 2182 struct rule_head *r; 2183 STRUCT_ENTRY *e; 2184 2185 iptc_fn = TC_SET_COUNTER; 2186 CHECK(handle); 2187 2188 if (!(c = iptcc_find_label(chain, handle))) { 2189 errno = ENOENT; 2190 return 0; 2191 } 2192 2193 if (!(r = iptcc_get_rule_num(c, rulenum))) { 2194 errno = E2BIG; 2195 return 0; 2196 } 2197 2198 e = r->entry; 2199 r->counter_map.maptype = COUNTER_MAP_SET; 2200 2201 memcpy(&e->counters, counters, sizeof(STRUCT_COUNTERS)); 2202 2203 set_changed(handle); 2204 2205 return 1; 2206} 2207 2208/* Creates a new chain. */ 2209/* To create a chain, create two rules: error node and unconditional 2210 * return. */ 2211int 2212TC_CREATE_CHAIN(const IPT_CHAINLABEL chain, struct xtc_handle *handle) 2213{ 2214 static struct chain_head *c; 2215 int capacity; 2216 int exceeded; 2217 2218 iptc_fn = TC_CREATE_CHAIN; 2219 2220 /* find_label doesn't cover built-in targets: DROP, ACCEPT, 2221 QUEUE, RETURN. */ 2222 if (iptcc_find_label(chain, handle) 2223 || strcmp(chain, LABEL_DROP) == 0 2224 || strcmp(chain, LABEL_ACCEPT) == 0 2225 || strcmp(chain, LABEL_QUEUE) == 0 2226 || strcmp(chain, LABEL_RETURN) == 0) { 2227 DEBUGP("Chain `%s' already exists\n", chain); 2228 errno = EEXIST; 2229 return 0; 2230 } 2231 2232 if (strlen(chain)+1 > sizeof(IPT_CHAINLABEL)) { 2233 DEBUGP("Chain name `%s' too long\n", chain); 2234 errno = EINVAL; 2235 return 0; 2236 } 2237 2238 c = iptcc_alloc_chain_head(chain, 0); 2239 if (!c) { 2240 DEBUGP("Cannot allocate memory for chain `%s'\n", chain); 2241 errno = ENOMEM; 2242 return 0; 2243 2244 } 2245 handle->num_chains++; /* New user defined chain */ 2246 2247 DEBUGP("Creating chain `%s'\n", chain); 2248 iptc_insert_chain(handle, c); /* Insert sorted */ 2249 2250 /* Inserting chains don't change the correctness of the chain 2251 * index (except if its smaller than index[0], but that 2252 * handled by iptc_insert_chain). It only causes longer lists 2253 * in the buckets. Thus, only rebuild chain index when the 2254 * capacity is exceed with CHAIN_INDEX_INSERT_MAX chains. 2255 */ 2256 capacity = handle->chain_index_sz * CHAIN_INDEX_BUCKET_LEN; 2257 exceeded = handle->num_chains - capacity; 2258 if (exceeded > CHAIN_INDEX_INSERT_MAX) { 2259 debug("Capacity(%d) exceeded(%d) rebuild (chains:%d)\n", 2260 capacity, exceeded, handle->num_chains); 2261 iptcc_chain_index_rebuild(handle); 2262 } 2263 2264 set_changed(handle); 2265 2266 return 1; 2267} 2268 2269/* Get the number of references to this chain. */ 2270int 2271TC_GET_REFERENCES(unsigned int *ref, const IPT_CHAINLABEL chain, 2272 struct xtc_handle *handle) 2273{ 2274 struct chain_head *c; 2275 2276 iptc_fn = TC_GET_REFERENCES; 2277 if (!(c = iptcc_find_label(chain, handle))) { 2278 errno = ENOENT; 2279 return 0; 2280 } 2281 2282 *ref = c->references; 2283 2284 return 1; 2285} 2286 2287/* Deletes a chain. */ 2288int 2289TC_DELETE_CHAIN(const IPT_CHAINLABEL chain, struct xtc_handle *handle) 2290{ 2291 unsigned int references; 2292 struct chain_head *c; 2293 2294 iptc_fn = TC_DELETE_CHAIN; 2295 2296 if (!(c = iptcc_find_label(chain, handle))) { 2297 DEBUGP("cannot find chain `%s'\n", chain); 2298 errno = ENOENT; 2299 return 0; 2300 } 2301 2302 if (TC_BUILTIN(chain, handle)) { 2303 DEBUGP("cannot remove builtin chain `%s'\n", chain); 2304 errno = EINVAL; 2305 return 0; 2306 } 2307 2308 if (!TC_GET_REFERENCES(&references, chain, handle)) { 2309 DEBUGP("cannot get references on chain `%s'\n", chain); 2310 return 0; 2311 } 2312 2313 if (references > 0) { 2314 DEBUGP("chain `%s' still has references\n", chain); 2315 errno = EMLINK; 2316 return 0; 2317 } 2318 2319 if (c->num_rules) { 2320 DEBUGP("chain `%s' is not empty\n", chain); 2321 errno = ENOTEMPTY; 2322 return 0; 2323 } 2324 2325 /* If we are about to delete the chain that is the current 2326 * iterator, move chain iterator forward. */ 2327 if (c == handle->chain_iterator_cur) 2328 iptcc_chain_iterator_advance(handle); 2329 2330 handle->num_chains--; /* One user defined chain deleted */ 2331 2332 //list_del(&c->list); /* Done in iptcc_chain_index_delete_chain() */ 2333 iptcc_chain_index_delete_chain(c, handle); 2334 free(c); 2335 2336 DEBUGP("chain `%s' deleted\n", chain); 2337 2338 set_changed(handle); 2339 2340 return 1; 2341} 2342 2343/* Renames a chain. */ 2344int TC_RENAME_CHAIN(const IPT_CHAINLABEL oldname, 2345 const IPT_CHAINLABEL newname, 2346 struct xtc_handle *handle) 2347{ 2348 struct chain_head *c; 2349 iptc_fn = TC_RENAME_CHAIN; 2350 2351 /* find_label doesn't cover built-in targets: DROP, ACCEPT, 2352 QUEUE, RETURN. */ 2353 if (iptcc_find_label(newname, handle) 2354 || strcmp(newname, LABEL_DROP) == 0 2355 || strcmp(newname, LABEL_ACCEPT) == 0 2356 || strcmp(newname, LABEL_QUEUE) == 0 2357 || strcmp(newname, LABEL_RETURN) == 0) { 2358 errno = EEXIST; 2359 return 0; 2360 } 2361 2362 if (!(c = iptcc_find_label(oldname, handle)) 2363 || TC_BUILTIN(oldname, handle)) { 2364 errno = ENOENT; 2365 return 0; 2366 } 2367 2368 if (strlen(newname)+1 > sizeof(IPT_CHAINLABEL)) { 2369 errno = EINVAL; 2370 return 0; 2371 } 2372 2373 /* This only unlinks "c" from the list, thus no free(c) */ 2374 iptcc_chain_index_delete_chain(c, handle); 2375 2376 /* Change the name of the chain */ 2377 strncpy(c->name, newname, sizeof(IPT_CHAINLABEL)); 2378 2379 /* Insert sorted into to list again */ 2380 iptc_insert_chain(handle, c); 2381 2382 set_changed(handle); 2383 2384 return 1; 2385} 2386 2387/* Sets the policy on a built-in chain. */ 2388int 2389TC_SET_POLICY(const IPT_CHAINLABEL chain, 2390 const IPT_CHAINLABEL policy, 2391 STRUCT_COUNTERS *counters, 2392 struct xtc_handle *handle) 2393{ 2394 struct chain_head *c; 2395 2396 iptc_fn = TC_SET_POLICY; 2397 2398 if (!(c = iptcc_find_label(chain, handle))) { 2399 DEBUGP("cannot find chain `%s'\n", chain); 2400 errno = ENOENT; 2401 return 0; 2402 } 2403 2404 if (!iptcc_is_builtin(c)) { 2405 DEBUGP("cannot set policy of userdefinedchain `%s'\n", chain); 2406 errno = ENOENT; 2407 return 0; 2408 } 2409 2410 if (strcmp(policy, LABEL_ACCEPT) == 0) 2411 c->verdict = -NF_ACCEPT - 1; 2412 else if (strcmp(policy, LABEL_DROP) == 0) 2413 c->verdict = -NF_DROP - 1; 2414 else { 2415 errno = EINVAL; 2416 return 0; 2417 } 2418 2419 if (counters) { 2420 /* set byte and packet counters */ 2421 memcpy(&c->counters, counters, sizeof(STRUCT_COUNTERS)); 2422 c->counter_map.maptype = COUNTER_MAP_SET; 2423 } else { 2424 c->counter_map.maptype = COUNTER_MAP_NOMAP; 2425 } 2426 2427 set_changed(handle); 2428 2429 return 1; 2430} 2431 2432/* Without this, on gcc 2.7.2.3, we get: 2433 libiptc.c: In function `TC_COMMIT': 2434 libiptc.c:833: fixed or forbidden register was spilled. 2435 This may be due to a compiler bug or to impossible asm 2436 statements or clauses. 2437*/ 2438static void 2439subtract_counters(STRUCT_COUNTERS *answer, 2440 const STRUCT_COUNTERS *a, 2441 const STRUCT_COUNTERS *b) 2442{ 2443 answer->pcnt = a->pcnt - b->pcnt; 2444 answer->bcnt = a->bcnt - b->bcnt; 2445} 2446 2447 2448static void counters_nomap(STRUCT_COUNTERS_INFO *newcounters, unsigned int idx) 2449{ 2450 newcounters->counters[idx] = ((STRUCT_COUNTERS) { 0, 0}); 2451 DEBUGP_C("NOMAP => zero\n"); 2452} 2453 2454static void counters_normal_map(STRUCT_COUNTERS_INFO *newcounters, 2455 STRUCT_REPLACE *repl, unsigned int idx, 2456 unsigned int mappos) 2457{ 2458 /* Original read: X. 2459 * Atomic read on replacement: X + Y. 2460 * Currently in kernel: Z. 2461 * Want in kernel: X + Y + Z. 2462 * => Add in X + Y 2463 * => Add in replacement read. 2464 */ 2465 newcounters->counters[idx] = repl->counters[mappos]; 2466 DEBUGP_C("NORMAL_MAP => mappos %u \n", mappos); 2467} 2468 2469static void counters_map_zeroed(STRUCT_COUNTERS_INFO *newcounters, 2470 STRUCT_REPLACE *repl, unsigned int idx, 2471 unsigned int mappos, STRUCT_COUNTERS *counters) 2472{ 2473 /* Original read: X. 2474 * Atomic read on replacement: X + Y. 2475 * Currently in kernel: Z. 2476 * Want in kernel: Y + Z. 2477 * => Add in Y. 2478 * => Add in (replacement read - original read). 2479 */ 2480 subtract_counters(&newcounters->counters[idx], 2481 &repl->counters[mappos], 2482 counters); 2483 DEBUGP_C("ZEROED => mappos %u\n", mappos); 2484} 2485 2486static void counters_map_set(STRUCT_COUNTERS_INFO *newcounters, 2487 unsigned int idx, STRUCT_COUNTERS *counters) 2488{ 2489 /* Want to set counter (iptables-restore) */ 2490 2491 memcpy(&newcounters->counters[idx], counters, 2492 sizeof(STRUCT_COUNTERS)); 2493 2494 DEBUGP_C("SET\n"); 2495} 2496 2497 2498int 2499TC_COMMIT(struct xtc_handle *handle) 2500{ 2501 /* Replace, then map back the counters. */ 2502 STRUCT_REPLACE *repl; 2503 STRUCT_COUNTERS_INFO *newcounters; 2504 struct chain_head *c; 2505 int ret; 2506 size_t counterlen; 2507 int new_number; 2508 unsigned int new_size; 2509 2510 iptc_fn = TC_COMMIT; 2511 CHECK(*handle); 2512 2513 /* Don't commit if nothing changed. */ 2514 if (!handle->changed) 2515 goto finished; 2516 2517 new_number = iptcc_compile_table_prep(handle, &new_size); 2518 if (new_number < 0) { 2519 errno = ENOMEM; 2520 goto out_zero; 2521 } 2522 2523 repl = malloc(sizeof(*repl) + new_size); 2524 if (!repl) { 2525 errno = ENOMEM; 2526 goto out_zero; 2527 } 2528 memset(repl, 0, sizeof(*repl) + new_size); 2529 2530#if 0 2531 TC_DUMP_ENTRIES(*handle); 2532#endif 2533 2534 counterlen = sizeof(STRUCT_COUNTERS_INFO) 2535 + sizeof(STRUCT_COUNTERS) * new_number; 2536 2537 /* These are the old counters we will get from kernel */ 2538 repl->counters = malloc(sizeof(STRUCT_COUNTERS) 2539 * handle->info.num_entries); 2540 if (!repl->counters) { 2541 errno = ENOMEM; 2542 goto out_free_repl; 2543 } 2544 /* These are the counters we're going to put back, later. */ 2545 newcounters = malloc(counterlen); 2546 if (!newcounters) { 2547 errno = ENOMEM; 2548 goto out_free_repl_counters; 2549 } 2550 memset(newcounters, 0, counterlen); 2551 2552 strcpy(repl->name, handle->info.name); 2553 repl->num_entries = new_number; 2554 repl->size = new_size; 2555 2556 repl->num_counters = handle->info.num_entries; 2557 repl->valid_hooks = handle->info.valid_hooks; 2558 2559 DEBUGP("num_entries=%u, size=%u, num_counters=%u\n", 2560 repl->num_entries, repl->size, repl->num_counters); 2561 2562 ret = iptcc_compile_table(handle, repl); 2563 if (ret < 0) { 2564 errno = ret; 2565 goto out_free_newcounters; 2566 } 2567 2568 2569#ifdef IPTC_DEBUG2 2570 { 2571 int fd = open("/tmp/libiptc-so_set_replace.blob", 2572 O_CREAT|O_WRONLY); 2573 if (fd >= 0) { 2574 write(fd, repl, sizeof(*repl) + repl->size); 2575 close(fd); 2576 } 2577 } 2578#endif 2579 2580 ret = setsockopt(handle->sockfd, TC_IPPROTO, SO_SET_REPLACE, repl, 2581 sizeof(*repl) + repl->size); 2582 if (ret < 0) 2583 goto out_free_newcounters; 2584 2585 /* Put counters back. */ 2586 strcpy(newcounters->name, handle->info.name); 2587 newcounters->num_counters = new_number; 2588 2589 list_for_each_entry(c, &handle->chains, list) { 2590 struct rule_head *r; 2591 2592 /* Builtin chains have their own counters */ 2593 if (iptcc_is_builtin(c)) { 2594 DEBUGP("counter for chain-index %u: ", c->foot_index); 2595 switch(c->counter_map.maptype) { 2596 case COUNTER_MAP_NOMAP: 2597 counters_nomap(newcounters, c->foot_index); 2598 break; 2599 case COUNTER_MAP_NORMAL_MAP: 2600 counters_normal_map(newcounters, repl, 2601 c->foot_index, 2602 c->counter_map.mappos); 2603 break; 2604 case COUNTER_MAP_ZEROED: 2605 counters_map_zeroed(newcounters, repl, 2606 c->foot_index, 2607 c->counter_map.mappos, 2608 &c->counters); 2609 break; 2610 case COUNTER_MAP_SET: 2611 counters_map_set(newcounters, c->foot_index, 2612 &c->counters); 2613 break; 2614 } 2615 } 2616 2617 list_for_each_entry(r, &c->rules, list) { 2618 DEBUGP("counter for index %u: ", r->index); 2619 switch (r->counter_map.maptype) { 2620 case COUNTER_MAP_NOMAP: 2621 counters_nomap(newcounters, r->index); 2622 break; 2623 2624 case COUNTER_MAP_NORMAL_MAP: 2625 counters_normal_map(newcounters, repl, 2626 r->index, 2627 r->counter_map.mappos); 2628 break; 2629 2630 case COUNTER_MAP_ZEROED: 2631 counters_map_zeroed(newcounters, repl, 2632 r->index, 2633 r->counter_map.mappos, 2634 &r->entry->counters); 2635 break; 2636 2637 case COUNTER_MAP_SET: 2638 counters_map_set(newcounters, r->index, 2639 &r->entry->counters); 2640 break; 2641 } 2642 } 2643 } 2644 2645#ifdef IPTC_DEBUG2 2646 { 2647 int fd = open("/tmp/libiptc-so_set_add_counters.blob", 2648 O_CREAT|O_WRONLY); 2649 if (fd >= 0) { 2650 write(fd, newcounters, counterlen); 2651 close(fd); 2652 } 2653 } 2654#endif 2655 2656 ret = setsockopt(handle->sockfd, TC_IPPROTO, SO_SET_ADD_COUNTERS, 2657 newcounters, counterlen); 2658 if (ret < 0) 2659 goto out_free_newcounters; 2660 2661 free(repl->counters); 2662 free(repl); 2663 free(newcounters); 2664 2665finished: 2666 return 1; 2667 2668out_free_newcounters: 2669 free(newcounters); 2670out_free_repl_counters: 2671 free(repl->counters); 2672out_free_repl: 2673 free(repl); 2674out_zero: 2675 return 0; 2676} 2677 2678/* Translates errno numbers into more human-readable form than strerror. */ 2679const char * 2680TC_STRERROR(int err) 2681{ 2682 unsigned int i; 2683 struct table_struct { 2684 void *fn; 2685 int err; 2686 const char *message; 2687 } table [] = 2688 { { TC_INIT, EPERM, "Permission denied (you must be root)" }, 2689 { TC_INIT, EINVAL, "Module is wrong version" }, 2690 { TC_INIT, ENOENT, 2691 "Table does not exist (do you need to insmod?)" }, 2692 { TC_DELETE_CHAIN, ENOTEMPTY, "Chain is not empty" }, 2693 { TC_DELETE_CHAIN, EINVAL, "Can't delete built-in chain" }, 2694 { TC_DELETE_CHAIN, EMLINK, 2695 "Can't delete chain with references left" }, 2696 { TC_CREATE_CHAIN, EEXIST, "Chain already exists" }, 2697 { TC_INSERT_ENTRY, E2BIG, "Index of insertion too big" }, 2698 { TC_REPLACE_ENTRY, E2BIG, "Index of replacement too big" }, 2699 { TC_DELETE_NUM_ENTRY, E2BIG, "Index of deletion too big" }, 2700 { TC_READ_COUNTER, E2BIG, "Index of counter too big" }, 2701 { TC_ZERO_COUNTER, E2BIG, "Index of counter too big" }, 2702 { TC_INSERT_ENTRY, ELOOP, "Loop found in table" }, 2703 { TC_INSERT_ENTRY, EINVAL, "Target problem" }, 2704 /* ENOENT for DELETE probably means no matching rule */ 2705 { TC_DELETE_ENTRY, ENOENT, 2706 "Bad rule (does a matching rule exist in that chain?)" }, 2707 { TC_SET_POLICY, ENOENT, 2708 "Bad built-in chain name" }, 2709 { TC_SET_POLICY, EINVAL, 2710 "Bad policy name" }, 2711 2712 { NULL, 0, "Incompatible with this kernel" }, 2713 { NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" }, 2714 { NULL, ENOSYS, "Will be implemented real soon. I promise ;)" }, 2715 { NULL, ENOMEM, "Memory allocation problem" }, 2716 { NULL, ENOENT, "No chain/target/match by that name" }, 2717 }; 2718 2719 for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) { 2720 if ((!table[i].fn || table[i].fn == iptc_fn) 2721 && table[i].err == err) 2722 return table[i].message; 2723 } 2724 2725 return strerror(err); 2726} 2727