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 (at) netfilter.org> 14 * 15 * 2003-Jun-20: Harald Welte <laforge (at) netfilter.org>: 16 * - Reimplementation of chain cache to use offsets instead of entries 17 * 2003-Jun-23: Harald Welte <laforge (at) 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 (at) 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 (at) 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 56 static void *iptc_fn = NULL; 57 58 static 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 */ 70 struct ipt_error_target 71 { 72 STRUCT_ENTRY_TARGET t; 73 char error[TABLE_MAXNAMELEN]; 74 }; 75 76 struct chain_head; 77 struct rule_head; 78 79 struct 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 90 enum 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 97 struct 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 113 struct 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 133 STRUCT_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 157 enum 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 */ 163 static 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 */ 178 static 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 */ 192 static inline void 193 set_changed(struct xtc_handle *h) 194 { 195 h->changed = 1; 196 } 197 198 #ifdef IPTC_DEBUG 199 static 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 210 static inline int 211 iptcb_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 221 static inline int 222 iptcb_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 235 static inline STRUCT_ENTRY * 236 iptcb_get_entry(struct xtc_handle *h, unsigned int offset) 237 { 238 return (STRUCT_ENTRY *)((char *)h->entries->entrytable + offset); 239 } 240 241 static unsigned int 242 iptcb_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 255 static inline STRUCT_ENTRY * 256 iptcb_offset2entry(struct xtc_handle *h, unsigned int offset) 257 { 258 return (STRUCT_ENTRY *) ((void *)h->entries->entrytable+offset); 259 } 260 261 262 static inline unsigned long 263 iptcb_entry2offset(struct xtc_handle *const h, const STRUCT_ENTRY *e) 264 { 265 return (void *)e - (void *)h->entries->entrytable; 266 } 267 268 static inline unsigned int 269 iptcb_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 */ 275 static inline unsigned int 276 iptcb_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 322 static 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 */ 335 static 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 */ 438 static struct list_head * 439 iptcc_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 */ 447 static struct list_head * 448 iptcc_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 */ 468 static struct list_head * 469 iptcc_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 497 static 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 522 static 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 530 static 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 */ 545 static 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 587 static 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 */ 609 static int iptcc_chain_index_delete_chain(struct chain_head *c, struct xtc_handle *h) 610 { 611 struct list_head *index_ptr, *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 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) */ 652 static 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 */ 658 static 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 */ 673 static 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. */ 688 static struct chain_head * 689 iptcc_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. */ 720 static struct chain_head * 721 iptcc_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 */ 797 static 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 */ 818 static 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 */ 852 static 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 */ 895 static 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 */ 937 static 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; 994 new_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 } 1041 out_inc: 1042 (*num)++; 1043 return 0; 1044 } 1045 1046 1047 /* parse an iptables blob into it's pieces */ 1048 static 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 */ 1095 struct 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 1102 struct 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 1109 struct 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 */ 1119 static 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 */ 1144 static 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 */ 1192 static 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 */ 1227 static 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 1250 static 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 */ 1279 static struct xtc_handle * 1280 alloc_handle(const char *tablename, unsigned int size, unsigned int num_rules) 1281 { 1282 struct xtc_handle *h; 1283 1284 h = malloc(sizeof(STRUCT_TC_HANDLE)); 1285 if (!h) { 1286 errno = ENOMEM; 1287 return NULL; 1288 } 1289 memset(h, 0, sizeof(*h)); 1290 INIT_LIST_HEAD(&h->chains); 1291 strcpy(h->info.name, tablename); 1292 1293 h->entries = malloc(sizeof(STRUCT_GET_ENTRIES) + size); 1294 if (!h->entries) 1295 goto out_free_handle; 1296 1297 strcpy(h->entries->name, tablename); 1298 h->entries->size = size; 1299 1300 return h; 1301 1302 out_free_handle: 1303 free(h); 1304 1305 return NULL; 1306 } 1307 1308 1309 struct xtc_handle * 1310 TC_INIT(const char *tablename) 1311 { 1312 struct xtc_handle *h; 1313 STRUCT_GETINFO info; 1314 unsigned int tmp; 1315 socklen_t s; 1316 int sockfd; 1317 1318 iptc_fn = TC_INIT; 1319 1320 if (strlen(tablename) >= TABLE_MAXNAMELEN) { 1321 errno = EINVAL; 1322 return NULL; 1323 } 1324 1325 sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW); 1326 if (sockfd < 0) 1327 return NULL; 1328 1329 retry: 1330 s = sizeof(info); 1331 1332 strcpy(info.name, tablename); 1333 if (getsockopt(sockfd, TC_IPPROTO, SO_GET_INFO, &info, &s) < 0) { 1334 close(sockfd); 1335 return NULL; 1336 } 1337 1338 DEBUGP("valid_hooks=0x%08x, num_entries=%u, size=%u\n", 1339 info.valid_hooks, info.num_entries, info.size); 1340 1341 if ((h = alloc_handle(info.name, info.size, info.num_entries)) 1342 == NULL) { 1343 close(sockfd); 1344 return NULL; 1345 } 1346 1347 /* Initialize current state */ 1348 h->sockfd = sockfd; 1349 h->info = info; 1350 1351 h->entries->size = h->info.size; 1352 1353 tmp = sizeof(STRUCT_GET_ENTRIES) + h->info.size; 1354 1355 if (getsockopt(h->sockfd, TC_IPPROTO, SO_GET_ENTRIES, h->entries, 1356 &tmp) < 0) 1357 goto error; 1358 1359 #ifdef IPTC_DEBUG2 1360 { 1361 int fd = open("/tmp/libiptc-so_get_entries.blob", 1362 O_CREAT|O_WRONLY); 1363 if (fd >= 0) { 1364 write(fd, h->entries, tmp); 1365 close(fd); 1366 } 1367 } 1368 #endif 1369 1370 if (parse_table(h) < 0) 1371 goto error; 1372 1373 CHECK(h); 1374 return h; 1375 error: 1376 TC_FREE(h); 1377 /* A different process changed the ruleset size, retry */ 1378 if (errno == EAGAIN) 1379 goto retry; 1380 return NULL; 1381 } 1382 1383 void 1384 TC_FREE(struct xtc_handle *h) 1385 { 1386 struct chain_head *c, *tmp; 1387 1388 iptc_fn = TC_FREE; 1389 close(h->sockfd); 1390 1391 list_for_each_entry_safe(c, tmp, &h->chains, list) { 1392 struct rule_head *r, *rtmp; 1393 1394 list_for_each_entry_safe(r, rtmp, &c->rules, list) { 1395 free(r); 1396 } 1397 1398 free(c); 1399 } 1400 1401 iptcc_chain_index_free(h); 1402 1403 free(h->entries); 1404 free(h); 1405 } 1406 1407 static inline int 1408 print_match(const STRUCT_ENTRY_MATCH *m) 1409 { 1410 printf("Match name: `%s'\n", m->u.user.name); 1411 return 0; 1412 } 1413 1414 static int dump_entry(STRUCT_ENTRY *e, struct xtc_handle *const handle); 1415 1416 void 1417 TC_DUMP_ENTRIES(struct xtc_handle *const handle) 1418 { 1419 iptc_fn = TC_DUMP_ENTRIES; 1420 CHECK(handle); 1421 1422 printf("libiptc v%s. %u bytes.\n", 1423 XTABLES_VERSION, handle->entries->size); 1424 printf("Table `%s'\n", handle->info.name); 1425 printf("Hooks: pre/in/fwd/out/post = %x/%x/%x/%x/%x\n", 1426 handle->info.hook_entry[HOOK_PRE_ROUTING], 1427 handle->info.hook_entry[HOOK_LOCAL_IN], 1428 handle->info.hook_entry[HOOK_FORWARD], 1429 handle->info.hook_entry[HOOK_LOCAL_OUT], 1430 handle->info.hook_entry[HOOK_POST_ROUTING]); 1431 printf("Underflows: pre/in/fwd/out/post = %x/%x/%x/%x/%x\n", 1432 handle->info.underflow[HOOK_PRE_ROUTING], 1433 handle->info.underflow[HOOK_LOCAL_IN], 1434 handle->info.underflow[HOOK_FORWARD], 1435 handle->info.underflow[HOOK_LOCAL_OUT], 1436 handle->info.underflow[HOOK_POST_ROUTING]); 1437 1438 ENTRY_ITERATE(handle->entries->entrytable, handle->entries->size, 1439 dump_entry, handle); 1440 } 1441 1442 /* Does this chain exist? */ 1443 int TC_IS_CHAIN(const char *chain, struct xtc_handle *const handle) 1444 { 1445 iptc_fn = TC_IS_CHAIN; 1446 return iptcc_find_label(chain, handle) != NULL; 1447 } 1448 1449 static void iptcc_chain_iterator_advance(struct xtc_handle *handle) 1450 { 1451 struct chain_head *c = handle->chain_iterator_cur; 1452 1453 if (c->list.next == &handle->chains) 1454 handle->chain_iterator_cur = NULL; 1455 else 1456 handle->chain_iterator_cur = 1457 list_entry(c->list.next, struct chain_head, list); 1458 } 1459 1460 /* Iterator functions to run through the chains. */ 1461 const char * 1462 TC_FIRST_CHAIN(struct xtc_handle *handle) 1463 { 1464 struct chain_head *c = list_entry(handle->chains.next, 1465 struct chain_head, list); 1466 1467 iptc_fn = TC_FIRST_CHAIN; 1468 1469 1470 if (list_empty(&handle->chains)) { 1471 DEBUGP(": no chains\n"); 1472 return NULL; 1473 } 1474 1475 handle->chain_iterator_cur = c; 1476 iptcc_chain_iterator_advance(handle); 1477 1478 DEBUGP(": returning `%s'\n", c->name); 1479 return c->name; 1480 } 1481 1482 /* Iterator functions to run through the chains. Returns NULL at end. */ 1483 const char * 1484 TC_NEXT_CHAIN(struct xtc_handle *handle) 1485 { 1486 struct chain_head *c = handle->chain_iterator_cur; 1487 1488 iptc_fn = TC_NEXT_CHAIN; 1489 1490 if (!c) { 1491 DEBUGP(": no more chains\n"); 1492 return NULL; 1493 } 1494 1495 iptcc_chain_iterator_advance(handle); 1496 1497 DEBUGP(": returning `%s'\n", c->name); 1498 return c->name; 1499 } 1500 1501 /* Get first rule in the given chain: NULL for empty chain. */ 1502 const STRUCT_ENTRY * 1503 TC_FIRST_RULE(const char *chain, struct xtc_handle *handle) 1504 { 1505 struct chain_head *c; 1506 struct rule_head *r; 1507 1508 iptc_fn = TC_FIRST_RULE; 1509 1510 DEBUGP("first rule(%s): ", chain); 1511 1512 c = iptcc_find_label(chain, handle); 1513 if (!c) { 1514 errno = ENOENT; 1515 return NULL; 1516 } 1517 1518 /* Empty chain: single return/policy rule */ 1519 if (list_empty(&c->rules)) { 1520 DEBUGP_C("no rules, returning NULL\n"); 1521 return NULL; 1522 } 1523 1524 r = list_entry(c->rules.next, struct rule_head, list); 1525 handle->rule_iterator_cur = r; 1526 DEBUGP_C("%p\n", r); 1527 1528 return r->entry; 1529 } 1530 1531 /* Returns NULL when rules run out. */ 1532 const STRUCT_ENTRY * 1533 TC_NEXT_RULE(const STRUCT_ENTRY *prev, struct xtc_handle *handle) 1534 { 1535 struct rule_head *r; 1536 1537 iptc_fn = TC_NEXT_RULE; 1538 DEBUGP("rule_iterator_cur=%p...", handle->rule_iterator_cur); 1539 1540 if (handle->rule_iterator_cur == NULL) { 1541 DEBUGP_C("returning NULL\n"); 1542 return NULL; 1543 } 1544 1545 r = list_entry(handle->rule_iterator_cur->list.next, 1546 struct rule_head, list); 1547 1548 iptc_fn = TC_NEXT_RULE; 1549 1550 DEBUGP_C("next=%p, head=%p...", &r->list, 1551 &handle->rule_iterator_cur->chain->rules); 1552 1553 if (&r->list == &handle->rule_iterator_cur->chain->rules) { 1554 handle->rule_iterator_cur = NULL; 1555 DEBUGP_C("finished, returning NULL\n"); 1556 return NULL; 1557 } 1558 1559 handle->rule_iterator_cur = r; 1560 1561 /* NOTE: prev is without any influence ! */ 1562 DEBUGP_C("returning rule %p\n", r); 1563 return r->entry; 1564 } 1565 1566 /* Returns a pointer to the target name of this position. */ 1567 static const char *standard_target_map(int verdict) 1568 { 1569 switch (verdict) { 1570 case RETURN: 1571 return LABEL_RETURN; 1572 break; 1573 case -NF_ACCEPT-1: 1574 return LABEL_ACCEPT; 1575 break; 1576 case -NF_DROP-1: 1577 return LABEL_DROP; 1578 break; 1579 case -NF_QUEUE-1: 1580 return LABEL_QUEUE; 1581 break; 1582 default: 1583 fprintf(stderr, "ERROR: %d not a valid target)\n", 1584 verdict); 1585 abort(); 1586 break; 1587 } 1588 /* not reached */ 1589 return NULL; 1590 } 1591 1592 /* Returns a pointer to the target name of this position. */ 1593 const char *TC_GET_TARGET(const STRUCT_ENTRY *ce, 1594 struct xtc_handle *handle) 1595 { 1596 STRUCT_ENTRY *e = (STRUCT_ENTRY *)ce; 1597 struct rule_head *r = container_of(e, struct rule_head, entry[0]); 1598 const unsigned char *data; 1599 1600 iptc_fn = TC_GET_TARGET; 1601 1602 switch(r->type) { 1603 int spos; 1604 case IPTCC_R_FALLTHROUGH: 1605 return ""; 1606 break; 1607 case IPTCC_R_JUMP: 1608 DEBUGP("r=%p, jump=%p, name=`%s'\n", r, r->jump, r->jump->name); 1609 return r->jump->name; 1610 break; 1611 case IPTCC_R_STANDARD: 1612 data = GET_TARGET(e)->data; 1613 spos = *(const int *)data; 1614 DEBUGP("r=%p, spos=%d'\n", r, spos); 1615 return standard_target_map(spos); 1616 break; 1617 case IPTCC_R_MODULE: 1618 return GET_TARGET(e)->u.user.name; 1619 break; 1620 } 1621 return NULL; 1622 } 1623 /* Is this a built-in chain? Actually returns hook + 1. */ 1624 int 1625 TC_BUILTIN(const char *chain, struct xtc_handle *const handle) 1626 { 1627 struct chain_head *c; 1628 1629 iptc_fn = TC_BUILTIN; 1630 1631 c = iptcc_find_label(chain, handle); 1632 if (!c) { 1633 errno = ENOENT; 1634 return 0; 1635 } 1636 1637 return iptcc_is_builtin(c); 1638 } 1639 1640 /* Get the policy of a given built-in chain */ 1641 const char * 1642 TC_GET_POLICY(const char *chain, 1643 STRUCT_COUNTERS *counters, 1644 struct xtc_handle *handle) 1645 { 1646 struct chain_head *c; 1647 1648 iptc_fn = TC_GET_POLICY; 1649 1650 DEBUGP("called for chain %s\n", chain); 1651 1652 c = iptcc_find_label(chain, handle); 1653 if (!c) { 1654 errno = ENOENT; 1655 return NULL; 1656 } 1657 1658 if (!iptcc_is_builtin(c)) 1659 return NULL; 1660 1661 *counters = c->counters; 1662 1663 return standard_target_map(c->verdict); 1664 } 1665 1666 static int 1667 iptcc_standard_map(struct rule_head *r, int verdict) 1668 { 1669 STRUCT_ENTRY *e = r->entry; 1670 STRUCT_STANDARD_TARGET *t; 1671 1672 t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e); 1673 1674 if (t->target.u.target_size 1675 != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) { 1676 errno = EINVAL; 1677 return 0; 1678 } 1679 /* memset for memcmp convenience on delete/replace */ 1680 memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN); 1681 strcpy(t->target.u.user.name, STANDARD_TARGET); 1682 t->verdict = verdict; 1683 1684 r->type = IPTCC_R_STANDARD; 1685 1686 return 1; 1687 } 1688 1689 static int 1690 iptcc_map_target(struct xtc_handle *const handle, 1691 struct rule_head *r) 1692 { 1693 STRUCT_ENTRY *e = r->entry; 1694 STRUCT_ENTRY_TARGET *t = GET_TARGET(e); 1695 1696 /* Maybe it's empty (=> fall through) */ 1697 if (strcmp(t->u.user.name, "") == 0) { 1698 r->type = IPTCC_R_FALLTHROUGH; 1699 return 1; 1700 } 1701 /* Maybe it's a standard target name... */ 1702 else if (strcmp(t->u.user.name, LABEL_ACCEPT) == 0) 1703 return iptcc_standard_map(r, -NF_ACCEPT - 1); 1704 else if (strcmp(t->u.user.name, LABEL_DROP) == 0) 1705 return iptcc_standard_map(r, -NF_DROP - 1); 1706 else if (strcmp(t->u.user.name, LABEL_QUEUE) == 0) 1707 return iptcc_standard_map(r, -NF_QUEUE - 1); 1708 else if (strcmp(t->u.user.name, LABEL_RETURN) == 0) 1709 return iptcc_standard_map(r, RETURN); 1710 else if (TC_BUILTIN(t->u.user.name, handle)) { 1711 /* Can't jump to builtins. */ 1712 errno = EINVAL; 1713 return 0; 1714 } else { 1715 /* Maybe it's an existing chain name. */ 1716 struct chain_head *c; 1717 DEBUGP("trying to find chain `%s': ", t->u.user.name); 1718 1719 c = iptcc_find_label(t->u.user.name, handle); 1720 if (c) { 1721 DEBUGP_C("found!\n"); 1722 r->type = IPTCC_R_JUMP; 1723 r->jump = c; 1724 c->references++; 1725 return 1; 1726 } 1727 DEBUGP_C("not found :(\n"); 1728 } 1729 1730 /* Must be a module? If not, kernel will reject... */ 1731 /* memset to all 0 for your memcmp convenience: don't clear version */ 1732 memset(t->u.user.name + strlen(t->u.user.name), 1733 0, 1734 FUNCTION_MAXNAMELEN - 1 - strlen(t->u.user.name)); 1735 r->type = IPTCC_R_MODULE; 1736 set_changed(handle); 1737 return 1; 1738 } 1739 1740 /* Insert the entry `fw' in chain `chain' into position `rulenum'. */ 1741 int 1742 TC_INSERT_ENTRY(const IPT_CHAINLABEL chain, 1743 const STRUCT_ENTRY *e, 1744 unsigned int rulenum, 1745 struct xtc_handle *handle) 1746 { 1747 struct chain_head *c; 1748 struct rule_head *r; 1749 struct list_head *prev; 1750 1751 iptc_fn = TC_INSERT_ENTRY; 1752 1753 if (!(c = iptcc_find_label(chain, handle))) { 1754 errno = ENOENT; 1755 return 0; 1756 } 1757 1758 /* first rulenum index = 0 1759 first c->num_rules index = 1 */ 1760 if (rulenum > c->num_rules) { 1761 errno = E2BIG; 1762 return 0; 1763 } 1764 1765 /* If we are inserting at the end just take advantage of the 1766 double linked list, insert will happen before the entry 1767 prev points to. */ 1768 if (rulenum == c->num_rules) { 1769 prev = &c->rules; 1770 } else if (rulenum + 1 <= c->num_rules/2) { 1771 r = iptcc_get_rule_num(c, rulenum + 1); 1772 prev = &r->list; 1773 } else { 1774 r = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum); 1775 prev = &r->list; 1776 } 1777 1778 if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1779 errno = ENOMEM; 1780 return 0; 1781 } 1782 1783 memcpy(r->entry, e, e->next_offset); 1784 r->counter_map.maptype = COUNTER_MAP_SET; 1785 1786 if (!iptcc_map_target(handle, r)) { 1787 free(r); 1788 return 0; 1789 } 1790 1791 list_add_tail(&r->list, prev); 1792 c->num_rules++; 1793 1794 set_changed(handle); 1795 1796 return 1; 1797 } 1798 1799 /* Atomically replace rule `rulenum' in `chain' with `fw'. */ 1800 int 1801 TC_REPLACE_ENTRY(const IPT_CHAINLABEL chain, 1802 const STRUCT_ENTRY *e, 1803 unsigned int rulenum, 1804 struct xtc_handle *handle) 1805 { 1806 struct chain_head *c; 1807 struct rule_head *r, *old; 1808 1809 iptc_fn = TC_REPLACE_ENTRY; 1810 1811 if (!(c = iptcc_find_label(chain, handle))) { 1812 errno = ENOENT; 1813 return 0; 1814 } 1815 1816 if (rulenum >= c->num_rules) { 1817 errno = E2BIG; 1818 return 0; 1819 } 1820 1821 /* Take advantage of the double linked list if possible. */ 1822 if (rulenum + 1 <= c->num_rules/2) { 1823 old = iptcc_get_rule_num(c, rulenum + 1); 1824 } else { 1825 old = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum); 1826 } 1827 1828 if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1829 errno = ENOMEM; 1830 return 0; 1831 } 1832 1833 memcpy(r->entry, e, e->next_offset); 1834 r->counter_map.maptype = COUNTER_MAP_SET; 1835 1836 if (!iptcc_map_target(handle, r)) { 1837 free(r); 1838 return 0; 1839 } 1840 1841 list_add(&r->list, &old->list); 1842 iptcc_delete_rule(old); 1843 1844 set_changed(handle); 1845 1846 return 1; 1847 } 1848 1849 /* Append entry `fw' to chain `chain'. Equivalent to insert with 1850 rulenum = length of chain. */ 1851 int 1852 TC_APPEND_ENTRY(const IPT_CHAINLABEL chain, 1853 const STRUCT_ENTRY *e, 1854 struct xtc_handle *handle) 1855 { 1856 struct chain_head *c; 1857 struct rule_head *r; 1858 1859 iptc_fn = TC_APPEND_ENTRY; 1860 if (!(c = iptcc_find_label(chain, handle))) { 1861 DEBUGP("unable to find chain `%s'\n", chain); 1862 errno = ENOENT; 1863 return 0; 1864 } 1865 1866 if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1867 DEBUGP("unable to allocate rule for chain `%s'\n", chain); 1868 errno = ENOMEM; 1869 return 0; 1870 } 1871 1872 memcpy(r->entry, e, e->next_offset); 1873 r->counter_map.maptype = COUNTER_MAP_SET; 1874 1875 if (!iptcc_map_target(handle, r)) { 1876 DEBUGP("unable to map target of rule for chain `%s'\n", chain); 1877 free(r); 1878 return 0; 1879 } 1880 1881 list_add_tail(&r->list, &c->rules); 1882 c->num_rules++; 1883 1884 set_changed(handle); 1885 1886 return 1; 1887 } 1888 1889 static inline int 1890 match_different(const STRUCT_ENTRY_MATCH *a, 1891 const unsigned char *a_elems, 1892 const unsigned char *b_elems, 1893 unsigned char **maskptr) 1894 { 1895 const STRUCT_ENTRY_MATCH *b; 1896 unsigned int i; 1897 1898 /* Offset of b is the same as a. */ 1899 b = (void *)b_elems + ((unsigned char *)a - a_elems); 1900 1901 if (a->u.match_size != b->u.match_size) 1902 return 1; 1903 1904 if (strcmp(a->u.user.name, b->u.user.name) != 0) 1905 return 1; 1906 1907 *maskptr += ALIGN(sizeof(*a)); 1908 1909 for (i = 0; i < a->u.match_size - ALIGN(sizeof(*a)); i++) 1910 if (((a->data[i] ^ b->data[i]) & (*maskptr)[i]) != 0) 1911 return 1; 1912 *maskptr += i; 1913 return 0; 1914 } 1915 1916 static inline int 1917 target_same(struct rule_head *a, struct rule_head *b,const unsigned char *mask) 1918 { 1919 unsigned int i; 1920 STRUCT_ENTRY_TARGET *ta, *tb; 1921 1922 if (a->type != b->type) 1923 return 0; 1924 1925 ta = GET_TARGET(a->entry); 1926 tb = GET_TARGET(b->entry); 1927 1928 switch (a->type) { 1929 case IPTCC_R_FALLTHROUGH: 1930 return 1; 1931 case IPTCC_R_JUMP: 1932 return a->jump == b->jump; 1933 case IPTCC_R_STANDARD: 1934 return ((STRUCT_STANDARD_TARGET *)ta)->verdict 1935 == ((STRUCT_STANDARD_TARGET *)tb)->verdict; 1936 case IPTCC_R_MODULE: 1937 if (ta->u.target_size != tb->u.target_size) 1938 return 0; 1939 if (strcmp(ta->u.user.name, tb->u.user.name) != 0) 1940 return 0; 1941 1942 for (i = 0; i < ta->u.target_size - sizeof(*ta); i++) 1943 if (((ta->data[i] ^ tb->data[i]) & mask[i]) != 0) 1944 return 0; 1945 return 1; 1946 default: 1947 fprintf(stderr, "ERROR: bad type %i\n", a->type); 1948 abort(); 1949 } 1950 } 1951 1952 static unsigned char * 1953 is_same(const STRUCT_ENTRY *a, 1954 const STRUCT_ENTRY *b, 1955 unsigned char *matchmask); 1956 1957 1958 /* find the first rule in `chain' which matches `fw' and remove it unless dry_run is set */ 1959 static int delete_entry(const IPT_CHAINLABEL chain, const STRUCT_ENTRY *origfw, 1960 unsigned char *matchmask, struct xtc_handle *handle, 1961 bool dry_run) 1962 { 1963 struct chain_head *c; 1964 struct rule_head *r, *i; 1965 1966 iptc_fn = TC_DELETE_ENTRY; 1967 if (!(c = iptcc_find_label(chain, handle))) { 1968 errno = ENOENT; 1969 return 0; 1970 } 1971 1972 /* Create a rule_head from origfw. */ 1973 r = iptcc_alloc_rule(c, origfw->next_offset); 1974 if (!r) { 1975 errno = ENOMEM; 1976 return 0; 1977 } 1978 1979 memcpy(r->entry, origfw, origfw->next_offset); 1980 r->counter_map.maptype = COUNTER_MAP_NOMAP; 1981 if (!iptcc_map_target(handle, r)) { 1982 DEBUGP("unable to map target of rule for chain `%s'\n", chain); 1983 free(r); 1984 return 0; 1985 } else { 1986 /* iptcc_map_target increment target chain references 1987 * since this is a fake rule only used for matching 1988 * the chain references count is decremented again. 1989 */ 1990 if (r->type == IPTCC_R_JUMP 1991 && r->jump) 1992 r->jump->references--; 1993 } 1994 1995 list_for_each_entry(i, &c->rules, list) { 1996 unsigned char *mask; 1997 1998 mask = is_same(r->entry, i->entry, matchmask); 1999 if (!mask) 2000 continue; 2001 2002 if (!target_same(r, i, mask)) 2003 continue; 2004 2005 /* if we are just doing a dry run, we simply skip the rest */ 2006 if (dry_run) 2007 return 1; 2008 2009 /* If we are about to delete the rule that is the 2010 * current iterator, move rule iterator back. next 2011 * pointer will then point to real next node */ 2012 if (i == handle->rule_iterator_cur) { 2013 handle->rule_iterator_cur = 2014 list_entry(handle->rule_iterator_cur->list.prev, 2015 struct rule_head, list); 2016 } 2017 2018 c->num_rules--; 2019 iptcc_delete_rule(i); 2020 2021 set_changed(handle); 2022 free(r); 2023 return 1; 2024 } 2025 2026 free(r); 2027 errno = ENOENT; 2028 return 0; 2029 } 2030 2031 /* check whether a specified rule is present */ 2032 int TC_CHECK_ENTRY(const IPT_CHAINLABEL chain, const STRUCT_ENTRY *origfw, 2033 unsigned char *matchmask, struct xtc_handle *handle) 2034 { 2035 /* do a dry-run delete to find out whether a matching rule exists */ 2036 return delete_entry(chain, origfw, matchmask, handle, true); 2037 } 2038 2039 /* Delete the first rule in `chain' which matches `fw'. */ 2040 int TC_DELETE_ENTRY(const IPT_CHAINLABEL chain, const STRUCT_ENTRY *origfw, 2041 unsigned char *matchmask, struct xtc_handle *handle) 2042 { 2043 return delete_entry(chain, origfw, matchmask, handle, false); 2044 } 2045 2046 /* Delete the rule in position `rulenum' in `chain'. */ 2047 int 2048 TC_DELETE_NUM_ENTRY(const IPT_CHAINLABEL chain, 2049 unsigned int rulenum, 2050 struct xtc_handle *handle) 2051 { 2052 struct chain_head *c; 2053 struct rule_head *r; 2054 2055 iptc_fn = TC_DELETE_NUM_ENTRY; 2056 2057 if (!(c = iptcc_find_label(chain, handle))) { 2058 errno = ENOENT; 2059 return 0; 2060 } 2061 2062 if (rulenum >= c->num_rules) { 2063 errno = E2BIG; 2064 return 0; 2065 } 2066 2067 /* Take advantage of the double linked list if possible. */ 2068 if (rulenum + 1 <= c->num_rules/2) { 2069 r = iptcc_get_rule_num(c, rulenum + 1); 2070 } else { 2071 r = iptcc_get_rule_num_reverse(c, c->num_rules - rulenum); 2072 } 2073 2074 /* If we are about to delete the rule that is the current 2075 * iterator, move rule iterator back. next pointer will then 2076 * point to real next node */ 2077 if (r == handle->rule_iterator_cur) { 2078 handle->rule_iterator_cur = 2079 list_entry(handle->rule_iterator_cur->list.prev, 2080 struct rule_head, list); 2081 } 2082 2083 c->num_rules--; 2084 iptcc_delete_rule(r); 2085 2086 set_changed(handle); 2087 2088 return 1; 2089 } 2090 2091 /* Flushes the entries in the given chain (ie. empties chain). */ 2092 int 2093 TC_FLUSH_ENTRIES(const IPT_CHAINLABEL chain, struct xtc_handle *handle) 2094 { 2095 struct chain_head *c; 2096 struct rule_head *r, *tmp; 2097 2098 iptc_fn = TC_FLUSH_ENTRIES; 2099 if (!(c = iptcc_find_label(chain, handle))) { 2100 errno = ENOENT; 2101 return 0; 2102 } 2103 2104 list_for_each_entry_safe(r, tmp, &c->rules, list) { 2105 iptcc_delete_rule(r); 2106 } 2107 2108 c->num_rules = 0; 2109 2110 set_changed(handle); 2111 2112 return 1; 2113 } 2114 2115 /* Zeroes the counters in a chain. */ 2116 int 2117 TC_ZERO_ENTRIES(const IPT_CHAINLABEL chain, struct xtc_handle *handle) 2118 { 2119 struct chain_head *c; 2120 struct rule_head *r; 2121 2122 iptc_fn = TC_ZERO_ENTRIES; 2123 if (!(c = iptcc_find_label(chain, handle))) { 2124 errno = ENOENT; 2125 return 0; 2126 } 2127 2128 if (c->counter_map.maptype == COUNTER_MAP_NORMAL_MAP) 2129 c->counter_map.maptype = COUNTER_MAP_ZEROED; 2130 2131 list_for_each_entry(r, &c->rules, list) { 2132 if (r->counter_map.maptype == COUNTER_MAP_NORMAL_MAP) 2133 r->counter_map.maptype = COUNTER_MAP_ZEROED; 2134 } 2135 2136 set_changed(handle); 2137 2138 return 1; 2139 } 2140 2141 STRUCT_COUNTERS * 2142 TC_READ_COUNTER(const IPT_CHAINLABEL chain, 2143 unsigned int rulenum, 2144 struct xtc_handle *handle) 2145 { 2146 struct chain_head *c; 2147 struct rule_head *r; 2148 2149 iptc_fn = TC_READ_COUNTER; 2150 CHECK(*handle); 2151 2152 if (!(c = iptcc_find_label(chain, handle))) { 2153 errno = ENOENT; 2154 return NULL; 2155 } 2156 2157 if (!(r = iptcc_get_rule_num(c, rulenum))) { 2158 errno = E2BIG; 2159 return NULL; 2160 } 2161 2162 return &r->entry[0].counters; 2163 } 2164 2165 int 2166 TC_ZERO_COUNTER(const IPT_CHAINLABEL chain, 2167 unsigned int rulenum, 2168 struct xtc_handle *handle) 2169 { 2170 struct chain_head *c; 2171 struct rule_head *r; 2172 2173 iptc_fn = TC_ZERO_COUNTER; 2174 CHECK(handle); 2175 2176 if (!(c = iptcc_find_label(chain, handle))) { 2177 errno = ENOENT; 2178 return 0; 2179 } 2180 2181 if (!(r = iptcc_get_rule_num(c, rulenum))) { 2182 errno = E2BIG; 2183 return 0; 2184 } 2185 2186 if (r->counter_map.maptype == COUNTER_MAP_NORMAL_MAP) 2187 r->counter_map.maptype = COUNTER_MAP_ZEROED; 2188 2189 set_changed(handle); 2190 2191 return 1; 2192 } 2193 2194 int 2195 TC_SET_COUNTER(const IPT_CHAINLABEL chain, 2196 unsigned int rulenum, 2197 STRUCT_COUNTERS *counters, 2198 struct xtc_handle *handle) 2199 { 2200 struct chain_head *c; 2201 struct rule_head *r; 2202 STRUCT_ENTRY *e; 2203 2204 iptc_fn = TC_SET_COUNTER; 2205 CHECK(handle); 2206 2207 if (!(c = iptcc_find_label(chain, handle))) { 2208 errno = ENOENT; 2209 return 0; 2210 } 2211 2212 if (!(r = iptcc_get_rule_num(c, rulenum))) { 2213 errno = E2BIG; 2214 return 0; 2215 } 2216 2217 e = r->entry; 2218 r->counter_map.maptype = COUNTER_MAP_SET; 2219 2220 memcpy(&e->counters, counters, sizeof(STRUCT_COUNTERS)); 2221 2222 set_changed(handle); 2223 2224 return 1; 2225 } 2226 2227 /* Creates a new chain. */ 2228 /* To create a chain, create two rules: error node and unconditional 2229 * return. */ 2230 int 2231 TC_CREATE_CHAIN(const IPT_CHAINLABEL chain, struct xtc_handle *handle) 2232 { 2233 static struct chain_head *c; 2234 int capacity; 2235 int exceeded; 2236 2237 iptc_fn = TC_CREATE_CHAIN; 2238 2239 /* find_label doesn't cover built-in targets: DROP, ACCEPT, 2240 QUEUE, RETURN. */ 2241 if (iptcc_find_label(chain, handle) 2242 || strcmp(chain, LABEL_DROP) == 0 2243 || strcmp(chain, LABEL_ACCEPT) == 0 2244 || strcmp(chain, LABEL_QUEUE) == 0 2245 || strcmp(chain, LABEL_RETURN) == 0) { 2246 DEBUGP("Chain `%s' already exists\n", chain); 2247 errno = EEXIST; 2248 return 0; 2249 } 2250 2251 if (strlen(chain)+1 > sizeof(IPT_CHAINLABEL)) { 2252 DEBUGP("Chain name `%s' too long\n", chain); 2253 errno = EINVAL; 2254 return 0; 2255 } 2256 2257 c = iptcc_alloc_chain_head(chain, 0); 2258 if (!c) { 2259 DEBUGP("Cannot allocate memory for chain `%s'\n", chain); 2260 errno = ENOMEM; 2261 return 0; 2262 2263 } 2264 handle->num_chains++; /* New user defined chain */ 2265 2266 DEBUGP("Creating chain `%s'\n", chain); 2267 iptc_insert_chain(handle, c); /* Insert sorted */ 2268 2269 /* Inserting chains don't change the correctness of the chain 2270 * index (except if its smaller than index[0], but that 2271 * handled by iptc_insert_chain). It only causes longer lists 2272 * in the buckets. Thus, only rebuild chain index when the 2273 * capacity is exceed with CHAIN_INDEX_INSERT_MAX chains. 2274 */ 2275 capacity = handle->chain_index_sz * CHAIN_INDEX_BUCKET_LEN; 2276 exceeded = handle->num_chains - capacity; 2277 if (exceeded > CHAIN_INDEX_INSERT_MAX) { 2278 debug("Capacity(%d) exceeded(%d) rebuild (chains:%d)\n", 2279 capacity, exceeded, handle->num_chains); 2280 iptcc_chain_index_rebuild(handle); 2281 } 2282 2283 set_changed(handle); 2284 2285 return 1; 2286 } 2287 2288 /* Get the number of references to this chain. */ 2289 int 2290 TC_GET_REFERENCES(unsigned int *ref, const IPT_CHAINLABEL chain, 2291 struct xtc_handle *handle) 2292 { 2293 struct chain_head *c; 2294 2295 iptc_fn = TC_GET_REFERENCES; 2296 if (!(c = iptcc_find_label(chain, handle))) { 2297 errno = ENOENT; 2298 return 0; 2299 } 2300 2301 *ref = c->references; 2302 2303 return 1; 2304 } 2305 2306 /* Deletes a chain. */ 2307 int 2308 TC_DELETE_CHAIN(const IPT_CHAINLABEL chain, struct xtc_handle *handle) 2309 { 2310 unsigned int references; 2311 struct chain_head *c; 2312 2313 iptc_fn = TC_DELETE_CHAIN; 2314 2315 if (!(c = iptcc_find_label(chain, handle))) { 2316 DEBUGP("cannot find chain `%s'\n", chain); 2317 errno = ENOENT; 2318 return 0; 2319 } 2320 2321 if (TC_BUILTIN(chain, handle)) { 2322 DEBUGP("cannot remove builtin chain `%s'\n", chain); 2323 errno = EINVAL; 2324 return 0; 2325 } 2326 2327 if (!TC_GET_REFERENCES(&references, chain, handle)) { 2328 DEBUGP("cannot get references on chain `%s'\n", chain); 2329 return 0; 2330 } 2331 2332 if (references > 0) { 2333 DEBUGP("chain `%s' still has references\n", chain); 2334 errno = EMLINK; 2335 return 0; 2336 } 2337 2338 if (c->num_rules) { 2339 DEBUGP("chain `%s' is not empty\n", chain); 2340 errno = ENOTEMPTY; 2341 return 0; 2342 } 2343 2344 /* If we are about to delete the chain that is the current 2345 * iterator, move chain iterator forward. */ 2346 if (c == handle->chain_iterator_cur) 2347 iptcc_chain_iterator_advance(handle); 2348 2349 handle->num_chains--; /* One user defined chain deleted */ 2350 2351 //list_del(&c->list); /* Done in iptcc_chain_index_delete_chain() */ 2352 iptcc_chain_index_delete_chain(c, handle); 2353 free(c); 2354 2355 DEBUGP("chain `%s' deleted\n", chain); 2356 2357 set_changed(handle); 2358 2359 return 1; 2360 } 2361 2362 /* Renames a chain. */ 2363 int TC_RENAME_CHAIN(const IPT_CHAINLABEL oldname, 2364 const IPT_CHAINLABEL newname, 2365 struct xtc_handle *handle) 2366 { 2367 struct chain_head *c; 2368 iptc_fn = TC_RENAME_CHAIN; 2369 2370 /* find_label doesn't cover built-in targets: DROP, ACCEPT, 2371 QUEUE, RETURN. */ 2372 if (iptcc_find_label(newname, handle) 2373 || strcmp(newname, LABEL_DROP) == 0 2374 || strcmp(newname, LABEL_ACCEPT) == 0 2375 || strcmp(newname, LABEL_QUEUE) == 0 2376 || strcmp(newname, LABEL_RETURN) == 0) { 2377 errno = EEXIST; 2378 return 0; 2379 } 2380 2381 if (!(c = iptcc_find_label(oldname, handle)) 2382 || TC_BUILTIN(oldname, handle)) { 2383 errno = ENOENT; 2384 return 0; 2385 } 2386 2387 if (strlen(newname)+1 > sizeof(IPT_CHAINLABEL)) { 2388 errno = EINVAL; 2389 return 0; 2390 } 2391 2392 /* This only unlinks "c" from the list, thus no free(c) */ 2393 iptcc_chain_index_delete_chain(c, handle); 2394 2395 /* Change the name of the chain */ 2396 strncpy(c->name, newname, sizeof(IPT_CHAINLABEL)); 2397 2398 /* Insert sorted into to list again */ 2399 iptc_insert_chain(handle, c); 2400 2401 set_changed(handle); 2402 2403 return 1; 2404 } 2405 2406 /* Sets the policy on a built-in chain. */ 2407 int 2408 TC_SET_POLICY(const IPT_CHAINLABEL chain, 2409 const IPT_CHAINLABEL policy, 2410 STRUCT_COUNTERS *counters, 2411 struct xtc_handle *handle) 2412 { 2413 struct chain_head *c; 2414 2415 iptc_fn = TC_SET_POLICY; 2416 2417 if (!(c = iptcc_find_label(chain, handle))) { 2418 DEBUGP("cannot find chain `%s'\n", chain); 2419 errno = ENOENT; 2420 return 0; 2421 } 2422 2423 if (!iptcc_is_builtin(c)) { 2424 DEBUGP("cannot set policy of userdefinedchain `%s'\n", chain); 2425 errno = ENOENT; 2426 return 0; 2427 } 2428 2429 if (strcmp(policy, LABEL_ACCEPT) == 0) 2430 c->verdict = -NF_ACCEPT - 1; 2431 else if (strcmp(policy, LABEL_DROP) == 0) 2432 c->verdict = -NF_DROP - 1; 2433 else { 2434 errno = EINVAL; 2435 return 0; 2436 } 2437 2438 if (counters) { 2439 /* set byte and packet counters */ 2440 memcpy(&c->counters, counters, sizeof(STRUCT_COUNTERS)); 2441 c->counter_map.maptype = COUNTER_MAP_SET; 2442 } else { 2443 c->counter_map.maptype = COUNTER_MAP_NOMAP; 2444 } 2445 2446 set_changed(handle); 2447 2448 return 1; 2449 } 2450 2451 /* Without this, on gcc 2.7.2.3, we get: 2452 libiptc.c: In function `TC_COMMIT': 2453 libiptc.c:833: fixed or forbidden register was spilled. 2454 This may be due to a compiler bug or to impossible asm 2455 statements or clauses. 2456 */ 2457 static void 2458 subtract_counters(STRUCT_COUNTERS *answer, 2459 const STRUCT_COUNTERS *a, 2460 const STRUCT_COUNTERS *b) 2461 { 2462 answer->pcnt = a->pcnt - b->pcnt; 2463 answer->bcnt = a->bcnt - b->bcnt; 2464 } 2465 2466 2467 static void counters_nomap(STRUCT_COUNTERS_INFO *newcounters, unsigned int idx) 2468 { 2469 newcounters->counters[idx] = ((STRUCT_COUNTERS) { 0, 0}); 2470 DEBUGP_C("NOMAP => zero\n"); 2471 } 2472 2473 static void counters_normal_map(STRUCT_COUNTERS_INFO *newcounters, 2474 STRUCT_REPLACE *repl, unsigned int idx, 2475 unsigned int mappos) 2476 { 2477 /* Original read: X. 2478 * Atomic read on replacement: X + Y. 2479 * Currently in kernel: Z. 2480 * Want in kernel: X + Y + Z. 2481 * => Add in X + Y 2482 * => Add in replacement read. 2483 */ 2484 newcounters->counters[idx] = repl->counters[mappos]; 2485 DEBUGP_C("NORMAL_MAP => mappos %u \n", mappos); 2486 } 2487 2488 static void counters_map_zeroed(STRUCT_COUNTERS_INFO *newcounters, 2489 STRUCT_REPLACE *repl, unsigned int idx, 2490 unsigned int mappos, STRUCT_COUNTERS *counters) 2491 { 2492 /* Original read: X. 2493 * Atomic read on replacement: X + Y. 2494 * Currently in kernel: Z. 2495 * Want in kernel: Y + Z. 2496 * => Add in Y. 2497 * => Add in (replacement read - original read). 2498 */ 2499 subtract_counters(&newcounters->counters[idx], 2500 &repl->counters[mappos], 2501 counters); 2502 DEBUGP_C("ZEROED => mappos %u\n", mappos); 2503 } 2504 2505 static void counters_map_set(STRUCT_COUNTERS_INFO *newcounters, 2506 unsigned int idx, STRUCT_COUNTERS *counters) 2507 { 2508 /* Want to set counter (iptables-restore) */ 2509 2510 memcpy(&newcounters->counters[idx], counters, 2511 sizeof(STRUCT_COUNTERS)); 2512 2513 DEBUGP_C("SET\n"); 2514 } 2515 2516 2517 int 2518 TC_COMMIT(struct xtc_handle *handle) 2519 { 2520 /* Replace, then map back the counters. */ 2521 STRUCT_REPLACE *repl; 2522 STRUCT_COUNTERS_INFO *newcounters; 2523 struct chain_head *c; 2524 int ret; 2525 size_t counterlen; 2526 int new_number; 2527 unsigned int new_size; 2528 2529 iptc_fn = TC_COMMIT; 2530 CHECK(*handle); 2531 2532 /* Don't commit if nothing changed. */ 2533 if (!handle->changed) 2534 goto finished; 2535 2536 new_number = iptcc_compile_table_prep(handle, &new_size); 2537 if (new_number < 0) { 2538 errno = ENOMEM; 2539 goto out_zero; 2540 } 2541 2542 repl = malloc(sizeof(*repl) + new_size); 2543 if (!repl) { 2544 errno = ENOMEM; 2545 goto out_zero; 2546 } 2547 memset(repl, 0, sizeof(*repl) + new_size); 2548 2549 #if 0 2550 TC_DUMP_ENTRIES(*handle); 2551 #endif 2552 2553 counterlen = sizeof(STRUCT_COUNTERS_INFO) 2554 + sizeof(STRUCT_COUNTERS) * new_number; 2555 2556 /* These are the old counters we will get from kernel */ 2557 repl->counters = malloc(sizeof(STRUCT_COUNTERS) 2558 * handle->info.num_entries); 2559 if (!repl->counters) { 2560 errno = ENOMEM; 2561 goto out_free_repl; 2562 } 2563 /* These are the counters we're going to put back, later. */ 2564 newcounters = malloc(counterlen); 2565 if (!newcounters) { 2566 errno = ENOMEM; 2567 goto out_free_repl_counters; 2568 } 2569 memset(newcounters, 0, counterlen); 2570 2571 strcpy(repl->name, handle->info.name); 2572 repl->num_entries = new_number; 2573 repl->size = new_size; 2574 2575 repl->num_counters = handle->info.num_entries; 2576 repl->valid_hooks = handle->info.valid_hooks; 2577 2578 DEBUGP("num_entries=%u, size=%u, num_counters=%u\n", 2579 repl->num_entries, repl->size, repl->num_counters); 2580 2581 ret = iptcc_compile_table(handle, repl); 2582 if (ret < 0) { 2583 errno = ret; 2584 goto out_free_newcounters; 2585 } 2586 2587 2588 #ifdef IPTC_DEBUG2 2589 { 2590 int fd = open("/tmp/libiptc-so_set_replace.blob", 2591 O_CREAT|O_WRONLY); 2592 if (fd >= 0) { 2593 write(fd, repl, sizeof(*repl) + repl->size); 2594 close(fd); 2595 } 2596 } 2597 #endif 2598 2599 ret = setsockopt(handle->sockfd, TC_IPPROTO, SO_SET_REPLACE, repl, 2600 sizeof(*repl) + repl->size); 2601 if (ret < 0) 2602 goto out_free_newcounters; 2603 2604 /* Put counters back. */ 2605 strcpy(newcounters->name, handle->info.name); 2606 newcounters->num_counters = new_number; 2607 2608 list_for_each_entry(c, &handle->chains, list) { 2609 struct rule_head *r; 2610 2611 /* Builtin chains have their own counters */ 2612 if (iptcc_is_builtin(c)) { 2613 DEBUGP("counter for chain-index %u: ", c->foot_index); 2614 switch(c->counter_map.maptype) { 2615 case COUNTER_MAP_NOMAP: 2616 counters_nomap(newcounters, c->foot_index); 2617 break; 2618 case COUNTER_MAP_NORMAL_MAP: 2619 counters_normal_map(newcounters, repl, 2620 c->foot_index, 2621 c->counter_map.mappos); 2622 break; 2623 case COUNTER_MAP_ZEROED: 2624 counters_map_zeroed(newcounters, repl, 2625 c->foot_index, 2626 c->counter_map.mappos, 2627 &c->counters); 2628 break; 2629 case COUNTER_MAP_SET: 2630 counters_map_set(newcounters, c->foot_index, 2631 &c->counters); 2632 break; 2633 } 2634 } 2635 2636 list_for_each_entry(r, &c->rules, list) { 2637 DEBUGP("counter for index %u: ", r->index); 2638 switch (r->counter_map.maptype) { 2639 case COUNTER_MAP_NOMAP: 2640 counters_nomap(newcounters, r->index); 2641 break; 2642 2643 case COUNTER_MAP_NORMAL_MAP: 2644 counters_normal_map(newcounters, repl, 2645 r->index, 2646 r->counter_map.mappos); 2647 break; 2648 2649 case COUNTER_MAP_ZEROED: 2650 counters_map_zeroed(newcounters, repl, 2651 r->index, 2652 r->counter_map.mappos, 2653 &r->entry->counters); 2654 break; 2655 2656 case COUNTER_MAP_SET: 2657 counters_map_set(newcounters, r->index, 2658 &r->entry->counters); 2659 break; 2660 } 2661 } 2662 } 2663 2664 #ifdef IPTC_DEBUG2 2665 { 2666 int fd = open("/tmp/libiptc-so_set_add_counters.blob", 2667 O_CREAT|O_WRONLY); 2668 if (fd >= 0) { 2669 write(fd, newcounters, counterlen); 2670 close(fd); 2671 } 2672 } 2673 #endif 2674 2675 ret = setsockopt(handle->sockfd, TC_IPPROTO, SO_SET_ADD_COUNTERS, 2676 newcounters, counterlen); 2677 if (ret < 0) 2678 goto out_free_newcounters; 2679 2680 free(repl->counters); 2681 free(repl); 2682 free(newcounters); 2683 2684 finished: 2685 return 1; 2686 2687 out_free_newcounters: 2688 free(newcounters); 2689 out_free_repl_counters: 2690 free(repl->counters); 2691 out_free_repl: 2692 free(repl); 2693 out_zero: 2694 return 0; 2695 } 2696 2697 /* Translates errno numbers into more human-readable form than strerror. */ 2698 const char * 2699 TC_STRERROR(int err) 2700 { 2701 unsigned int i; 2702 struct table_struct { 2703 void *fn; 2704 int err; 2705 const char *message; 2706 } table [] = 2707 { { TC_INIT, EPERM, "Permission denied (you must be root)" }, 2708 { TC_INIT, EINVAL, "Module is wrong version" }, 2709 { TC_INIT, ENOENT, 2710 "Table does not exist (do you need to insmod?)" }, 2711 { TC_DELETE_CHAIN, ENOTEMPTY, "Chain is not empty" }, 2712 { TC_DELETE_CHAIN, EINVAL, "Can't delete built-in chain" }, 2713 { TC_DELETE_CHAIN, EMLINK, 2714 "Can't delete chain with references left" }, 2715 { TC_CREATE_CHAIN, EEXIST, "Chain already exists" }, 2716 { TC_INSERT_ENTRY, E2BIG, "Index of insertion too big" }, 2717 { TC_REPLACE_ENTRY, E2BIG, "Index of replacement too big" }, 2718 { TC_DELETE_NUM_ENTRY, E2BIG, "Index of deletion too big" }, 2719 { TC_READ_COUNTER, E2BIG, "Index of counter too big" }, 2720 { TC_ZERO_COUNTER, E2BIG, "Index of counter too big" }, 2721 { TC_INSERT_ENTRY, ELOOP, "Loop found in table" }, 2722 { TC_INSERT_ENTRY, EINVAL, "Target problem" }, 2723 /* ENOENT for DELETE probably means no matching rule */ 2724 { TC_DELETE_ENTRY, ENOENT, 2725 "Bad rule (does a matching rule exist in that chain?)" }, 2726 { TC_SET_POLICY, ENOENT, 2727 "Bad built-in chain name" }, 2728 { TC_SET_POLICY, EINVAL, 2729 "Bad policy name" }, 2730 2731 { NULL, 0, "Incompatible with this kernel" }, 2732 { NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" }, 2733 { NULL, ENOSYS, "Will be implemented real soon. I promise ;)" }, 2734 { NULL, ENOMEM, "Memory allocation problem" }, 2735 { NULL, ENOENT, "No chain/target/match by that name" }, 2736 }; 2737 2738 for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) { 2739 if ((!table[i].fn || table[i].fn == iptc_fn) 2740 && table[i].err == err) 2741 return table[i].message; 2742 } 2743 2744 return strerror(err); 2745 } 2746