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