21
22
#include <stdlib.h>
23
24
#include <string.h>
24
25
#include <unistd.h>
25
26
#include <sys/errno.h>
26
#include <libiptc/libiptc.h>
27
#include <libiptc/libip6tc.h>
27
#include <sys/socket.h>
28
28
#include <xtables.h>
30
#include <linux/netfilter/x_tables.h>
31
#include <linux/netfilter/xt_quota.h>
33
static void print_match(const struct ipt_entry *e)
30
#include <linux/netfilter_ipv4/ip_tables.h>
34
static const char *hooknames[] = {
35
[NF_IP_PRE_ROUTING] = "PREROUTING",
36
[NF_IP_LOCAL_IN] = "INPUT",
37
[NF_IP_FORWARD] = "FORWARD",
38
[NF_IP_LOCAL_OUT] = "OUTPUT",
39
[NF_IP_POST_ROUTING] = "POSTROUTING",
42
#define LABEL_ACCEPT "ACCEPT"
43
#define LABEL_DROP "DROP"
44
#define LABEL_QUEUE "QUEUE"
45
#define LABEL_RETURN "RETURN"
47
/* fn returns 0 to continue iteration */
48
#define _XT_ENTRY_ITERATE_CONTINUE(type, entries, size, n, fn, args...) \
55
for (__i = 0, __n = 0; __i < (size); \
56
__i += __entry->next_offset, __n++) { \
57
__entry = (void *)(entries) + __i; \
61
__ret = fn(__entry, ## args); \
68
/* fn returns 0 to continue iteration */
69
#define _XT_ENTRY_ITERATE(type, entries, size, fn, args...) \
70
_XT_ENTRY_ITERATE_CONTINUE(type, entries, size, 0, fn, args)
72
#define ENTRY_ITERATE(entries, size, fn, args...) \
73
_XT_ENTRY_ITERATE(struct ipt_entry, entries, size, fn, ## args)
75
#define MIN_ALIGN (__alignof__(struct ipt_entry))
77
#define ALIGN(s) (((s) + ((MIN_ALIGN)-1)) & ~((MIN_ALIGN)-1))
80
struct xt_entry_target t;
81
char error[IPT_TABLE_MAXNAMELEN];
84
struct connman_iptables_entry {
88
struct ipt_entry *entry;
91
struct connman_iptables {
94
struct ipt_getinfo *info;
95
struct ipt_get_entries *blob_entries;
97
unsigned int num_entries;
98
unsigned int old_entries;
101
unsigned int underflow[NF_INET_NUMHOOKS];
102
unsigned int hook_entry[NF_INET_NUMHOOKS];
108
static struct ipt_entry *get_entry(struct connman_iptables *table,
111
return (struct ipt_entry *)((char *)table->blob_entries->entrytable +
115
static int is_hook_entry(struct connman_iptables *table,
116
struct ipt_entry *entry)
120
for (i = 0; i < NF_INET_NUMHOOKS; i++) {
121
if ((table->info->valid_hooks & (1 << i))
122
&& get_entry(table, table->info->hook_entry[i]) == entry)
129
static unsigned long entry_to_offset(struct connman_iptables *table,
130
struct ipt_entry *entry)
132
return (void *)entry - (void *)table->blob_entries->entrytable;
135
static int target_to_verdict(char *target_name)
137
if (!strcmp(target_name, LABEL_ACCEPT))
138
return -NF_ACCEPT - 1;
140
if (!strcmp(target_name, LABEL_DROP))
143
if (!strcmp(target_name, LABEL_QUEUE))
144
return -NF_QUEUE - 1;
146
if (!strcmp(target_name, LABEL_RETURN))
152
static gboolean is_builtin_target(char *target_name)
154
if (!strcmp(target_name, LABEL_ACCEPT) ||
155
!strcmp(target_name, LABEL_DROP) ||
156
!strcmp(target_name, LABEL_QUEUE) ||
157
!strcmp(target_name, LABEL_RETURN))
163
static gboolean is_jump(struct connman_iptables_entry *e)
165
struct xt_entry_target *target;
167
target = ipt_get_target(e->entry);
169
if (!strcmp(target->u.user.name, IPT_STANDARD_TARGET)) {
170
struct xt_standard_target *t;
172
t = (struct xt_standard_target *)target;
174
switch (t->verdict) {
190
static gboolean is_chain(struct connman_iptables *table,
191
struct connman_iptables_entry *e)
193
struct ipt_entry *entry;
194
struct xt_entry_target *target;
200
target = ipt_get_target(entry);
201
if (!strcmp(target->u.user.name, IPT_ERROR_TARGET))
207
static GList *find_chain_head(struct connman_iptables *table,
211
struct connman_iptables_entry *head;
212
struct ipt_entry *entry;
213
struct xt_entry_target *target;
216
for (list = table->entries; list; list = list->next) {
221
builtin = head->builtin;
222
if (builtin >= 0 && !strcmp(hooknames[builtin], chain_name))
225
/* User defined chain */
226
target = ipt_get_target(entry);
227
if (!strcmp(target->u.user.name, IPT_ERROR_TARGET) &&
228
!strcmp((char *)target->data, chain_name))
235
static GList *find_chain_tail(struct connman_iptables *table,
238
GList *chain_head, *list;
239
struct connman_iptables_entry *head, *tail;
240
struct ipt_entry *entry;
241
struct xt_entry_target *target;
244
/* First we look for the head */
245
for (list = table->entries; list; list = list->next) {
250
builtin = head->builtin;
251
if (builtin >= 0 && !strcmp(hooknames[builtin], chain_name))
254
/* User defined chain */
255
target = ipt_get_target(entry);
256
if (!strcmp(target->u.user.name, IPT_ERROR_TARGET) &&
257
!strcmp((char *)target->data, chain_name))
266
/* Then we look for the next chain */
267
for (list = chain_head->next; list; list = list->next) {
271
if (is_chain(table, tail))
275
/* Nothing found, we return the table end */
276
return g_list_last(table->entries);
279
static void update_offsets(struct connman_iptables *table)
282
struct connman_iptables_entry *entry, *prev_entry;
284
for (list = table->entries; list; list = list->next) {
287
if (list == table->entries) {
294
prev_entry = prev->data;
296
entry->offset = prev_entry->offset +
297
prev_entry->entry->next_offset;
301
static int connman_add_entry(struct connman_iptables *table,
302
struct ipt_entry *entry, GList *before,
306
struct connman_iptables_entry *e, *tmp, *entry_before;
307
struct xt_standard_target *t;
312
e = g_try_malloc0(sizeof(struct connman_iptables_entry));
317
e->builtin = builtin;
319
table->entries = g_list_insert_before(table->entries, before, e);
320
table->num_entries++;
321
table->size += entry->next_offset;
323
if (before == NULL) {
324
e->offset = table->size - entry->next_offset;
329
entry_before = before->data;
332
* We've just insterted a new entry. All references before it
333
* should be bumped accordingly.
335
for (list = table->entries; list != before; list = list->next) {
341
t = (struct xt_standard_target *)ipt_get_target(tmp->entry);
343
if (t->verdict >= entry_before->offset)
344
t->verdict += entry->next_offset;
347
update_offsets(table);
352
static int connman_iptables_flush_chain(struct connman_iptables *table,
355
GList *chain_head, *chain_tail, *list, *next;
356
struct connman_iptables_entry *entry;
357
int builtin, removed = 0;
359
chain_head = find_chain_head(table, name);
360
if (chain_head == NULL)
363
chain_tail = find_chain_tail(table, name);
364
if (chain_tail == NULL)
367
entry = chain_head->data;
368
builtin = entry->builtin;
373
list = chain_head->next;
375
if (list == chain_tail->prev)
378
while (list != chain_tail->prev) {
380
next = g_list_next(list);
382
table->num_entries--;
383
table->size -= entry->entry->next_offset;
384
removed += entry->entry->next_offset;
386
table->entries = g_list_remove(table->entries, list->data);
392
struct connman_iptables_entry *e;
396
entry->builtin = builtin;
398
table->underflow[builtin] -= removed;
400
for (list = chain_tail; list; list = list->next) {
403
builtin = e->builtin;
407
table->hook_entry[builtin] -= removed;
408
table->underflow[builtin] -= removed;
412
update_offsets(table);
417
static int connman_iptables_delete_chain(struct connman_iptables *table,
420
GList *chain_head, *chain_tail, *list, *next;
421
struct connman_iptables_entry *entry;
423
chain_head = find_chain_head(table, name);
424
if (chain_head == NULL)
427
chain_tail = find_chain_tail(table, name);
428
if (chain_tail == NULL)
433
while (list != chain_tail) {
435
next = g_list_next(list);
437
table->num_entries--;
438
table->size -= entry->entry->next_offset;
440
table->entries = g_list_remove(table->entries, list->data);
445
update_offsets(table);
450
static int connman_iptables_add_chain(struct connman_iptables *table,
454
struct ipt_entry *entry_head;
455
struct ipt_entry *entry_return;
456
struct error_target *error;
457
struct ipt_standard_target *standard;
458
u_int16_t entry_head_size, entry_return_size;
460
last = g_list_last(table->entries);
463
* An empty chain is composed of:
464
* - A head entry, with no match and an error target.
465
* The error target data is the chain name.
466
* - A tail entry, with no match and a standard target.
467
* The standard target verdict is XT_RETURN (return to the
472
entry_head_size = sizeof(struct ipt_entry) +
473
sizeof(struct error_target);
474
entry_head = g_try_malloc0(entry_head_size);
475
if (entry_head == NULL)
478
memset(entry_head, 0, entry_head_size);
480
entry_head->target_offset = sizeof(struct ipt_entry);
481
entry_head->next_offset = entry_head_size;
483
error = (struct error_target *) entry_head->elems;
484
strcpy(error->t.u.user.name, IPT_ERROR_TARGET);
485
error->t.u.user.target_size = ALIGN(sizeof(struct error_target));
486
strcpy(error->error, name);
488
if (connman_add_entry(table, entry_head, last, -1) < 0)
492
entry_return_size = sizeof(struct ipt_entry) +
493
sizeof(struct ipt_standard_target);
494
entry_return = g_try_malloc0(entry_return_size);
495
if (entry_return == NULL)
498
memset(entry_return, 0, entry_return_size);
500
entry_return->target_offset = sizeof(struct ipt_entry);
501
entry_return->next_offset = entry_return_size;
503
standard = (struct ipt_standard_target *) entry_return->elems;
504
standard->target.u.user.target_size =
505
ALIGN(sizeof(struct ipt_standard_target));
506
standard->verdict = XT_RETURN;
508
if (connman_add_entry(table, entry_return, last, -1) < 0)
515
g_free(entry_return);
520
static struct ipt_entry *
521
new_rule(struct connman_iptables *table,
522
char *target_name, struct xtables_target *xt_t,
523
char *match_name, struct xtables_match *xt_m)
525
struct ipt_entry *new_entry;
526
size_t match_size, target_size;
527
int is_builtin = is_builtin_target(target_name);
530
match_size = xt_m->m->u.match_size;
535
target_size = ALIGN(xt_t->t->u.target_size);
537
target_size = ALIGN(sizeof(struct xt_standard_target));
539
new_entry = g_try_malloc0(sizeof(struct ipt_entry) + target_size +
541
if (new_entry == NULL)
544
new_entry->target_offset = sizeof(struct ipt_entry) + match_size;
545
new_entry->next_offset = sizeof(struct ipt_entry) + target_size +
548
struct xt_entry_match *entry_match;
550
entry_match = (struct xt_entry_match *)new_entry->elems;
551
memcpy(entry_match, xt_m->m, match_size);
555
struct xt_entry_target *entry_target;
558
struct xt_standard_target *target;
560
target = (struct xt_standard_target *)(xt_t->t);
561
strcpy(target->target.u.user.name, IPT_STANDARD_TARGET);
562
target->verdict = target_to_verdict(target_name);
565
entry_target = ipt_get_target(new_entry);
566
memcpy(entry_target, xt_t->t, target_size);
568
struct connman_iptables_entry *target_rule;
569
struct xt_standard_target *target;
573
* This is a user defined target, i.e. a chain jump.
574
* We search for the chain head, and the target verdict
575
* is the first rule's offset on this chain.
576
* The offset is from the beginning of the table.
579
chain_head = find_chain_head(table, target_name);
580
if (chain_head == NULL || chain_head->next == NULL) {
585
target_rule = chain_head->next->data;
587
target = (struct xt_standard_target *)ipt_get_target(new_entry);
588
strcpy(target->target.u.user.name, IPT_STANDARD_TARGET);
589
target->target.u.user.target_size = target_size;
590
target->verdict = target_rule->offset;
596
static void update_hooks(struct connman_iptables *table, GList *chain_head, struct ipt_entry *entry)
599
struct connman_iptables_entry *head, *e;
602
if (chain_head == NULL)
605
head = chain_head->data;
607
builtin = head->builtin;
611
table->underflow[builtin] += entry->next_offset;
613
for (list = chain_head->next; list; list = list->next) {
616
builtin = e->builtin;
620
table->hook_entry[builtin] += entry->next_offset;
621
table->underflow[builtin] += entry->next_offset;
626
connman_iptables_add_rule(struct connman_iptables *table, char *chain_name,
627
char *target_name, struct xtables_target *xt_t,
628
char *match_name, struct xtables_match *xt_m)
630
GList *chain_tail, *chain_head;
631
struct ipt_entry *new_entry;
632
struct connman_iptables_entry *head;
635
chain_head = find_chain_head(table, chain_name);
636
if (chain_head == NULL)
639
chain_tail = find_chain_tail(table, chain_name);
640
if (chain_tail == NULL)
643
new_entry = new_rule(table,
646
if (new_entry == NULL)
649
update_hooks(table, chain_head, new_entry);
652
* If the chain is builtin, and does not have any rule,
653
* then the one that we're inserting is becoming the head
654
* and thus needs the builtin flag.
656
head = chain_head->data;
657
if (head->builtin < 0)
659
else if (chain_head == chain_tail->prev) {
660
builtin = head->builtin;
664
return connman_add_entry(table, new_entry, chain_tail->prev, builtin);
667
static struct ipt_replace *
668
connman_iptables_blob(struct connman_iptables *table)
670
struct ipt_replace *r;
672
struct connman_iptables_entry *e;
673
unsigned char *entry_index;
675
r = g_try_malloc0(sizeof(struct ipt_replace) + table->size);
679
memset(r, 0, sizeof(*r) + table->size);
681
r->counters = g_try_malloc0(sizeof(struct xt_counters)
682
* table->old_entries);
683
if (r->counters == NULL) {
688
strcpy(r->name, table->info->name);
689
r->num_entries = table->num_entries;
690
r->size = table->size;
692
r->num_counters = table->old_entries;
693
r->valid_hooks = table->info->valid_hooks;
695
memcpy(r->hook_entry, table->hook_entry, sizeof(table->hook_entry));
696
memcpy(r->underflow, table->underflow, sizeof(table->underflow));
698
entry_index = (unsigned char *)r->entries;
699
for (list = table->entries; list; list = list->next) {
702
memcpy(entry_index, e->entry, e->entry->next_offset);
703
entry_index += e->entry->next_offset;
709
static void dump_target(struct connman_iptables *table,
710
struct ipt_entry *entry)
713
struct xtables_target *xt_t;
714
struct xt_entry_target *target;
716
target = ipt_get_target(entry);
718
if (!strcmp(target->u.user.name, IPT_STANDARD_TARGET)) {
719
struct xt_standard_target *t;
721
t = (struct xt_standard_target *)target;
723
switch (t->verdict) {
725
printf("\ttarget RETURN\n");
729
printf("\ttarget ACCEPT\n");
733
printf("\ttarget DROP\n");
737
printf("\ttarget QUEUE\n");
741
printf("\ttarget STOP\n");
745
printf("\tJUMP @%p (0x%x)\n",
746
(char*)table->blob_entries->entrytable +
747
t->verdict, t->verdict);
751
xt_t = xtables_find_target(IPT_STANDARD_TARGET,
752
XTF_LOAD_MUST_SUCCEED);
754
if(xt_t->print != NULL)
755
xt_t->print(NULL, target, 1);
757
xt_t = xtables_find_target(target->u.user.name, XTF_TRY_LOAD);
759
printf("\ttarget %s\n", target->u.user.name);
763
if(xt_t->print != NULL) {
765
xt_t->print(NULL, target, 1);
771
static void dump_match(struct connman_iptables *table, struct ipt_entry *entry)
773
struct xtables_match *xt_m;
35
774
struct xt_entry_match *match;
36
struct xtables_match *xt_match;
38
match = (struct xt_entry_match *)e->elems;
42
xt_match = xtables_find_match(match->u.user.name, XTF_TRY_LOAD, NULL);
46
printf("\tMATCH:%s\n", xt_match->m->u.user.name);
776
if (entry->elems == (unsigned char *)entry + entry->target_offset)
779
match = (struct xt_entry_match *) entry->elems;
781
if (!strlen(match->u.user.name))
784
xt_m = xtables_find_match(match->u.user.name, XTF_TRY_LOAD, NULL);
788
if(xt_m->print != NULL) {
790
xt_m->print(NULL, match, 1);
797
printf("\tmatch %s\n", match->u.user.name);
49
static void print_target(const struct ipt_entry *e)
801
static int connman_iptables_dump_entry(struct ipt_entry *entry,
802
struct connman_iptables *table)
51
804
struct xt_entry_target *target;
52
struct xtables_target *xt_target;
54
target = (void *)e + e->target_offset;
58
xt_target = xtables_find_target(target->u.user.name, XTF_TRY_LOAD);
59
if (xt_target == NULL)
62
printf("\tTARGET: %s\n", xt_target->t->u.user.name);
66
static void print_rule(const struct ipt_entry *e, const char *chain)
68
/* print chain name */
69
printf("CHAIN %s:\n", chain);
75
static void print_tables(struct iptc_handle *h)
78
const struct ipt_entry *rule;
80
chain = iptc_first_chain(h);
83
rule = iptc_first_rule(chain, h);
85
print_rule(rule, chain);
87
rule = iptc_next_rule(rule, h);
90
chain = iptc_next_chain(h);
94
static struct ipt_entry *build_quota_drop_entry(void)
97
size_t match_size, target_size;
98
struct xtables_target *t;
99
struct xtables_match *m;
100
struct xtables_rule_match *matches = NULL;
102
m = xtables_find_match("quota", XTF_LOAD_MUST_SUCCEED, &matches);
106
match_size = IPT_ALIGN(sizeof(struct ipt_entry_match)) + m->size;
108
m->m = xtables_calloc(1, match_size);
111
m->m->u.match_size = match_size;
112
strcpy(m->m->u.user.name, m->name);
113
xtables_set_revision(m->m->u.user.name, m->revision);
117
t = xtables_find_target("DROP", XTF_TRY_LOAD);
123
target_size = IPT_ALIGN(sizeof(struct ipt_entry_target)) + t->size;
125
t->t = xtables_calloc(1, target_size);
126
t->t->u.target_size = target_size;
127
strcpy(t->t->u.user.name, "DROP");
128
xtables_set_revision(t->t->u.user.name, t->revision);
132
e = calloc(1, sizeof(struct ipt_entry) + match_size + target_size);
138
e->target_offset = sizeof(struct ipt_entry) + match_size;
139
e->next_offset = sizeof(struct ipt_entry) + match_size + target_size;
141
memcpy(e->elems, m->m, match_size);
142
memcpy(e->elems + match_size, t->t, target_size);
147
static int add_rule(const ipt_chainlabel chain, struct ipt_entry *e,
148
struct iptc_handle *h)
150
if (!iptc_create_chain(chain, h)) {
151
printf("Chain creation error (%s)\n", iptc_strerror(errno));
155
if (!iptc_insert_entry(chain, e, 0, h)) {
156
printf("Entry insertion error (%s)\n", iptc_strerror(errno));
160
if (!iptc_commit(h)) {
161
printf("Commit error (%s)\n", iptc_strerror(errno));
808
offset = (char *)entry - (char *)table->blob_entries->entrytable;
809
target = ipt_get_target(entry);
810
builtin = is_hook_entry(table, entry);
812
if (entry_to_offset(table, entry) + entry->next_offset ==
813
table->blob_entries->size) {
814
printf("End of CHAIN 0x%x\n", offset);
818
if (!strcmp(target->u.user.name, IPT_ERROR_TARGET)) {
819
printf("USER CHAIN (%s) %p match %p target %p size %d\n",
820
target->data, entry, entry->elems,
821
(char *)entry + entry->target_offset,
825
} else if (builtin >= 0) {
826
printf("CHAIN (%s) %p match %p target %p size %d\n",
827
hooknames[builtin], entry, entry->elems,
828
(char *)entry + entry->target_offset,
831
printf("RULE %p match %p target %p size %d\n", entry,
833
(char *)entry + entry->target_offset,
837
dump_match(table, entry);
838
dump_target(table, entry);
168
static void remove_rule(const ipt_chainlabel chain, struct iptc_handle *h)
170
iptc_flush_entries(chain, h);
171
iptc_delete_chain(chain, h);
843
static void connman_iptables_dump_hook(struct connman_iptables *table)
847
for (i = 0; i < NF_INET_NUMHOOKS; i++) {
848
if ((table->info->valid_hooks & (1 << i)))
849
printf("%s entry %p underflow %p (%#x)\n",
851
table->blob_entries->entrytable +
852
table->info->hook_entry[i],
853
table->blob_entries->entrytable +
854
table->info->underflow[i],
855
table->info->underflow[i]);
859
static void connman_iptables_dump(struct connman_iptables *table)
861
printf("%s valid_hooks=0x%08x, num_entries=%u, size=%u\n",
863
table->info->valid_hooks, table->info->num_entries,
866
connman_iptables_dump_hook(table);
868
ENTRY_ITERATE(table->blob_entries->entrytable,
869
table->blob_entries->size,
870
connman_iptables_dump_entry, table);
874
static int connman_iptables_get_entries(struct connman_iptables *table)
876
socklen_t entry_size;
878
entry_size = sizeof(struct ipt_get_entries) + table->info->size;
880
return getsockopt(table->ipt_sock, IPPROTO_IP, IPT_SO_GET_ENTRIES,
881
table->blob_entries, &entry_size);
884
static int connman_iptables_replace(struct connman_iptables *table,
885
struct ipt_replace *r)
887
return setsockopt(table->ipt_sock, IPPROTO_IP, IPT_SO_SET_REPLACE, r,
888
sizeof(*r) + r->size);
891
static void connman_iptables_cleanup(struct connman_iptables *table)
894
struct connman_iptables_entry *entry;
896
close(table->ipt_sock);
898
for (list = table->entries; list; list = list->next) {
901
g_free(entry->entry);
905
g_free(table->blob_entries);
908
xtables_free_opts(1);
911
static int connman_iptables_commit(struct connman_iptables *table)
913
struct ipt_replace *repl;
915
repl = connman_iptables_blob(table);
917
return connman_iptables_replace(table, repl);
920
static int add_entry(struct ipt_entry *entry, struct connman_iptables *table)
922
struct ipt_entry *new_entry;
925
new_entry = g_try_malloc0(entry->next_offset);
926
if (new_entry == NULL)
929
memcpy(new_entry, entry, entry->next_offset);
931
builtin = is_hook_entry(table, entry);
933
return connman_add_entry(table, new_entry, NULL, builtin);
936
static struct connman_iptables *connman_iptables_init(const char *table_name)
938
struct connman_iptables *table;
941
table = g_try_new0(struct connman_iptables, 1);
945
table->info = g_try_new0(struct ipt_getinfo, 1);
946
if (table->info == NULL)
949
table->ipt_sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
950
if (table->ipt_sock < 0)
953
s = sizeof(*table->info);
954
strcpy(table->info->name, table_name);
955
if (getsockopt(table->ipt_sock, IPPROTO_IP, IPT_SO_GET_INFO,
956
table->info, &s) < 0)
959
table->blob_entries = g_try_malloc0(sizeof(struct ipt_get_entries) +
961
if (table->blob_entries == NULL)
964
strcpy(table->blob_entries->name, table_name);
965
table->blob_entries->size = table->info->size;
967
if (connman_iptables_get_entries(table) < 0)
970
table->num_entries = 0;
971
table->old_entries = table->info->num_entries;
974
memcpy(table->underflow, table->info->underflow,
975
sizeof(table->info->underflow));
976
memcpy(table->hook_entry, table->info->hook_entry,
977
sizeof(table->info->hook_entry));
979
ENTRY_ITERATE(table->blob_entries->entrytable,
980
table->blob_entries->size,
988
connman_iptables_cleanup(table);
994
static struct option connman_iptables_opts[] = {
995
{.name = "append", .has_arg = 1, .val = 'A'},
996
{.name = "flush-chain", .has_arg = 1, .val = 'F'},
997
{.name = "list", .has_arg = 2, .val = 'L'},
998
{.name = "new-chain", .has_arg = 1, .val = 'N'},
999
{.name = "delete-chain", .has_arg = 1, .val = 'X'},
1000
{.name = "in-interface", .has_arg = 1, .val = 'i'},
1001
{.name = "jump", .has_arg = 1, .val = 'j'},
1002
{.name = "match", .has_arg = 1, .val = 'm'},
1003
{.name = "out-interface", .has_arg = 1, .val = 'o'},
1004
{.name = "table", .has_arg = 1, .val = 't'},
1008
struct xtables_globals connman_iptables_globals = {
1010
.opts = connman_iptables_opts,
1011
.orig_opts = connman_iptables_opts,
176
1014
int main(int argc, char *argv[])
178
struct iptc_handle *h;
182
printf("Usage: iptables-test [chain-name]\n");
186
h = iptc_init("filter");
188
printf("libiptc initialization error (%s)\n",
189
iptc_strerror(errno));
194
xtables_set_nfproto(NFPROTO_IPV4);
196
e = build_quota_drop_entry();
200
add_rule(argv[1], e, h);
204
remove_rule(argv[1], h);
1016
struct connman_iptables *table;
1017
struct xtables_match *xt_m;
1018
struct xtables_target *xt_t;
1019
char *table_name, *chain, *new_chain, *match_name, *target_name;
1020
char *delete_chain, *flush_chain;
1023
gboolean dump, invert, delete;
1025
xtables_init_all(&connman_iptables_globals, NFPROTO_IPV4);
1030
table_name = chain = new_chain = match_name = target_name = NULL;
1031
delete_chain = flush_chain = NULL;
1036
while ((c = getopt_long(argc, argv,
1037
"-A:F:L::N:X:j:i:m:o:t:", connman_iptables_globals.opts, NULL)) != -1) {
1044
flush_chain = optarg;
1057
delete_chain = optarg;
1061
target_name = optarg;
1062
xt_t = xtables_find_target(target_name, XTF_TRY_LOAD);
1067
size = ALIGN(sizeof(struct ipt_entry_target)) + xt_t->size;
1069
xt_t->t = g_try_malloc0(size);
1070
if (xt_t->t == NULL)
1072
xt_t->t->u.target_size = size;
1073
strcpy(xt_t->t->u.user.name, target_name);
1074
xt_t->t->u.user.revision = xt_t->revision;
1075
if (xt_t->init != NULL)
1076
xt_t->init(xt_t->t);
1077
connman_iptables_globals.opts =
1078
xtables_merge_options(connman_iptables_globals.opts,
1080
&xt_t->option_offset);
1081
if (connman_iptables_globals.opts == NULL)
1090
match_name = optarg;
1092
xt_m = xtables_find_match(optarg, XTF_LOAD_MUST_SUCCEED, NULL);
1093
size = ALIGN(sizeof(struct ipt_entry_match)) + xt_m->size;
1094
xt_m->m = g_try_malloc0(size);
1097
xt_m->m->u.match_size = size;
1098
strcpy(xt_m->m->u.user.name, xt_m->name);
1099
xt_m->m->u.user.revision = xt_m->revision;
1100
if (xt_m->init != NULL)
1101
xt_m->init(xt_m->m);
1102
if (xt_m != xt_m->next) {
1103
connman_iptables_globals.opts =
1104
xtables_merge_options(connman_iptables_globals.opts,
1106
&xt_m->option_offset);
1107
if (connman_iptables_globals.opts == NULL)
1117
table_name = optarg;
1121
if (optarg[0] == '!' && optarg[1] == '\0') {
1123
printf("Consecutive ! not allowed\n");
1130
printf("Invalid option\n");
1135
if (xt_t == NULL || xt_t->parse == NULL ||
1136
!xt_t->parse(c - xt_t->option_offset, argv, invert,
1137
&xt_t->tflags, NULL, &xt_t->t)) {
1138
if (xt_m == NULL || xt_m->parse == NULL)
1141
xt_m->parse(c - xt_m->option_offset, argv,
1142
invert, &xt_m->mflags, NULL, &xt_m->m);
1149
if (table_name == NULL)
1150
table_name = "filter";
1152
table = connman_iptables_init(table_name);
1157
if (delete_chain == NULL)
1160
printf("Delete chain %s\n", delete_chain);
1162
connman_iptables_delete_chain(table, delete_chain);
1168
printf("Flush chain %s\n", flush_chain);
1170
connman_iptables_flush_chain(table, flush_chain);
1176
connman_iptables_dump(table);
1181
if (chain && new_chain)
1185
printf("New chain %s\n", new_chain);
1187
connman_iptables_add_chain(table, new_chain);
1193
if (target_name == NULL)
1196
printf("Adding %s to %s (match %s)\n", target_name, chain, match_name);
1198
connman_iptables_add_rule(table, chain, target_name, xt_t,
1206
connman_iptables_commit(table);
1209
connman_iptables_cleanup(table);