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