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