1/* Shared library add-on to iptables to add IP pool mangling target. */
2#include <stdio.h>
3#include <netdb.h>
4#include <string.h>
5#include <stdlib.h>
6#include <getopt.h>
7#include <ctype.h>
8
9#include <iptables.h>
10#include <linux/netfilter_ipv4/ip_tables.h>
11#include <linux/netfilter_ipv4/ip_nat_rule.h>
12#include <linux/netfilter_ipv4/ip_pool.h>
13#include <linux/netfilter_ipv4/ipt_pool.h>
14
15#include <libippool/ip_pool_support.h>
16
17#define ip_pool_init           ip_POOL_init
18#define ip_pool_get_index      ip_POOL_get_index
19#define ip_pool_get_name       ip_POOL_get_name
20#include "../ippool/libippool.c"
21
22/* Function which prints out usage message. */
23static void
24help(void)
25{
26	printf(
27"POOL v%s options:\n"
28" --add-srcip <pool>\n"
29" --del-srcip <pool>\n"
30" --add-dstip <pool>\n"
31" --del-dstip <pool>\n"
32"				add/del src/dst IP from pool.\n\n",
33IPTABLES_VERSION);
34}
35
36static struct option opts[] = {
37	{ "add-srcip", 1, 0, '1' },
38	{ "del-srcip", 1, 0, '2' },
39	{ "add-dstip", 1, 0, '3' },
40	{ "del-dstip", 1, 0, '4' },
41	{ 0 }
42};
43
44/* Initialize the target. */
45static void
46init(struct ipt_entry_target *target, unsigned int *nfcache)
47{
48	struct ipt_pool_info *ipi = (struct ipt_pool_info *) target->data;
49
50	ipi->src = ipi->dst = IP_POOL_NONE;
51	ipi->flags = 0;
52
53	/* Can't cache this */
54	*nfcache |= NFC_UNKNOWN;
55}
56
57/* Function which parses command options; returns true if it
58   ate an option */
59static int
60parse(int c, char **argv, int invert, unsigned int *flags,
61      const struct ipt_entry *entry,
62      struct ipt_entry_target **target)
63{
64	struct ipt_pool_info *ipi = (struct ipt_pool_info *) (*target)->data;
65	switch (c) {
66	case '1':	/* --add-srcip <pool> */
67		ipi->src = ip_pool_get_index(optarg);
68		ipi->flags &= ~IPT_POOL_DEL_SRC;
69		break;
70	case '2':	/* --del-srcip <pool> */
71		ipi->src = ip_pool_get_index(optarg);
72		ipi->flags |= IPT_POOL_DEL_SRC;
73		break;
74	case '3':	/* --add-dstip <pool> */
75		ipi->dst = ip_pool_get_index(optarg);
76		ipi->flags &= ~IPT_POOL_DEL_DST;
77		break;
78	case '4':	/* --del-dstip <pool> */
79		ipi->dst = ip_pool_get_index(optarg);
80		ipi->flags |= IPT_POOL_DEL_DST;
81		break;
82	default:
83		return 0;
84	}
85	return 1;
86}
87
88/* Final check; don't care. */
89static void final_check(unsigned int flags)
90{
91}
92
93/* Prints out the targinfo. */
94static void
95print(const struct ipt_ip *ip,
96      const struct ipt_entry_target *target,
97      int numeric)
98{
99	char buf[256];
100	struct ipt_pool_info *ipi = (struct ipt_pool_info *) target->data;
101
102	printf("POOL");
103	if (ipi->src != IP_POOL_NONE) {
104		printf(" --%s-srcip %s",
105			(ipi->flags & IPT_POOL_DEL_SRC) ? "del" : "add",
106			ip_pool_get_name(buf, sizeof(buf), ipi->src, numeric));
107	}
108	if (ipi->dst != IP_POOL_NONE) {
109		printf(" --%s-dstip %s",
110			(ipi->flags & IPT_POOL_DEL_DST) ? "del" : "add",
111			ip_pool_get_name(buf, sizeof(buf), ipi->dst, numeric));
112	}
113}
114
115/* Saves the union ipt_targinfo in parsable form to stdout. */
116static void
117save(const struct ipt_ip *ip, const struct ipt_entry_target *target)
118{
119	char buf[256];
120	struct ipt_pool_info *ipi = (struct ipt_pool_info *) target->data;
121
122	printf("-j POOL");
123	if (ipi->src != IP_POOL_NONE) {
124		printf(" --%s-srcip %s",
125			(ipi->flags & IPT_POOL_DEL_SRC) ? "del" : "add",
126			ip_pool_get_name(buf, sizeof(buf), ipi->src, 0));
127	}
128	if (ipi->dst != IP_POOL_NONE) {
129		printf(" --%s-dstip %s",
130			(ipi->flags & IPT_POOL_DEL_DST) ? "del" : "add",
131			ip_pool_get_name(buf, sizeof(buf), ipi->dst, 0));
132	}
133}
134
135static
136struct iptables_target ipt_pool_target
137= { NULL,
138    "POOL",
139    IPTABLES_VERSION,
140    IPT_ALIGN(sizeof(struct ipt_pool_info)),
141    IPT_ALIGN(sizeof(struct ipt_pool_info)),
142    &help,
143    &init,
144    &parse,
145    &final_check,
146    &print,
147    &save,
148    opts
149};
150
151void _init(void)
152{
153	register_target(&ipt_pool_target);
154}
155