libiptc.c revision 7c4d668c9c2ee007c82063b7fc784cbbf46b2ec4
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 const unsigned char *data; 820 821 if (h->chain_iterator_cur) { 822 /* policy rule is last rule */ 823 struct rule_head *pr = (struct rule_head *) 824 h->chain_iterator_cur->rules.prev; 825 826 /* save verdict */ 827 data = GET_TARGET(pr->entry)->data; 828 h->chain_iterator_cur->verdict = *(const int *)data; 829 830 /* save counter and counter_map information */ 831 h->chain_iterator_cur->counter_map.maptype = 832 COUNTER_MAP_ZEROED; 833 h->chain_iterator_cur->counter_map.mappos = num-1; 834 memcpy(&h->chain_iterator_cur->counters, &pr->entry->counters, 835 sizeof(h->chain_iterator_cur->counters)); 836 837 /* foot_offset points to verdict rule */ 838 h->chain_iterator_cur->foot_index = num; 839 h->chain_iterator_cur->foot_offset = pr->offset; 840 841 /* delete rule from cache */ 842 iptcc_delete_rule(pr); 843 h->chain_iterator_cur->num_rules--; 844 845 return 1; 846 } 847 return 0; 848} 849 850/* alphabetically insert a chain into the list */ 851static void iptc_insert_chain(struct xtc_handle *h, struct chain_head *c) 852{ 853 struct chain_head *tmp; 854 struct list_head *list_start_pos; 855 unsigned int i=1; 856 857 /* Find a smart place to start the insert search */ 858 list_start_pos = iptcc_bsearch_chain_index(c->name, &i, h); 859 860 /* Handle the case, where chain.name is smaller than index[0] */ 861 if (i==0 && strcmp(c->name, h->chain_index[0]->name) <= 0) { 862 h->chain_index[0] = c; /* Update chain index head */ 863 list_start_pos = h->chains.next; 864 debug("Update chain_index[0] with %s\n", c->name); 865 } 866 867 /* Handel if bsearch bails out early */ 868 if (list_start_pos == &h->chains) { 869 list_start_pos = h->chains.next; 870 } 871 872 /* sort only user defined chains */ 873 if (!c->hooknum) { 874 list_for_each_entry(tmp, list_start_pos->prev, list) { 875 if (!tmp->hooknum && strcmp(c->name, tmp->name) <= 0) { 876 list_add(&c->list, tmp->list.prev); 877 return; 878 } 879 880 /* Stop if list head is reached */ 881 if (&tmp->list == &h->chains) { 882 debug("Insert, list head reached add to tail\n"); 883 break; 884 } 885 } 886 } 887 888 /* survived till end of list: add at tail */ 889 list_add_tail(&c->list, &h->chains); 890} 891 892/* Another ugly helper function split out of cache_add_entry to make it less 893 * spaghetti code */ 894static void __iptcc_p_add_chain(struct xtc_handle *h, struct chain_head *c, 895 unsigned int offset, unsigned int *num) 896{ 897 struct list_head *tail = h->chains.prev; 898 struct chain_head *ctail; 899 900 __iptcc_p_del_policy(h, *num); 901 902 c->head_offset = offset; 903 c->index = *num; 904 905 /* Chains from kernel are already sorted, as they are inserted 906 * sorted. But there exists an issue when shifting to 1.4.0 907 * from an older version, as old versions allow last created 908 * chain to be unsorted. 909 */ 910 if (iptcc_is_builtin(c)) /* Only user defined chains are sorted*/ 911 list_add_tail(&c->list, &h->chains); 912 else { 913 ctail = list_entry(tail, struct chain_head, list); 914 915 if (strcmp(c->name, ctail->name) > 0 || 916 iptcc_is_builtin(ctail)) 917 list_add_tail(&c->list, &h->chains);/* Already sorted*/ 918 else { 919 iptc_insert_chain(h, c);/* Was not sorted */ 920 921 /* Notice, if chains were not received sorted 922 * from kernel, then an offset bsearch is no 923 * longer valid. 924 */ 925 h->sorted_offsets = 0; 926 927 debug("NOTICE: chain:[%s] was NOT sorted(ctail:%s)\n", 928 c->name, ctail->name); 929 } 930 } 931 932 h->chain_iterator_cur = c; 933} 934 935/* main parser function: add an entry from the blob to the cache */ 936static int cache_add_entry(STRUCT_ENTRY *e, 937 struct xtc_handle *h, 938 STRUCT_ENTRY **prev, 939 unsigned int *num) 940{ 941 unsigned int builtin; 942 unsigned int offset = (char *)e - (char *)h->entries->entrytable; 943 944 DEBUGP("entering..."); 945 946 /* Last entry ("policy rule"). End it.*/ 947 if (iptcb_entry2offset(h,e) + e->next_offset == h->entries->size) { 948 /* This is the ERROR node at the end of the chain */ 949 DEBUGP_C("%u:%u: end of table:\n", *num, offset); 950 951 __iptcc_p_del_policy(h, *num); 952 953 h->chain_iterator_cur = NULL; 954 goto out_inc; 955 } 956 957 /* We know this is the start of a new chain if it's an ERROR 958 * target, or a hook entry point */ 959 960 if (strcmp(GET_TARGET(e)->u.user.name, ERROR_TARGET) == 0) { 961 struct chain_head *c = 962 iptcc_alloc_chain_head((const char *)GET_TARGET(e)->data, 0); 963 DEBUGP_C("%u:%u:new userdefined chain %s: %p\n", *num, offset, 964 (char *)c->name, c); 965 if (!c) { 966 errno = -ENOMEM; 967 return -1; 968 } 969 h->num_chains++; /* New user defined chain */ 970 971 __iptcc_p_add_chain(h, c, offset, num); 972 973 } else if ((builtin = iptcb_ent_is_hook_entry(e, h)) != 0) { 974 struct chain_head *c = 975 iptcc_alloc_chain_head((char *)hooknames[builtin-1], 976 builtin); 977 DEBUGP_C("%u:%u new builtin chain: %p (rules=%p)\n", 978 *num, offset, c, &c->rules); 979 if (!c) { 980 errno = -ENOMEM; 981 return -1; 982 } 983 984 c->hooknum = builtin; 985 986 __iptcc_p_add_chain(h, c, offset, num); 987 988 /* FIXME: this is ugly. */ 989 goto new_rule; 990 } else { 991 /* has to be normal rule */ 992 struct rule_head *r; 993new_rule: 994 995 if (!(r = iptcc_alloc_rule(h->chain_iterator_cur, 996 e->next_offset))) { 997 errno = ENOMEM; 998 return -1; 999 } 1000 DEBUGP_C("%u:%u normal rule: %p: ", *num, offset, r); 1001 1002 r->index = *num; 1003 r->offset = offset; 1004 memcpy(r->entry, e, e->next_offset); 1005 r->counter_map.maptype = COUNTER_MAP_NORMAL_MAP; 1006 r->counter_map.mappos = r->index; 1007 1008 /* handling of jumps, etc. */ 1009 if (!strcmp(GET_TARGET(e)->u.user.name, STANDARD_TARGET)) { 1010 STRUCT_STANDARD_TARGET *t; 1011 1012 t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e); 1013 if (t->target.u.target_size 1014 != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) { 1015 errno = EINVAL; 1016 return -1; 1017 } 1018 1019 if (t->verdict < 0) { 1020 DEBUGP_C("standard, verdict=%d\n", t->verdict); 1021 r->type = IPTCC_R_STANDARD; 1022 } else if (t->verdict == r->offset+e->next_offset) { 1023 DEBUGP_C("fallthrough\n"); 1024 r->type = IPTCC_R_FALLTHROUGH; 1025 } else { 1026 DEBUGP_C("jump, target=%u\n", t->verdict); 1027 r->type = IPTCC_R_JUMP; 1028 /* Jump target fixup has to be deferred 1029 * until second pass, since we migh not 1030 * yet have parsed the target */ 1031 } 1032 } else { 1033 DEBUGP_C("module, target=%s\n", GET_TARGET(e)->u.user.name); 1034 r->type = IPTCC_R_MODULE; 1035 } 1036 1037 list_add_tail(&r->list, &h->chain_iterator_cur->rules); 1038 h->chain_iterator_cur->num_rules++; 1039 } 1040out_inc: 1041 (*num)++; 1042 return 0; 1043} 1044 1045 1046/* parse an iptables blob into it's pieces */ 1047static int parse_table(struct xtc_handle *h) 1048{ 1049 STRUCT_ENTRY *prev; 1050 unsigned int num = 0; 1051 struct chain_head *c; 1052 1053 /* Assume that chains offsets are sorted, this verified during 1054 parsing of ruleset (in __iptcc_p_add_chain())*/ 1055 h->sorted_offsets = 1; 1056 1057 /* First pass: over ruleset blob */ 1058 ENTRY_ITERATE(h->entries->entrytable, h->entries->size, 1059 cache_add_entry, h, &prev, &num); 1060 1061 /* Build the chain index, used for chain list search speedup */ 1062 if ((iptcc_chain_index_alloc(h)) < 0) 1063 return -ENOMEM; 1064 iptcc_chain_index_build(h); 1065 1066 /* Second pass: fixup parsed data from first pass */ 1067 list_for_each_entry(c, &h->chains, list) { 1068 struct rule_head *r; 1069 list_for_each_entry(r, &c->rules, list) { 1070 struct chain_head *lc; 1071 STRUCT_STANDARD_TARGET *t; 1072 1073 if (r->type != IPTCC_R_JUMP) 1074 continue; 1075 1076 t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry); 1077 lc = iptcc_find_chain_by_offset(h, t->verdict); 1078 if (!lc) 1079 return -1; 1080 r->jump = lc; 1081 lc->references++; 1082 } 1083 } 1084 1085 return 1; 1086} 1087 1088 1089/********************************************************************** 1090 * RULESET COMPILATION (cache -> blob) 1091 **********************************************************************/ 1092 1093/* Convenience structures */ 1094struct iptcb_chain_start{ 1095 STRUCT_ENTRY e; 1096 struct ipt_error_target name; 1097}; 1098#define IPTCB_CHAIN_START_SIZE (sizeof(STRUCT_ENTRY) + \ 1099 ALIGN(sizeof(struct ipt_error_target))) 1100 1101struct iptcb_chain_foot { 1102 STRUCT_ENTRY e; 1103 STRUCT_STANDARD_TARGET target; 1104}; 1105#define IPTCB_CHAIN_FOOT_SIZE (sizeof(STRUCT_ENTRY) + \ 1106 ALIGN(sizeof(STRUCT_STANDARD_TARGET))) 1107 1108struct iptcb_chain_error { 1109 STRUCT_ENTRY entry; 1110 struct ipt_error_target target; 1111}; 1112#define IPTCB_CHAIN_ERROR_SIZE (sizeof(STRUCT_ENTRY) + \ 1113 ALIGN(sizeof(struct ipt_error_target))) 1114 1115 1116 1117/* compile rule from cache into blob */ 1118static inline int iptcc_compile_rule (struct xtc_handle *h, STRUCT_REPLACE *repl, struct rule_head *r) 1119{ 1120 /* handle jumps */ 1121 if (r->type == IPTCC_R_JUMP) { 1122 STRUCT_STANDARD_TARGET *t; 1123 t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry); 1124 /* memset for memcmp convenience on delete/replace */ 1125 memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN); 1126 strcpy(t->target.u.user.name, STANDARD_TARGET); 1127 /* Jumps can only happen to builtin chains, so we 1128 * can safely assume that they always have a header */ 1129 t->verdict = r->jump->head_offset + IPTCB_CHAIN_START_SIZE; 1130 } else if (r->type == IPTCC_R_FALLTHROUGH) { 1131 STRUCT_STANDARD_TARGET *t; 1132 t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry); 1133 t->verdict = r->offset + r->size; 1134 } 1135 1136 /* copy entry from cache to blob */ 1137 memcpy((char *)repl->entries+r->offset, r->entry, r->size); 1138 1139 return 1; 1140} 1141 1142/* compile chain from cache into blob */ 1143static int iptcc_compile_chain(struct xtc_handle *h, STRUCT_REPLACE *repl, struct chain_head *c) 1144{ 1145 int ret; 1146 struct rule_head *r; 1147 struct iptcb_chain_start *head; 1148 struct iptcb_chain_foot *foot; 1149 1150 /* only user-defined chains have heaer */ 1151 if (!iptcc_is_builtin(c)) { 1152 /* put chain header in place */ 1153 head = (void *)repl->entries + c->head_offset; 1154 head->e.target_offset = sizeof(STRUCT_ENTRY); 1155 head->e.next_offset = IPTCB_CHAIN_START_SIZE; 1156 strcpy(head->name.t.u.user.name, ERROR_TARGET); 1157 head->name.t.u.target_size = 1158 ALIGN(sizeof(struct ipt_error_target)); 1159 strcpy(head->name.error, c->name); 1160 } else { 1161 repl->hook_entry[c->hooknum-1] = c->head_offset; 1162 repl->underflow[c->hooknum-1] = c->foot_offset; 1163 } 1164 1165 /* iterate over rules */ 1166 list_for_each_entry(r, &c->rules, list) { 1167 ret = iptcc_compile_rule(h, repl, r); 1168 if (ret < 0) 1169 return ret; 1170 } 1171 1172 /* put chain footer in place */ 1173 foot = (void *)repl->entries + c->foot_offset; 1174 foot->e.target_offset = sizeof(STRUCT_ENTRY); 1175 foot->e.next_offset = IPTCB_CHAIN_FOOT_SIZE; 1176 strcpy(foot->target.target.u.user.name, STANDARD_TARGET); 1177 foot->target.target.u.target_size = 1178 ALIGN(sizeof(STRUCT_STANDARD_TARGET)); 1179 /* builtin targets have verdict, others return */ 1180 if (iptcc_is_builtin(c)) 1181 foot->target.verdict = c->verdict; 1182 else 1183 foot->target.verdict = RETURN; 1184 /* set policy-counters */ 1185 memcpy(&foot->e.counters, &c->counters, sizeof(STRUCT_COUNTERS)); 1186 1187 return 0; 1188} 1189 1190/* calculate offset and number for every rule in the cache */ 1191static int iptcc_compile_chain_offsets(struct xtc_handle *h, struct chain_head *c, 1192 unsigned int *offset, unsigned int *num) 1193{ 1194 struct rule_head *r; 1195 1196 c->head_offset = *offset; 1197 DEBUGP("%s: chain_head %u, offset=%u\n", c->name, *num, *offset); 1198 1199 if (!iptcc_is_builtin(c)) { 1200 /* Chain has header */ 1201 *offset += sizeof(STRUCT_ENTRY) 1202 + ALIGN(sizeof(struct ipt_error_target)); 1203 (*num)++; 1204 } 1205 1206 list_for_each_entry(r, &c->rules, list) { 1207 DEBUGP("rule %u, offset=%u, index=%u\n", *num, *offset, *num); 1208 r->offset = *offset; 1209 r->index = *num; 1210 *offset += r->size; 1211 (*num)++; 1212 } 1213 1214 DEBUGP("%s; chain_foot %u, offset=%u, index=%u\n", c->name, *num, 1215 *offset, *num); 1216 c->foot_offset = *offset; 1217 c->foot_index = *num; 1218 *offset += sizeof(STRUCT_ENTRY) 1219 + ALIGN(sizeof(STRUCT_STANDARD_TARGET)); 1220 (*num)++; 1221 1222 return 1; 1223} 1224 1225/* put the pieces back together again */ 1226static int iptcc_compile_table_prep(struct xtc_handle *h, unsigned int *size) 1227{ 1228 struct chain_head *c; 1229 unsigned int offset = 0, num = 0; 1230 int ret = 0; 1231 1232 /* First pass: calculate offset for every rule */ 1233 list_for_each_entry(c, &h->chains, list) { 1234 ret = iptcc_compile_chain_offsets(h, c, &offset, &num); 1235 if (ret < 0) 1236 return ret; 1237 } 1238 1239 /* Append one error rule at end of chain */ 1240 num++; 1241 offset += sizeof(STRUCT_ENTRY) 1242 + ALIGN(sizeof(struct ipt_error_target)); 1243 1244 /* ruleset size is now in offset */ 1245 *size = offset; 1246 return num; 1247} 1248 1249static int iptcc_compile_table(struct xtc_handle *h, STRUCT_REPLACE *repl) 1250{ 1251 struct chain_head *c; 1252 struct iptcb_chain_error *error; 1253 1254 /* Second pass: copy from cache to offsets, fill in jumps */ 1255 list_for_each_entry(c, &h->chains, list) { 1256 int ret = iptcc_compile_chain(h, repl, c); 1257 if (ret < 0) 1258 return ret; 1259 } 1260 1261 /* Append error rule at end of chain */ 1262 error = (void *)repl->entries + repl->size - IPTCB_CHAIN_ERROR_SIZE; 1263 error->entry.target_offset = sizeof(STRUCT_ENTRY); 1264 error->entry.next_offset = IPTCB_CHAIN_ERROR_SIZE; 1265 error->target.t.u.user.target_size = 1266 ALIGN(sizeof(struct ipt_error_target)); 1267 strcpy((char *)&error->target.t.u.user.name, ERROR_TARGET); 1268 strcpy((char *)&error->target.error, "ERROR"); 1269 1270 return 1; 1271} 1272 1273/********************************************************************** 1274 * EXTERNAL API (operates on cache only) 1275 **********************************************************************/ 1276 1277/* Allocate handle of given size */ 1278static struct xtc_handle * 1279alloc_handle(const char *tablename, unsigned int size, unsigned int num_rules) 1280{ 1281 size_t len; 1282 struct xtc_handle *h; 1283 1284 len = sizeof(STRUCT_TC_HANDLE) + size; 1285 1286 h = malloc(sizeof(STRUCT_TC_HANDLE)); 1287 if (!h) { 1288 errno = ENOMEM; 1289 return NULL; 1290 } 1291 memset(h, 0, sizeof(*h)); 1292 INIT_LIST_HEAD(&h->chains); 1293 strcpy(h->info.name, tablename); 1294 1295 h->entries = malloc(sizeof(STRUCT_GET_ENTRIES) + size); 1296 if (!h->entries) 1297 goto out_free_handle; 1298 1299 strcpy(h->entries->name, tablename); 1300 h->entries->size = size; 1301 1302 return h; 1303 1304out_free_handle: 1305 free(h); 1306 1307 return NULL; 1308} 1309 1310 1311struct xtc_handle * 1312TC_INIT(const char *tablename) 1313{ 1314 struct xtc_handle *h; 1315 STRUCT_GETINFO info; 1316 unsigned int tmp; 1317 socklen_t s; 1318 int sockfd; 1319 1320 iptc_fn = TC_INIT; 1321 1322 if (strlen(tablename) >= TABLE_MAXNAMELEN) { 1323 errno = EINVAL; 1324 return NULL; 1325 } 1326 1327 sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW); 1328 if (sockfd < 0) 1329 return NULL; 1330 1331retry: 1332 s = sizeof(info); 1333 1334 strcpy(info.name, tablename); 1335 if (getsockopt(sockfd, TC_IPPROTO, SO_GET_INFO, &info, &s) < 0) { 1336 close(sockfd); 1337 return NULL; 1338 } 1339 1340 DEBUGP("valid_hooks=0x%08x, num_entries=%u, size=%u\n", 1341 info.valid_hooks, info.num_entries, info.size); 1342 1343 if ((h = alloc_handle(info.name, info.size, info.num_entries)) 1344 == NULL) { 1345 close(sockfd); 1346 return NULL; 1347 } 1348 1349 /* Initialize current state */ 1350 h->sockfd = sockfd; 1351 h->info = info; 1352 1353 h->entries->size = h->info.size; 1354 1355 tmp = sizeof(STRUCT_GET_ENTRIES) + h->info.size; 1356 1357 if (getsockopt(h->sockfd, TC_IPPROTO, SO_GET_ENTRIES, h->entries, 1358 &tmp) < 0) 1359 goto error; 1360 1361#ifdef IPTC_DEBUG2 1362 { 1363 int fd = open("/tmp/libiptc-so_get_entries.blob", 1364 O_CREAT|O_WRONLY); 1365 if (fd >= 0) { 1366 write(fd, h->entries, tmp); 1367 close(fd); 1368 } 1369 } 1370#endif 1371 1372 if (parse_table(h) < 0) 1373 goto error; 1374 1375 CHECK(h); 1376 return h; 1377error: 1378 TC_FREE(h); 1379 /* A different process changed the ruleset size, retry */ 1380 if (errno == EAGAIN) 1381 goto retry; 1382 return NULL; 1383} 1384 1385void 1386TC_FREE(struct xtc_handle *h) 1387{ 1388 struct chain_head *c, *tmp; 1389 1390 iptc_fn = TC_FREE; 1391 close(h->sockfd); 1392 1393 list_for_each_entry_safe(c, tmp, &h->chains, list) { 1394 struct rule_head *r, *rtmp; 1395 1396 list_for_each_entry_safe(r, rtmp, &c->rules, list) { 1397 free(r); 1398 } 1399 1400 free(c); 1401 } 1402 1403 iptcc_chain_index_free(h); 1404 1405 free(h->entries); 1406 free(h); 1407} 1408 1409static inline int 1410print_match(const STRUCT_ENTRY_MATCH *m) 1411{ 1412 printf("Match name: `%s'\n", m->u.user.name); 1413 return 0; 1414} 1415 1416static int dump_entry(STRUCT_ENTRY *e, struct xtc_handle *const handle); 1417 1418void 1419TC_DUMP_ENTRIES(struct xtc_handle *const handle) 1420{ 1421 iptc_fn = TC_DUMP_ENTRIES; 1422 CHECK(handle); 1423 1424 printf("libiptc v%s. %u bytes.\n", 1425 XTABLES_VERSION, handle->entries->size); 1426 printf("Table `%s'\n", handle->info.name); 1427 printf("Hooks: pre/in/fwd/out/post = %x/%x/%x/%x/%x\n", 1428 handle->info.hook_entry[HOOK_PRE_ROUTING], 1429 handle->info.hook_entry[HOOK_LOCAL_IN], 1430 handle->info.hook_entry[HOOK_FORWARD], 1431 handle->info.hook_entry[HOOK_LOCAL_OUT], 1432 handle->info.hook_entry[HOOK_POST_ROUTING]); 1433 printf("Underflows: pre/in/fwd/out/post = %x/%x/%x/%x/%x\n", 1434 handle->info.underflow[HOOK_PRE_ROUTING], 1435 handle->info.underflow[HOOK_LOCAL_IN], 1436 handle->info.underflow[HOOK_FORWARD], 1437 handle->info.underflow[HOOK_LOCAL_OUT], 1438 handle->info.underflow[HOOK_POST_ROUTING]); 1439 1440 ENTRY_ITERATE(handle->entries->entrytable, handle->entries->size, 1441 dump_entry, handle); 1442} 1443 1444/* Does this chain exist? */ 1445int TC_IS_CHAIN(const char *chain, struct xtc_handle *const handle) 1446{ 1447 iptc_fn = TC_IS_CHAIN; 1448 return iptcc_find_label(chain, handle) != NULL; 1449} 1450 1451static void iptcc_chain_iterator_advance(struct xtc_handle *handle) 1452{ 1453 struct chain_head *c = handle->chain_iterator_cur; 1454 1455 if (c->list.next == &handle->chains) 1456 handle->chain_iterator_cur = NULL; 1457 else 1458 handle->chain_iterator_cur = 1459 list_entry(c->list.next, struct chain_head, list); 1460} 1461 1462/* Iterator functions to run through the chains. */ 1463const char * 1464TC_FIRST_CHAIN(struct xtc_handle *handle) 1465{ 1466 struct chain_head *c = list_entry(handle->chains.next, 1467 struct chain_head, list); 1468 1469 iptc_fn = TC_FIRST_CHAIN; 1470 1471 1472 if (list_empty(&handle->chains)) { 1473 DEBUGP(": no chains\n"); 1474 return NULL; 1475 } 1476 1477 handle->chain_iterator_cur = c; 1478 iptcc_chain_iterator_advance(handle); 1479 1480 DEBUGP(": returning `%s'\n", c->name); 1481 return c->name; 1482} 1483 1484/* Iterator functions to run through the chains. Returns NULL at end. */ 1485const char * 1486TC_NEXT_CHAIN(struct xtc_handle *handle) 1487{ 1488 struct chain_head *c = handle->chain_iterator_cur; 1489 1490 iptc_fn = TC_NEXT_CHAIN; 1491 1492 if (!c) { 1493 DEBUGP(": no more chains\n"); 1494 return NULL; 1495 } 1496 1497 iptcc_chain_iterator_advance(handle); 1498 1499 DEBUGP(": returning `%s'\n", c->name); 1500 return c->name; 1501} 1502 1503/* Get first rule in the given chain: NULL for empty chain. */ 1504const STRUCT_ENTRY * 1505TC_FIRST_RULE(const char *chain, struct xtc_handle *handle) 1506{ 1507 struct chain_head *c; 1508 struct rule_head *r; 1509 1510 iptc_fn = TC_FIRST_RULE; 1511 1512 DEBUGP("first rule(%s): ", chain); 1513 1514 c = iptcc_find_label(chain, handle); 1515 if (!c) { 1516 errno = ENOENT; 1517 return NULL; 1518 } 1519 1520 /* Empty chain: single return/policy rule */ 1521 if (list_empty(&c->rules)) { 1522 DEBUGP_C("no rules, returning NULL\n"); 1523 return NULL; 1524 } 1525 1526 r = list_entry(c->rules.next, struct rule_head, list); 1527 handle->rule_iterator_cur = r; 1528 DEBUGP_C("%p\n", r); 1529 1530 return r->entry; 1531} 1532 1533/* Returns NULL when rules run out. */ 1534const STRUCT_ENTRY * 1535TC_NEXT_RULE(const STRUCT_ENTRY *prev, struct xtc_handle *handle) 1536{ 1537 struct rule_head *r; 1538 1539 iptc_fn = TC_NEXT_RULE; 1540 DEBUGP("rule_iterator_cur=%p...", handle->rule_iterator_cur); 1541 1542 if (handle->rule_iterator_cur == NULL) { 1543 DEBUGP_C("returning NULL\n"); 1544 return NULL; 1545 } 1546 1547 r = list_entry(handle->rule_iterator_cur->list.next, 1548 struct rule_head, list); 1549 1550 iptc_fn = TC_NEXT_RULE; 1551 1552 DEBUGP_C("next=%p, head=%p...", &r->list, 1553 &handle->rule_iterator_cur->chain->rules); 1554 1555 if (&r->list == &handle->rule_iterator_cur->chain->rules) { 1556 handle->rule_iterator_cur = NULL; 1557 DEBUGP_C("finished, returning NULL\n"); 1558 return NULL; 1559 } 1560 1561 handle->rule_iterator_cur = r; 1562 1563 /* NOTE: prev is without any influence ! */ 1564 DEBUGP_C("returning rule %p\n", r); 1565 return r->entry; 1566} 1567 1568/* Returns a pointer to the target name of this position. */ 1569static const char *standard_target_map(int verdict) 1570{ 1571 switch (verdict) { 1572 case RETURN: 1573 return LABEL_RETURN; 1574 break; 1575 case -NF_ACCEPT-1: 1576 return LABEL_ACCEPT; 1577 break; 1578 case -NF_DROP-1: 1579 return LABEL_DROP; 1580 break; 1581 case -NF_QUEUE-1: 1582 return LABEL_QUEUE; 1583 break; 1584 default: 1585 fprintf(stderr, "ERROR: %d not a valid target)\n", 1586 verdict); 1587 abort(); 1588 break; 1589 } 1590 /* not reached */ 1591 return NULL; 1592} 1593 1594/* Returns a pointer to the target name of this position. */ 1595const char *TC_GET_TARGET(const STRUCT_ENTRY *ce, 1596 struct xtc_handle *handle) 1597{ 1598 STRUCT_ENTRY *e = (STRUCT_ENTRY *)ce; 1599 struct rule_head *r = container_of(e, struct rule_head, entry[0]); 1600 const unsigned char *data; 1601 1602 iptc_fn = TC_GET_TARGET; 1603 1604 switch(r->type) { 1605 int spos; 1606 case IPTCC_R_FALLTHROUGH: 1607 return ""; 1608 break; 1609 case IPTCC_R_JUMP: 1610 DEBUGP("r=%p, jump=%p, name=`%s'\n", r, r->jump, r->jump->name); 1611 return r->jump->name; 1612 break; 1613 case IPTCC_R_STANDARD: 1614 data = GET_TARGET(e)->data; 1615 spos = *(const int *)data; 1616 DEBUGP("r=%p, spos=%d'\n", r, spos); 1617 return standard_target_map(spos); 1618 break; 1619 case IPTCC_R_MODULE: 1620 return GET_TARGET(e)->u.user.name; 1621 break; 1622 } 1623 return NULL; 1624} 1625/* Is this a built-in chain? Actually returns hook + 1. */ 1626int 1627TC_BUILTIN(const char *chain, struct xtc_handle *const handle) 1628{ 1629 struct chain_head *c; 1630 1631 iptc_fn = TC_BUILTIN; 1632 1633 c = iptcc_find_label(chain, handle); 1634 if (!c) { 1635 errno = ENOENT; 1636 return 0; 1637 } 1638 1639 return iptcc_is_builtin(c); 1640} 1641 1642/* Get the policy of a given built-in chain */ 1643const char * 1644TC_GET_POLICY(const char *chain, 1645 STRUCT_COUNTERS *counters, 1646 struct xtc_handle *handle) 1647{ 1648 struct chain_head *c; 1649 1650 iptc_fn = TC_GET_POLICY; 1651 1652 DEBUGP("called for chain %s\n", chain); 1653 1654 c = iptcc_find_label(chain, handle); 1655 if (!c) { 1656 errno = ENOENT; 1657 return NULL; 1658 } 1659 1660 if (!iptcc_is_builtin(c)) 1661 return NULL; 1662 1663 *counters = c->counters; 1664 1665 return standard_target_map(c->verdict); 1666} 1667 1668static int 1669iptcc_standard_map(struct rule_head *r, int verdict) 1670{ 1671 STRUCT_ENTRY *e = r->entry; 1672 STRUCT_STANDARD_TARGET *t; 1673 1674 t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e); 1675 1676 if (t->target.u.target_size 1677 != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) { 1678 errno = EINVAL; 1679 return 0; 1680 } 1681 /* memset for memcmp convenience on delete/replace */ 1682 memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN); 1683 strcpy(t->target.u.user.name, STANDARD_TARGET); 1684 t->verdict = verdict; 1685 1686 r->type = IPTCC_R_STANDARD; 1687 1688 return 1; 1689} 1690 1691static int 1692iptcc_map_target(struct xtc_handle *const handle, 1693 struct rule_head *r) 1694{ 1695 STRUCT_ENTRY *e = r->entry; 1696 STRUCT_ENTRY_TARGET *t = GET_TARGET(e); 1697 1698 /* Maybe it's empty (=> fall through) */ 1699 if (strcmp(t->u.user.name, "") == 0) { 1700 r->type = IPTCC_R_FALLTHROUGH; 1701 return 1; 1702 } 1703 /* Maybe it's a standard target name... */ 1704 else if (strcmp(t->u.user.name, LABEL_ACCEPT) == 0) 1705 return iptcc_standard_map(r, -NF_ACCEPT - 1); 1706 else if (strcmp(t->u.user.name, LABEL_DROP) == 0) 1707 return iptcc_standard_map(r, -NF_DROP - 1); 1708 else if (strcmp(t->u.user.name, LABEL_QUEUE) == 0) 1709 return iptcc_standard_map(r, -NF_QUEUE - 1); 1710 else if (strcmp(t->u.user.name, LABEL_RETURN) == 0) 1711 return iptcc_standard_map(r, RETURN); 1712 else if (TC_BUILTIN(t->u.user.name, handle)) { 1713 /* Can't jump to builtins. */ 1714 errno = EINVAL; 1715 return 0; 1716 } else { 1717 /* Maybe it's an existing chain name. */ 1718 struct chain_head *c; 1719 DEBUGP("trying to find chain `%s': ", t->u.user.name); 1720 1721 c = iptcc_find_label(t->u.user.name, handle); 1722 if (c) { 1723 DEBUGP_C("found!\n"); 1724 r->type = IPTCC_R_JUMP; 1725 r->jump = c; 1726 c->references++; 1727 return 1; 1728 } 1729 DEBUGP_C("not found :(\n"); 1730 } 1731 1732 /* Must be a module? If not, kernel will reject... */ 1733 /* memset to all 0 for your memcmp convenience: don't clear version */ 1734 memset(t->u.user.name + strlen(t->u.user.name), 1735 0, 1736 FUNCTION_MAXNAMELEN - 1 - strlen(t->u.user.name)); 1737 r->type = IPTCC_R_MODULE; 1738 set_changed(handle); 1739 return 1; 1740} 1741 1742/* Insert the entry `fw' in chain `chain' into position `rulenum'. */ 1743int 1744TC_INSERT_ENTRY(const IPT_CHAINLABEL chain, 1745 const STRUCT_ENTRY *e, 1746 unsigned int rulenum, 1747 struct xtc_handle *handle) 1748{ 1749 struct chain_head *c; 1750 struct rule_head *r; 1751 struct list_head *prev; 1752 1753 iptc_fn = TC_INSERT_ENTRY; 1754 1755 if (!(c = iptcc_find_label(chain, handle))) { 1756 errno = ENOENT; 1757 return 0; 1758 } 1759 1760 /* first rulenum index = 0 1761 first c->num_rules index = 1 */ 1762 if (rulenum > c->num_rules) { 1763 errno = E2BIG; 1764 return 0; 1765 } 1766 1767 /* If we are inserting at the end just take advantage of the 1768 double linked list, insert will happen before the entry 1769 prev points to. */ 1770 if (rulenum == c->num_rules) { 1771 prev = &c->rules; 1772 } else if (rulenum + 1 <= c->num_rules/2) { 1773 r = iptcc_get_rule_num(c, rulenum + 1); 1774 prev = &r->list; 1775 } else { 1776 r = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum); 1777 prev = &r->list; 1778 } 1779 1780 if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1781 errno = ENOMEM; 1782 return 0; 1783 } 1784 1785 memcpy(r->entry, e, e->next_offset); 1786 r->counter_map.maptype = COUNTER_MAP_SET; 1787 1788 if (!iptcc_map_target(handle, r)) { 1789 free(r); 1790 return 0; 1791 } 1792 1793 list_add_tail(&r->list, prev); 1794 c->num_rules++; 1795 1796 set_changed(handle); 1797 1798 return 1; 1799} 1800 1801/* Atomically replace rule `rulenum' in `chain' with `fw'. */ 1802int 1803TC_REPLACE_ENTRY(const IPT_CHAINLABEL chain, 1804 const STRUCT_ENTRY *e, 1805 unsigned int rulenum, 1806 struct xtc_handle *handle) 1807{ 1808 struct chain_head *c; 1809 struct rule_head *r, *old; 1810 1811 iptc_fn = TC_REPLACE_ENTRY; 1812 1813 if (!(c = iptcc_find_label(chain, handle))) { 1814 errno = ENOENT; 1815 return 0; 1816 } 1817 1818 if (rulenum >= c->num_rules) { 1819 errno = E2BIG; 1820 return 0; 1821 } 1822 1823 /* Take advantage of the double linked list if possible. */ 1824 if (rulenum + 1 <= c->num_rules/2) { 1825 old = iptcc_get_rule_num(c, rulenum + 1); 1826 } else { 1827 old = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum); 1828 } 1829 1830 if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1831 errno = ENOMEM; 1832 return 0; 1833 } 1834 1835 memcpy(r->entry, e, e->next_offset); 1836 r->counter_map.maptype = COUNTER_MAP_SET; 1837 1838 if (!iptcc_map_target(handle, r)) { 1839 free(r); 1840 return 0; 1841 } 1842 1843 list_add(&r->list, &old->list); 1844 iptcc_delete_rule(old); 1845 1846 set_changed(handle); 1847 1848 return 1; 1849} 1850 1851/* Append entry `fw' to chain `chain'. Equivalent to insert with 1852 rulenum = length of chain. */ 1853int 1854TC_APPEND_ENTRY(const IPT_CHAINLABEL chain, 1855 const STRUCT_ENTRY *e, 1856 struct xtc_handle *handle) 1857{ 1858 struct chain_head *c; 1859 struct rule_head *r; 1860 1861 iptc_fn = TC_APPEND_ENTRY; 1862 if (!(c = iptcc_find_label(chain, handle))) { 1863 DEBUGP("unable to find chain `%s'\n", chain); 1864 errno = ENOENT; 1865 return 0; 1866 } 1867 1868 if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1869 DEBUGP("unable to allocate rule for chain `%s'\n", chain); 1870 errno = ENOMEM; 1871 return 0; 1872 } 1873 1874 memcpy(r->entry, e, e->next_offset); 1875 r->counter_map.maptype = COUNTER_MAP_SET; 1876 1877 if (!iptcc_map_target(handle, r)) { 1878 DEBUGP("unable to map target of rule for chain `%s'\n", chain); 1879 free(r); 1880 return 0; 1881 } 1882 1883 list_add_tail(&r->list, &c->rules); 1884 c->num_rules++; 1885 1886 set_changed(handle); 1887 1888 return 1; 1889} 1890 1891static inline int 1892match_different(const STRUCT_ENTRY_MATCH *a, 1893 const unsigned char *a_elems, 1894 const unsigned char *b_elems, 1895 unsigned char **maskptr) 1896{ 1897 const STRUCT_ENTRY_MATCH *b; 1898 unsigned int i; 1899 1900 /* Offset of b is the same as a. */ 1901 b = (void *)b_elems + ((unsigned char *)a - a_elems); 1902 1903 if (a->u.match_size != b->u.match_size) 1904 return 1; 1905 1906 if (strcmp(a->u.user.name, b->u.user.name) != 0) 1907 return 1; 1908 1909 *maskptr += ALIGN(sizeof(*a)); 1910 1911 for (i = 0; i < a->u.match_size - ALIGN(sizeof(*a)); i++) 1912 if (((a->data[i] ^ b->data[i]) & (*maskptr)[i]) != 0) 1913 return 1; 1914 *maskptr += i; 1915 return 0; 1916} 1917 1918static inline int 1919target_same(struct rule_head *a, struct rule_head *b,const unsigned char *mask) 1920{ 1921 unsigned int i; 1922 STRUCT_ENTRY_TARGET *ta, *tb; 1923 1924 if (a->type != b->type) 1925 return 0; 1926 1927 ta = GET_TARGET(a->entry); 1928 tb = GET_TARGET(b->entry); 1929 1930 switch (a->type) { 1931 case IPTCC_R_FALLTHROUGH: 1932 return 1; 1933 case IPTCC_R_JUMP: 1934 return a->jump == b->jump; 1935 case IPTCC_R_STANDARD: 1936 return ((STRUCT_STANDARD_TARGET *)ta)->verdict 1937 == ((STRUCT_STANDARD_TARGET *)tb)->verdict; 1938 case IPTCC_R_MODULE: 1939 if (ta->u.target_size != tb->u.target_size) 1940 return 0; 1941 if (strcmp(ta->u.user.name, tb->u.user.name) != 0) 1942 return 0; 1943 1944 for (i = 0; i < ta->u.target_size - sizeof(*ta); i++) 1945 if (((ta->data[i] ^ tb->data[i]) & mask[i]) != 0) 1946 return 0; 1947 return 1; 1948 default: 1949 fprintf(stderr, "ERROR: bad type %i\n", a->type); 1950 abort(); 1951 } 1952} 1953 1954static unsigned char * 1955is_same(const STRUCT_ENTRY *a, 1956 const STRUCT_ENTRY *b, 1957 unsigned char *matchmask); 1958 1959/* Delete the first rule in `chain' which matches `fw'. */ 1960int 1961TC_DELETE_ENTRY(const IPT_CHAINLABEL chain, 1962 const STRUCT_ENTRY *origfw, 1963 unsigned char *matchmask, 1964 struct xtc_handle *handle) 1965{ 1966 struct chain_head *c; 1967 struct rule_head *r, *i; 1968 1969 iptc_fn = TC_DELETE_ENTRY; 1970 if (!(c = iptcc_find_label(chain, handle))) { 1971 errno = ENOENT; 1972 return 0; 1973 } 1974 1975 /* Create a rule_head from origfw. */ 1976 r = iptcc_alloc_rule(c, origfw->next_offset); 1977 if (!r) { 1978 errno = ENOMEM; 1979 return 0; 1980 } 1981 1982 memcpy(r->entry, origfw, origfw->next_offset); 1983 r->counter_map.maptype = COUNTER_MAP_NOMAP; 1984 if (!iptcc_map_target(handle, r)) { 1985 DEBUGP("unable to map target of rule for chain `%s'\n", chain); 1986 free(r); 1987 return 0; 1988 } else { 1989 /* iptcc_map_target increment target chain references 1990 * since this is a fake rule only used for matching 1991 * the chain references count is decremented again. 1992 */ 1993 if (r->type == IPTCC_R_JUMP 1994 && r->jump) 1995 r->jump->references--; 1996 } 1997 1998 list_for_each_entry(i, &c->rules, list) { 1999 unsigned char *mask; 2000 2001 mask = is_same(r->entry, i->entry, matchmask); 2002 if (!mask) 2003 continue; 2004 2005 if (!target_same(r, i, mask)) 2006 continue; 2007 2008 /* If we are about to delete the rule that is the 2009 * current iterator, move rule iterator back. next 2010 * pointer will then point to real next node */ 2011 if (i == handle->rule_iterator_cur) { 2012 handle->rule_iterator_cur = 2013 list_entry(handle->rule_iterator_cur->list.prev, 2014 struct rule_head, list); 2015 } 2016 2017 c->num_rules--; 2018 iptcc_delete_rule(i); 2019 2020 set_changed(handle); 2021 free(r); 2022 return 1; 2023 } 2024 2025 free(r); 2026 errno = ENOENT; 2027 return 0; 2028} 2029 2030 2031/* Delete the rule in position `rulenum' in `chain'. */ 2032int 2033TC_DELETE_NUM_ENTRY(const IPT_CHAINLABEL chain, 2034 unsigned int rulenum, 2035 struct xtc_handle *handle) 2036{ 2037 struct chain_head *c; 2038 struct rule_head *r; 2039 2040 iptc_fn = TC_DELETE_NUM_ENTRY; 2041 2042 if (!(c = iptcc_find_label(chain, handle))) { 2043 errno = ENOENT; 2044 return 0; 2045 } 2046 2047 if (rulenum >= c->num_rules) { 2048 errno = E2BIG; 2049 return 0; 2050 } 2051 2052 /* Take advantage of the double linked list if possible. */ 2053 if (rulenum + 1 <= c->num_rules/2) { 2054 r = iptcc_get_rule_num(c, rulenum + 1); 2055 } else { 2056 r = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum); 2057 } 2058 2059 /* If we are about to delete the rule that is the current 2060 * iterator, move rule iterator back. next pointer will then 2061 * point to real next node */ 2062 if (r == handle->rule_iterator_cur) { 2063 handle->rule_iterator_cur = 2064 list_entry(handle->rule_iterator_cur->list.prev, 2065 struct rule_head, list); 2066 } 2067 2068 c->num_rules--; 2069 iptcc_delete_rule(r); 2070 2071 set_changed(handle); 2072 2073 return 1; 2074} 2075 2076/* Flushes the entries in the given chain (ie. empties chain). */ 2077int 2078TC_FLUSH_ENTRIES(const IPT_CHAINLABEL chain, struct xtc_handle *handle) 2079{ 2080 struct chain_head *c; 2081 struct rule_head *r, *tmp; 2082 2083 iptc_fn = TC_FLUSH_ENTRIES; 2084 if (!(c = iptcc_find_label(chain, handle))) { 2085 errno = ENOENT; 2086 return 0; 2087 } 2088 2089 list_for_each_entry_safe(r, tmp, &c->rules, list) { 2090 iptcc_delete_rule(r); 2091 } 2092 2093 c->num_rules = 0; 2094 2095 set_changed(handle); 2096 2097 return 1; 2098} 2099 2100/* Zeroes the counters in a chain. */ 2101int 2102TC_ZERO_ENTRIES(const IPT_CHAINLABEL chain, struct xtc_handle *handle) 2103{ 2104 struct chain_head *c; 2105 struct rule_head *r; 2106 2107 iptc_fn = TC_ZERO_ENTRIES; 2108 if (!(c = iptcc_find_label(chain, handle))) { 2109 errno = ENOENT; 2110 return 0; 2111 } 2112 2113 if (c->counter_map.maptype == COUNTER_MAP_NORMAL_MAP) 2114 c->counter_map.maptype = COUNTER_MAP_ZEROED; 2115 2116 list_for_each_entry(r, &c->rules, list) { 2117 if (r->counter_map.maptype == COUNTER_MAP_NORMAL_MAP) 2118 r->counter_map.maptype = COUNTER_MAP_ZEROED; 2119 } 2120 2121 set_changed(handle); 2122 2123 return 1; 2124} 2125 2126STRUCT_COUNTERS * 2127TC_READ_COUNTER(const IPT_CHAINLABEL chain, 2128 unsigned int rulenum, 2129 struct xtc_handle *handle) 2130{ 2131 struct chain_head *c; 2132 struct rule_head *r; 2133 2134 iptc_fn = TC_READ_COUNTER; 2135 CHECK(*handle); 2136 2137 if (!(c = iptcc_find_label(chain, handle))) { 2138 errno = ENOENT; 2139 return NULL; 2140 } 2141 2142 if (!(r = iptcc_get_rule_num(c, rulenum))) { 2143 errno = E2BIG; 2144 return NULL; 2145 } 2146 2147 return &r->entry[0].counters; 2148} 2149 2150int 2151TC_ZERO_COUNTER(const IPT_CHAINLABEL chain, 2152 unsigned int rulenum, 2153 struct xtc_handle *handle) 2154{ 2155 struct chain_head *c; 2156 struct rule_head *r; 2157 2158 iptc_fn = TC_ZERO_COUNTER; 2159 CHECK(handle); 2160 2161 if (!(c = iptcc_find_label(chain, handle))) { 2162 errno = ENOENT; 2163 return 0; 2164 } 2165 2166 if (!(r = iptcc_get_rule_num(c, rulenum))) { 2167 errno = E2BIG; 2168 return 0; 2169 } 2170 2171 if (r->counter_map.maptype == COUNTER_MAP_NORMAL_MAP) 2172 r->counter_map.maptype = COUNTER_MAP_ZEROED; 2173 2174 set_changed(handle); 2175 2176 return 1; 2177} 2178 2179int 2180TC_SET_COUNTER(const IPT_CHAINLABEL chain, 2181 unsigned int rulenum, 2182 STRUCT_COUNTERS *counters, 2183 struct xtc_handle *handle) 2184{ 2185 struct chain_head *c; 2186 struct rule_head *r; 2187 STRUCT_ENTRY *e; 2188 2189 iptc_fn = TC_SET_COUNTER; 2190 CHECK(handle); 2191 2192 if (!(c = iptcc_find_label(chain, handle))) { 2193 errno = ENOENT; 2194 return 0; 2195 } 2196 2197 if (!(r = iptcc_get_rule_num(c, rulenum))) { 2198 errno = E2BIG; 2199 return 0; 2200 } 2201 2202 e = r->entry; 2203 r->counter_map.maptype = COUNTER_MAP_SET; 2204 2205 memcpy(&e->counters, counters, sizeof(STRUCT_COUNTERS)); 2206 2207 set_changed(handle); 2208 2209 return 1; 2210} 2211 2212/* Creates a new chain. */ 2213/* To create a chain, create two rules: error node and unconditional 2214 * return. */ 2215int 2216TC_CREATE_CHAIN(const IPT_CHAINLABEL chain, struct xtc_handle *handle) 2217{ 2218 static struct chain_head *c; 2219 int capacity; 2220 int exceeded; 2221 2222 iptc_fn = TC_CREATE_CHAIN; 2223 2224 /* find_label doesn't cover built-in targets: DROP, ACCEPT, 2225 QUEUE, RETURN. */ 2226 if (iptcc_find_label(chain, handle) 2227 || strcmp(chain, LABEL_DROP) == 0 2228 || strcmp(chain, LABEL_ACCEPT) == 0 2229 || strcmp(chain, LABEL_QUEUE) == 0 2230 || strcmp(chain, LABEL_RETURN) == 0) { 2231 DEBUGP("Chain `%s' already exists\n", chain); 2232 errno = EEXIST; 2233 return 0; 2234 } 2235 2236 if (strlen(chain)+1 > sizeof(IPT_CHAINLABEL)) { 2237 DEBUGP("Chain name `%s' too long\n", chain); 2238 errno = EINVAL; 2239 return 0; 2240 } 2241 2242 c = iptcc_alloc_chain_head(chain, 0); 2243 if (!c) { 2244 DEBUGP("Cannot allocate memory for chain `%s'\n", chain); 2245 errno = ENOMEM; 2246 return 0; 2247 2248 } 2249 handle->num_chains++; /* New user defined chain */ 2250 2251 DEBUGP("Creating chain `%s'\n", chain); 2252 iptc_insert_chain(handle, c); /* Insert sorted */ 2253 2254 /* Inserting chains don't change the correctness of the chain 2255 * index (except if its smaller than index[0], but that 2256 * handled by iptc_insert_chain). It only causes longer lists 2257 * in the buckets. Thus, only rebuild chain index when the 2258 * capacity is exceed with CHAIN_INDEX_INSERT_MAX chains. 2259 */ 2260 capacity = handle->chain_index_sz * CHAIN_INDEX_BUCKET_LEN; 2261 exceeded = handle->num_chains - capacity; 2262 if (exceeded > CHAIN_INDEX_INSERT_MAX) { 2263 debug("Capacity(%d) exceeded(%d) rebuild (chains:%d)\n", 2264 capacity, exceeded, handle->num_chains); 2265 iptcc_chain_index_rebuild(handle); 2266 } 2267 2268 set_changed(handle); 2269 2270 return 1; 2271} 2272 2273/* Get the number of references to this chain. */ 2274int 2275TC_GET_REFERENCES(unsigned int *ref, const IPT_CHAINLABEL chain, 2276 struct xtc_handle *handle) 2277{ 2278 struct chain_head *c; 2279 2280 iptc_fn = TC_GET_REFERENCES; 2281 if (!(c = iptcc_find_label(chain, handle))) { 2282 errno = ENOENT; 2283 return 0; 2284 } 2285 2286 *ref = c->references; 2287 2288 return 1; 2289} 2290 2291/* Deletes a chain. */ 2292int 2293TC_DELETE_CHAIN(const IPT_CHAINLABEL chain, struct xtc_handle *handle) 2294{ 2295 unsigned int references; 2296 struct chain_head *c; 2297 2298 iptc_fn = TC_DELETE_CHAIN; 2299 2300 if (!(c = iptcc_find_label(chain, handle))) { 2301 DEBUGP("cannot find chain `%s'\n", chain); 2302 errno = ENOENT; 2303 return 0; 2304 } 2305 2306 if (TC_BUILTIN(chain, handle)) { 2307 DEBUGP("cannot remove builtin chain `%s'\n", chain); 2308 errno = EINVAL; 2309 return 0; 2310 } 2311 2312 if (!TC_GET_REFERENCES(&references, chain, handle)) { 2313 DEBUGP("cannot get references on chain `%s'\n", chain); 2314 return 0; 2315 } 2316 2317 if (references > 0) { 2318 DEBUGP("chain `%s' still has references\n", chain); 2319 errno = EMLINK; 2320 return 0; 2321 } 2322 2323 if (c->num_rules) { 2324 DEBUGP("chain `%s' is not empty\n", chain); 2325 errno = ENOTEMPTY; 2326 return 0; 2327 } 2328 2329 /* If we are about to delete the chain that is the current 2330 * iterator, move chain iterator forward. */ 2331 if (c == handle->chain_iterator_cur) 2332 iptcc_chain_iterator_advance(handle); 2333 2334 handle->num_chains--; /* One user defined chain deleted */ 2335 2336 //list_del(&c->list); /* Done in iptcc_chain_index_delete_chain() */ 2337 iptcc_chain_index_delete_chain(c, handle); 2338 free(c); 2339 2340 DEBUGP("chain `%s' deleted\n", chain); 2341 2342 set_changed(handle); 2343 2344 return 1; 2345} 2346 2347/* Renames a chain. */ 2348int TC_RENAME_CHAIN(const IPT_CHAINLABEL oldname, 2349 const IPT_CHAINLABEL newname, 2350 struct xtc_handle *handle) 2351{ 2352 struct chain_head *c; 2353 iptc_fn = TC_RENAME_CHAIN; 2354 2355 /* find_label doesn't cover built-in targets: DROP, ACCEPT, 2356 QUEUE, RETURN. */ 2357 if (iptcc_find_label(newname, handle) 2358 || strcmp(newname, LABEL_DROP) == 0 2359 || strcmp(newname, LABEL_ACCEPT) == 0 2360 || strcmp(newname, LABEL_QUEUE) == 0 2361 || strcmp(newname, LABEL_RETURN) == 0) { 2362 errno = EEXIST; 2363 return 0; 2364 } 2365 2366 if (!(c = iptcc_find_label(oldname, handle)) 2367 || TC_BUILTIN(oldname, handle)) { 2368 errno = ENOENT; 2369 return 0; 2370 } 2371 2372 if (strlen(newname)+1 > sizeof(IPT_CHAINLABEL)) { 2373 errno = EINVAL; 2374 return 0; 2375 } 2376 2377 /* This only unlinks "c" from the list, thus no free(c) */ 2378 iptcc_chain_index_delete_chain(c, handle); 2379 2380 /* Change the name of the chain */ 2381 strncpy(c->name, newname, sizeof(IPT_CHAINLABEL)); 2382 2383 /* Insert sorted into to list again */ 2384 iptc_insert_chain(handle, c); 2385 2386 set_changed(handle); 2387 2388 return 1; 2389} 2390 2391/* Sets the policy on a built-in chain. */ 2392int 2393TC_SET_POLICY(const IPT_CHAINLABEL chain, 2394 const IPT_CHAINLABEL policy, 2395 STRUCT_COUNTERS *counters, 2396 struct xtc_handle *handle) 2397{ 2398 struct chain_head *c; 2399 2400 iptc_fn = TC_SET_POLICY; 2401 2402 if (!(c = iptcc_find_label(chain, handle))) { 2403 DEBUGP("cannot find chain `%s'\n", chain); 2404 errno = ENOENT; 2405 return 0; 2406 } 2407 2408 if (!iptcc_is_builtin(c)) { 2409 DEBUGP("cannot set policy of userdefinedchain `%s'\n", chain); 2410 errno = ENOENT; 2411 return 0; 2412 } 2413 2414 if (strcmp(policy, LABEL_ACCEPT) == 0) 2415 c->verdict = -NF_ACCEPT - 1; 2416 else if (strcmp(policy, LABEL_DROP) == 0) 2417 c->verdict = -NF_DROP - 1; 2418 else { 2419 errno = EINVAL; 2420 return 0; 2421 } 2422 2423 if (counters) { 2424 /* set byte and packet counters */ 2425 memcpy(&c->counters, counters, sizeof(STRUCT_COUNTERS)); 2426 c->counter_map.maptype = COUNTER_MAP_SET; 2427 } else { 2428 c->counter_map.maptype = COUNTER_MAP_NOMAP; 2429 } 2430 2431 set_changed(handle); 2432 2433 return 1; 2434} 2435 2436/* Without this, on gcc 2.7.2.3, we get: 2437 libiptc.c: In function `TC_COMMIT': 2438 libiptc.c:833: fixed or forbidden register was spilled. 2439 This may be due to a compiler bug or to impossible asm 2440 statements or clauses. 2441*/ 2442static void 2443subtract_counters(STRUCT_COUNTERS *answer, 2444 const STRUCT_COUNTERS *a, 2445 const STRUCT_COUNTERS *b) 2446{ 2447 answer->pcnt = a->pcnt - b->pcnt; 2448 answer->bcnt = a->bcnt - b->bcnt; 2449} 2450 2451 2452static void counters_nomap(STRUCT_COUNTERS_INFO *newcounters, unsigned int idx) 2453{ 2454 newcounters->counters[idx] = ((STRUCT_COUNTERS) { 0, 0}); 2455 DEBUGP_C("NOMAP => zero\n"); 2456} 2457 2458static void counters_normal_map(STRUCT_COUNTERS_INFO *newcounters, 2459 STRUCT_REPLACE *repl, unsigned int idx, 2460 unsigned int mappos) 2461{ 2462 /* Original read: X. 2463 * Atomic read on replacement: X + Y. 2464 * Currently in kernel: Z. 2465 * Want in kernel: X + Y + Z. 2466 * => Add in X + Y 2467 * => Add in replacement read. 2468 */ 2469 newcounters->counters[idx] = repl->counters[mappos]; 2470 DEBUGP_C("NORMAL_MAP => mappos %u \n", mappos); 2471} 2472 2473static void counters_map_zeroed(STRUCT_COUNTERS_INFO *newcounters, 2474 STRUCT_REPLACE *repl, unsigned int idx, 2475 unsigned int mappos, STRUCT_COUNTERS *counters) 2476{ 2477 /* Original read: X. 2478 * Atomic read on replacement: X + Y. 2479 * Currently in kernel: Z. 2480 * Want in kernel: Y + Z. 2481 * => Add in Y. 2482 * => Add in (replacement read - original read). 2483 */ 2484 subtract_counters(&newcounters->counters[idx], 2485 &repl->counters[mappos], 2486 counters); 2487 DEBUGP_C("ZEROED => mappos %u\n", mappos); 2488} 2489 2490static void counters_map_set(STRUCT_COUNTERS_INFO *newcounters, 2491 unsigned int idx, STRUCT_COUNTERS *counters) 2492{ 2493 /* Want to set counter (iptables-restore) */ 2494 2495 memcpy(&newcounters->counters[idx], counters, 2496 sizeof(STRUCT_COUNTERS)); 2497 2498 DEBUGP_C("SET\n"); 2499} 2500 2501 2502int 2503TC_COMMIT(struct xtc_handle *handle) 2504{ 2505 /* Replace, then map back the counters. */ 2506 STRUCT_REPLACE *repl; 2507 STRUCT_COUNTERS_INFO *newcounters; 2508 struct chain_head *c; 2509 int ret; 2510 size_t counterlen; 2511 int new_number; 2512 unsigned int new_size; 2513 2514 iptc_fn = TC_COMMIT; 2515 CHECK(*handle); 2516 2517 /* Don't commit if nothing changed. */ 2518 if (!handle->changed) 2519 goto finished; 2520 2521 new_number = iptcc_compile_table_prep(handle, &new_size); 2522 if (new_number < 0) { 2523 errno = ENOMEM; 2524 goto out_zero; 2525 } 2526 2527 repl = malloc(sizeof(*repl) + new_size); 2528 if (!repl) { 2529 errno = ENOMEM; 2530 goto out_zero; 2531 } 2532 memset(repl, 0, sizeof(*repl) + new_size); 2533 2534#if 0 2535 TC_DUMP_ENTRIES(*handle); 2536#endif 2537 2538 counterlen = sizeof(STRUCT_COUNTERS_INFO) 2539 + sizeof(STRUCT_COUNTERS) * new_number; 2540 2541 /* These are the old counters we will get from kernel */ 2542 repl->counters = malloc(sizeof(STRUCT_COUNTERS) 2543 * handle->info.num_entries); 2544 if (!repl->counters) { 2545 errno = ENOMEM; 2546 goto out_free_repl; 2547 } 2548 /* These are the counters we're going to put back, later. */ 2549 newcounters = malloc(counterlen); 2550 if (!newcounters) { 2551 errno = ENOMEM; 2552 goto out_free_repl_counters; 2553 } 2554 memset(newcounters, 0, counterlen); 2555 2556 strcpy(repl->name, handle->info.name); 2557 repl->num_entries = new_number; 2558 repl->size = new_size; 2559 2560 repl->num_counters = handle->info.num_entries; 2561 repl->valid_hooks = handle->info.valid_hooks; 2562 2563 DEBUGP("num_entries=%u, size=%u, num_counters=%u\n", 2564 repl->num_entries, repl->size, repl->num_counters); 2565 2566 ret = iptcc_compile_table(handle, repl); 2567 if (ret < 0) { 2568 errno = ret; 2569 goto out_free_newcounters; 2570 } 2571 2572 2573#ifdef IPTC_DEBUG2 2574 { 2575 int fd = open("/tmp/libiptc-so_set_replace.blob", 2576 O_CREAT|O_WRONLY); 2577 if (fd >= 0) { 2578 write(fd, repl, sizeof(*repl) + repl->size); 2579 close(fd); 2580 } 2581 } 2582#endif 2583 2584 ret = setsockopt(handle->sockfd, TC_IPPROTO, SO_SET_REPLACE, repl, 2585 sizeof(*repl) + repl->size); 2586 if (ret < 0) 2587 goto out_free_newcounters; 2588 2589 /* Put counters back. */ 2590 strcpy(newcounters->name, handle->info.name); 2591 newcounters->num_counters = new_number; 2592 2593 list_for_each_entry(c, &handle->chains, list) { 2594 struct rule_head *r; 2595 2596 /* Builtin chains have their own counters */ 2597 if (iptcc_is_builtin(c)) { 2598 DEBUGP("counter for chain-index %u: ", c->foot_index); 2599 switch(c->counter_map.maptype) { 2600 case COUNTER_MAP_NOMAP: 2601 counters_nomap(newcounters, c->foot_index); 2602 break; 2603 case COUNTER_MAP_NORMAL_MAP: 2604 counters_normal_map(newcounters, repl, 2605 c->foot_index, 2606 c->counter_map.mappos); 2607 break; 2608 case COUNTER_MAP_ZEROED: 2609 counters_map_zeroed(newcounters, repl, 2610 c->foot_index, 2611 c->counter_map.mappos, 2612 &c->counters); 2613 break; 2614 case COUNTER_MAP_SET: 2615 counters_map_set(newcounters, c->foot_index, 2616 &c->counters); 2617 break; 2618 } 2619 } 2620 2621 list_for_each_entry(r, &c->rules, list) { 2622 DEBUGP("counter for index %u: ", r->index); 2623 switch (r->counter_map.maptype) { 2624 case COUNTER_MAP_NOMAP: 2625 counters_nomap(newcounters, r->index); 2626 break; 2627 2628 case COUNTER_MAP_NORMAL_MAP: 2629 counters_normal_map(newcounters, repl, 2630 r->index, 2631 r->counter_map.mappos); 2632 break; 2633 2634 case COUNTER_MAP_ZEROED: 2635 counters_map_zeroed(newcounters, repl, 2636 r->index, 2637 r->counter_map.mappos, 2638 &r->entry->counters); 2639 break; 2640 2641 case COUNTER_MAP_SET: 2642 counters_map_set(newcounters, r->index, 2643 &r->entry->counters); 2644 break; 2645 } 2646 } 2647 } 2648 2649#ifdef IPTC_DEBUG2 2650 { 2651 int fd = open("/tmp/libiptc-so_set_add_counters.blob", 2652 O_CREAT|O_WRONLY); 2653 if (fd >= 0) { 2654 write(fd, newcounters, counterlen); 2655 close(fd); 2656 } 2657 } 2658#endif 2659 2660 ret = setsockopt(handle->sockfd, TC_IPPROTO, SO_SET_ADD_COUNTERS, 2661 newcounters, counterlen); 2662 if (ret < 0) 2663 goto out_free_newcounters; 2664 2665 free(repl->counters); 2666 free(repl); 2667 free(newcounters); 2668 2669finished: 2670 return 1; 2671 2672out_free_newcounters: 2673 free(newcounters); 2674out_free_repl_counters: 2675 free(repl->counters); 2676out_free_repl: 2677 free(repl); 2678out_zero: 2679 return 0; 2680} 2681 2682/* Translates errno numbers into more human-readable form than strerror. */ 2683const char * 2684TC_STRERROR(int err) 2685{ 2686 unsigned int i; 2687 struct table_struct { 2688 void *fn; 2689 int err; 2690 const char *message; 2691 } table [] = 2692 { { TC_INIT, EPERM, "Permission denied (you must be root)" }, 2693 { TC_INIT, EINVAL, "Module is wrong version" }, 2694 { TC_INIT, ENOENT, 2695 "Table does not exist (do you need to insmod?)" }, 2696 { TC_DELETE_CHAIN, ENOTEMPTY, "Chain is not empty" }, 2697 { TC_DELETE_CHAIN, EINVAL, "Can't delete built-in chain" }, 2698 { TC_DELETE_CHAIN, EMLINK, 2699 "Can't delete chain with references left" }, 2700 { TC_CREATE_CHAIN, EEXIST, "Chain already exists" }, 2701 { TC_INSERT_ENTRY, E2BIG, "Index of insertion too big" }, 2702 { TC_REPLACE_ENTRY, E2BIG, "Index of replacement too big" }, 2703 { TC_DELETE_NUM_ENTRY, E2BIG, "Index of deletion too big" }, 2704 { TC_READ_COUNTER, E2BIG, "Index of counter too big" }, 2705 { TC_ZERO_COUNTER, E2BIG, "Index of counter too big" }, 2706 { TC_INSERT_ENTRY, ELOOP, "Loop found in table" }, 2707 { TC_INSERT_ENTRY, EINVAL, "Target problem" }, 2708 /* ENOENT for DELETE probably means no matching rule */ 2709 { TC_DELETE_ENTRY, ENOENT, 2710 "Bad rule (does a matching rule exist in that chain?)" }, 2711 { TC_SET_POLICY, ENOENT, 2712 "Bad built-in chain name" }, 2713 { TC_SET_POLICY, EINVAL, 2714 "Bad policy name" }, 2715 2716 { NULL, 0, "Incompatible with this kernel" }, 2717 { NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" }, 2718 { NULL, ENOSYS, "Will be implemented real soon. I promise ;)" }, 2719 { NULL, ENOMEM, "Memory allocation problem" }, 2720 { NULL, ENOENT, "No chain/target/match by that name" }, 2721 }; 2722 2723 for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) { 2724 if ((!table[i].fn || table[i].fn == iptc_fn) 2725 && table[i].err == err) 2726 return table[i].message; 2727 } 2728 2729 return strerror(err); 2730} 2731