|
@@ -9,7 +9,7 @@
|
9
|
9
|
*/
|
10
|
10
|
|
11
|
11
|
/* (C) 1999 Paul ``Rusty'' Russell - Placed under the GNU GPL (See
|
12
|
|
- * COPYING for details).
|
|
12
|
+ * COPYING for details).
|
13
|
13
|
* (C) 2000-2004 by the Netfilter Core Team <coreteam@netfilter.org>
|
14
|
14
|
*
|
15
|
15
|
* 2003-Jun-20: Harald Welte <laforge@netfilter.org>:
|
|
@@ -17,7 +17,7 @@
|
17
|
17
|
* 2003-Jun-23: Harald Welte <laforge@netfilter.org>:
|
18
|
18
|
* - performance optimization, sponsored by Astaro AG (http://www.astaro.com/)
|
19
|
19
|
* don't rebuild the chain cache after every operation, instead fix it
|
20
|
|
- * up after a ruleset change.
|
|
20
|
+ * up after a ruleset change.
|
21
|
21
|
* 2004-Aug-18: Harald Welte <laforge@netfilter.org>:
|
22
|
22
|
* - futher performance work: total reimplementation of libiptc.
|
23
|
23
|
* - libiptc now has a real internal (linked-list) represntation of the
|
|
@@ -27,6 +27,8 @@
|
27
|
27
|
#include <sys/types.h>
|
28
|
28
|
#include <sys/socket.h>
|
29
|
29
|
|
|
30
|
+#include <linux/version.h>
|
|
31
|
+
|
30
|
32
|
#include "linux_list.h"
|
31
|
33
|
|
32
|
34
|
//#define IPTC_DEBUG2 1
|
|
@@ -44,6 +46,7 @@
|
44
|
46
|
#define IPT_LIB_DIR "/usr/local/lib/iptables"
|
45
|
47
|
#endif
|
46
|
48
|
|
|
49
|
+
|
47
|
50
|
static int sockfd = -1;
|
48
|
51
|
static int sockfd_use = 0;
|
49
|
52
|
static void *iptc_fn = NULL;
|
|
@@ -130,7 +133,7 @@ STRUCT_TC_HANDLE
|
130
|
133
|
int changed; /* Have changes been made? */
|
131
|
134
|
|
132
|
135
|
struct list_head chains;
|
133
|
|
-
|
|
136
|
+
|
134
|
137
|
struct chain_head *chain_iterator_cur;
|
135
|
138
|
struct rule_head *rule_iterator_cur;
|
136
|
139
|
|
|
@@ -370,14 +373,14 @@ static int __iptcc_p_del_policy(TC_HANDLE_T h, unsigned int num)
|
370
|
373
|
h->chain_iterator_cur->rules.prev;
|
371
|
374
|
|
372
|
375
|
/* save verdict */
|
373
|
|
- h->chain_iterator_cur->verdict =
|
|
376
|
+ h->chain_iterator_cur->verdict =
|
374
|
377
|
*(int *)GET_TARGET(pr->entry)->data;
|
375
|
378
|
|
376
|
379
|
/* save counter and counter_map information */
|
377
|
|
- h->chain_iterator_cur->counter_map.maptype =
|
|
380
|
+ h->chain_iterator_cur->counter_map.maptype =
|
378
|
381
|
COUNTER_MAP_NORMAL_MAP;
|
379
|
382
|
h->chain_iterator_cur->counter_map.mappos = num-1;
|
380
|
|
- memcpy(&h->chain_iterator_cur->counters, &pr->entry->counters,
|
|
383
|
+ memcpy(&h->chain_iterator_cur->counters, &pr->entry->counters,
|
381
|
384
|
sizeof(h->chain_iterator_cur->counters));
|
382
|
385
|
|
383
|
386
|
/* foot_offset points to verdict rule */
|
|
@@ -423,13 +426,13 @@ static void __iptcc_p_add_chain(TC_HANDLE_T h, struct chain_head *c,
|
423
|
426
|
c->index = *num;
|
424
|
427
|
|
425
|
428
|
iptc_insert_chain(h, c);
|
426
|
|
-
|
|
429
|
+
|
427
|
430
|
h->chain_iterator_cur = c;
|
428
|
431
|
}
|
429
|
432
|
|
430
|
433
|
/* main parser function: add an entry from the blob to the cache */
|
431
|
|
-static int cache_add_entry(STRUCT_ENTRY *e,
|
432
|
|
- TC_HANDLE_T h,
|
|
434
|
+static int cache_add_entry(STRUCT_ENTRY *e,
|
|
435
|
+ TC_HANDLE_T h,
|
433
|
436
|
STRUCT_ENTRY **prev,
|
434
|
437
|
unsigned int *num)
|
435
|
438
|
{
|
|
@@ -453,9 +456,9 @@ static int cache_add_entry(STRUCT_ENTRY *e,
|
453
|
456
|
* target, or a hook entry point */
|
454
|
457
|
|
455
|
458
|
if (strcmp(GET_TARGET(e)->u.user.name, ERROR_TARGET) == 0) {
|
456
|
|
- struct chain_head *c =
|
|
459
|
+ struct chain_head *c =
|
457
|
460
|
iptcc_alloc_chain_head((const char *)GET_TARGET(e)->data, 0);
|
458
|
|
- DEBUGP_C("%u:%u:new userdefined chain %s: %p\n", *num, offset,
|
|
461
|
+ DEBUGP_C("%u:%u:new userdefined chain %s: %p\n", *num, offset,
|
459
|
462
|
(char *)c->name, c);
|
460
|
463
|
if (!c) {
|
461
|
464
|
errno = -ENOMEM;
|
|
@@ -466,9 +469,9 @@ static int cache_add_entry(STRUCT_ENTRY *e,
|
466
|
469
|
|
467
|
470
|
} else if ((builtin = iptcb_ent_is_hook_entry(e, h)) != 0) {
|
468
|
471
|
struct chain_head *c =
|
469
|
|
- iptcc_alloc_chain_head((char *)hooknames[builtin-1],
|
|
472
|
+ iptcc_alloc_chain_head((char *)hooknames[builtin-1],
|
470
|
473
|
builtin);
|
471
|
|
- DEBUGP_C("%u:%u new builtin chain: %p (rules=%p)\n",
|
|
474
|
+ DEBUGP_C("%u:%u new builtin chain: %p (rules=%p)\n",
|
472
|
475
|
*num, offset, c, &c->rules);
|
473
|
476
|
if (!c) {
|
474
|
477
|
errno = -ENOMEM;
|
|
@@ -486,7 +489,7 @@ static int cache_add_entry(STRUCT_ENTRY *e,
|
486
|
489
|
struct rule_head *r;
|
487
|
490
|
new_rule:
|
488
|
491
|
|
489
|
|
- if (!(r = iptcc_alloc_rule(h->chain_iterator_cur,
|
|
492
|
+ if (!(r = iptcc_alloc_rule(h->chain_iterator_cur,
|
490
|
493
|
e->next_offset))) {
|
491
|
494
|
errno = ENOMEM;
|
492
|
495
|
return -1;
|
|
@@ -619,7 +622,7 @@ static inline int iptcc_compile_rule (TC_HANDLE_T h, STRUCT_REPLACE *repl, struc
|
619
|
622
|
t = (STRUCT_STANDARD_TARGET *)GET_TARGET(r->entry);
|
620
|
623
|
t->verdict = r->offset + r->size;
|
621
|
624
|
}
|
622
|
|
-
|
|
625
|
+
|
623
|
626
|
/* copy entry from cache to blob */
|
624
|
627
|
memcpy((char *)repl->entries+r->offset, r->entry, r->size);
|
625
|
628
|
|
|
@@ -634,6 +637,25 @@ static int iptcc_compile_chain(TC_HANDLE_T h, STRUCT_REPLACE *repl, struct chain
|
634
|
637
|
struct iptcb_chain_start *head;
|
635
|
638
|
struct iptcb_chain_foot *foot;
|
636
|
639
|
|
|
640
|
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 7, 0)
|
|
641
|
+
|
|
642
|
+ /* only user-defined chains have heaer */
|
|
643
|
+ if (!iptcc_is_builtin(c)) {
|
|
644
|
+ /* put chain header in place */
|
|
645
|
+ head = (void *)repl->entries + c->head_offset;
|
|
646
|
+ head->e.target_offset = sizeof(STRUCT_ENTRY);
|
|
647
|
+ head->e.next_offset = IPTCB_CHAIN_START_SIZE;
|
|
648
|
+ strcpy(head->name.t.u.user.name, ERROR_TARGET);
|
|
649
|
+ head->name.t.u.target_size =
|
|
650
|
+ ALIGN(sizeof(struct ipt_error_target));
|
|
651
|
+ strcpy(head->name.error, c->name);
|
|
652
|
+ } else {
|
|
653
|
+ repl->hook_entry[c->hooknum-1] = c->head_offset;
|
|
654
|
+ repl->underflow[c->hooknum-1] = c->foot_offset;
|
|
655
|
+ }
|
|
656
|
+#endif
|
|
657
|
+
|
|
658
|
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
|
637
|
659
|
/* only user-defined chains have heaer */
|
638
|
660
|
if (!iptcc_is_builtin(c)) {
|
639
|
661
|
/* put chain header in place */
|
|
@@ -641,13 +663,14 @@ static int iptcc_compile_chain(TC_HANDLE_T h, STRUCT_REPLACE *repl, struct chain
|
641
|
663
|
head->e.target_offset = sizeof(STRUCT_ENTRY);
|
642
|
664
|
head->e.next_offset = IPTCB_CHAIN_START_SIZE;
|
643
|
665
|
strcpy(head->name.target.u.user.name, ERROR_TARGET);
|
644
|
|
- head->name.target.u.target_size =
|
|
666
|
+ head->name.target.u.target_size =
|
645
|
667
|
ALIGN(sizeof(struct ipt_error_target));
|
646
|
|
- strcpy(head->name.errorname, c->name);
|
|
668
|
+ strcpy(head->name.error, c->name);
|
647
|
669
|
} else {
|
648
|
|
- repl->hook_entry[c->hooknum-1] = c->head_offset;
|
|
670
|
+ repl->hook_entry[c->hooknum-1] = c->head_offset;
|
649
|
671
|
repl->underflow[c->hooknum-1] = c->foot_offset;
|
650
|
672
|
}
|
|
673
|
+#endif
|
651
|
674
|
|
652
|
675
|
/* iterate over rules */
|
653
|
676
|
list_for_each_entry(r, &c->rules, list) {
|
|
@@ -685,7 +708,7 @@ static int iptcc_compile_chain_offsets(TC_HANDLE_T h, struct chain_head *c,
|
685
|
708
|
|
686
|
709
|
if (!iptcc_is_builtin(c)) {
|
687
|
710
|
/* Chain has header */
|
688
|
|
- *offset += sizeof(STRUCT_ENTRY)
|
|
711
|
+ *offset += sizeof(STRUCT_ENTRY)
|
689
|
712
|
+ ALIGN(sizeof(struct ipt_error_target));
|
690
|
713
|
(*num)++;
|
691
|
714
|
}
|
|
@@ -698,7 +721,7 @@ static int iptcc_compile_chain_offsets(TC_HANDLE_T h, struct chain_head *c,
|
698
|
721
|
(*num)++;
|
699
|
722
|
}
|
700
|
723
|
|
701
|
|
- DEBUGP("%s; chain_foot %u, offset=%u, index=%u\n", c->name, *num,
|
|
724
|
+ DEBUGP("%s; chain_foot %u, offset=%u, index=%u\n", c->name, *num,
|
702
|
725
|
*offset, *num);
|
703
|
726
|
c->foot_offset = *offset;
|
704
|
727
|
c->foot_index = *num;
|
|
@@ -744,16 +767,27 @@ static int iptcc_compile_table(TC_HANDLE_T h, STRUCT_REPLACE *repl)
|
744
|
767
|
if (ret < 0)
|
745
|
768
|
return ret;
|
746
|
769
|
}
|
747
|
|
-
|
|
770
|
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 7, 0)
|
748
|
771
|
/* Append error rule at end of chain */
|
749
|
772
|
error = (void *)repl->entries + repl->size - IPTCB_CHAIN_ERROR_SIZE;
|
750
|
773
|
error->entry.target_offset = sizeof(STRUCT_ENTRY);
|
751
|
774
|
error->entry.next_offset = IPTCB_CHAIN_ERROR_SIZE;
|
752
|
|
- error->target.target.u.user.target_size =
|
|
775
|
+ error->target.t.u.user.target_size =
|
753
|
776
|
ALIGN(sizeof(struct ipt_error_target));
|
754
|
|
- strcpy((char *)&error->target.target.u.user.name, ERROR_TARGET);
|
755
|
|
- strcpy((char *)&error->target.errorname, "ERROR");
|
|
777
|
+ strcpy((char *)&error->target.t.u.user.name, ERROR_TARGET);
|
|
778
|
+ strcpy((char *)&error->target.error, "ERROR");
|
|
779
|
+#endif
|
756
|
780
|
|
|
781
|
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
|
|
782
|
+ /* Append error rule at end of chain */
|
|
783
|
+ error = (void *)repl->entries + repl->size - IPTCB_CHAIN_ERROR_SIZE;
|
|
784
|
+ error->entry.target_offset = sizeof(STRUCT_ENTRY);
|
|
785
|
+ error->entry.next_offset = IPTCB_CHAIN_ERROR_SIZE;
|
|
786
|
+ error->target.target.u.user.target_size =
|
|
787
|
+ ALIGN(sizeof(struct ipt_error_target));
|
|
788
|
+ strcpy((char *)&error->target.target.u.user.name, ERROR_TARGET);
|
|
789
|
+ strcpy((char *)&error->target.errorname, "ERROR");
|
|
790
|
+#endif
|
757
|
791
|
return 1;
|
758
|
792
|
}
|
759
|
793
|
|
|
@@ -809,7 +843,7 @@ TC_INIT(const char *tablename)
|
809
|
843
|
errno = EINVAL;
|
810
|
844
|
return NULL;
|
811
|
845
|
}
|
812
|
|
-
|
|
846
|
+
|
813
|
847
|
if (sockfd_use == 0) {
|
814
|
848
|
sockfd = socket(TC_AF, SOCK_RAW, IPPROTO_RAW);
|
815
|
849
|
if (sockfd < 0)
|
|
@@ -853,7 +887,7 @@ TC_INIT(const char *tablename)
|
853
|
887
|
|
854
|
888
|
#ifdef IPTC_DEBUG2
|
855
|
889
|
{
|
856
|
|
- int fd = open("/tmp/libiptc-so_get_entries.blob",
|
|
890
|
+ int fd = open("/tmp/libiptc-so_get_entries.blob",
|
857
|
891
|
O_CREAT|O_WRONLY);
|
858
|
892
|
if (fd >= 0) {
|
859
|
893
|
write(fd, h->entries, tmp);
|
|
@@ -911,7 +945,7 @@ print_match(const STRUCT_ENTRY_MATCH *m)
|
911
|
945
|
}
|
912
|
946
|
|
913
|
947
|
/*static int dump_entry(STRUCT_ENTRY *e, const TC_HANDLE_T handle);*/
|
914
|
|
-
|
|
948
|
+
|
915
|
949
|
void
|
916
|
950
|
TC_DUMP_ENTRIES(const TC_HANDLE_T handle)
|
917
|
951
|
{
|
|
@@ -953,7 +987,7 @@ static void iptcc_chain_iterator_advance(TC_HANDLE_T handle)
|
953
|
987
|
if (c->list.next == &handle->chains)
|
954
|
988
|
handle->chain_iterator_cur = NULL;
|
955
|
989
|
else
|
956
|
|
- handle->chain_iterator_cur =
|
|
990
|
+ handle->chain_iterator_cur =
|
957
|
991
|
list_entry(c->list.next, struct chain_head, list);
|
958
|
992
|
}
|
959
|
993
|
|
|
@@ -993,7 +1027,7 @@ TC_NEXT_CHAIN(TC_HANDLE_T *handle)
|
993
|
1027
|
}
|
994
|
1028
|
|
995
|
1029
|
iptcc_chain_iterator_advance(*handle);
|
996
|
|
-
|
|
1030
|
+
|
997
|
1031
|
DEBUGP(": returning `%s'\n", c->name);
|
998
|
1032
|
return c->name;
|
999
|
1033
|
}
|
|
@@ -1041,13 +1075,13 @@ TC_NEXT_RULE(const STRUCT_ENTRY *prev, TC_HANDLE_T *handle)
|
1041
|
1075
|
DEBUGP_C("returning NULL\n");
|
1042
|
1076
|
return NULL;
|
1043
|
1077
|
}
|
1044
|
|
-
|
1045
|
|
- r = list_entry((*handle)->rule_iterator_cur->list.next,
|
|
1078
|
+
|
|
1079
|
+ r = list_entry((*handle)->rule_iterator_cur->list.next,
|
1046
|
1080
|
struct rule_head, list);
|
1047
|
1081
|
|
1048
|
1082
|
iptc_fn = TC_NEXT_RULE;
|
1049
|
1083
|
|
1050
|
|
- DEBUGP_C("next=%p, head=%p...", &r->list,
|
|
1084
|
+ DEBUGP_C("next=%p, head=%p...", &r->list,
|
1051
|
1085
|
&(*handle)->rule_iterator_cur->chain->rules);
|
1052
|
1086
|
|
1053
|
1087
|
if (&r->list == &(*handle)->rule_iterator_cur->chain->rules) {
|
|
@@ -1076,7 +1110,7 @@ TC_NUM_RULES(const char *chain, TC_HANDLE_T *handle)
|
1076
|
1110
|
errno = ENOENT;
|
1077
|
1111
|
return (unsigned int)-1;
|
1078
|
1112
|
}
|
1079
|
|
-
|
|
1113
|
+
|
1080
|
1114
|
return c->num_rules;
|
1081
|
1115
|
}
|
1082
|
1116
|
|
|
@@ -1086,7 +1120,7 @@ const STRUCT_ENTRY *TC_GET_RULE(const char *chain,
|
1086
|
1120
|
{
|
1087
|
1121
|
struct chain_head *c;
|
1088
|
1122
|
struct rule_head *r;
|
1089
|
|
-
|
|
1123
|
+
|
1090
|
1124
|
iptc_fn = TC_GET_RULE;
|
1091
|
1125
|
|
1092
|
1126
|
CHECK(*handle);
|
|
@@ -1163,7 +1197,7 @@ int
|
1163
|
1197
|
TC_BUILTIN(const char *chain, const TC_HANDLE_T handle)
|
1164
|
1198
|
{
|
1165
|
1199
|
struct chain_head *c;
|
1166
|
|
-
|
|
1200
|
+
|
1167
|
1201
|
iptc_fn = TC_BUILTIN;
|
1168
|
1202
|
|
1169
|
1203
|
c = iptcc_find_label(chain, handle);
|
|
@@ -1537,7 +1571,7 @@ TC_DELETE_ENTRY(const IPT_CHAINLABEL chain,
|
1537
|
1571
|
* current iterator, move rule iterator back. next
|
1538
|
1572
|
* pointer will then point to real next node */
|
1539
|
1573
|
if (i == (*handle)->rule_iterator_cur) {
|
1540
|
|
- (*handle)->rule_iterator_cur =
|
|
1574
|
+ (*handle)->rule_iterator_cur =
|
1541
|
1575
|
list_entry((*handle)->rule_iterator_cur->list.prev,
|
1542
|
1576
|
struct rule_head, list);
|
1543
|
1577
|
}
|
|
@@ -1588,7 +1622,7 @@ TC_DELETE_NUM_ENTRY(const IPT_CHAINLABEL chain,
|
1588
|
1622
|
* iterator, move rule iterator back. next pointer will then
|
1589
|
1623
|
* point to real next node */
|
1590
|
1624
|
if (r == (*handle)->rule_iterator_cur) {
|
1591
|
|
- (*handle)->rule_iterator_cur =
|
|
1625
|
+ (*handle)->rule_iterator_cur =
|
1592
|
1626
|
list_entry((*handle)->rule_iterator_cur->list.prev,
|
1593
|
1627
|
struct rule_head, list);
|
1594
|
1628
|
}
|
|
@@ -1691,7 +1725,7 @@ TC_ZERO_COUNTER(const IPT_CHAINLABEL chain,
|
1691
|
1725
|
{
|
1692
|
1726
|
struct chain_head *c;
|
1693
|
1727
|
struct rule_head *r;
|
1694
|
|
-
|
|
1728
|
+
|
1695
|
1729
|
iptc_fn = TC_ZERO_COUNTER;
|
1696
|
1730
|
CHECK(*handle);
|
1697
|
1731
|
|
|
@@ -1713,7 +1747,7 @@ TC_ZERO_COUNTER(const IPT_CHAINLABEL chain,
|
1713
|
1747
|
return 1;
|
1714
|
1748
|
}
|
1715
|
1749
|
|
1716
|
|
-int
|
|
1750
|
+int
|
1717
|
1751
|
TC_SET_COUNTER(const IPT_CHAINLABEL chain,
|
1718
|
1752
|
unsigned int rulenum,
|
1719
|
1753
|
STRUCT_COUNTERS *counters,
|
|
@@ -1892,7 +1926,7 @@ int TC_RENAME_CHAIN(const IPT_CHAINLABEL oldname,
|
1892
|
1926
|
}
|
1893
|
1927
|
|
1894
|
1928
|
strncpy(c->name, newname, sizeof(IPT_CHAINLABEL));
|
1895
|
|
-
|
|
1929
|
+
|
1896
|
1930
|
set_changed(*handle);
|
1897
|
1931
|
|
1898
|
1932
|
return 1;
|
|
@@ -2092,7 +2126,7 @@ TC_COMMIT(TC_HANDLE_T *handle)
|
2092
|
2126
|
|
2093
|
2127
|
#ifdef IPTC_DEBUG2
|
2094
|
2128
|
{
|
2095
|
|
- int fd = open("/tmp/libiptc-so_set_replace.blob",
|
|
2129
|
+ int fd = open("/tmp/libiptc-so_set_replace.blob",
|
2096
|
2130
|
O_CREAT|O_WRONLY);
|
2097
|
2131
|
if (fd >= 0) {
|
2098
|
2132
|
write(fd, repl, sizeof(*repl) + repl->size);
|
|
@@ -2125,12 +2159,12 @@ TC_COMMIT(TC_HANDLE_T *handle)
|
2125
|
2159
|
break;
|
2126
|
2160
|
case COUNTER_MAP_NORMAL_MAP:
|
2127
|
2161
|
counters_normal_map(newcounters, repl,
|
2128
|
|
- c->foot_index,
|
|
2162
|
+ c->foot_index,
|
2129
|
2163
|
c->counter_map.mappos);
|
2130
|
2164
|
break;
|
2131
|
2165
|
case COUNTER_MAP_ZEROED:
|
2132
|
2166
|
counters_map_zeroed(newcounters, repl,
|
2133
|
|
- c->foot_index,
|
|
2167
|
+ c->foot_index,
|
2134
|
2168
|
c->counter_map.mappos,
|
2135
|
2169
|
&c->counters);
|
2136
|
2170
|
break;
|
|
@@ -2150,7 +2184,7 @@ TC_COMMIT(TC_HANDLE_T *handle)
|
2150
|
2184
|
|
2151
|
2185
|
case COUNTER_MAP_NORMAL_MAP:
|
2152
|
2186
|
counters_normal_map(newcounters, repl,
|
2153
|
|
- r->index,
|
|
2187
|
+ r->index,
|
2154
|
2188
|
r->counter_map.mappos);
|
2155
|
2189
|
break;
|
2156
|
2190
|
|
|
@@ -2187,7 +2221,7 @@ TC_COMMIT(TC_HANDLE_T *handle)
|
2187
|
2221
|
|
2188
|
2222
|
#ifdef IPTC_DEBUG2
|
2189
|
2223
|
{
|
2190
|
|
- int fd = open("/tmp/libiptc-so_set_add_counters.blob",
|
|
2224
|
+ int fd = open("/tmp/libiptc-so_set_add_counters.blob",
|
2191
|
2225
|
O_CREAT|O_WRONLY);
|
2192
|
2226
|
if (fd >= 0) {
|
2193
|
2227
|
write(fd, newcounters, counterlen);
|
|
@@ -2232,7 +2266,7 @@ TC_STRERROR(int err)
|
2232
|
2266
|
} table [] =
|
2233
|
2267
|
{ { TC_INIT, EPERM, "Permission denied (you must be root)" },
|
2234
|
2268
|
{ TC_INIT, EINVAL, "Module is wrong version" },
|
2235
|
|
- { TC_INIT, ENOENT,
|
|
2269
|
+ { TC_INIT, ENOENT,
|
2236
|
2270
|
"Table does not exist (do you need to insmod?)" },
|
2237
|
2271
|
{ TC_DELETE_CHAIN, ENOTEMPTY, "Chain is not empty" },
|
2238
|
2272
|
{ TC_DELETE_CHAIN, EINVAL, "Can't delete built-in chain" },
|