blob: 26419f5db5bd38ec80d65ad4f36d2c9da4524a8a [file] [log] [blame]
KOVACS Krisztian92b54aa2008-10-15 11:49:37 +02001/*
2 * Shared library add-on to iptables to add TPROXY target support.
3 *
4 * Copyright (C) 2002-2008 BalaBit IT Ltd.
5 */
6#include <getopt.h>
7#include <stdbool.h>
Jan Engelhardt9e152fa2010-12-03 22:08:32 +01008#include <stdint.h>
KOVACS Krisztian92b54aa2008-10-15 11:49:37 +02009#include <stdio.h>
10#include <string.h>
11#include <stdlib.h>
12#include <limits.h>
13
KOVACS Krisztian92b54aa2008-10-15 11:49:37 +020014#include <xtables.h>
15#include <linux/netfilter/x_tables.h>
16#include <linux/netfilter/xt_TPROXY.h>
17
18static const struct option tproxy_tg_opts[] = {
Jan Engelhardt32b8e612010-07-23 21:16:14 +020019 {.name = "on-port", .has_arg = true, .val = '1'},
20 {.name = "on-ip", .has_arg = true, .val = '2'},
21 {.name = "tproxy-mark", .has_arg = true, .val = '3'},
22 XT_GETOPT_TABLEEND,
KOVACS Krisztian92b54aa2008-10-15 11:49:37 +020023};
24
25enum {
26 PARAM_ONPORT = 1 << 0,
27 PARAM_ONIP = 1 << 1,
28 PARAM_MARK = 1 << 2,
29};
30
31static void tproxy_tg_help(void)
32{
33 printf(
34"TPROXY target options:\n"
35" --on-port port Redirect connection to port, or the original port if 0\n"
36" --on-ip ip Optionally redirect to the given IP\n"
37" --tproxy-mark value[/mask] Mark packets with the given value/mask\n\n");
38}
39
Jan Engelhardt9e152fa2010-12-03 22:08:32 +010040static void parse_tproxy_lport(const char *s, uint16_t *portp)
KOVACS Krisztian92b54aa2008-10-15 11:49:37 +020041{
42 unsigned int lport;
43
Jan Engelhardt5f2922c2009-01-27 18:43:01 +010044 if (xtables_strtoui(s, NULL, &lport, 0, UINT16_MAX))
Jan Engelhardt9e152fa2010-12-03 22:08:32 +010045 *portp = htons(lport);
KOVACS Krisztian92b54aa2008-10-15 11:49:37 +020046 else
Jan Engelhardta41545c2009-01-27 21:27:19 +010047 xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--on-port", s);
KOVACS Krisztian92b54aa2008-10-15 11:49:37 +020048}
49
Jan Engelhardt9e152fa2010-12-03 22:08:32 +010050static void parse_tproxy_laddr(const char *s, union nf_inet_addr *addrp,
51 unsigned int nfproto)
KOVACS Krisztian92b54aa2008-10-15 11:49:37 +020052{
Jan Engelhardt9e152fa2010-12-03 22:08:32 +010053 struct in6_addr *laddr6 = NULL;
54 struct in_addr *laddr4 = NULL;
KOVACS Krisztian92b54aa2008-10-15 11:49:37 +020055
Jan Engelhardt9e152fa2010-12-03 22:08:32 +010056 if (nfproto == NFPROTO_IPV6) {
57 laddr6 = xtables_numeric_to_ip6addr(s);
58 if (laddr6 == NULL)
59 goto out;
60 addrp->in6 = *laddr6;
61 } else if (nfproto == NFPROTO_IPV4) {
62 laddr4 = xtables_numeric_to_ipaddr(s);
63 if (laddr4 == NULL)
64 goto out;
65 addrp->in = *laddr4;
66 }
67 return;
68 out:
69 xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--on-ip", s);
KOVACS Krisztian92b54aa2008-10-15 11:49:37 +020070}
71
Jan Engelhardt9e152fa2010-12-03 22:08:32 +010072static void parse_tproxy_mark(char *s, uint32_t *markp, uint32_t *maskp)
KOVACS Krisztian92b54aa2008-10-15 11:49:37 +020073{
Jan Engelhardta8097542009-01-27 17:39:01 +010074 unsigned int value, mask = UINT32_MAX;
KOVACS Krisztian92b54aa2008-10-15 11:49:37 +020075 char *end;
76
Jan Engelhardt5f2922c2009-01-27 18:43:01 +010077 if (!xtables_strtoui(s, &end, &value, 0, UINT32_MAX))
Jan Engelhardta41545c2009-01-27 21:27:19 +010078 xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--tproxy-mark", s);
KOVACS Krisztian92b54aa2008-10-15 11:49:37 +020079 if (*end == '/')
Jan Engelhardt5f2922c2009-01-27 18:43:01 +010080 if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX))
Jan Engelhardta41545c2009-01-27 21:27:19 +010081 xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--tproxy-mark", s);
KOVACS Krisztian92b54aa2008-10-15 11:49:37 +020082 if (*end != '\0')
Jan Engelhardta41545c2009-01-27 21:27:19 +010083 xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--tproxy-mark", s);
KOVACS Krisztian92b54aa2008-10-15 11:49:37 +020084
Jan Engelhardt9e152fa2010-12-03 22:08:32 +010085 *markp = value;
86 *maskp = mask;
KOVACS Krisztian92b54aa2008-10-15 11:49:37 +020087}
88
89static int tproxy_tg_parse(int c, char **argv, int invert, unsigned int *flags,
90 const void *entry, struct xt_entry_target **target)
91{
Jan Engelhardt9e152fa2010-12-03 22:08:32 +010092 struct xt_tproxy_target_info *info = (void *)(*target)->data;
KOVACS Krisztian92b54aa2008-10-15 11:49:37 +020093
94 switch (c) {
95 case '1':
Jan Engelhardta41545c2009-01-27 21:27:19 +010096 xtables_param_act(XTF_ONLY_ONCE, "TPROXY", "--on-port", *flags & PARAM_ONPORT);
97 xtables_param_act(XTF_NO_INVERT, "TPROXY", "--on-port", invert);
Jan Engelhardt9e152fa2010-12-03 22:08:32 +010098 parse_tproxy_lport(optarg, &info->lport);
KOVACS Krisztian92b54aa2008-10-15 11:49:37 +020099 *flags |= PARAM_ONPORT;
100 return 1;
101 case '2':
Jan Engelhardta41545c2009-01-27 21:27:19 +0100102 xtables_param_act(XTF_ONLY_ONCE, "TPROXY", "--on-ip", *flags & PARAM_ONIP);
103 xtables_param_act(XTF_NO_INVERT, "TPROXY", "--on-ip", invert);
Jan Engelhardt9e152fa2010-12-03 22:08:32 +0100104 parse_tproxy_laddr(optarg, (void *)&info->laddr, NFPROTO_IPV4);
KOVACS Krisztian92b54aa2008-10-15 11:49:37 +0200105 *flags |= PARAM_ONIP;
106 return 1;
107 case '3':
Jan Engelhardta41545c2009-01-27 21:27:19 +0100108 xtables_param_act(XTF_ONLY_ONCE, "TPROXY", "--tproxy-mark", *flags & PARAM_MARK);
109 xtables_param_act(XTF_NO_INVERT, "TPROXY", "--tproxy-mark", invert);
Jan Engelhardt9e152fa2010-12-03 22:08:32 +0100110 parse_tproxy_mark(optarg, &info->mark_value, &info->mark_mask);
KOVACS Krisztian92b54aa2008-10-15 11:49:37 +0200111 *flags |= PARAM_MARK;
112 return 1;
113 }
114
115 return 0;
116}
117
Jan Engelhardt9e152fa2010-12-03 22:08:32 +0100118static int
119tproxy_tg_parse1(int c, char **argv, int invert, unsigned int *flags,
120 struct xt_tproxy_target_info_v1 *info, unsigned int nfproto)
121{
122 switch (c) {
123 case '1':
124 xtables_param_act(XTF_ONLY_ONCE, "TPROXY", "--on-port", *flags & PARAM_ONPORT);
125 xtables_param_act(XTF_NO_INVERT, "TPROXY", "--on-port", invert);
126 parse_tproxy_lport(optarg, &info->lport);
127 *flags |= PARAM_ONPORT;
128 return true;
129 case '2':
130 xtables_param_act(XTF_ONLY_ONCE, "TPROXY", "--on-ip", *flags & PARAM_ONIP);
131 xtables_param_act(XTF_NO_INVERT, "TPROXY", "--on-ip", invert);
132 parse_tproxy_laddr(optarg, (void *)&info->laddr, nfproto);
133 *flags |= PARAM_ONIP;
134 return true;
135 case '3':
136 xtables_param_act(XTF_ONLY_ONCE, "TPROXY", "--tproxy-mark", *flags & PARAM_MARK);
137 xtables_param_act(XTF_NO_INVERT, "TPROXY", "--tproxy-mark", invert);
138 parse_tproxy_mark(optarg, &info->mark_value, &info->mark_mask);
139 *flags |= PARAM_MARK;
140 return true;
141 }
142 return false;
143}
144
145static int
146tproxy_tg_parse4(int c, char **argv, int invert, unsigned int *flags,
147 const void *entry, struct xt_entry_target **target)
148{
149 struct xt_tproxy_target_info_v1 *info = (void *)(*target)->data;
150 return tproxy_tg_parse1(c, argv, invert, flags, info, NFPROTO_IPV4);
151}
152
153static int
154tproxy_tg_parse6(int c, char **argv, int invert, unsigned int *flags,
155 const void *entry, struct xt_entry_target **target)
156{
157 struct xt_tproxy_target_info_v1 *info = (void *)(*target)->data;
158 return tproxy_tg_parse1(c, argv, invert, flags, info, NFPROTO_IPV6);
159}
160
KOVACS Krisztian92b54aa2008-10-15 11:49:37 +0200161static void tproxy_tg_check(unsigned int flags)
162{
163 if (!(flags & PARAM_ONPORT))
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100164 xtables_error(PARAMETER_PROBLEM,
KOVACS Krisztian92b54aa2008-10-15 11:49:37 +0200165 "TPROXY target: Parameter --on-port is required");
166}
167
168static void tproxy_tg_print(const void *ip, const struct xt_entry_target *target,
169 int numeric)
170{
171 const struct xt_tproxy_target_info *info = (const void *)target->data;
172 printf("TPROXY redirect %s:%u mark 0x%x/0x%x",
Jan Engelhardte44ea7f2009-01-30 03:55:09 +0100173 xtables_ipaddr_to_numeric((const struct in_addr *)&info->laddr),
KOVACS Krisztian92b54aa2008-10-15 11:49:37 +0200174 ntohs(info->lport), (unsigned int)info->mark_value,
175 (unsigned int)info->mark_mask);
176}
177
Jan Engelhardt9e152fa2010-12-03 22:08:32 +0100178static void
179tproxy_tg_print4(const void *ip, const struct xt_entry_target *target,
180 int numeric)
181{
182 const struct xt_tproxy_target_info_v1 *info =
183 (const void *)target->data;
184
185 printf("TPROXY redirect %s:%u mark 0x%x/0x%x",
186 xtables_ipaddr_to_numeric(&info->laddr.in),
187 ntohs(info->lport), (unsigned int)info->mark_value,
188 (unsigned int)info->mark_mask);
189}
190
191static void
192tproxy_tg_print6(const void *ip, const struct xt_entry_target *target,
193 int numeric)
194{
195 const struct xt_tproxy_target_info_v1 *info =
196 (const void *)target->data;
197
198 printf("TPROXY redirect %s:%u mark 0x%x/0x%x",
199 xtables_ip6addr_to_numeric(&info->laddr.in6),
200 ntohs(info->lport), (unsigned int)info->mark_value,
201 (unsigned int)info->mark_mask);
202}
203
KOVACS Krisztian92b54aa2008-10-15 11:49:37 +0200204static void tproxy_tg_save(const void *ip, const struct xt_entry_target *target)
205{
206 const struct xt_tproxy_target_info *info = (const void *)target->data;
207
208 printf("--on-port %u ", ntohs(info->lport));
209 printf("--on-ip %s ",
Jan Engelhardte44ea7f2009-01-30 03:55:09 +0100210 xtables_ipaddr_to_numeric((const struct in_addr *)&info->laddr));
KOVACS Krisztian92b54aa2008-10-15 11:49:37 +0200211 printf("--tproxy-mark 0x%x/0x%x ",
212 (unsigned int)info->mark_value, (unsigned int)info->mark_mask);
213}
214
Jan Engelhardt9e152fa2010-12-03 22:08:32 +0100215static void
216tproxy_tg_save4(const void *ip, const struct xt_entry_target *target)
217{
218 const struct xt_tproxy_target_info_v1 *info;
219
220 info = (const void *)target->data;
221 printf("--on-port %u ", ntohs(info->lport));
222 printf("--on-ip %s ", xtables_ipaddr_to_numeric(&info->laddr.in));
223 printf("--tproxy-mark 0x%x/0x%x ",
224 (unsigned int)info->mark_value, (unsigned int)info->mark_mask);
225}
226
227static void
228tproxy_tg_save6(const void *ip, const struct xt_entry_target *target)
229{
230 const struct xt_tproxy_target_info_v1 *info;
231
232 info = (const void *)target->data;
233 printf("--on-port %u ", ntohs(info->lport));
234 printf("--on-ip %s ", xtables_ip6addr_to_numeric(&info->laddr.in6));
235 printf("--tproxy-mark 0x%x/0x%x ",
236 (unsigned int)info->mark_value, (unsigned int)info->mark_mask);
237}
238
239static struct xtables_target tproxy_tg_reg[] = {
240 {
241 .name = "TPROXY",
242 .revision = 0,
243 .family = NFPROTO_IPV4,
244 .version = XTABLES_VERSION,
245 .size = XT_ALIGN(sizeof(struct xt_tproxy_target_info)),
246 .userspacesize = XT_ALIGN(sizeof(struct xt_tproxy_target_info)),
247 .help = tproxy_tg_help,
248 .parse = tproxy_tg_parse,
249 .final_check = tproxy_tg_check,
250 .print = tproxy_tg_print,
251 .save = tproxy_tg_save,
252 .extra_opts = tproxy_tg_opts,
253 },
254 {
255 .name = "TPROXY",
256 .revision = 1,
257 .family = NFPROTO_IPV4,
258 .version = XTABLES_VERSION,
259 .size = XT_ALIGN(sizeof(struct xt_tproxy_target_info_v1)),
260 .userspacesize = XT_ALIGN(sizeof(struct xt_tproxy_target_info_v1)),
261 .help = tproxy_tg_help,
262 .parse = tproxy_tg_parse4,
263 .final_check = tproxy_tg_check,
264 .print = tproxy_tg_print4,
265 .save = tproxy_tg_save4,
266 .extra_opts = tproxy_tg_opts,
267 },
268 {
269 .name = "TPROXY",
270 .revision = 1,
271 .family = NFPROTO_IPV6,
272 .version = XTABLES_VERSION,
273 .size = XT_ALIGN(sizeof(struct xt_tproxy_target_info_v1)),
274 .userspacesize = XT_ALIGN(sizeof(struct xt_tproxy_target_info_v1)),
275 .help = tproxy_tg_help,
276 .parse = tproxy_tg_parse6,
277 .final_check = tproxy_tg_check,
278 .print = tproxy_tg_print6,
279 .save = tproxy_tg_save6,
280 .extra_opts = tproxy_tg_opts,
281 },
KOVACS Krisztian92b54aa2008-10-15 11:49:37 +0200282};
283
284void _init(void)
285{
Jan Engelhardt9e152fa2010-12-03 22:08:32 +0100286 xtables_register_targets(tproxy_tg_reg, ARRAY_SIZE(tproxy_tg_reg));
KOVACS Krisztian92b54aa2008-10-15 11:49:37 +0200287}