1fb9e932d194af8cd37dcdc758b0880b2bc6fdd0
[ipt_ACCOUNT] / iptables / extensions / libipt_ACCOUNT.c
1 /* Shared library add-on to iptables to add ACCOUNT(ing) support.
2    Author: Intra2net AG <opensource@intra2net.com>
3 */
4
5 #include <stdio.h>
6 #include <netdb.h>
7 #include <string.h>
8 #include <stdlib.h>
9 #include <syslog.h>
10 #include <getopt.h>
11 #include <iptables.h>
12 #include <linux/netfilter_ipv4/ip_tables.h>
13 #include <linux/netfilter_ipv4/ipt_ACCOUNT.h>
14
15 static struct option opts[] = {
16     { .name = "addr",        .has_arg = 1, .flag = 0, .val = 'a' },
17     { .name = "tname",       .has_arg = 1, .flag = 0, .val = 't' },
18     { .name = 0 }
19 };
20
21 /* Function which prints out usage message. */
22 static void help(void)
23 {
24     printf(
25 "ACCOUNT v%s options:\n"
26 " --%s ip/netmask\t\tBase network IP and netmask used for this table\n"
27 " --%s name\t\t\tTable name for the userspace library\n",
28 IPTABLES_VERSION, opts[0].name, opts[1].name);
29 }
30
31 /* Initialize the target. */
32 static void
33 init(struct xt_entry_target *t)
34 {
35     struct ipt_acc_info *accountinfo = (struct ipt_acc_info *)t->data;
36
37     accountinfo->table_nr = -1;
38 }
39
40 #define IPT_ACCOUNT_OPT_ADDR 0x01
41 #define IPT_ACCOUNT_OPT_TABLE 0x02
42
43 /* Function which parses command options; returns true if it
44    ate an option */
45
46 static int parse(int c, char **argv, int invert, unsigned int *flags,
47                      const void *entry, struct xt_entry_target **target)
48 {
49     struct ipt_acc_info *accountinfo = (struct ipt_acc_info *)(*target)->data;
50     struct in_addr *addrs = NULL, mask;
51     unsigned int naddrs = 0;
52
53     switch (c) {
54     case 'a':
55         if (*flags & IPT_ACCOUNT_OPT_ADDR)
56                 exit_error(PARAMETER_PROBLEM, "Can't specify --%s twice",
57                             opts[0].name);
58
59         if (check_inverse(optarg, &invert, NULL, 0))
60                 exit_error(PARAMETER_PROBLEM, "Unexpected `!' after --%s",
61                             opts[0].name);
62
63         //loginfo->level = parse_level(optarg);
64         parse_hostnetworkmask(optarg, &addrs, &mask, &naddrs);
65
66         if (naddrs > 1)
67                 exit_error(PARAMETER_PROBLEM, "multiple IP addresses not allowed");
68
69         accountinfo->net_ip = addrs[0].s_addr;
70         accountinfo->net_mask = mask.s_addr;
71
72         *flags |= IPT_ACCOUNT_OPT_ADDR;
73         break;
74
75     case 't':
76             if (*flags & IPT_ACCOUNT_OPT_TABLE)
77                     exit_error(PARAMETER_PROBLEM,
78                                 "Can't specify --%s twice", opts[1].name);
79
80             if (check_inverse(optarg, &invert, NULL, 0))
81                     exit_error(PARAMETER_PROBLEM,
82                                 "Unexpected `!' after --%s", opts[1].name);
83
84             if (strlen(optarg) > ACCOUNT_TABLE_NAME_LEN - 1)
85                     exit_error(PARAMETER_PROBLEM,
86                                 "Maximum table name length %u for --%s",
87                                 ACCOUNT_TABLE_NAME_LEN - 1, opts[1].name);
88
89             strcpy(accountinfo->table_name, optarg);
90             *flags |= IPT_ACCOUNT_OPT_TABLE;
91             break;
92
93     default:
94             return 0;
95     }
96     return 1;
97 }
98
99 /* Final check; nothing. */
100 static void final_check(unsigned int flags)
101 {
102     if (!(flags&IPT_ACCOUNT_OPT_ADDR) || !(flags&IPT_ACCOUNT_OPT_TABLE))
103         exit_error(PARAMETER_PROBLEM, "ACCOUNT: needs --%s and --%s",
104                     opts[0].name, opts[1].name);
105 }
106
107 static void print_it(const void *ip,
108                      const struct xt_entry_target *target, char do_prefix)
109 {
110     const struct ipt_acc_info *accountinfo
111         = (const struct ipt_acc_info *)target->data;
112     struct in_addr a;
113
114     if (!do_prefix)
115         printf("ACCOUNT ");
116
117     // Network information
118     if (do_prefix)
119         printf("--");
120     printf("%s ", opts[0].name);
121
122     a.s_addr = accountinfo->net_ip;     
123     printf("%s", addr_to_dotted(&a));
124     a.s_addr = accountinfo->net_mask;
125     printf("%s", mask_to_dotted(&a));
126
127     printf(" ");
128     if (do_prefix)
129         printf("--");
130
131     printf("%s %s", opts[1].name, accountinfo->table_name);
132 }
133
134
135 static void
136 print(const void *ip,
137       const struct xt_entry_target *target,
138       int numeric)
139 {
140     print_it (ip, target, 0);
141 }
142
143 /* Saves the union ipt_targinfo in parsable form to stdout. */
144 static void
145 save(const void *ip, const struct xt_entry_target *target)
146 {
147     print_it(ip, target, 1);
148 }
149
150 static
151 struct iptables_target account
152 = {
153     .next          = NULL,
154     .name          = "ACCOUNT",
155     .version       = IPTABLES_VERSION,
156     .size          = IPT_ALIGN(sizeof(struct ipt_acc_info)),
157     .userspacesize = IPT_ALIGN(sizeof(struct ipt_acc_info)),
158     .help          = &help,
159     .init          = &init,
160     .parse         = &parse,
161     .final_check   = &final_check,
162     .print         = &print,
163     .save          = &save,
164     .extra_opts    = opts
165 };
166
167 void _init(void)
168 {
169     register_target(&account);
170 }