1 /* Library which manipulates firewall rules. Version $Revision: 1.39 $ */
3 /* Architecture of firewall rules is as follows:
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.
11 /* (C) 1999 Paul ``Rusty'' Russell - Placed under the GNU GPL (See
12 * COPYING for details).
13 * (C) 2000-2003 by the Netfilter Core Team <coreteam@netfilter.org>
15 * 2003-Jun-20: Harald Welte <laforge@netfilter.org:
16 * - Reimplementation of chain cache to use offsets instead of entries
21 #define IPT_LIB_DIR "/usr/lib/iptables"
26 GET_TARGET(STRUCT_ENTRY *e)
28 return (void *)e + e->target_offset;
32 static int sockfd = -1;
33 static void *iptc_fn = NULL;
35 static const char *hooknames[]
36 = { [HOOK_PRE_ROUTING] "PREROUTING",
37 [HOOK_LOCAL_IN] "INPUT",
38 [HOOK_FORWARD] "FORWARD",
39 [HOOK_LOCAL_OUT] "OUTPUT",
40 [HOOK_POST_ROUTING] "POSTROUTING",
42 [HOOK_DROPPING] "DROPPING"
50 COUNTER_MAP_NORMAL_MAP,
57 /* Convenience structures */
58 struct ipt_error_target
60 STRUCT_ENTRY_TARGET t;
61 char error[TABLE_MAXNAMELEN];
66 struct list_head list;
68 struct chain_head *chain;
71 STRUCT_ENTRY entry[0];
76 struct list_head list;
78 char name[TABLE_MAXNAMELEN];
80 struct list_head rules;
85 /* Have changes been made? */
88 struct list_head chains;
90 struct chain_head *chain_iterator_cur;
93 /* Size in here reflects original state. */
96 struct counter_map *counter_map;
97 /* Array of hook names */
98 const char **hooknames;
100 /* Cached position of chain heads (NULL = no cache). */
101 unsigned int cache_num_chains;
102 unsigned int cache_num_builtins;
103 struct chain_cache *cache_chain_heads;
105 /* Chain iterator: current chain cache entry. */
106 struct chain_cache *cache_chain_iteration;
108 /* Rule iterator: terminal rule */
109 STRUCT_ENTRY *cache_rule_end;
111 /* Number in here reflects current state. */
112 unsigned int new_number;
113 STRUCT_GET_ENTRIES entries;
118 set_changed(TC_HANDLE_T h)
124 static void do_check(TC_HANDLE_T h, unsigned int line);
125 #define CHECK(h) do { if (!getenv("IPTC_NO_CHECK")) do_check((h), __LINE__); } while(0)
131 get_number(const STRUCT_ENTRY *i,
132 const STRUCT_ENTRY *seek,
142 entry2index(const TC_HANDLE_T h, const STRUCT_ENTRY *seek)
144 unsigned int pos = 0;
146 if (ENTRY_ITERATE(h->entries.entrytable, h->entries.size,
147 get_number, seek, &pos) == 0) {
148 fprintf(stderr, "ERROR: offset %i not an entry!\n",
149 (char *)seek - (char *)h->entries.entrytable);
156 get_entry_n(STRUCT_ENTRY *i,
161 if (*pos == number) {
169 static STRUCT_ENTRY *
170 index2entry(TC_HANDLE_T h, unsigned int index)
172 unsigned int pos = 0;
173 STRUCT_ENTRY *ret = NULL;
175 ENTRY_ITERATE(h->entries.entrytable, h->entries.size,
176 get_entry_n, index, &pos, &ret);
181 static inline STRUCT_ENTRY *
182 get_entry(TC_HANDLE_T h, unsigned int offset)
184 return (STRUCT_ENTRY *)((char *)h->entries.entrytable + offset);
187 static inline unsigned long
188 entry2offset(const TC_HANDLE_T h, const STRUCT_ENTRY *e)
190 return (void *)e - (void *)h->entries.entrytable;
193 static inline unsigned long
194 index2offset(TC_HANDLE_T h, unsigned int index)
196 return entry2offset(h, index2entry(h, index));
199 static inline STRUCT_ENTRY *
200 offset2entry(TC_HANDLE_T h, unsigned int offset)
202 return (STRUCT_ENTRY *) ((void *)h->entries.entrytable+offset);
205 static inline unsigned int
206 offset2index(const TC_HANDLE_T h, unsigned int offset)
208 return entry2index(h, offset2entry(h, offset));
213 get_errorlabel(TC_HANDLE_T h, unsigned int offset)
217 e = get_entry(h, offset);
218 if (strcmp(GET_TARGET(e)->u.user.name, ERROR_TARGET) != 0) {
219 fprintf(stderr, "ERROR: offset %u not an error node!\n",
224 return (const char *)GET_TARGET(e)->data;
227 /* Allocate handle of given size */
229 alloc_handle(const char *tablename, unsigned int size, unsigned int num_rules)
234 len = sizeof(STRUCT_TC_HANDLE)
236 + num_rules * sizeof(struct counter_map);
238 if ((h = malloc(len)) == NULL) {
244 h->cache_num_chains = 0;
245 h->cache_chain_heads = NULL;
246 h->counter_map = (void *)h
247 + sizeof(STRUCT_TC_HANDLE)
249 strcpy(h->info.name, tablename);
250 strcpy(h->entries.name, tablename);
256 TC_INIT(const char *tablename)
271 if (strlen(tablename) >= TABLE_MAXNAMELEN) {
276 sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW);
282 strcpy(info.name, tablename);
283 if (getsockopt(sockfd, TC_IPPROTO, SO_GET_INFO, &info, &s) < 0)
286 if ((h = alloc_handle(info.name, info.size, info.num_entries))
295 sprintf(pathname, "%s/%s", IPT_LIB_DIR, info.name);
296 dynlib = dlopen(pathname, RTLD_NOW);
301 h->hooknames = dlsym(dynlib, "hooknames");
307 h->hooknames = hooknames;
310 /* Initialize current state */
312 h->new_number = h->info.num_entries;
313 for (i = 0; i < h->info.num_entries; i++)
315 = ((struct counter_map){COUNTER_MAP_NORMAL_MAP, i});
317 h->entries.size = h->info.size;
319 tmp = sizeof(STRUCT_GET_ENTRIES) + h->info.size;
321 if (getsockopt(sockfd, TC_IPPROTO, SO_GET_ENTRIES, &h->entries,
334 TC_FREE(TC_HANDLE_T *h)
338 if ((*h)->cache_chain_heads)
339 free((*h)->cache_chain_heads);
345 print_match(const STRUCT_ENTRY_MATCH *m)
347 printf("Match name: `%s'\n", m->u.user.name);
351 static int dump_entry(STRUCT_ENTRY *e, const TC_HANDLE_T handle);
354 TC_DUMP_ENTRIES(const TC_HANDLE_T handle)
358 printf("libiptc v%s. %u entries, %u bytes.\n",
360 handle->new_number, handle->entries.size);
361 printf("Table `%s'\n", handle->info.name);
362 printf("Hooks: pre/in/fwd/out/post = %u/%u/%u/%u/%u\n",
363 handle->info.hook_entry[HOOK_PRE_ROUTING],
364 handle->info.hook_entry[HOOK_LOCAL_IN],
365 handle->info.hook_entry[HOOK_FORWARD],
366 handle->info.hook_entry[HOOK_LOCAL_OUT],
367 handle->info.hook_entry[HOOK_POST_ROUTING]);
368 printf("Underflows: pre/in/fwd/out/post = %u/%u/%u/%u/%u\n",
369 handle->info.underflow[HOOK_PRE_ROUTING],
370 handle->info.underflow[HOOK_LOCAL_IN],
371 handle->info.underflow[HOOK_FORWARD],
372 handle->info.underflow[HOOK_LOCAL_OUT],
373 handle->info.underflow[HOOK_POST_ROUTING]);
375 ENTRY_ITERATE(handle->entries.entrytable, handle->entries.size,
379 /* Returns 0 if not hook entry, else hooknumber + 1 */
380 static inline unsigned int
381 is_hook_entry(STRUCT_ENTRY *e, TC_HANDLE_T h)
385 for (i = 0; i < NUMHOOKS; i++) {
386 if ((h->info.valid_hooks & (1 << i))
387 && get_entry(h, h->info.hook_entry[i]) == e)
392 static int alphasort(const void *a, const void *b)
394 return strcmp(((struct chain_cache *)a)->name,
395 ((struct chain_cache *)b)->name);
398 /* Returns chain head if found, otherwise NULL. */
399 static struct chain_head *
400 find_label(const char *name, TC_HANDLE_T handle)
402 struct list_head *pos;
407 list_for_each(pos, &handle->chains) {
408 struct chain_head *c = list_entry(pos, struct chain_head, list);
409 if (!strcmp(c->name, name))
416 /* Does this chain exist? */
417 int TC_IS_CHAIN(const char *chain, const TC_HANDLE_T handle)
419 return find_label(chain, handle) != NULL;
422 /* Returns the position of the final (ie. unconditional) element. */
424 get_chain_end(const TC_HANDLE_T handle, unsigned int start)
426 unsigned int last_off, off;
430 e = get_entry(handle, start);
432 /* Terminate when we meet a error label or a hook entry. */
433 for (off = start + e->next_offset;
434 off < handle->entries.size;
435 last_off = off, off += e->next_offset) {
436 STRUCT_ENTRY_TARGET *t;
439 e = get_entry(handle, off);
441 /* We hit an entry point. */
442 for (i = 0; i < NUMHOOKS; i++) {
443 if ((handle->info.valid_hooks & (1 << i))
444 && off == handle->info.hook_entry[i])
448 /* We hit a user chain label */
450 if (strcmp(t->u.user.name, ERROR_TARGET) == 0)
453 /* SHOULD NEVER HAPPEN */
454 fprintf(stderr, "ERROR: Off end (%u) of chain from %u!\n",
455 handle->entries.size, off);
459 /* Iterator functions to run through the chains. */
461 TC_FIRST_CHAIN(TC_HANDLE_T *handle)
463 (*handle)->chain_iterator_cur = (*handle)->chains;
465 return (*handle)->chains.name;
468 /* Iterator functions to run through the chains. Returns NULL at end. */
470 TC_NEXT_CHAIN(TC_HANDLE_T *handle)
472 struct chain_head *next = list_entry(&(*handle)->chain_iterator_cur->list.next, struct chain_head, list);
473 (*handle)->chain_iterator_cur = next;
475 if (next == (*handle)->chains)
481 /* Get first rule in the given chain: NULL for empty chain. */
483 TC_FIRST_RULE(const char *chain, TC_HANDLE_T *handle)
485 struct chain_head *c;
488 c = find_label(chain, *handle);
494 /* Empty chain: single return/policy rule */
495 if (list_empty(c->rules))
498 r = list_entry(&c->rules.next, struct rule_head, list);
499 (*handle)->rule_iterator_cur = r;
504 /* Returns NULL when rules run out. */
506 TC_NEXT_RULE(const STRUCT_ENTRY *prev, TC_HANDLE_T *handle)
508 struct rule_head *r = list_entry((*handle)->rule_iterator_cur->list.next, struct rule_head, list);
513 /* NOTE: prev is without any influence ! */
518 /* How many rules in this chain? */
520 TC_NUM_RULES(const char *chain, TC_HANDLE_T *handle)
522 unsigned int off = 0;
523 STRUCT_ENTRY *start, *end;
526 if (!find_label(&off, chain, *handle)) {
528 return (unsigned int)-1;
531 start = get_entry(*handle, off);
532 end = get_entry(*handle, get_chain_end(*handle, off));
534 return entry2index(*handle, end) - entry2index(*handle, start);
537 /* Get n'th rule in this chain. */
538 const STRUCT_ENTRY *TC_GET_RULE(const char *chain,
542 unsigned int pos = 0, chainindex;
545 if (!find_label(&pos, chain, *handle)) {
550 chainindex = entry2index(*handle, get_entry(*handle, pos));
552 return index2entry(*handle, chainindex + n);
557 target_name(TC_HANDLE_T handle, const STRUCT_ENTRY *ce)
560 unsigned int labelidx;
561 STRUCT_ENTRY *jumpto;
563 /* To avoid const warnings */
564 STRUCT_ENTRY *e = (STRUCT_ENTRY *)ce;
566 if (strcmp(GET_TARGET(e)->u.user.name, STANDARD_TARGET) != 0)
567 return GET_TARGET(e)->u.user.name;
569 /* Standard target: evaluate */
570 spos = *(int *)GET_TARGET(e)->data;
574 else if (spos == -NF_ACCEPT-1)
576 else if (spos == -NF_DROP-1)
578 else if (spos == -NF_QUEUE-1)
581 fprintf(stderr, "ERROR: off %lu/%u not a valid target (%i)\n",
582 entry2offset(handle, e), handle->entries.size,
587 jumpto = get_entry(handle, spos);
589 /* Fall through rule */
590 if (jumpto == (void *)e + e->next_offset)
593 /* Must point to head of a chain: ie. after error rule */
594 labelidx = entry2index(handle, jumpto) - 1;
595 return get_errorlabel(handle, index2offset(handle, labelidx));
598 /* Returns a pointer to the target name of this position. */
599 const char *TC_GET_TARGET(const STRUCT_ENTRY *e,
602 return target_name(*handle, e);
605 /* Is this a built-in chain? Actually returns hook + 1. */
607 TC_BUILTIN(const char *chain, const TC_HANDLE_T handle)
611 for (i = 0; i < NUMHOOKS; i++) {
612 if ((handle->info.valid_hooks & (1 << i))
613 && handle->hooknames[i]
614 && strcmp(handle->hooknames[i], chain) == 0)
620 /* Get the policy of a given built-in chain */
622 TC_GET_POLICY(const char *chain,
623 STRUCT_COUNTERS *counters,
630 hook = TC_BUILTIN(chain, *handle);
632 start = (*handle)->info.hook_entry[hook-1];
636 e = get_entry(*handle, get_chain_end(*handle, start));
637 *counters = e->counters;
639 return target_name(*handle, e);
643 correct_verdict(STRUCT_ENTRY *e,
645 unsigned int offset, int delta_offset)
647 STRUCT_STANDARD_TARGET *t = (void *)GET_TARGET(e);
648 unsigned int curr = (char *)e - base;
650 /* Trap: insert of fall-through rule. Don't change fall-through
651 verdict to jump-over-next-rule. */
652 if (strcmp(t->target.u.user.name, STANDARD_TARGET) == 0
653 && t->verdict > (int)offset
654 && !(curr == offset &&
655 t->verdict == curr + e->next_offset)) {
656 t->verdict += delta_offset;
662 /* Adjusts standard verdict jump positions after an insertion/deletion. */
664 set_verdict(unsigned int offset, int delta_offset, TC_HANDLE_T *handle)
666 ENTRY_ITERATE((*handle)->entries.entrytable,
667 (*handle)->entries.size,
668 correct_verdict, (char *)(*handle)->entries.entrytable,
669 offset, delta_offset);
671 set_changed(*handle);
675 /* If prepend is set, then we are prepending to a chain: if the
676 * insertion position is an entry point, keep the entry point. */
678 insert_rules(unsigned int num_rules, unsigned int rules_size,
679 const STRUCT_ENTRY *insert,
680 unsigned int offset, unsigned int num_rules_offset,
685 STRUCT_GETINFO newinfo;
688 if (offset >= (*handle)->entries.size) {
693 newinfo = (*handle)->info;
695 /* Fix up entry points. */
696 for (i = 0; i < NUMHOOKS; i++) {
697 /* Entry points to START of chain, so keep same if
698 inserting on at that point. */
699 if ((*handle)->info.hook_entry[i] > offset)
700 newinfo.hook_entry[i] += rules_size;
702 /* Underflow always points to END of chain (policy),
703 so if something is inserted at same point, it
704 should be advanced. */
705 if ((*handle)->info.underflow[i] >= offset)
706 newinfo.underflow[i] += rules_size;
709 newh = alloc_handle((*handle)->info.name,
710 (*handle)->entries.size + rules_size,
711 (*handle)->new_number + num_rules);
714 newh->info = newinfo;
717 memcpy(newh->entries.entrytable, (*handle)->entries.entrytable,offset);
718 /* ... Insert new ... */
719 memcpy((char *)newh->entries.entrytable + offset, insert, rules_size);
721 memcpy((char *)newh->entries.entrytable + offset + rules_size,
722 (char *)(*handle)->entries.entrytable + offset,
723 (*handle)->entries.size - offset);
725 /* Move counter map. */
727 memcpy(newh->counter_map, (*handle)->counter_map,
728 sizeof(struct counter_map) * num_rules_offset);
730 memcpy(newh->counter_map + num_rules_offset + num_rules,
731 (*handle)->counter_map + num_rules_offset,
732 sizeof(struct counter_map) * ((*handle)->new_number
733 - num_rules_offset));
734 /* Set intermediates to no counter copy */
735 for (i = 0; i < num_rules; i++)
736 newh->counter_map[num_rules_offset+i]
737 = ((struct counter_map){ COUNTER_MAP_SET, 0 });
739 newh->new_number = (*handle)->new_number + num_rules;
740 newh->entries.size = (*handle)->entries.size + rules_size;
741 newh->hooknames = (*handle)->hooknames;
743 if ((*handle)->cache_chain_heads)
744 free((*handle)->cache_chain_heads);
748 return set_verdict(offset, rules_size, handle);
752 delete_rules(unsigned int num_rules, unsigned int rules_size,
753 unsigned int offset, unsigned int num_rules_offset,
758 if (offset + rules_size > (*handle)->entries.size) {
763 /* Fix up entry points. */
764 for (i = 0; i < NUMHOOKS; i++) {
765 /* In practice, we never delete up to a hook entry,
766 since the built-in chains are always first,
767 so these two are never equal */
768 if ((*handle)->info.hook_entry[i] >= offset + rules_size)
769 (*handle)->info.hook_entry[i] -= rules_size;
770 else if ((*handle)->info.hook_entry[i] > offset) {
771 fprintf(stderr, "ERROR: Deleting entry %u %u %u\n",
772 i, (*handle)->info.hook_entry[i], offset);
776 /* Underflow points to policy (terminal) rule in
777 built-in, so sequality is valid here (when deleting
779 if ((*handle)->info.underflow[i] >= offset + rules_size)
780 (*handle)->info.underflow[i] -= rules_size;
781 else if ((*handle)->info.underflow[i] > offset) {
782 fprintf(stderr, "ERROR: Deleting uflow %u %u %u\n",
783 i, (*handle)->info.underflow[i], offset);
788 /* Move the rules down. */
789 memmove((char *)(*handle)->entries.entrytable + offset,
790 (char *)(*handle)->entries.entrytable + offset + rules_size,
791 (*handle)->entries.size - (offset + rules_size));
793 /* Move the counter map down. */
794 memmove(&(*handle)->counter_map[num_rules_offset],
795 &(*handle)->counter_map[num_rules_offset + num_rules],
796 sizeof(struct counter_map)
797 * ((*handle)->new_number - (num_rules + num_rules_offset)));
800 (*handle)->new_number -= num_rules;
801 (*handle)->entries.size -= rules_size;
803 return set_verdict(offset, -(int)rules_size, handle);
807 standard_map(STRUCT_ENTRY *e, int verdict)
809 STRUCT_STANDARD_TARGET *t;
811 t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e);
813 if (t->target.u.target_size
814 != ALIGN(sizeof(STRUCT_STANDARD_TARGET))) {
818 /* memset for memcmp convenience on delete/replace */
819 memset(t->target.u.user.name, 0, FUNCTION_MAXNAMELEN);
820 strcpy(t->target.u.user.name, STANDARD_TARGET);
821 t->verdict = verdict;
827 map_target(const TC_HANDLE_T handle,
830 STRUCT_ENTRY_TARGET *old)
832 STRUCT_ENTRY_TARGET *t = GET_TARGET(e);
834 /* Save old target (except data, which we don't change, except for
835 standard case, where we don't care). */
838 /* Maybe it's empty (=> fall through) */
839 if (strcmp(t->u.user.name, "") == 0)
840 return standard_map(e, offset + e->next_offset);
841 /* Maybe it's a standard target name... */
842 else if (strcmp(t->u.user.name, LABEL_ACCEPT) == 0)
843 return standard_map(e, -NF_ACCEPT - 1);
844 else if (strcmp(t->u.user.name, LABEL_DROP) == 0)
845 return standard_map(e, -NF_DROP - 1);
846 else if (strcmp(t->u.user.name, LABEL_QUEUE) == 0)
847 return standard_map(e, -NF_QUEUE - 1);
848 else if (strcmp(t->u.user.name, LABEL_RETURN) == 0)
849 return standard_map(e, RETURN);
850 else if (TC_BUILTIN(t->u.user.name, handle)) {
851 /* Can't jump to builtins. */
855 /* Maybe it's an existing chain name. */
856 struct chain_cache *c;
858 c = find_label(t->u.user.name, handle);
860 return standard_map(e, c->start_off);
863 /* Must be a module? If not, kernel will reject... */
864 /* memset to all 0 for your memcmp convenience. */
865 memset(t->u.user.name + strlen(t->u.user.name),
867 FUNCTION_MAXNAMELEN - strlen(t->u.user.name));
872 unmap_target(STRUCT_ENTRY *e, STRUCT_ENTRY_TARGET *old)
874 STRUCT_ENTRY_TARGET *t = GET_TARGET(e);
876 /* Save old target (except data, which we don't change, except for
877 standard case, where we don't care). */
881 /* Insert the entry `fw' in chain `chain' into position `rulenum'. */
883 TC_INSERT_ENTRY(const IPT_CHAINLABEL chain,
884 const STRUCT_ENTRY *e,
885 unsigned int rulenum,
888 unsigned int chainindex, offset;
889 STRUCT_ENTRY_TARGET old;
890 struct chain_cache *c;
894 iptc_fn = TC_INSERT_ENTRY;
895 if (!(c = find_label(chain, *handle))) {
900 chainindex = offset2index(*handle, c->start_off);
902 tmp = index2entry(*handle, chainindex + rulenum);
903 if (!tmp || tmp > offset2entry(*handle, c->end_off)) {
907 offset = index2offset(*handle, chainindex + rulenum);
909 /* Mapping target actually alters entry, but that's
910 transparent to the caller. */
911 if (!map_target(*handle, (STRUCT_ENTRY *)e, offset, &old))
914 ret = insert_rules(1, e->next_offset, e, offset,
915 chainindex + rulenum, rulenum == 0, handle);
916 unmap_target((STRUCT_ENTRY *)e, &old);
920 /* Atomically replace rule `rulenum' in `chain' with `fw'. */
922 TC_REPLACE_ENTRY(const IPT_CHAINLABEL chain,
923 const STRUCT_ENTRY *e,
924 unsigned int rulenum,
927 unsigned int chainindex, offset;
928 STRUCT_ENTRY_TARGET old;
929 struct chain_cache *c;
933 iptc_fn = TC_REPLACE_ENTRY;
935 if (!(c = find_label(chain, *handle))) {
940 chainindex = offset2index(*handle, c->start_off);
942 tmp = index2entry(*handle, chainindex + rulenum);
943 if (!tmp || tmp >= offset2entry(*handle, c->end_off)) {
948 offset = index2offset(*handle, chainindex + rulenum);
949 /* Replace = delete and insert. */
950 if (!delete_rules(1, get_entry(*handle, offset)->next_offset,
951 offset, chainindex + rulenum, handle))
954 if (!map_target(*handle, (STRUCT_ENTRY *)e, offset, &old))
957 ret = insert_rules(1, e->next_offset, e, offset,
958 chainindex + rulenum, 1, handle);
959 unmap_target((STRUCT_ENTRY *)e, &old);
963 /* Append entry `fw' to chain `chain'. Equivalent to insert with
964 rulenum = length of chain. */
966 TC_APPEND_ENTRY(const IPT_CHAINLABEL chain,
967 const STRUCT_ENTRY *e,
970 struct chain_cache *c;
971 STRUCT_ENTRY_TARGET old;
974 iptc_fn = TC_APPEND_ENTRY;
975 if (!(c = find_label(chain, *handle))) {
980 if (!map_target(*handle, (STRUCT_ENTRY *)e,
984 ret = insert_rules(1, e->next_offset, e, c->end_off,
985 offset2index(*handle, c->end_off), 0, handle);
986 unmap_target((STRUCT_ENTRY *)e, &old);
991 match_different(const STRUCT_ENTRY_MATCH *a,
992 const unsigned char *a_elems,
993 const unsigned char *b_elems,
994 unsigned char **maskptr)
996 const STRUCT_ENTRY_MATCH *b;
999 /* Offset of b is the same as a. */
1000 b = (void *)b_elems + ((unsigned char *)a - a_elems);
1002 if (a->u.match_size != b->u.match_size)
1005 if (strcmp(a->u.user.name, b->u.user.name) != 0)
1008 *maskptr += ALIGN(sizeof(*a));
1010 for (i = 0; i < a->u.match_size - ALIGN(sizeof(*a)); i++)
1011 if (((a->data[i] ^ b->data[i]) & (*maskptr)[i]) != 0)
1018 target_different(const unsigned char *a_targdata,
1019 const unsigned char *b_targdata,
1020 unsigned int tdatasize,
1021 const unsigned char *mask)
1024 for (i = 0; i < tdatasize; i++)
1025 if (((a_targdata[i] ^ b_targdata[i]) & mask[i]) != 0)
1032 is_same(const STRUCT_ENTRY *a,
1033 const STRUCT_ENTRY *b,
1034 unsigned char *matchmask);
1036 /* Delete the first rule in `chain' which matches `fw'. */
1038 TC_DELETE_ENTRY(const IPT_CHAINLABEL chain,
1039 const STRUCT_ENTRY *origfw,
1040 unsigned char *matchmask,
1041 TC_HANDLE_T *handle)
1043 unsigned int offset;
1044 struct chain_cache *c;
1045 STRUCT_ENTRY *e, *fw;
1047 iptc_fn = TC_DELETE_ENTRY;
1048 if (!(c = find_label(chain, *handle))) {
1053 fw = malloc(origfw->next_offset);
1059 for (offset = c->start_off; offset < c->end_off;
1060 offset += e->next_offset) {
1061 STRUCT_ENTRY_TARGET discard;
1063 memcpy(fw, origfw, origfw->next_offset);
1065 /* FIXME: handle this in is_same --RR */
1066 if (!map_target(*handle, fw, offset, &discard)) {
1070 e = get_entry(*handle, offset);
1073 printf("Deleting:\n");
1076 if (is_same(e, fw, matchmask)) {
1078 ret = delete_rules(1, e->next_offset,
1079 offset, entry2index(*handle, e),
1091 /* Delete the rule in position `rulenum' in `chain'. */
1093 TC_DELETE_NUM_ENTRY(const IPT_CHAINLABEL chain,
1094 unsigned int rulenum,
1095 TC_HANDLE_T *handle)
1100 struct chain_cache *c;
1102 iptc_fn = TC_DELETE_NUM_ENTRY;
1103 if (!(c = find_label(chain, *handle))) {
1108 index = offset2index(*handle, c->start_off) + rulenum;
1110 if (index >= offset2index(*handle, c->end_off)) {
1115 e = index2entry(*handle, index);
1121 ret = delete_rules(1, e->next_offset, entry2offset(*handle, e),
1126 /* Check the packet `fw' on chain `chain'. Returns the verdict, or
1127 NULL and sets errno. */
1129 TC_CHECK_PACKET(const IPT_CHAINLABEL chain,
1130 STRUCT_ENTRY *entry,
1131 TC_HANDLE_T *handle)
1137 /* Flushes the entries in the given chain (ie. empties chain). */
1139 TC_FLUSH_ENTRIES(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle)
1141 unsigned int startindex, endindex;
1142 STRUCT_ENTRY *startentry, *endentry;
1143 struct chain_cache *c;
1146 iptc_fn = TC_FLUSH_ENTRIES;
1147 if (!(c = find_label(chain, *handle))) {
1151 startindex = offset2index(*handle, c->start_off);
1152 endindex = offset2index(*handle, c->end_off);
1153 startentry = offset2entry(*handle, c->start_off);
1154 endentry = offset2entry(*handle, c->end_off);
1156 ret = delete_rules(endindex - startindex,
1157 (char *)endentry - (char *)startentry,
1158 c->start_off, startindex,
1163 /* Zeroes the counters in a chain. */
1165 TC_ZERO_ENTRIES(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle)
1167 unsigned int i, end;
1168 struct chain_cache *c;
1170 if (!(c = find_label(chain, *handle))) {
1175 i = offset2index(*handle, c->start_off);
1176 end = offset2index(*handle, c->end_off);
1178 for (; i <= end; i++) {
1179 if ((*handle)->counter_map[i].maptype ==COUNTER_MAP_NORMAL_MAP)
1180 (*handle)->counter_map[i].maptype = COUNTER_MAP_ZEROED;
1182 set_changed(*handle);
1188 TC_READ_COUNTER(const IPT_CHAINLABEL chain,
1189 unsigned int rulenum,
1190 TC_HANDLE_T *handle)
1193 struct chain_cache *c;
1194 unsigned int chainindex, end;
1196 iptc_fn = TC_READ_COUNTER;
1199 if (!(c = find_label(chain, *handle))) {
1204 chainindex = offset2index(*handle, c->start_off);
1205 end = offset2index(*handle, c->end_off);
1207 if (chainindex + rulenum > end) {
1212 e = index2entry(*handle, chainindex + rulenum);
1214 return &e->counters;
1218 TC_ZERO_COUNTER(const IPT_CHAINLABEL chain,
1219 unsigned int rulenum,
1220 TC_HANDLE_T *handle)
1223 struct chain_cache *c;
1224 unsigned int chainindex, end;
1226 iptc_fn = TC_ZERO_COUNTER;
1229 if (!(c = find_label(chain, *handle))) {
1234 chainindex = offset2index(*handle, c->start_off);
1235 end = offset2index(*handle, c->end_off);
1237 if (chainindex + rulenum > end) {
1242 e = index2entry(*handle, chainindex + rulenum);
1244 if ((*handle)->counter_map[chainindex + rulenum].maptype
1245 == COUNTER_MAP_NORMAL_MAP) {
1246 (*handle)->counter_map[chainindex + rulenum].maptype
1247 = COUNTER_MAP_ZEROED;
1250 set_changed(*handle);
1256 TC_SET_COUNTER(const IPT_CHAINLABEL chain,
1257 unsigned int rulenum,
1258 STRUCT_COUNTERS *counters,
1259 TC_HANDLE_T *handle)
1262 struct chain_cache *c;
1263 unsigned int chainindex, end;
1265 iptc_fn = TC_SET_COUNTER;
1268 if (!(c = find_label(chain, *handle))) {
1273 chainindex = offset2index(*handle, c->start_off);
1274 end = offset2index(*handle, c->end_off);
1276 if (chainindex + rulenum > end) {
1281 e = index2entry(*handle, chainindex + rulenum);
1283 (*handle)->counter_map[chainindex + rulenum].maptype
1286 memcpy(&e->counters, counters, sizeof(STRUCT_COUNTERS));
1288 set_changed(*handle);
1293 /* Creates a new chain. */
1294 /* To create a chain, create two rules: error node and unconditional
1297 TC_CREATE_CHAIN(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle)
1302 struct ipt_error_target name;
1304 STRUCT_STANDARD_TARGET target;
1307 iptc_fn = TC_CREATE_CHAIN;
1309 /* find_label doesn't cover built-in targets: DROP, ACCEPT,
1311 if (find_label(chain, *handle)
1312 || strcmp(chain, LABEL_DROP) == 0
1313 || strcmp(chain, LABEL_ACCEPT) == 0
1314 || strcmp(chain, LABEL_QUEUE) == 0
1315 || strcmp(chain, LABEL_RETURN) == 0) {
1320 if (strlen(chain)+1 > sizeof(IPT_CHAINLABEL)) {
1325 memset(&newc, 0, sizeof(newc));
1326 newc.head.target_offset = sizeof(STRUCT_ENTRY);
1327 newc.head.next_offset
1328 = sizeof(STRUCT_ENTRY)
1329 + ALIGN(sizeof(struct ipt_error_target));
1330 strcpy(newc.name.t.u.user.name, ERROR_TARGET);
1331 newc.name.t.u.target_size = ALIGN(sizeof(struct ipt_error_target));
1332 strcpy(newc.name.error, chain);
1334 newc.ret.target_offset = sizeof(STRUCT_ENTRY);
1335 newc.ret.next_offset
1336 = sizeof(STRUCT_ENTRY)
1337 + ALIGN(sizeof(STRUCT_STANDARD_TARGET));
1338 strcpy(newc.target.target.u.user.name, STANDARD_TARGET);
1339 newc.target.target.u.target_size
1340 = ALIGN(sizeof(STRUCT_STANDARD_TARGET));
1341 newc.target.verdict = RETURN;
1343 /* Add just before terminal entry */
1344 ret = insert_rules(2, sizeof(newc), &newc.head,
1345 index2offset(*handle, (*handle)->new_number - 1),
1346 (*handle)->new_number - 1,
1352 count_ref(STRUCT_ENTRY *e, unsigned int offset, unsigned int *ref)
1354 STRUCT_STANDARD_TARGET *t;
1356 if (strcmp(GET_TARGET(e)->u.user.name, STANDARD_TARGET) == 0) {
1357 t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e);
1359 if (t->verdict == offset)
1366 /* Get the number of references to this chain. */
1368 TC_GET_REFERENCES(unsigned int *ref, const IPT_CHAINLABEL chain,
1369 TC_HANDLE_T *handle)
1371 struct chain_cache *c;
1373 if (!(c = find_label(chain, *handle))) {
1379 ENTRY_ITERATE((*handle)->entries.entrytable,
1380 (*handle)->entries.size,
1381 count_ref, c->start_off, ref);
1385 /* Deletes a chain. */
1387 TC_DELETE_CHAIN(const IPT_CHAINLABEL chain, TC_HANDLE_T *handle)
1389 unsigned int labelidx, labeloff;
1390 unsigned int references;
1391 struct chain_cache *c;
1393 STRUCT_ENTRY *start;
1395 if (!TC_GET_REFERENCES(&references, chain, handle))
1398 iptc_fn = TC_DELETE_CHAIN;
1400 if (TC_BUILTIN(chain, *handle)) {
1405 if (references > 0) {
1410 if (!(c = find_label(chain, *handle))) {
1415 if (c->start_off != c->end_off) {
1420 /* Need label index: preceeds chain start */
1421 labelidx = offset2index(*handle, c->start_off) - 1;
1422 labeloff = index2offset(*handle, labelidx);
1424 start = offset2entry(*handle, c->start_off);
1426 ret = delete_rules(2,
1427 get_entry(*handle, labeloff)->next_offset
1428 + start->next_offset,
1429 labeloff, labelidx, handle);
1433 /* Renames a chain. */
1434 int TC_RENAME_CHAIN(const IPT_CHAINLABEL oldname,
1435 const IPT_CHAINLABEL newname,
1436 TC_HANDLE_T *handle)
1438 unsigned int labeloff, labelidx;
1439 struct chain_cache *c;
1440 struct ipt_error_target *t;
1442 iptc_fn = TC_RENAME_CHAIN;
1444 /* find_label doesn't cover built-in targets: DROP, ACCEPT,
1446 if (find_label(newname, *handle)
1447 || strcmp(newname, LABEL_DROP) == 0
1448 || strcmp(newname, LABEL_ACCEPT) == 0
1449 || strcmp(newname, LABEL_QUEUE) == 0
1450 || strcmp(newname, LABEL_RETURN) == 0) {
1455 if (!(c = find_label(oldname, *handle))
1456 || TC_BUILTIN(oldname, *handle)) {
1461 if (strlen(newname)+1 > sizeof(IPT_CHAINLABEL)) {
1466 /* Need label index: preceeds chain start */
1467 labelidx = offset2index(*handle, c->start_off) - 1;
1468 labeloff = index2offset(*handle, labelidx);
1470 t = (struct ipt_error_target *)
1471 GET_TARGET(get_entry(*handle, labeloff));
1473 memset(t->error, 0, sizeof(t->error));
1474 strcpy(t->error, newname);
1475 set_changed(*handle);
1480 /* Sets the policy on a built-in chain. */
1482 TC_SET_POLICY(const IPT_CHAINLABEL chain,
1483 const IPT_CHAINLABEL policy,
1484 STRUCT_COUNTERS *counters,
1485 TC_HANDLE_T *handle)
1488 unsigned int policyoff, ctrindex;
1490 STRUCT_STANDARD_TARGET *t;
1492 iptc_fn = TC_SET_POLICY;
1493 /* Figure out which chain. */
1494 hook = TC_BUILTIN(chain, *handle);
1501 policyoff = get_chain_end(*handle, (*handle)->info.hook_entry[hook]);
1502 if (policyoff != (*handle)->info.underflow[hook]) {
1503 printf("ERROR: Policy for `%s' offset %u != underflow %u\n",
1504 chain, policyoff, (*handle)->info.underflow[hook]);
1508 e = get_entry(*handle, policyoff);
1509 t = (STRUCT_STANDARD_TARGET *)GET_TARGET(e);
1511 if (strcmp(policy, LABEL_ACCEPT) == 0)
1512 t->verdict = -NF_ACCEPT - 1;
1513 else if (strcmp(policy, LABEL_DROP) == 0)
1514 t->verdict = -NF_DROP - 1;
1520 ctrindex = entry2index(*handle, e);
1523 /* set byte and packet counters */
1524 memcpy(&e->counters, counters, sizeof(STRUCT_COUNTERS));
1526 (*handle)->counter_map[ctrindex].maptype
1530 (*handle)->counter_map[ctrindex]
1531 = ((struct counter_map){ COUNTER_MAP_NOMAP, 0 });
1534 set_changed(*handle);
1539 /* Without this, on gcc 2.7.2.3, we get:
1540 libiptc.c: In function `TC_COMMIT':
1541 libiptc.c:833: fixed or forbidden register was spilled.
1542 This may be due to a compiler bug or to impossible asm
1543 statements or clauses.
1546 subtract_counters(STRUCT_COUNTERS *answer,
1547 const STRUCT_COUNTERS *a,
1548 const STRUCT_COUNTERS *b)
1550 answer->pcnt = a->pcnt - b->pcnt;
1551 answer->bcnt = a->bcnt - b->bcnt;
1555 TC_COMMIT(TC_HANDLE_T *handle)
1557 /* Replace, then map back the counters. */
1558 STRUCT_REPLACE *repl;
1559 STRUCT_COUNTERS_INFO *newcounters;
1565 counterlen = sizeof(STRUCT_COUNTERS_INFO)
1566 + sizeof(STRUCT_COUNTERS) * (*handle)->new_number;
1569 TC_DUMP_ENTRIES(*handle);
1572 /* Don't commit if nothing changed. */
1573 if (!(*handle)->changed)
1576 repl = malloc(sizeof(*repl) + (*handle)->entries.size);
1582 /* These are the old counters we will get from kernel */
1583 repl->counters = malloc(sizeof(STRUCT_COUNTERS)
1584 * (*handle)->info.num_entries);
1585 if (!repl->counters) {
1591 /* These are the counters we're going to put back, later. */
1592 newcounters = malloc(counterlen);
1594 free(repl->counters);
1600 strcpy(repl->name, (*handle)->info.name);
1601 repl->num_entries = (*handle)->new_number;
1602 repl->size = (*handle)->entries.size;
1603 memcpy(repl->hook_entry, (*handle)->info.hook_entry,
1604 sizeof(repl->hook_entry));
1605 memcpy(repl->underflow, (*handle)->info.underflow,
1606 sizeof(repl->underflow));
1607 repl->num_counters = (*handle)->info.num_entries;
1608 repl->valid_hooks = (*handle)->info.valid_hooks;
1609 memcpy(repl->entries, (*handle)->entries.entrytable,
1610 (*handle)->entries.size);
1612 if (setsockopt(sockfd, TC_IPPROTO, SO_SET_REPLACE, repl,
1613 sizeof(*repl) + (*handle)->entries.size) < 0) {
1614 free(repl->counters);
1620 /* Put counters back. */
1621 strcpy(newcounters->name, (*handle)->info.name);
1622 newcounters->num_counters = (*handle)->new_number;
1623 for (i = 0; i < (*handle)->new_number; i++) {
1624 unsigned int mappos = (*handle)->counter_map[i].mappos;
1625 switch ((*handle)->counter_map[i].maptype) {
1626 case COUNTER_MAP_NOMAP:
1627 newcounters->counters[i]
1628 = ((STRUCT_COUNTERS){ 0, 0 });
1631 case COUNTER_MAP_NORMAL_MAP:
1632 /* Original read: X.
1633 * Atomic read on replacement: X + Y.
1634 * Currently in kernel: Z.
1635 * Want in kernel: X + Y + Z.
1637 * => Add in replacement read.
1639 newcounters->counters[i] = repl->counters[mappos];
1642 case COUNTER_MAP_ZEROED:
1643 /* Original read: X.
1644 * Atomic read on replacement: X + Y.
1645 * Currently in kernel: Z.
1646 * Want in kernel: Y + Z.
1648 * => Add in (replacement read - original read).
1650 subtract_counters(&newcounters->counters[i],
1651 &repl->counters[mappos],
1652 &index2entry(*handle, i)->counters);
1655 case COUNTER_MAP_SET:
1656 /* Want to set counter (iptables-restore) */
1658 memcpy(&newcounters->counters[i],
1659 &index2entry(*handle, i)->counters,
1660 sizeof(STRUCT_COUNTERS));
1666 #ifdef KERNEL_64_USERSPACE_32
1668 /* Kernel will think that pointer should be 64-bits, and get
1669 padding. So we accomodate here (assumption: alignment of
1670 `counters' is on 64-bit boundary). */
1671 u_int64_t *kernptr = (u_int64_t *)&newcounters->counters;
1672 if ((unsigned long)&newcounters->counters % 8 != 0) {
1674 "counters alignment incorrect! Mail rusty!\n");
1677 *kernptr = newcounters->counters;
1679 #endif /* KERNEL_64_USERSPACE_32 */
1681 if (setsockopt(sockfd, TC_IPPROTO, SO_SET_ADD_COUNTERS,
1682 newcounters, counterlen) < 0) {
1683 free(repl->counters);
1689 free(repl->counters);
1698 /* Get raw socket. */
1705 /* Translates errno numbers into more human-readable form than strerror. */
1707 TC_STRERROR(int err)
1710 struct table_struct {
1713 const char *message;
1715 { { TC_INIT, EPERM, "Permission denied (you must be root)" },
1716 { TC_INIT, EINVAL, "Module is wrong version" },
1718 "Table does not exist (do you need to insmod?)" },
1719 { TC_DELETE_CHAIN, ENOTEMPTY, "Chain is not empty" },
1720 { TC_DELETE_CHAIN, EINVAL, "Can't delete built-in chain" },
1721 { TC_DELETE_CHAIN, EMLINK,
1722 "Can't delete chain with references left" },
1723 { TC_CREATE_CHAIN, EEXIST, "Chain already exists" },
1724 { TC_INSERT_ENTRY, E2BIG, "Index of insertion too big" },
1725 { TC_REPLACE_ENTRY, E2BIG, "Index of replacement too big" },
1726 { TC_DELETE_NUM_ENTRY, E2BIG, "Index of deletion too big" },
1727 { TC_READ_COUNTER, E2BIG, "Index of counter too big" },
1728 { TC_ZERO_COUNTER, E2BIG, "Index of counter too big" },
1729 { TC_INSERT_ENTRY, ELOOP, "Loop found in table" },
1730 { TC_INSERT_ENTRY, EINVAL, "Target problem" },
1731 /* EINVAL for CHECK probably means bad interface. */
1732 { TC_CHECK_PACKET, EINVAL,
1733 "Bad arguments (does that interface exist?)" },
1734 { TC_CHECK_PACKET, ENOSYS,
1735 "Checking will most likely never get implemented" },
1736 /* ENOENT for DELETE probably means no matching rule */
1737 { TC_DELETE_ENTRY, ENOENT,
1738 "Bad rule (does a matching rule exist in that chain?)" },
1739 { TC_SET_POLICY, ENOENT,
1740 "Bad built-in chain name" },
1741 { TC_SET_POLICY, EINVAL,
1742 "Bad policy name" },
1744 { NULL, 0, "Incompatible with this kernel" },
1745 { NULL, ENOPROTOOPT, "iptables who? (do you need to insmod?)" },
1746 { NULL, ENOSYS, "Will be implemented real soon. I promise ;)" },
1747 { NULL, ENOMEM, "Memory allocation problem" },
1748 { NULL, ENOENT, "No chain/target/match by that name" },
1751 for (i = 0; i < sizeof(table)/sizeof(struct table_struct); i++) {
1752 if ((!table[i].fn || table[i].fn == iptc_fn)
1753 && table[i].err == err)
1754 return table[i].message;
1757 return strerror(err);