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