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