libiptc.c revision 52c380208a87191a8c25608d2c501c0dc32aa9ad
1/* Library which manipulates firewall rules. Version $Revision: 1.50 $ */ 2 3/* Architecture of firewall rules is as follows: 4 * 5 * Chains go INPUT, FORWARD, OUTPUT then user chains. 6 * Each user chain starts with an ERROR node. 7 * Every chain ends with an unconditional jump: a RETURN for user chains, 8 * and a POLICY for built-ins. 9 */ 10 11/* (C) 1999 Paul ``Rusty'' Russell - Placed under the GNU GPL (See 12 * COPYING for details). 13 * (C) 2000-2004 by the Netfilter Core Team <coreteam@netfilter.org> 14 * 15 * 2003-Jun-20: Harald Welte <laforge@netfilter.org>: 16 * - Reimplementation of chain cache to use offsets instead of entries 17 * 2003-Jun-23: Harald Welte <laforge@netfilter.org>: 18 * - performance optimization, sponsored by Astaro AG (http://www.astaro.com/) 19 * don't rebuild the chain cache after every operation, instead fix it 20 * up after a ruleset change. 21 * 2004-Aug-18: Harald Welte <laforge@netfilter.org>: 22 * - futher 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#include <sys/types.h> 28#include <sys/socket.h> 29 30#include "linux_list.h" 31 32//#define IPTC_DEBUG2 1 33 34#ifdef IPTC_DEBUG2 35#include <fcntl.h> 36#define DEBUGP(x, args...) fprintf(stderr, "%s: " x, __FUNCTION__, ## args) 37#define DEBUGP_C(x, args...) fprintf(stderr, x, ## args) 38#else 39#define DEBUGP(x, args...) 40#define DEBUGP_C(x, args...) 41#endif 42 43#ifndef IPT_LIB_DIR 44#define IPT_LIB_DIR "/usr/local/lib/iptables" 45#endif 46 47#ifndef __OPTIMIZE__ 48STRUCT_ENTRY_TARGET * 49GET_TARGET(STRUCT_ENTRY *e) 50{ 51 return (void *)e + e->target_offset; 52} 53#endif 54 55static int sockfd = -1; 56static void *iptc_fn = NULL; 57 58static const char *hooknames[] 59= { [HOOK_PRE_ROUTING] "PREROUTING", 60 [HOOK_LOCAL_IN] "INPUT", 61 [HOOK_FORWARD] "FORWARD", 62 [HOOK_LOCAL_OUT] "OUTPUT", 63 [HOOK_POST_ROUTING] "POSTROUTING", 64#ifdef HOOK_DROPPING 65 [HOOK_DROPPING] "DROPPING" 66#endif 67}; 68 69/* Convenience structures */ 70struct ipt_error_target 71{ 72 STRUCT_ENTRY_TARGET t; 73 char error[TABLE_MAXNAMELEN]; 74}; 75 76struct chain_head; 77struct rule_head; 78 79struct counter_map 80{ 81 enum { 82 COUNTER_MAP_NOMAP, 83 COUNTER_MAP_NORMAL_MAP, 84 COUNTER_MAP_ZEROED, 85 COUNTER_MAP_SET 86 } maptype; 87 unsigned int mappos; 88}; 89 90enum iptcc_rule_type { 91 IPTCC_R_STANDARD, /* standard target (ACCEPT, ...) */ 92 IPTCC_R_MODULE, /* extension module (SNAT, ...) */ 93 IPTCC_R_FALLTHROUGH, /* fallthrough rule */ 94 IPTCC_R_JUMP, /* jump to other chain */ 95}; 96 97struct rule_head 98{ 99 struct list_head list; 100 struct chain_head *chain; 101 struct counter_map counter_map; 102 103 unsigned int index; /* index (needed for counter_map) */ 104 unsigned int offset; /* offset in rule blob */ 105 106 enum iptcc_rule_type type; 107 struct chain_head *jump; /* jump target, if IPTCC_R_JUMP */ 108 109 unsigned int size; /* size of entry data */ 110 STRUCT_ENTRY entry[0]; 111}; 112 113struct chain_head 114{ 115 struct list_head list; 116 char name[TABLE_MAXNAMELEN]; 117 unsigned int hooknum; /* hook number+1 if builtin */ 118 unsigned int references; /* how many jumps reference us */ 119 int verdict; /* verdict if builtin */ 120 121 STRUCT_COUNTERS counters; /* per-chain counters */ 122 struct counter_map counter_map; 123 124 unsigned int num_rules; /* number of rules in list */ 125 struct list_head rules; /* list of rules */ 126 127 unsigned int index; /* index (needed for jump resolval) */ 128 unsigned int head_offset; /* offset in rule blob */ 129 unsigned int foot_index; /* index (needed for counter_map) */ 130 unsigned int foot_offset; /* offset in rule blob */ 131}; 132 133STRUCT_TC_HANDLE 134{ 135 int changed; /* Have changes been made? */ 136 137 struct list_head chains; 138 139 struct chain_head *chain_iterator_cur; 140 struct rule_head *rule_iterator_cur; 141 142 STRUCT_GETINFO info; 143 STRUCT_GET_ENTRIES *entries; 144}; 145 146/* allocate a new chain head for the cache */ 147static struct chain_head *iptcc_alloc_chain_head(const char *name, int hooknum) 148{ 149 struct chain_head *c = malloc(sizeof(*c)); 150 if (!c) 151 return NULL; 152 memset(c, 0, sizeof(*c)); 153 154 strncpy(c->name, name, TABLE_MAXNAMELEN); 155 c->hooknum = hooknum; 156 INIT_LIST_HEAD(&c->rules); 157 158 return c; 159} 160 161/* allocate and initialize a new rule for the cache */ 162static struct rule_head *iptcc_alloc_rule(struct chain_head *c, unsigned int size) 163{ 164 struct rule_head *r = malloc(sizeof(*r)+size); 165 if (!r) 166 return NULL; 167 memset(r, 0, sizeof(*r)); 168 169 r->chain = c; 170 r->size = size; 171 172 return r; 173} 174 175/* notify us that the ruleset has been modified by the user */ 176static void 177set_changed(TC_HANDLE_T h) 178{ 179 h->changed = 1; 180} 181 182#ifdef IPTC_DEBUG 183static void do_check(TC_HANDLE_T h, unsigned int line); 184#define CHECK(h) do { if (!getenv("IPTC_NO_CHECK")) do_check((h), __LINE__); } while(0) 185#else 186#define CHECK(h) 187#endif 188 189 190/********************************************************************** 191 * iptc blob utility functions (iptcb_*) 192 **********************************************************************/ 193 194static inline int 195iptcb_get_number(const STRUCT_ENTRY *i, 196 const STRUCT_ENTRY *seek, 197 unsigned int *pos) 198{ 199 if (i == seek) 200 return 1; 201 (*pos)++; 202 return 0; 203} 204 205static inline int 206iptcb_get_entry_n(STRUCT_ENTRY *i, 207 unsigned int number, 208 unsigned int *pos, 209 STRUCT_ENTRY **pe) 210{ 211 if (*pos == number) { 212 *pe = i; 213 return 1; 214 } 215 (*pos)++; 216 return 0; 217} 218 219static inline STRUCT_ENTRY * 220iptcb_get_entry(TC_HANDLE_T h, unsigned int offset) 221{ 222 return (STRUCT_ENTRY *)((char *)h->entries->entrytable + offset); 223} 224 225static unsigned int 226iptcb_entry2index(const TC_HANDLE_T h, const STRUCT_ENTRY *seek) 227{ 228 unsigned int pos = 0; 229 230 if (ENTRY_ITERATE(h->entries->entrytable, h->entries->size, 231 iptcb_get_number, seek, &pos) == 0) { 232 fprintf(stderr, "ERROR: offset %u not an entry!\n", 233 (unsigned int)((char *)seek - (char *)h->entries->entrytable)); 234 abort(); 235 } 236 return pos; 237} 238 239static inline STRUCT_ENTRY * 240iptcb_offset2entry(TC_HANDLE_T h, unsigned int offset) 241{ 242 return (STRUCT_ENTRY *) ((void *)h->entries->entrytable+offset); 243} 244 245 246static inline unsigned long 247iptcb_entry2offset(const TC_HANDLE_T h, const STRUCT_ENTRY *e) 248{ 249 return (void *)e - (void *)h->entries->entrytable; 250} 251 252static inline unsigned int 253iptcb_offset2index(const TC_HANDLE_T h, unsigned int offset) 254{ 255 return iptcb_entry2index(h, iptcb_offset2entry(h, offset)); 256} 257 258/* Returns 0 if not hook entry, else hooknumber + 1 */ 259static inline unsigned int 260iptcb_ent_is_hook_entry(STRUCT_ENTRY *e, TC_HANDLE_T h) 261{ 262 unsigned int i; 263 264 for (i = 0; i < NUMHOOKS; i++) { 265 if ((h->info.valid_hooks & (1 << i)) 266 && iptcb_get_entry(h, h->info.hook_entry[i]) == e) 267 return i+1; 268 } 269 return 0; 270} 271 272 273/********************************************************************** 274 * iptc cache utility functions (iptcc_*) 275 **********************************************************************/ 276 277/* Is the given chain builtin (1) or user-defined (0) */ 278static unsigned int iptcc_is_builtin(struct chain_head *c) 279{ 280 return (c->hooknum ? 1 : 0); 281} 282 283/* Get a specific rule within a chain */ 284static struct rule_head *iptcc_get_rule_num(struct chain_head *c, 285 unsigned int rulenum) 286{ 287 struct rule_head *r; 288 unsigned int num = 0; 289 290 list_for_each_entry(r, &c->rules, list) { 291 num++; 292 if (num == rulenum) 293 return r; 294 } 295 return NULL; 296} 297 298/* Returns chain head if found, otherwise NULL. */ 299static struct chain_head * 300iptcc_find_chain_by_offset(TC_HANDLE_T handle, unsigned int offset) 301{ 302 struct list_head *pos; 303 304 if (list_empty(&handle->chains)) 305 return NULL; 306 307 list_for_each(pos, &handle->chains) { 308 struct chain_head *c = list_entry(pos, struct chain_head, list); 309 if (offset >= c->head_offset && offset <= c->foot_offset) 310 return c; 311 } 312 313 return NULL; 314} 315/* Returns chain head if found, otherwise NULL. */ 316static struct chain_head * 317iptcc_find_label(const char *name, TC_HANDLE_T handle) 318{ 319 struct list_head *pos; 320 321 if (list_empty(&handle->chains)) 322 return NULL; 323 324 list_for_each(pos, &handle->chains) { 325 struct chain_head *c = list_entry(pos, struct chain_head, list); 326 if (!strcmp(c->name, name)) 327 return c; 328 } 329 330 return NULL; 331} 332 333/* called when rule is to be removed from cache */ 334static void iptcc_delete_rule(struct rule_head *r) 335{ 336 DEBUGP("deleting rule %p (offset %u)\n", r, r->offset); 337 /* clean up reference count of called chain */ 338 if (r->type == IPTCC_R_JUMP 339 && r->jump) 340 r->jump->references--; 341 342 list_del(&r->list); 343 free(r); 344} 345 346 347/********************************************************************** 348 * RULESET PARSER (blob -> cache) 349 **********************************************************************/ 350 351static int alphasort(const void *a, const void *b) 352{ 353 return strcmp(((struct chain_head *)a)->name, 354 ((struct chain_head *)b)->name); 355} 356 357/* Delete policy rule of previous chain, since cache doesn't contain 358 * chain policy rules. 359 * WARNING: This function has ugly design and relies on a lot of context, only 360 * to be called from specific places within the parser */ 361static int __iptcc_p_del_policy(TC_HANDLE_T h, unsigned int num) 362{ 363 if (h->chain_iterator_cur) { 364 /* policy rule is last rule */ 365 struct rule_head *pr = (struct rule_head *) 366 h->chain_iterator_cur->rules.prev; 367 368 /* save verdict */ 369 h->chain_iterator_cur->verdict = 370 *(int *)GET_TARGET(pr->entry)->data; 371 372 /* save counter and counter_map information */ 373 h->chain_iterator_cur->counter_map.maptype = 374 COUNTER_MAP_NORMAL_MAP; 375 h->chain_iterator_cur->counter_map.mappos = num-1; 376 memcpy(&h->chain_iterator_cur->counters, &pr->entry->counters, 377 sizeof(h->chain_iterator_cur->counters)); 378 379 /* foot_offset points to verdict rule */ 380 h->chain_iterator_cur->foot_index = num; 381 h->chain_iterator_cur->foot_offset = pr->offset; 382 383 /* delete rule from cache */ 384 iptcc_delete_rule(pr); 385 386 return 1; 387 } 388 return 0; 389} 390 391/* Another ugly helper function split out of cache_add_entry to make it less 392 * spaghetti code */ 393static void __iptcc_p_add_chain(TC_HANDLE_T h, struct chain_head *c, 394 unsigned int offset, unsigned int *num) 395{ 396 __iptcc_p_del_policy(h, *num); 397 398 c->head_offset = offset; 399 c->index = *num; 400 401 list_add_tail(&c->list, &h->chains); 402 h->chain_iterator_cur = c; 403} 404 405/* main parser function: add an entry from the blob to the cache */ 406static int cache_add_entry(STRUCT_ENTRY *e, 407 TC_HANDLE_T h, 408 STRUCT_ENTRY **prev, 409 unsigned int *num) 410{ 411 unsigned int builtin; 412 unsigned int offset = (char *)e - (char *)h->entries->entrytable; 413 414 DEBUGP("entering..."); 415 416 /* Last entry ("policy rule"). End it.*/ 417 if (iptcb_entry2offset(h,e) + e->next_offset == h->entries->size) { 418 /* This is the ERROR node at the end of the chain */ 419 DEBUGP_C("%u:%u: end of table:\n", *num, offset); 420 421 __iptcc_p_del_policy(h, *num); 422 423 h->chain_iterator_cur = NULL; 424 goto out_inc; 425 } 426 427 /* We know this is the start of a new chain if it's an ERROR 428 * target, or a hook entry point */ 429 430 if (strcmp(GET_TARGET(e)->u.user.name, ERROR_TARGET) == 0) { 431 struct chain_head *c = 432 iptcc_alloc_chain_head((const char *)GET_TARGET(e)->data, 0); 433 DEBUGP_C("%u:%u:new userdefined chain %s: %p\n", *num, offset, 434 (char *)c->name, c); 435 if (!c) { 436 errno = -ENOMEM; 437 return -1; 438 } 439 440 __iptcc_p_add_chain(h, c, offset, num); 441 442 } else if ((builtin = iptcb_ent_is_hook_entry(e, h)) != 0) { 443 struct chain_head *c = 444 iptcc_alloc_chain_head((char *)hooknames[builtin-1], 445 builtin); 446 DEBUGP_C("%u:%u new builtin chain: %p (rules=%p)\n", 447 *num, offset, c, &c->rules); 448 if (!c) { 449 errno = -ENOMEM; 450 return -1; 451 } 452 453 c->hooknum = builtin; 454 455 __iptcc_p_add_chain(h, c, offset, num); 456 457 /* FIXME: this is ugly. */ 458 goto new_rule; 459 } else { 460 /* has to be normal rule */ 461 struct rule_head *r; 462new_rule: 463 464 if (!(r = iptcc_alloc_rule(h->chain_iterator_cur, 465 e->next_offset))) { 466 errno = ENOMEM; 467 return -1; 468 } 469 DEBUGP_C("%u:%u normal rule: %p: ", *num, offset, r); 470 471 r->index = *num; 472 r->offset = offset; 473 memcpy(r->entry, e, e->next_offset); 474 r->counter_map.maptype = COUNTER_MAP_NORMAL_MAP; 475 r->counter_map.mappos = r->index; 476 477 /* handling of jumps, etc. */ 478 if (!strcmp(GET_TARGET(e)->u.user.name, STANDARD_TARGET)) { 479 STRUCT_STANDARD_TARGET *t; 480 481 t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e); 482 if (t->target.u.target_size 483 != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) { 484 errno = EINVAL; 485 return -1; 486 } 487 488 if (t->verdict < 0) { 489 DEBUGP_C("standard, verdict=%d\n", t->verdict); 490 r->type = IPTCC_R_STANDARD; 491 } else if (t->verdict == r->offset+e->next_offset) { 492 DEBUGP_C("fallthrough\n"); 493 r->type = IPTCC_R_FALLTHROUGH; 494 } else { 495 DEBUGP_C("jump, target=%u\n", t->verdict); 496 r->type = IPTCC_R_JUMP; 497 /* Jump target fixup has to be deferred 498 * until second pass, since we migh not 499 * yet have parsed the target */ 500 } 501 } else { 502 DEBUGP_C("module, target=%s\n", GET_TARGET(e)->u.user.name); 503 r->type = IPTCC_R_MODULE; 504 } 505 506 list_add_tail(&r->list, &h->chain_iterator_cur->rules); 507 } 508out_inc: 509 (*num)++; 510 return 0; 511} 512 513 514/* parse an iptables blob into it's pieces */ 515static int parse_table(TC_HANDLE_T h) 516{ 517 STRUCT_ENTRY *prev; 518 unsigned int num = 0; 519 struct chain_head *c; 520 521 /* First pass: over ruleset blob */ 522 ENTRY_ITERATE(h->entries->entrytable, h->entries->size, 523 cache_add_entry, h, &prev, &num); 524 525 /* Second pass: fixup parsed data from first pass */ 526 list_for_each_entry(c, &h->chains, list) { 527 struct rule_head *r; 528 list_for_each_entry(r, &c->rules, list) { 529 struct chain_head *c; 530 STRUCT_STANDARD_TARGET *t; 531 532 if (r->type != IPTCC_R_JUMP) 533 continue; 534 535 t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry); 536 c = iptcc_find_chain_by_offset(h, t->verdict); 537 if (!c) 538 return -1; 539 r->jump = c; 540 c->references++; 541 } 542 } 543 544 /* FIXME: sort chains */ 545 546 return 1; 547} 548 549 550/********************************************************************** 551 * RULESET COMPILATION (cache -> blob) 552 **********************************************************************/ 553 554/* Convenience structures */ 555struct iptcb_chain_start{ 556 STRUCT_ENTRY e; 557 struct ipt_error_target name; 558}; 559#define IPTCB_CHAIN_START_SIZE (sizeof(STRUCT_ENTRY) + \ 560 ALIGN(sizeof(struct ipt_error_target))) 561 562struct iptcb_chain_foot { 563 STRUCT_ENTRY e; 564 STRUCT_STANDARD_TARGET target; 565}; 566#define IPTCB_CHAIN_FOOT_SIZE (sizeof(STRUCT_ENTRY) + \ 567 ALIGN(sizeof(STRUCT_STANDARD_TARGET))) 568 569struct iptcb_chain_error { 570 STRUCT_ENTRY entry; 571 struct ipt_error_target target; 572}; 573#define IPTCB_CHAIN_ERROR_SIZE (sizeof(STRUCT_ENTRY) + \ 574 ALIGN(sizeof(struct ipt_error_target))) 575 576 577 578/* compile rule from cache into blob */ 579static inline int iptcc_compile_rule (TC_HANDLE_T h, STRUCT_REPLACE *repl, struct rule_head *r) 580{ 581 /* handle jumps */ 582 if (r->type == IPTCC_R_JUMP) { 583 STRUCT_STANDARD_TARGET *t; 584 t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry); 585 /* memset for memcmp convenience on delete/replace */ 586 memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN); 587 strcpy(t->target.u.user.name, STANDARD_TARGET); 588 /* Jumps can only happen to builtin chains, so we 589 * can safely assume that they always have a header */ 590 t->verdict = r->jump->head_offset + IPTCB_CHAIN_START_SIZE; 591 } else if (r->type == IPTCC_R_FALLTHROUGH) { 592 STRUCT_STANDARD_TARGET *t; 593 t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry); 594 t->verdict = r->offset + r->size; 595 } 596 597 /* copy entry from cache to blob */ 598 memcpy((char *)repl->entries+r->offset, r->entry, r->size); 599 600 return 1; 601} 602 603/* compile chain from cache into blob */ 604static int iptcc_compile_chain(TC_HANDLE_T h, STRUCT_REPLACE *repl, struct chain_head *c) 605{ 606 int ret; 607 struct rule_head *r; 608 struct iptcb_chain_start *head; 609 struct iptcb_chain_foot *foot; 610 611 /* only user-defined chains have heaer */ 612 if (!iptcc_is_builtin(c)) { 613 /* put chain header in place */ 614 head = (void *)repl->entries + c->head_offset; 615 head->e.target_offset = sizeof(STRUCT_ENTRY); 616 head->e.next_offset = IPTCB_CHAIN_START_SIZE; 617 strcpy(head->name.t.u.user.name, ERROR_TARGET); 618 head->name.t.u.target_size = 619 ALIGN(sizeof(struct ipt_error_target)); 620 strcpy(head->name.error, c->name); 621 } else { 622 repl->hook_entry[c->hooknum-1] = c->head_offset; 623 repl->underflow[c->hooknum-1] = c->foot_offset; 624 } 625 626 /* iterate over rules */ 627 list_for_each_entry(r, &c->rules, list) { 628 ret = iptcc_compile_rule(h, repl, r); 629 if (ret < 0) 630 return ret; 631 } 632 633 /* put chain footer in place */ 634 foot = (void *)repl->entries + c->foot_offset; 635 foot->e.target_offset = sizeof(STRUCT_ENTRY); 636 foot->e.next_offset = IPTCB_CHAIN_FOOT_SIZE; 637 strcpy(foot->target.target.u.user.name, STANDARD_TARGET); 638 foot->target.target.u.target_size = 639 ALIGN(sizeof(STRUCT_STANDARD_TARGET)); 640 /* builtin targets have verdict, others return */ 641 if (iptcc_is_builtin(c)) 642 foot->target.verdict = c->verdict; 643 else 644 foot->target.verdict = RETURN; 645 /* set policy-counters */ 646 memcpy(&foot->e.counters, &c->counters, sizeof(STRUCT_COUNTERS)); 647 648 return 0; 649} 650 651/* calculate offset and number for every rule in the cache */ 652static int iptcc_compile_chain_offsets(TC_HANDLE_T h, struct chain_head *c, 653 int *offset, int *num) 654{ 655 struct rule_head *r; 656 657 c->head_offset = *offset; 658 DEBUGP("%s: chain_head %u, offset=%u\n", c->name, *num, *offset); 659 660 if (!iptcc_is_builtin(c)) { 661 /* Chain has header */ 662 *offset += sizeof(STRUCT_ENTRY) 663 + ALIGN(sizeof(struct ipt_error_target)); 664 (*num)++; 665 } 666 667 list_for_each_entry(r, &c->rules, list) { 668 DEBUGP("rule %u, offset=%u, index=%u\n", *num, *offset, *num); 669 r->offset = *offset; 670 r->index = *num; 671 *offset += r->size; 672 (*num)++; 673 } 674 675 DEBUGP("%s; chain_foot %u, offset=%u, index=%u\n", c->name, *num, 676 *offset, *num); 677 c->foot_offset = *offset; 678 c->foot_index = *num; 679 *offset += sizeof(STRUCT_ENTRY) 680 + ALIGN(sizeof(STRUCT_STANDARD_TARGET)); 681 (*num)++; 682 683 return 1; 684} 685 686/* put the pieces back together again */ 687static int iptcc_compile_table_prep(TC_HANDLE_T h, unsigned int *size) 688{ 689 struct chain_head *c; 690 unsigned int offset = 0, num = 0; 691 int ret = 0; 692 693 /* First pass: calculate offset for every rule */ 694 list_for_each_entry(c, &h->chains, list) { 695 ret = iptcc_compile_chain_offsets(h, c, &offset, &num); 696 if (ret < 0) 697 return ret; 698 } 699 700 /* Append one error rule at end of chain */ 701 num++; 702 offset += sizeof(STRUCT_ENTRY) 703 + ALIGN(sizeof(struct ipt_error_target)); 704 705 /* ruleset size is now in offset */ 706 *size = offset; 707 return num; 708} 709 710static int iptcc_compile_table(TC_HANDLE_T h, STRUCT_REPLACE *repl) 711{ 712 struct chain_head *c; 713 struct iptcb_chain_error *error; 714 715 /* Second pass: copy from cache to offsets, fill in jumps */ 716 list_for_each_entry(c, &h->chains, list) { 717 int ret = iptcc_compile_chain(h, repl, c); 718 if (ret < 0) 719 return ret; 720 } 721 722 /* Append error rule at end of chain */ 723 error = (void *)repl->entries + repl->size - IPTCB_CHAIN_ERROR_SIZE; 724 error->entry.target_offset = sizeof(STRUCT_ENTRY); 725 error->entry.next_offset = IPTCB_CHAIN_ERROR_SIZE; 726 error->target.t.u.user.target_size = 727 ALIGN(sizeof(struct ipt_error_target)); 728 strcpy((char *)&error->target.t.u.user.name, ERROR_TARGET); 729 strcpy((char *)&error->target.error, "ERROR"); 730 731 return 1; 732} 733 734/********************************************************************** 735 * EXTERNAL API (operates on cache only) 736 **********************************************************************/ 737 738/* Allocate handle of given size */ 739static TC_HANDLE_T 740alloc_handle(const char *tablename, unsigned int size, unsigned int num_rules) 741{ 742 size_t len; 743 TC_HANDLE_T h; 744 745 len = sizeof(STRUCT_TC_HANDLE) + size; 746 747 h = malloc(sizeof(STRUCT_TC_HANDLE)); 748 if (!h) { 749 errno = ENOMEM; 750 return NULL; 751 } 752 memset(h, 0, sizeof(*h)); 753 INIT_LIST_HEAD(&h->chains); 754 strcpy(h->info.name, tablename); 755 756 h->entries = malloc(sizeof(STRUCT_GET_ENTRIES) + size); 757 if (!h->entries) 758 goto out_free_handle; 759 760 strcpy(h->entries->name, tablename); 761 h->entries->size = size; 762 763 return h; 764 765out_free_handle: 766 free(h); 767 768 return NULL; 769} 770 771 772TC_HANDLE_T 773TC_INIT(const char *tablename) 774{ 775 TC_HANDLE_T h; 776 STRUCT_GETINFO info; 777 int tmp; 778 socklen_t s; 779 780 iptc_fn = TC_INIT; 781 782 if (sockfd != -1) { 783 close(sockfd); 784 sockfd = -1; 785 } 786 787 if (strlen(tablename) >= TABLE_MAXNAMELEN) { 788 errno = EINVAL; 789 return NULL; 790 } 791 792 sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW); 793 if (sockfd < 0) 794 return NULL; 795 796 s = sizeof(info); 797 798 strcpy(info.name, tablename); 799 if (getsockopt(sockfd, TC_IPPROTO, SO_GET_INFO, &info, &s) < 0) 800 return NULL; 801 802 DEBUGP("valid_hooks=0x%08x, num_entries=%u, size=%u\n", 803 info.valid_hooks, info.num_entries, info.size); 804 805 if ((h = alloc_handle(info.name, info.size, info.num_entries)) 806 == NULL) { 807 close(sockfd); 808 sockfd = -1; 809 return NULL; 810 } 811 812 /* Initialize current state */ 813 h->info = info; 814 815 h->entries->size = h->info.size; 816 817 tmp = sizeof(STRUCT_GET_ENTRIES) + h->info.size; 818 819 if (getsockopt(sockfd, TC_IPPROTO, SO_GET_ENTRIES, h->entries, 820 &tmp) < 0) 821 goto error; 822 823#ifdef IPTC_DEBUG2 824 { 825 int fd = open("/tmp/libiptc-so_get_entries.blob", 826 O_CREAT|O_WRONLY); 827 if (fd >= 0) { 828 write(fd, h->entries, tmp); 829 close(fd); 830 } 831 } 832#endif 833 834 if (parse_table(h) < 0) 835 goto error; 836 837 CHECK(h); 838 return h; 839error: 840 TC_FREE(&h); 841 return NULL; 842} 843 844void 845TC_FREE(TC_HANDLE_T *h) 846{ 847 struct chain_head *c, *tmp; 848 849 close(sockfd); 850 sockfd = -1; 851 852 list_for_each_entry_safe(c, tmp, &(*h)->chains, list) { 853 struct rule_head *r, *rtmp; 854 855 list_for_each_entry_safe(r, rtmp, &c->rules, list) { 856 free(r); 857 } 858 859 free(c); 860 } 861 862 free((*h)->entries); 863 free(*h); 864 865 *h = NULL; 866} 867 868static inline int 869print_match(const STRUCT_ENTRY_MATCH *m) 870{ 871 printf("Match name: `%s'\n", m->u.user.name); 872 return 0; 873} 874 875static int dump_entry(STRUCT_ENTRY *e, const TC_HANDLE_T handle); 876 877void 878TC_DUMP_ENTRIES(const TC_HANDLE_T handle) 879{ 880 CHECK(handle); 881#if 0 882 printf("libiptc v%s. %u entries, %u bytes.\n", 883 IPTABLES_VERSION, 884 handle->new_number, handle->entries->size); 885 printf("Table `%s'\n", handle->info.name); 886 printf("Hooks: pre/in/fwd/out/post = %u/%u/%u/%u/%u\n", 887 handle->info.hook_entry[HOOK_PRE_ROUTING], 888 handle->info.hook_entry[HOOK_LOCAL_IN], 889 handle->info.hook_entry[HOOK_FORWARD], 890 handle->info.hook_entry[HOOK_LOCAL_OUT], 891 handle->info.hook_entry[HOOK_POST_ROUTING]); 892 printf("Underflows: pre/in/fwd/out/post = %u/%u/%u/%u/%u\n", 893 handle->info.underflow[HOOK_PRE_ROUTING], 894 handle->info.underflow[HOOK_LOCAL_IN], 895 handle->info.underflow[HOOK_FORWARD], 896 handle->info.underflow[HOOK_LOCAL_OUT], 897 handle->info.underflow[HOOK_POST_ROUTING]); 898 899 ENTRY_ITERATE(handle->entries->entrytable, handle->entries->size, 900 dump_entry, handle); 901#endif 902} 903 904/* Does this chain exist? */ 905int TC_IS_CHAIN(const char *chain, const TC_HANDLE_T handle) 906{ 907 return iptcc_find_label(chain, handle) != NULL; 908} 909 910static void iptcc_chain_iterator_advance(TC_HANDLE_T handle) 911{ 912 struct chain_head *c = handle->chain_iterator_cur; 913 914 if (c->list.next == &handle->chains) 915 handle->chain_iterator_cur = NULL; 916 else 917 handle->chain_iterator_cur = 918 list_entry(c->list.next, struct chain_head, list); 919} 920 921/* Iterator functions to run through the chains. */ 922const char * 923TC_FIRST_CHAIN(TC_HANDLE_T *handle) 924{ 925 struct chain_head *c = list_entry((*handle)->chains.next, 926 struct chain_head, list); 927 928 iptc_fn = TC_FIRST_CHAIN; 929 930 931 if (list_empty(&(*handle)->chains)) { 932 DEBUGP(": no chains\n"); 933 return NULL; 934 } 935 936 (*handle)->chain_iterator_cur = c; 937 iptcc_chain_iterator_advance(*handle); 938 939 DEBUGP(": returning `%s'\n", c->name); 940 return c->name; 941} 942 943/* Iterator functions to run through the chains. Returns NULL at end. */ 944const char * 945TC_NEXT_CHAIN(TC_HANDLE_T *handle) 946{ 947 struct chain_head *c = (*handle)->chain_iterator_cur; 948 949 iptc_fn = TC_NEXT_CHAIN; 950 951 if (!c) { 952 DEBUGP(": no more chains\n"); 953 return NULL; 954 } 955 956 iptcc_chain_iterator_advance(*handle); 957 958 DEBUGP(": returning `%s'\n", c->name); 959 return c->name; 960} 961 962/* Get first rule in the given chain: NULL for empty chain. */ 963const STRUCT_ENTRY * 964TC_FIRST_RULE(const char *chain, TC_HANDLE_T *handle) 965{ 966 struct chain_head *c; 967 struct rule_head *r; 968 969 iptc_fn = TC_FIRST_RULE; 970 971 DEBUGP("first rule(%s): ", chain); 972 973 c = iptcc_find_label(chain, *handle); 974 if (!c) { 975 errno = ENOENT; 976 return NULL; 977 } 978 979 /* Empty chain: single return/policy rule */ 980 if (list_empty(&c->rules)) { 981 DEBUGP_C("no rules, returning NULL\n"); 982 return NULL; 983 } 984 985 r = list_entry(c->rules.next, struct rule_head, list); 986 (*handle)->rule_iterator_cur = r; 987 DEBUGP_C("%p\n", r); 988 989 return r->entry; 990} 991 992/* Returns NULL when rules run out. */ 993const STRUCT_ENTRY * 994TC_NEXT_RULE(const STRUCT_ENTRY *prev, TC_HANDLE_T *handle) 995{ 996 struct rule_head *r; 997 998 DEBUGP("rule_iterator_cur=%p...", (*handle)->rule_iterator_cur); 999 1000 if (!(*handle)->rule_iterator_cur) { 1001 DEBUGP_C("returning NULL\n"); 1002 return NULL; 1003 } 1004 1005 r = list_entry((*handle)->rule_iterator_cur->list.next, 1006 struct rule_head, list); 1007 1008 iptc_fn = TC_NEXT_RULE; 1009 1010 DEBUGP_C("next=%p, head=%p...", &r->list, 1011 &(*handle)->rule_iterator_cur->chain->rules); 1012 1013 if (&r->list == &(*handle)->rule_iterator_cur->chain->rules) { 1014 (*handle)->rule_iterator_cur = NULL; 1015 DEBUGP_C("finished, returning NULL\n"); 1016 return NULL; 1017 } 1018 1019 (*handle)->rule_iterator_cur = r; 1020 1021 /* NOTE: prev is without any influence ! */ 1022 DEBUGP_C("returning rule %p\n", r); 1023 return r->entry; 1024} 1025 1026/* How many rules in this chain? */ 1027unsigned int 1028TC_NUM_RULES(const char *chain, TC_HANDLE_T *handle) 1029{ 1030 struct chain_head *c; 1031 iptc_fn = TC_NUM_RULES; 1032 CHECK(*handle); 1033 1034 c = iptcc_find_label(chain, *handle); 1035 if (!c) { 1036 errno = ENOENT; 1037 return (unsigned int)-1; 1038 } 1039 1040 return c->num_rules; 1041} 1042 1043const STRUCT_ENTRY *TC_GET_RULE(const char *chain, 1044 unsigned int n, 1045 TC_HANDLE_T *handle) 1046{ 1047 struct chain_head *c; 1048 struct rule_head *r; 1049 1050 iptc_fn = TC_GET_RULE; 1051 1052 CHECK(*handle); 1053 1054 c = iptcc_find_label(chain, *handle); 1055 if (!c) { 1056 errno = ENOENT; 1057 return NULL; 1058 } 1059 1060 r = iptcc_get_rule_num(c, n); 1061 if (!r) 1062 return NULL; 1063 return r->entry; 1064} 1065 1066/* Returns a pointer to the target name of this position. */ 1067const char *standard_target_map(int verdict) 1068{ 1069 switch (verdict) { 1070 case RETURN: 1071 return LABEL_RETURN; 1072 break; 1073 case -NF_ACCEPT-1: 1074 return LABEL_ACCEPT; 1075 break; 1076 case -NF_DROP-1: 1077 return LABEL_DROP; 1078 break; 1079 case -NF_QUEUE-1: 1080 return LABEL_QUEUE; 1081 break; 1082 default: 1083 fprintf(stderr, "ERROR: %d not a valid target)\n", 1084 verdict); 1085 abort(); 1086 break; 1087 } 1088 /* not reached */ 1089 return NULL; 1090} 1091 1092/* Returns a pointer to the target name of this position. */ 1093const char *TC_GET_TARGET(const STRUCT_ENTRY *ce, 1094 TC_HANDLE_T *handle) 1095{ 1096 STRUCT_ENTRY *e = (STRUCT_ENTRY *)ce; 1097 struct rule_head *r = container_of(e, struct rule_head, entry); 1098 1099 iptc_fn = TC_GET_TARGET; 1100 1101 switch(r->type) { 1102 int spos; 1103 case IPTCC_R_FALLTHROUGH: 1104 return ""; 1105 break; 1106 case IPTCC_R_JUMP: 1107 DEBUGP("r=%p, jump=%p, name=`%s'\n", r, r->jump, r->jump->name); 1108 return r->jump->name; 1109 break; 1110 case IPTCC_R_STANDARD: 1111 spos = *(int *)GET_TARGET(e)->data; 1112 DEBUGP("r=%p, spos=%d'\n", r, spos); 1113 return standard_target_map(spos); 1114 break; 1115 case IPTCC_R_MODULE: 1116 return GET_TARGET(e)->u.user.name; 1117 break; 1118 } 1119 return NULL; 1120} 1121/* Is this a built-in chain? Actually returns hook + 1. */ 1122int 1123TC_BUILTIN(const char *chain, const TC_HANDLE_T handle) 1124{ 1125 struct chain_head *c; 1126 1127 iptc_fn = TC_BUILTIN; 1128 1129 c = iptcc_find_label(chain, handle); 1130 if (!c) { 1131 errno = ENOENT; 1132 return -1; 1133 } 1134 1135 return iptcc_is_builtin(c); 1136} 1137 1138/* Get the policy of a given built-in chain */ 1139const char * 1140TC_GET_POLICY(const char *chain, 1141 STRUCT_COUNTERS *counters, 1142 TC_HANDLE_T *handle) 1143{ 1144 struct chain_head *c; 1145 1146 iptc_fn = TC_GET_POLICY; 1147 1148 DEBUGP("called for chain %s\n", chain); 1149 1150 c = iptcc_find_label(chain, *handle); 1151 if (!c) { 1152 errno = ENOENT; 1153 return NULL; 1154 } 1155 1156 if (!iptcc_is_builtin(c)) 1157 return NULL; 1158 1159 *counters = c->counters; 1160 1161 return standard_target_map(c->verdict); 1162} 1163 1164static int 1165iptcc_standard_map(struct rule_head *r, int verdict) 1166{ 1167 STRUCT_ENTRY *e = r->entry; 1168 STRUCT_STANDARD_TARGET *t; 1169 1170 t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e); 1171 1172 if (t->target.u.target_size 1173 != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) { 1174 errno = EINVAL; 1175 return 0; 1176 } 1177 /* memset for memcmp convenience on delete/replace */ 1178 memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN); 1179 strcpy(t->target.u.user.name, STANDARD_TARGET); 1180 t->verdict = verdict; 1181 1182 r->type = IPTCC_R_STANDARD; 1183 1184 return 1; 1185} 1186 1187static int 1188iptcc_map_target(const TC_HANDLE_T handle, 1189 struct rule_head *r) 1190{ 1191 STRUCT_ENTRY *e = r->entry; 1192 STRUCT_ENTRY_TARGET *t = GET_TARGET(e); 1193 1194 /* Maybe it's empty (=> fall through) */ 1195 if (strcmp(t->u.user.name, "") == 0) { 1196 r->type = IPTCC_R_FALLTHROUGH; 1197 return 1; 1198 } 1199 /* Maybe it's a standard target name... */ 1200 else if (strcmp(t->u.user.name, LABEL_ACCEPT) == 0) 1201 return iptcc_standard_map(r, -NF_ACCEPT - 1); 1202 else if (strcmp(t->u.user.name, LABEL_DROP) == 0) 1203 return iptcc_standard_map(r, -NF_DROP - 1); 1204 else if (strcmp(t->u.user.name, LABEL_QUEUE) == 0) 1205 return iptcc_standard_map(r, -NF_QUEUE - 1); 1206 else if (strcmp(t->u.user.name, LABEL_RETURN) == 0) 1207 return iptcc_standard_map(r, RETURN); 1208 else if (TC_BUILTIN(t->u.user.name, handle)) { 1209 /* Can't jump to builtins. */ 1210 errno = EINVAL; 1211 return 0; 1212 } else { 1213 /* Maybe it's an existing chain name. */ 1214 struct chain_head *c; 1215 DEBUGP("trying to find chain `%s': ", t->u.user.name); 1216 1217 c = iptcc_find_label(t->u.user.name, handle); 1218 if (c) { 1219 DEBUGP_C("found!\n"); 1220 r->type = IPTCC_R_JUMP; 1221 r->jump = c; 1222 c->references++; 1223 return 1; 1224 } 1225 DEBUGP_C("not found :(\n"); 1226 } 1227 1228 /* Must be a module? If not, kernel will reject... */ 1229 /* memset to all 0 for your memcmp convenience. */ 1230 memset(t->u.user.name + strlen(t->u.user.name), 1231 0, 1232 FUNCTION_MAXNAMELEN - strlen(t->u.user.name)); 1233 1234 set_changed(handle); 1235 return 1; 1236} 1237 1238/* Insert the entry `fw' in chain `chain' into position `rulenum'. */ 1239int 1240TC_INSERT_ENTRY(const IPT_CHAINLABEL chain, 1241 const STRUCT_ENTRY *e, 1242 unsigned int rulenum, 1243 TC_HANDLE_T *handle) 1244{ 1245 struct chain_head *c; 1246 struct rule_head *r, *prev; 1247 1248 iptc_fn = TC_INSERT_ENTRY; 1249 1250 if (!(c = iptcc_find_label(chain, *handle))) { 1251 errno = ENOENT; 1252 return 0; 1253 } 1254 1255 prev = iptcc_get_rule_num(c, rulenum); 1256 if (!prev) { 1257 errno = E2BIG; 1258 return 0; 1259 } 1260 1261 if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1262 errno = ENOMEM; 1263 return 0; 1264 } 1265 1266 memcpy(r->entry, e, e->next_offset); 1267 r->counter_map.maptype = COUNTER_MAP_SET; 1268 1269 if (!iptcc_map_target(*handle, r)) { 1270 free(r); 1271 return 0; 1272 } 1273 1274 list_add_tail(&r->list, &prev->list); 1275 c->num_rules++; 1276 1277 set_changed(*handle); 1278 1279 return 1; 1280} 1281 1282/* Atomically replace rule `rulenum' in `chain' with `fw'. */ 1283int 1284TC_REPLACE_ENTRY(const IPT_CHAINLABEL chain, 1285 const STRUCT_ENTRY *e, 1286 unsigned int rulenum, 1287 TC_HANDLE_T *handle) 1288{ 1289 struct chain_head *c; 1290 struct rule_head *r, *old; 1291 1292 iptc_fn = TC_REPLACE_ENTRY; 1293 1294 if (!(c = iptcc_find_label(chain, *handle))) { 1295 errno = ENOENT; 1296 return 0; 1297 } 1298 1299 if (!(old = iptcc_get_rule_num(c, rulenum))) { 1300 errno = E2BIG; 1301 return 0; 1302 } 1303 1304 if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1305 errno = ENOMEM; 1306 return 0; 1307 } 1308 1309 memcpy(r->entry, e, e->next_offset); 1310 r->counter_map.maptype = COUNTER_MAP_SET; 1311 1312 if (!iptcc_map_target(*handle, r)) { 1313 free(r); 1314 return 0; 1315 } 1316 1317 list_add(&r->list, &old->list); 1318 iptcc_delete_rule(old); 1319 1320 set_changed(*handle); 1321 1322 return 1; 1323} 1324 1325/* Append entry `fw' to chain `chain'. Equivalent to insert with 1326 rulenum = length of chain. */ 1327int 1328TC_APPEND_ENTRY(const IPT_CHAINLABEL chain, 1329 const STRUCT_ENTRY *e, 1330 TC_HANDLE_T *handle) 1331{ 1332 struct chain_head *c; 1333 struct rule_head *r; 1334 1335 iptc_fn = TC_APPEND_ENTRY; 1336 if (!(c = iptcc_find_label(chain, *handle))) { 1337 DEBUGP("unable to find chain `%s'\n", chain); 1338 errno = ENOENT; 1339 return 0; 1340 } 1341 1342 if (!(r = iptcc_alloc_rule(c, e->next_offset))) { 1343 DEBUGP("unable to allocate rule for chain `%s'\n", chain); 1344 errno = ENOMEM; 1345 return 0; 1346 } 1347 1348 memcpy(r->entry, e, e->next_offset); 1349 r->counter_map.maptype = COUNTER_MAP_SET; 1350 1351 if (!iptcc_map_target(*handle, r)) { 1352 DEBUGP("unable to ma target of rule for chain `%s'\n", chain); 1353 free(r); 1354 return 0; 1355 } 1356 1357 list_add_tail(&r->list, &c->rules); 1358 c->num_rules++; 1359 1360 set_changed(*handle); 1361 1362 return 1; 1363} 1364 1365static inline int 1366match_different(const STRUCT_ENTRY_MATCH *a, 1367 const unsigned char *a_elems, 1368 const unsigned char *b_elems, 1369 unsigned char **maskptr) 1370{ 1371 const STRUCT_ENTRY_MATCH *b; 1372 unsigned int i; 1373 1374 /* Offset of b is the same as a. */ 1375 b = (void *)b_elems + ((unsigned char *)a - a_elems); 1376 1377 if (a->u.match_size != b->u.match_size) 1378 return 1; 1379 1380 if (strcmp(a->u.user.name, b->u.user.name) != 0) 1381 return 1; 1382 1383 *maskptr += ALIGN(sizeof(*a)); 1384 1385 for (i = 0; i < a->u.match_size - ALIGN(sizeof(*a)); i++) 1386 if (((a->data[i] ^ b->data[i]) & (*maskptr)[i]) != 0) 1387 return 1; 1388 *maskptr += i; 1389 return 0; 1390} 1391 1392static inline int 1393target_different(const unsigned char *a_targdata, 1394 const unsigned char *b_targdata, 1395 unsigned int tdatasize, 1396 const unsigned char *mask) 1397{ 1398 unsigned int i; 1399 for (i = 0; i < tdatasize; i++) 1400 if (((a_targdata[i] ^ b_targdata[i]) & mask[i]) != 0) 1401 return 1; 1402 1403 return 0; 1404} 1405 1406static int 1407is_same(const STRUCT_ENTRY *a, 1408 const STRUCT_ENTRY *b, 1409 unsigned char *matchmask); 1410 1411/* Delete the first rule in `chain' which matches `fw'. */ 1412int 1413TC_DELETE_ENTRY(const IPT_CHAINLABEL chain, 1414 const STRUCT_ENTRY *origfw, 1415 unsigned char *matchmask, 1416 TC_HANDLE_T *handle) 1417{ 1418 struct chain_head *c; 1419 struct rule_head *r; 1420 STRUCT_ENTRY *e, *fw; 1421 1422 iptc_fn = TC_DELETE_ENTRY; 1423 if (!(c = iptcc_find_label(chain, *handle))) { 1424 errno = ENOENT; 1425 return 0; 1426 } 1427 1428 fw = malloc(origfw->next_offset); 1429 if (fw == NULL) { 1430 errno = ENOMEM; 1431 return 0; 1432 } 1433 1434 list_for_each_entry(r, &c->rules, list) { 1435 1436 memcpy(fw, origfw, origfw->next_offset); 1437 1438#if 0 1439 /* FIXME: handle this in is_same --RR */ 1440 if (!map_target(*handle, fw, offset, &discard)) { 1441 free(fw); 1442 return 0; 1443 } 1444#endif 1445 1446 e = r->entry; 1447 1448 if (is_same(e, fw, matchmask)) { 1449 /* If we are about to delete the rule that is the 1450 * current iterator, move rule iterator back. next 1451 * pointer will then point to real next node */ 1452 if (r == (*handle)->rule_iterator_cur) { 1453 (*handle)->rule_iterator_cur = 1454 list_entry((*handle)->rule_iterator_cur->list.prev, 1455 struct rule_head, list); 1456 } 1457 1458 c->num_rules--; 1459 iptcc_delete_rule(r); 1460 return 1; 1461 } 1462 } 1463 1464 free(fw); 1465 errno = ENOENT; 1466 return 0; 1467} 1468 1469 1470/* Delete the rule in position `rulenum' in `chain'. */ 1471int 1472TC_DELETE_NUM_ENTRY(const IPT_CHAINLABEL chain, 1473 unsigned int rulenum, 1474 TC_HANDLE_T *handle) 1475{ 1476 struct chain_head *c; 1477 struct rule_head *r; 1478 1479 iptc_fn = TC_DELETE_NUM_ENTRY; 1480 1481 if (!(c = iptcc_find_label(chain, *handle))) { 1482 errno = ENOENT; 1483 return 0; 1484 } 1485 1486 if (!(r = iptcc_get_rule_num(c, rulenum))) { 1487 errno = E2BIG; 1488 return 0; 1489 } 1490 1491 /* If we are about to delete the rule that is the current 1492 * iterator, move rule iterator back. next pointer will then 1493 * point to real next node */ 1494 if (r == (*handle)->rule_iterator_cur) { 1495 (*handle)->rule_iterator_cur = 1496 list_entry((*handle)->rule_iterator_cur->list.prev, 1497 struct rule_head, list); 1498 } 1499 1500 c->num_rules--; 1501 iptcc_delete_rule(r); 1502 1503 return 1; 1504} 1505 1506/* Check the packet `fw' on chain `chain'. Returns the verdict, or 1507 NULL and sets errno. */ 1508const char * 1509TC_CHECK_PACKET(const IPT_CHAINLABEL chain, 1510 STRUCT_ENTRY *entry, 1511 TC_HANDLE_T *handle) 1512{ 1513 errno = ENOSYS; 1514 return NULL; 1515} 1516 1517/* Flushes the entries in the given chain (ie. empties chain). */ 1518int 1519TC_FLUSH_ENTRIES(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1520{ 1521 struct chain_head *c; 1522 struct rule_head *r, *tmp; 1523 1524 iptc_fn = TC_FLUSH_ENTRIES; 1525 if (!(c = iptcc_find_label(chain, *handle))) { 1526 errno = ENOENT; 1527 return 0; 1528 } 1529 1530 list_for_each_entry_safe(r, tmp, &c->rules, list) { 1531 iptcc_delete_rule(r); 1532 } 1533 1534 c->num_rules = 0; 1535 1536 set_changed(*handle); 1537 1538 return 1; 1539} 1540 1541/* Zeroes the counters in a chain. */ 1542int 1543TC_ZERO_ENTRIES(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1544{ 1545 struct chain_head *c; 1546 struct rule_head *r; 1547 1548 if (!(c = iptcc_find_label(chain, *handle))) { 1549 errno = ENOENT; 1550 return 0; 1551 } 1552 1553 list_for_each_entry(r, &c->rules, list) { 1554 if (r->counter_map.maptype == COUNTER_MAP_NORMAL_MAP) 1555 r->counter_map.maptype = COUNTER_MAP_ZEROED; 1556 } 1557 1558 set_changed(*handle); 1559 1560 return 1; 1561} 1562 1563STRUCT_COUNTERS * 1564TC_READ_COUNTER(const IPT_CHAINLABEL chain, 1565 unsigned int rulenum, 1566 TC_HANDLE_T *handle) 1567{ 1568 struct chain_head *c; 1569 struct rule_head *r; 1570 1571 iptc_fn = TC_READ_COUNTER; 1572 CHECK(*handle); 1573 1574 if (!(c = iptcc_find_label(chain, *handle))) { 1575 errno = ENOENT; 1576 return NULL; 1577 } 1578 1579 if (!(r = iptcc_get_rule_num(c, rulenum))) { 1580 errno = E2BIG; 1581 return NULL; 1582 } 1583 1584 return &r->entry[0].counters; 1585} 1586 1587int 1588TC_ZERO_COUNTER(const IPT_CHAINLABEL chain, 1589 unsigned int rulenum, 1590 TC_HANDLE_T *handle) 1591{ 1592 struct chain_head *c; 1593 struct rule_head *r; 1594 1595 iptc_fn = TC_ZERO_COUNTER; 1596 CHECK(*handle); 1597 1598 if (!(c = iptcc_find_label(chain, *handle))) { 1599 errno = ENOENT; 1600 return 0; 1601 } 1602 1603 if (!(r = iptcc_get_rule_num(c, rulenum))) { 1604 errno = E2BIG; 1605 return 0; 1606 } 1607 1608 if (r->counter_map.maptype == COUNTER_MAP_NORMAL_MAP) 1609 r->counter_map.maptype = COUNTER_MAP_ZEROED; 1610 1611 set_changed(*handle); 1612 1613 return 1; 1614} 1615 1616int 1617TC_SET_COUNTER(const IPT_CHAINLABEL chain, 1618 unsigned int rulenum, 1619 STRUCT_COUNTERS *counters, 1620 TC_HANDLE_T *handle) 1621{ 1622 struct chain_head *c; 1623 struct rule_head *r; 1624 STRUCT_ENTRY *e; 1625 1626 iptc_fn = TC_SET_COUNTER; 1627 CHECK(*handle); 1628 1629 if (!(c = iptcc_find_label(chain, *handle))) { 1630 errno = ENOENT; 1631 return 0; 1632 } 1633 1634 if (!(r = iptcc_get_rule_num(c, rulenum))) { 1635 errno = E2BIG; 1636 return 0; 1637 } 1638 1639 e = r->entry; 1640 r->counter_map.maptype = COUNTER_MAP_SET; 1641 1642 memcpy(&e->counters, counters, sizeof(STRUCT_COUNTERS)); 1643 1644 set_changed(*handle); 1645 1646 return 1; 1647} 1648 1649/* Creates a new chain. */ 1650/* To create a chain, create two rules: error node and unconditional 1651 * return. */ 1652int 1653TC_CREATE_CHAIN(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1654{ 1655 static struct chain_head *c; 1656 1657 iptc_fn = TC_CREATE_CHAIN; 1658 1659 /* find_label doesn't cover built-in targets: DROP, ACCEPT, 1660 QUEUE, RETURN. */ 1661 if (iptcc_find_label(chain, *handle) 1662 || strcmp(chain, LABEL_DROP) == 0 1663 || strcmp(chain, LABEL_ACCEPT) == 0 1664 || strcmp(chain, LABEL_QUEUE) == 0 1665 || strcmp(chain, LABEL_RETURN) == 0) { 1666 DEBUGP("Chain `%s' already exists\n", chain); 1667 errno = EEXIST; 1668 return 0; 1669 } 1670 1671 if (strlen(chain)+1 > sizeof(IPT_CHAINLABEL)) { 1672 DEBUGP("Chain name `%s' too long\n", chain); 1673 errno = EINVAL; 1674 return 0; 1675 } 1676 1677 c = iptcc_alloc_chain_head(chain, 0); 1678 if (!c) { 1679 DEBUGP("Cannot allocate memory for chain `%s'\n", chain); 1680 errno = ENOMEM; 1681 return 0; 1682 1683 } 1684 1685 DEBUGP("Creating chain `%s'\n", chain); 1686 list_add_tail(&c->list, &(*handle)->chains); 1687 1688 set_changed(*handle); 1689 1690 return 1; 1691} 1692 1693/* Get the number of references to this chain. */ 1694int 1695TC_GET_REFERENCES(unsigned int *ref, const IPT_CHAINLABEL chain, 1696 TC_HANDLE_T *handle) 1697{ 1698 struct chain_head *c; 1699 1700 if (!(c = iptcc_find_label(chain, *handle))) { 1701 errno = ENOENT; 1702 return 0; 1703 } 1704 1705 *ref = c->references; 1706 1707 return 1; 1708} 1709 1710/* Deletes a chain. */ 1711int 1712TC_DELETE_CHAIN(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle) 1713{ 1714 unsigned int references; 1715 struct chain_head *c; 1716 1717 iptc_fn = TC_DELETE_CHAIN; 1718 1719 if (!(c = iptcc_find_label(chain, *handle))) { 1720 DEBUGP("cannot find chain `%s'\n", chain); 1721 errno = ENOENT; 1722 return 0; 1723 } 1724 1725 if (TC_BUILTIN(chain, *handle)) { 1726 DEBUGP("cannot remove builtin chain `%s'\n", chain); 1727 errno = EINVAL; 1728 return 0; 1729 } 1730 1731 if (!TC_GET_REFERENCES(&references, chain, handle)) { 1732 DEBUGP("cannot get references on chain `%s'\n", chain); 1733 return 0; 1734 } 1735 1736 if (references > 0) { 1737 DEBUGP("chain `%s' still has references\n", chain); 1738 errno = EMLINK; 1739 return 0; 1740 } 1741 1742 if (c->num_rules) { 1743 DEBUGP("chain `%s' is not empty\n", chain); 1744 errno = ENOTEMPTY; 1745 return 0; 1746 } 1747 1748 /* If we are about to delete the chain that is the current 1749 * iterator, move chain iterator firward. */ 1750 if (c == (*handle)->chain_iterator_cur) 1751 iptcc_chain_iterator_advance(*handle); 1752 1753 list_del(&c->list); 1754 free(c); 1755 1756 DEBUGP("chain `%s' deleted\n", chain); 1757 1758 set_changed(*handle); 1759 1760 return 1; 1761} 1762 1763/* Renames a chain. */ 1764int TC_RENAME_CHAIN(const IPT_CHAINLABEL oldname, 1765 const IPT_CHAINLABEL newname, 1766 TC_HANDLE_T *handle) 1767{ 1768 struct chain_head *c; 1769 iptc_fn = TC_RENAME_CHAIN; 1770 1771 /* find_label doesn't cover built-in targets: DROP, ACCEPT, 1772 QUEUE, RETURN. */ 1773 if (iptcc_find_label(newname, *handle) 1774 || strcmp(newname, LABEL_DROP) == 0 1775 || strcmp(newname, LABEL_ACCEPT) == 0 1776 || strcmp(newname, LABEL_QUEUE) == 0 1777 || strcmp(newname, LABEL_RETURN) == 0) { 1778 errno = EEXIST; 1779 return 0; 1780 } 1781 1782 if (!(c = iptcc_find_label(oldname, *handle)) 1783 || TC_BUILTIN(oldname, *handle)) { 1784 errno = ENOENT; 1785 return 0; 1786 } 1787 1788 if (strlen(newname)+1 > sizeof(IPT_CHAINLABEL)) { 1789 errno = EINVAL; 1790 return 0; 1791 } 1792 1793 strncpy(c->name, newname, sizeof(IPT_CHAINLABEL)); 1794 1795 set_changed(*handle); 1796 1797 return 1; 1798} 1799 1800/* Sets the policy on a built-in chain. */ 1801int 1802TC_SET_POLICY(const IPT_CHAINLABEL chain, 1803 const IPT_CHAINLABEL policy, 1804 STRUCT_COUNTERS *counters, 1805 TC_HANDLE_T *handle) 1806{ 1807 struct chain_head *c; 1808 1809 iptc_fn = TC_SET_POLICY; 1810 1811 if (!(c = iptcc_find_label(chain, *handle))) { 1812 DEBUGP("cannot find chain `%s'\n", chain); 1813 errno = ENOENT; 1814 return 0; 1815 } 1816 1817 if (!iptcc_is_builtin(c)) { 1818 DEBUGP("cannot set policy of userdefinedchain `%s'\n", chain); 1819 errno = ENOENT; 1820 return 0; 1821 } 1822 1823 if (strcmp(policy, LABEL_ACCEPT) == 0) 1824 c->verdict = -NF_ACCEPT - 1; 1825 else if (strcmp(policy, LABEL_DROP) == 0) 1826 c->verdict = -NF_DROP - 1; 1827 else { 1828 errno = EINVAL; 1829 return 0; 1830 } 1831 1832 if (counters) { 1833 /* set byte and packet counters */ 1834 memcpy(&c->counters, counters, sizeof(STRUCT_COUNTERS)); 1835 c->counter_map.maptype = COUNTER_MAP_SET; 1836 } else { 1837 c->counter_map.maptype = COUNTER_MAP_NOMAP; 1838 } 1839 1840 set_changed(*handle); 1841 1842 return 1; 1843} 1844 1845/* Without this, on gcc 2.7.2.3, we get: 1846 libiptc.c: In function `TC_COMMIT': 1847 libiptc.c:833: fixed or forbidden register was spilled. 1848 This may be due to a compiler bug or to impossible asm 1849 statements or clauses. 1850*/ 1851static void 1852subtract_counters(STRUCT_COUNTERS *answer, 1853 const STRUCT_COUNTERS *a, 1854 const STRUCT_COUNTERS *b) 1855{ 1856 answer->pcnt = a->pcnt - b->pcnt; 1857 answer->bcnt = a->bcnt - b->bcnt; 1858} 1859 1860 1861static void counters_nomap(STRUCT_COUNTERS_INFO *newcounters, 1862 unsigned int index) 1863{ 1864 newcounters->counters[index] = ((STRUCT_COUNTERS) { 0, 0}); 1865 DEBUGP_C("NOMAP => zero\n"); 1866} 1867 1868static void counters_normal_map(STRUCT_COUNTERS_INFO *newcounters, 1869 STRUCT_REPLACE *repl, 1870 unsigned int index, 1871 unsigned int mappos) 1872{ 1873 /* Original read: X. 1874 * Atomic read on replacement: X + Y. 1875 * Currently in kernel: Z. 1876 * Want in kernel: X + Y + Z. 1877 * => Add in X + Y 1878 * => Add in replacement read. 1879 */ 1880 newcounters->counters[index] = repl->counters[mappos]; 1881 DEBUGP_C("NORMAL_MAP => mappos %u \n", mappos); 1882} 1883 1884static void counters_map_zeroed(STRUCT_COUNTERS_INFO *newcounters, 1885 STRUCT_REPLACE *repl, 1886 unsigned int index, 1887 unsigned int mappos, 1888 STRUCT_COUNTERS *counters) 1889{ 1890 /* Original read: X. 1891 * Atomic read on replacement: X + Y. 1892 * Currently in kernel: Z. 1893 * Want in kernel: Y + Z. 1894 * => Add in Y. 1895 * => Add in (replacement read - original read). 1896 */ 1897 subtract_counters(&newcounters->counters[index], 1898 &repl->counters[mappos], 1899 counters); 1900 DEBUGP_C("ZEROED => mappos %u\n", mappos); 1901} 1902 1903static void counters_map_set(STRUCT_COUNTERS_INFO *newcounters, 1904 unsigned int index, 1905 STRUCT_COUNTERS *counters) 1906{ 1907 /* Want to set counter (iptables-restore) */ 1908 1909 memcpy(&newcounters->counters[index], counters, 1910 sizeof(STRUCT_COUNTERS)); 1911 1912 DEBUGP_C("SET\n"); 1913} 1914 1915 1916int 1917TC_COMMIT(TC_HANDLE_T *handle) 1918{ 1919 /* Replace, then map back the counters. */ 1920 STRUCT_REPLACE *repl; 1921 STRUCT_COUNTERS_INFO *newcounters; 1922 struct chain_head *c; 1923 int ret; 1924 size_t counterlen; 1925 int new_number; 1926 unsigned int new_size; 1927 1928 CHECK(*handle); 1929 1930#if 0 1931 TC_DUMP_ENTRIES(*handle); 1932#endif 1933 1934 /* Don't commit if nothing changed. */ 1935 if (!(*handle)->changed) 1936 goto finished; 1937 1938 new_number = iptcc_compile_table_prep(*handle, &new_size); 1939 if (new_number < 0) { 1940 errno = ENOMEM; 1941 return 0; 1942 } 1943 1944 repl = malloc(sizeof(*repl) + new_size); 1945 if (!repl) { 1946 errno = ENOMEM; 1947 return 0; 1948 } 1949 memset(repl, 0, sizeof(*repl)); 1950 1951 counterlen = sizeof(STRUCT_COUNTERS_INFO) 1952 + sizeof(STRUCT_COUNTERS) * new_number; 1953 1954 /* These are the old counters we will get from kernel */ 1955 repl->counters = malloc(sizeof(STRUCT_COUNTERS) 1956 * (*handle)->info.num_entries); 1957 if (!repl->counters) { 1958 free(repl); 1959 errno = ENOMEM; 1960 return 0; 1961 } 1962 /* These are the counters we're going to put back, later. */ 1963 newcounters = malloc(counterlen); 1964 if (!newcounters) { 1965 free(repl->counters); 1966 free(repl); 1967 errno = ENOMEM; 1968 return 0; 1969 } 1970 memset(newcounters, 0, counterlen); 1971 1972 strcpy(repl->name, (*handle)->info.name); 1973 repl->num_entries = new_number; 1974 repl->size = new_size; 1975 1976 repl->num_counters = (*handle)->info.num_entries; 1977 repl->valid_hooks = (*handle)->info.valid_hooks; 1978 1979 DEBUGP("num_entries=%u, size=%u, num_counters=%u\n", 1980 repl->num_entries, repl->size, repl->num_counters); 1981 1982 ret = iptcc_compile_table(*handle, repl); 1983 if (ret < 0) { 1984 errno = ret; 1985 free(repl->counters); 1986 free(repl); 1987 return 0; 1988 } 1989 1990 1991#ifdef IPTC_DEBUG2 1992 { 1993 int fd = open("/tmp/libiptc-so_set_replace.blob", 1994 O_CREAT|O_WRONLY); 1995 if (fd >= 0) { 1996 write(fd, repl, sizeof(*repl) + repl->size); 1997 close(fd); 1998 } 1999 } 2000#endif 2001 2002 if (setsockopt(sockfd, TC_IPPROTO, SO_SET_REPLACE, repl, 2003 sizeof(*repl) + repl->size) < 0) { 2004 free(repl->counters); 2005 free(repl); 2006 free(newcounters); 2007 return 0; 2008 } 2009 2010 /* Put counters back. */ 2011 strcpy(newcounters->name, (*handle)->info.name); 2012 newcounters->num_counters = new_number; 2013 2014 list_for_each_entry(c, &(*handle)->chains, list) { 2015 struct rule_head *r; 2016 2017 /* Builtin chains have their own counters */ 2018 if (iptcc_is_builtin(c)) { 2019 DEBUGP("counter for chain-index %u: ", c->foot_index); 2020 switch(c->counter_map.maptype) { 2021 case COUNTER_MAP_NOMAP: 2022 counters_nomap(newcounters, c->foot_index); 2023 break; 2024 case COUNTER_MAP_NORMAL_MAP: 2025 counters_normal_map(newcounters, repl, 2026 c->foot_index, 2027 c->counter_map.mappos); 2028 break; 2029 case COUNTER_MAP_ZEROED: 2030 counters_map_zeroed(newcounters, repl, 2031 c->foot_index, 2032 c->counter_map.mappos, 2033 &c->counters); 2034 break; 2035 case COUNTER_MAP_SET: 2036 counters_map_set(newcounters, c->foot_index, 2037 &c->counters); 2038 break; 2039 } 2040 } 2041 2042 list_for_each_entry(r, &c->rules, list) { 2043 DEBUGP("counter for index %u: ", r->index); 2044 switch (r->counter_map.maptype) { 2045 case COUNTER_MAP_NOMAP: 2046 counters_nomap(newcounters, r->index); 2047 break; 2048 2049 case COUNTER_MAP_NORMAL_MAP: 2050 counters_normal_map(newcounters, repl, 2051 r->index, 2052 r->counter_map.mappos); 2053 break; 2054 2055 case COUNTER_MAP_ZEROED: 2056 counters_map_zeroed(newcounters, repl, 2057 r->index, 2058 r->counter_map.mappos, 2059 &r->entry->counters); 2060 break; 2061 2062 case COUNTER_MAP_SET: 2063 counters_map_set(newcounters, r->index, 2064 &r->entry->counters); 2065 break; 2066 } 2067 } 2068 } 2069 2070 2071#ifdef KERNEL_64_USERSPACE_32 2072 { 2073 /* Kernel will think that pointer should be 64-bits, and get 2074 padding. So we accomodate here (assumption: alignment of 2075 `counters' is on 64-bit boundary). */ 2076 u_int64_t *kernptr = (u_int64_t *)&newcounters->counters; 2077 if ((unsigned long)&newcounters->counters % 8 != 0) { 2078 fprintf(stderr, 2079 "counters alignment incorrect! Mail rusty!\n"); 2080 abort(); 2081 } 2082 *kernptr = newcounters->counters; 2083 } 2084#endif /* KERNEL_64_USERSPACE_32 */ 2085 2086#ifdef IPTC_DEBUG2 2087 { 2088 int fd = open("/tmp/libiptc-so_set_add_counters.blob", 2089 O_CREAT|O_WRONLY); 2090 if (fd >= 0) { 2091 write(fd, newcounters, counterlen); 2092 close(fd); 2093 } 2094 } 2095#endif 2096 2097 if (setsockopt(sockfd, TC_IPPROTO, SO_SET_ADD_COUNTERS, 2098 newcounters, counterlen) < 0) { 2099 free(repl->counters); 2100 free(repl); 2101 free(newcounters); 2102 return 0; 2103 } 2104 2105 free(repl->counters); 2106 free(repl); 2107 free(newcounters); 2108 2109 finished: 2110 TC_FREE(handle); 2111 return 1; 2112} 2113 2114/* Get raw socket. */ 2115int 2116TC_GET_RAW_SOCKET() 2117{ 2118 return sockfd; 2119} 2120 2121/* Translates errno numbers into more human-readable form than strerror. */ 2122const char * 2123TC_STRERROR(int err) 2124{ 2125 unsigned int i; 2126 struct table_struct { 2127 void *fn; 2128 int err; 2129 const char *message; 2130 } table [] = 2131 { { TC_INIT, EPERM, "Permission denied (you must be root)" }, 2132 { TC_INIT, EINVAL, "Module is wrong version" }, 2133 { TC_INIT, ENOENT, 2134 "Table does not exist (do you need to insmod?)" }, 2135 { TC_DELETE_CHAIN, ENOTEMPTY, "Chain is not empty" }, 2136 { TC_DELETE_CHAIN, EINVAL, "Can't delete built-in chain" }, 2137 { TC_DELETE_CHAIN, EMLINK, 2138 "Can't delete chain with references left" }, 2139 { TC_CREATE_CHAIN, EEXIST, "Chain already exists" }, 2140 { TC_INSERT_ENTRY, E2BIG, "Index of insertion too big" }, 2141 { TC_REPLACE_ENTRY, E2BIG, "Index of replacement too big" }, 2142 { TC_DELETE_NUM_ENTRY, E2BIG, "Index of deletion too big" }, 2143 { TC_READ_COUNTER, E2BIG, "Index of counter too big" }, 2144 { TC_ZERO_COUNTER, E2BIG, "Index of counter too big" }, 2145 { TC_INSERT_ENTRY, ELOOP, "Loop found in table" }, 2146 { TC_INSERT_ENTRY, EINVAL, "Target problem" }, 2147 /* EINVAL for CHECK probably means bad interface. */ 2148 { TC_CHECK_PACKET, EINVAL, 2149 "Bad arguments (does that interface exist?)" }, 2150 { TC_CHECK_PACKET, ENOSYS, 2151 "Checking will most likely never get implemented" }, 2152 /* ENOENT for DELETE probably means no matching rule */ 2153 { TC_DELETE_ENTRY, ENOENT, 2154 "Bad rule (does a matching rule exist in that chain?)" }, 2155 { TC_SET_POLICY, ENOENT, 2156 "Bad built-in chain name" }, 2157 { TC_SET_POLICY, EINVAL, 2158 "Bad policy name" }, 2159 2160 { NULL, 0, "Incompatible with this kernel" }, 2161 { NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" }, 2162 { NULL, ENOSYS, "Will be implemented real soon. I promise ;)" }, 2163 { NULL, ENOMEM, "Memory allocation problem" }, 2164 { NULL, ENOENT, "No chain/target/match by that name" }, 2165 }; 2166 2167 for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) { 2168 if ((!table[i].fn || table[i].fn == iptc_fn) 2169 && table[i].err == err) 2170 return table[i].message; 2171 } 2172 2173 return strerror(err); 2174} 2175