1*a71a9546SAutomerger Merge Worker /*
2*a71a9546SAutomerger Merge Worker * shared library add-on to iptables to add TPROXY target support.
3*a71a9546SAutomerger Merge Worker *
4*a71a9546SAutomerger Merge Worker * Copyright (C) 2002-2008 BalaBit IT Ltd.
5*a71a9546SAutomerger Merge Worker */
6*a71a9546SAutomerger Merge Worker #include <stdio.h>
7*a71a9546SAutomerger Merge Worker #include <limits.h>
8*a71a9546SAutomerger Merge Worker #include <xtables.h>
9*a71a9546SAutomerger Merge Worker #include <linux/netfilter/xt_TPROXY.h>
10*a71a9546SAutomerger Merge Worker #include <arpa/inet.h>
11*a71a9546SAutomerger Merge Worker
12*a71a9546SAutomerger Merge Worker enum {
13*a71a9546SAutomerger Merge Worker P_PORT = 0,
14*a71a9546SAutomerger Merge Worker P_ADDR,
15*a71a9546SAutomerger Merge Worker P_MARK,
16*a71a9546SAutomerger Merge Worker F_PORT = 1 << P_PORT,
17*a71a9546SAutomerger Merge Worker F_ADDR = 1 << P_ADDR,
18*a71a9546SAutomerger Merge Worker F_MARK = 1 << P_MARK,
19*a71a9546SAutomerger Merge Worker };
20*a71a9546SAutomerger Merge Worker
21*a71a9546SAutomerger Merge Worker #define s struct xt_tproxy_target_info
22*a71a9546SAutomerger Merge Worker static const struct xt_option_entry tproxy_tg0_opts[] = {
23*a71a9546SAutomerger Merge Worker {.name = "on-port", .id = P_PORT, .type = XTTYPE_PORT,
24*a71a9546SAutomerger Merge Worker .flags = XTOPT_MAND | XTOPT_NBO | XTOPT_PUT, XTOPT_POINTER(s, lport)},
25*a71a9546SAutomerger Merge Worker {.name = "on-ip", .id = P_ADDR, .type = XTTYPE_HOST},
26*a71a9546SAutomerger Merge Worker {.name = "tproxy-mark", .id = P_MARK, .type = XTTYPE_MARKMASK32},
27*a71a9546SAutomerger Merge Worker XTOPT_TABLEEND,
28*a71a9546SAutomerger Merge Worker };
29*a71a9546SAutomerger Merge Worker #undef s
30*a71a9546SAutomerger Merge Worker #define s struct xt_tproxy_target_info_v1
31*a71a9546SAutomerger Merge Worker static const struct xt_option_entry tproxy_tg1_opts[] = {
32*a71a9546SAutomerger Merge Worker {.name = "on-port", .id = P_PORT, .type = XTTYPE_PORT,
33*a71a9546SAutomerger Merge Worker .flags = XTOPT_MAND | XTOPT_NBO | XTOPT_PUT, XTOPT_POINTER(s, lport)},
34*a71a9546SAutomerger Merge Worker {.name = "on-ip", .id = P_ADDR, .type = XTTYPE_HOST,
35*a71a9546SAutomerger Merge Worker .flags = XTOPT_PUT, XTOPT_POINTER(s, laddr)},
36*a71a9546SAutomerger Merge Worker {.name = "tproxy-mark", .id = P_MARK, .type = XTTYPE_MARKMASK32},
37*a71a9546SAutomerger Merge Worker XTOPT_TABLEEND,
38*a71a9546SAutomerger Merge Worker };
39*a71a9546SAutomerger Merge Worker #undef s
40*a71a9546SAutomerger Merge Worker
tproxy_tg_help(void)41*a71a9546SAutomerger Merge Worker static void tproxy_tg_help(void)
42*a71a9546SAutomerger Merge Worker {
43*a71a9546SAutomerger Merge Worker printf(
44*a71a9546SAutomerger Merge Worker "TPROXY target options:\n"
45*a71a9546SAutomerger Merge Worker " --on-port port Redirect connection to port, or the original port if 0\n"
46*a71a9546SAutomerger Merge Worker " --on-ip ip Optionally redirect to the given IP\n"
47*a71a9546SAutomerger Merge Worker " --tproxy-mark value[/mask] Mark packets with the given value/mask\n\n");
48*a71a9546SAutomerger Merge Worker }
49*a71a9546SAutomerger Merge Worker
tproxy_tg_print(const void * ip,const struct xt_entry_target * target,int numeric)50*a71a9546SAutomerger Merge Worker static void tproxy_tg_print(const void *ip, const struct xt_entry_target *target,
51*a71a9546SAutomerger Merge Worker int numeric)
52*a71a9546SAutomerger Merge Worker {
53*a71a9546SAutomerger Merge Worker const struct xt_tproxy_target_info *info = (const void *)target->data;
54*a71a9546SAutomerger Merge Worker printf(" TPROXY redirect %s:%u mark 0x%x/0x%x",
55*a71a9546SAutomerger Merge Worker xtables_ipaddr_to_numeric((const struct in_addr *)&info->laddr),
56*a71a9546SAutomerger Merge Worker ntohs(info->lport), (unsigned int)info->mark_value,
57*a71a9546SAutomerger Merge Worker (unsigned int)info->mark_mask);
58*a71a9546SAutomerger Merge Worker }
59*a71a9546SAutomerger Merge Worker
60*a71a9546SAutomerger Merge Worker static void
tproxy_tg_print4(const void * ip,const struct xt_entry_target * target,int numeric)61*a71a9546SAutomerger Merge Worker tproxy_tg_print4(const void *ip, const struct xt_entry_target *target,
62*a71a9546SAutomerger Merge Worker int numeric)
63*a71a9546SAutomerger Merge Worker {
64*a71a9546SAutomerger Merge Worker const struct xt_tproxy_target_info_v1 *info =
65*a71a9546SAutomerger Merge Worker (const void *)target->data;
66*a71a9546SAutomerger Merge Worker
67*a71a9546SAutomerger Merge Worker printf(" TPROXY redirect %s:%u mark 0x%x/0x%x",
68*a71a9546SAutomerger Merge Worker xtables_ipaddr_to_numeric(&info->laddr.in),
69*a71a9546SAutomerger Merge Worker ntohs(info->lport), (unsigned int)info->mark_value,
70*a71a9546SAutomerger Merge Worker (unsigned int)info->mark_mask);
71*a71a9546SAutomerger Merge Worker }
72*a71a9546SAutomerger Merge Worker
73*a71a9546SAutomerger Merge Worker static void
tproxy_tg_print6(const void * ip,const struct xt_entry_target * target,int numeric)74*a71a9546SAutomerger Merge Worker tproxy_tg_print6(const void *ip, const struct xt_entry_target *target,
75*a71a9546SAutomerger Merge Worker int numeric)
76*a71a9546SAutomerger Merge Worker {
77*a71a9546SAutomerger Merge Worker const struct xt_tproxy_target_info_v1 *info =
78*a71a9546SAutomerger Merge Worker (const void *)target->data;
79*a71a9546SAutomerger Merge Worker
80*a71a9546SAutomerger Merge Worker printf(" TPROXY redirect %s:%u mark 0x%x/0x%x",
81*a71a9546SAutomerger Merge Worker xtables_ip6addr_to_numeric(&info->laddr.in6),
82*a71a9546SAutomerger Merge Worker ntohs(info->lport), (unsigned int)info->mark_value,
83*a71a9546SAutomerger Merge Worker (unsigned int)info->mark_mask);
84*a71a9546SAutomerger Merge Worker }
85*a71a9546SAutomerger Merge Worker
tproxy_tg_save(const void * ip,const struct xt_entry_target * target)86*a71a9546SAutomerger Merge Worker static void tproxy_tg_save(const void *ip, const struct xt_entry_target *target)
87*a71a9546SAutomerger Merge Worker {
88*a71a9546SAutomerger Merge Worker const struct xt_tproxy_target_info *info = (const void *)target->data;
89*a71a9546SAutomerger Merge Worker
90*a71a9546SAutomerger Merge Worker printf(" --on-port %u", ntohs(info->lport));
91*a71a9546SAutomerger Merge Worker printf(" --on-ip %s",
92*a71a9546SAutomerger Merge Worker xtables_ipaddr_to_numeric((const struct in_addr *)&info->laddr));
93*a71a9546SAutomerger Merge Worker printf(" --tproxy-mark 0x%x/0x%x",
94*a71a9546SAutomerger Merge Worker (unsigned int)info->mark_value, (unsigned int)info->mark_mask);
95*a71a9546SAutomerger Merge Worker }
96*a71a9546SAutomerger Merge Worker
97*a71a9546SAutomerger Merge Worker static void
tproxy_tg_save4(const void * ip,const struct xt_entry_target * target)98*a71a9546SAutomerger Merge Worker tproxy_tg_save4(const void *ip, const struct xt_entry_target *target)
99*a71a9546SAutomerger Merge Worker {
100*a71a9546SAutomerger Merge Worker const struct xt_tproxy_target_info_v1 *info;
101*a71a9546SAutomerger Merge Worker
102*a71a9546SAutomerger Merge Worker info = (const void *)target->data;
103*a71a9546SAutomerger Merge Worker printf(" --on-port %u", ntohs(info->lport));
104*a71a9546SAutomerger Merge Worker printf(" --on-ip %s", xtables_ipaddr_to_numeric(&info->laddr.in));
105*a71a9546SAutomerger Merge Worker printf(" --tproxy-mark 0x%x/0x%x",
106*a71a9546SAutomerger Merge Worker (unsigned int)info->mark_value, (unsigned int)info->mark_mask);
107*a71a9546SAutomerger Merge Worker }
108*a71a9546SAutomerger Merge Worker
109*a71a9546SAutomerger Merge Worker static void
tproxy_tg_save6(const void * ip,const struct xt_entry_target * target)110*a71a9546SAutomerger Merge Worker tproxy_tg_save6(const void *ip, const struct xt_entry_target *target)
111*a71a9546SAutomerger Merge Worker {
112*a71a9546SAutomerger Merge Worker const struct xt_tproxy_target_info_v1 *info;
113*a71a9546SAutomerger Merge Worker
114*a71a9546SAutomerger Merge Worker info = (const void *)target->data;
115*a71a9546SAutomerger Merge Worker printf(" --on-port %u", ntohs(info->lport));
116*a71a9546SAutomerger Merge Worker printf(" --on-ip %s", xtables_ip6addr_to_numeric(&info->laddr.in6));
117*a71a9546SAutomerger Merge Worker printf(" --tproxy-mark 0x%x/0x%x",
118*a71a9546SAutomerger Merge Worker (unsigned int)info->mark_value, (unsigned int)info->mark_mask);
119*a71a9546SAutomerger Merge Worker }
120*a71a9546SAutomerger Merge Worker
tproxy_tg0_parse(struct xt_option_call * cb)121*a71a9546SAutomerger Merge Worker static void tproxy_tg0_parse(struct xt_option_call *cb)
122*a71a9546SAutomerger Merge Worker {
123*a71a9546SAutomerger Merge Worker struct xt_tproxy_target_info *info = cb->data;
124*a71a9546SAutomerger Merge Worker
125*a71a9546SAutomerger Merge Worker xtables_option_parse(cb);
126*a71a9546SAutomerger Merge Worker switch (cb->entry->id) {
127*a71a9546SAutomerger Merge Worker case P_MARK:
128*a71a9546SAutomerger Merge Worker info->mark_value = cb->val.mark;
129*a71a9546SAutomerger Merge Worker info->mark_mask = cb->val.mask;
130*a71a9546SAutomerger Merge Worker break;
131*a71a9546SAutomerger Merge Worker case P_ADDR:
132*a71a9546SAutomerger Merge Worker info->laddr = cb->val.haddr.ip;
133*a71a9546SAutomerger Merge Worker break;
134*a71a9546SAutomerger Merge Worker }
135*a71a9546SAutomerger Merge Worker }
136*a71a9546SAutomerger Merge Worker
tproxy_tg1_parse(struct xt_option_call * cb)137*a71a9546SAutomerger Merge Worker static void tproxy_tg1_parse(struct xt_option_call *cb)
138*a71a9546SAutomerger Merge Worker {
139*a71a9546SAutomerger Merge Worker struct xt_tproxy_target_info_v1 *info = cb->data;
140*a71a9546SAutomerger Merge Worker
141*a71a9546SAutomerger Merge Worker xtables_option_parse(cb);
142*a71a9546SAutomerger Merge Worker switch (cb->entry->id) {
143*a71a9546SAutomerger Merge Worker case P_MARK:
144*a71a9546SAutomerger Merge Worker info->mark_value = cb->val.mark;
145*a71a9546SAutomerger Merge Worker info->mark_mask = cb->val.mask;
146*a71a9546SAutomerger Merge Worker break;
147*a71a9546SAutomerger Merge Worker }
148*a71a9546SAutomerger Merge Worker }
149*a71a9546SAutomerger Merge Worker
150*a71a9546SAutomerger Merge Worker static struct xtables_target tproxy_tg_reg[] = {
151*a71a9546SAutomerger Merge Worker {
152*a71a9546SAutomerger Merge Worker .name = "TPROXY",
153*a71a9546SAutomerger Merge Worker .revision = 0,
154*a71a9546SAutomerger Merge Worker .family = NFPROTO_IPV4,
155*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION,
156*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct xt_tproxy_target_info)),
157*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct xt_tproxy_target_info)),
158*a71a9546SAutomerger Merge Worker .help = tproxy_tg_help,
159*a71a9546SAutomerger Merge Worker .print = tproxy_tg_print,
160*a71a9546SAutomerger Merge Worker .save = tproxy_tg_save,
161*a71a9546SAutomerger Merge Worker .x6_options = tproxy_tg0_opts,
162*a71a9546SAutomerger Merge Worker .x6_parse = tproxy_tg0_parse,
163*a71a9546SAutomerger Merge Worker },
164*a71a9546SAutomerger Merge Worker {
165*a71a9546SAutomerger Merge Worker .name = "TPROXY",
166*a71a9546SAutomerger Merge Worker .revision = 1,
167*a71a9546SAutomerger Merge Worker .family = NFPROTO_IPV4,
168*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION,
169*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct xt_tproxy_target_info_v1)),
170*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct xt_tproxy_target_info_v1)),
171*a71a9546SAutomerger Merge Worker .help = tproxy_tg_help,
172*a71a9546SAutomerger Merge Worker .print = tproxy_tg_print4,
173*a71a9546SAutomerger Merge Worker .save = tproxy_tg_save4,
174*a71a9546SAutomerger Merge Worker .x6_options = tproxy_tg1_opts,
175*a71a9546SAutomerger Merge Worker .x6_parse = tproxy_tg1_parse,
176*a71a9546SAutomerger Merge Worker },
177*a71a9546SAutomerger Merge Worker {
178*a71a9546SAutomerger Merge Worker .name = "TPROXY",
179*a71a9546SAutomerger Merge Worker .revision = 1,
180*a71a9546SAutomerger Merge Worker .family = NFPROTO_IPV6,
181*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION,
182*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct xt_tproxy_target_info_v1)),
183*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct xt_tproxy_target_info_v1)),
184*a71a9546SAutomerger Merge Worker .help = tproxy_tg_help,
185*a71a9546SAutomerger Merge Worker .print = tproxy_tg_print6,
186*a71a9546SAutomerger Merge Worker .save = tproxy_tg_save6,
187*a71a9546SAutomerger Merge Worker .x6_options = tproxy_tg1_opts,
188*a71a9546SAutomerger Merge Worker .x6_parse = tproxy_tg1_parse,
189*a71a9546SAutomerger Merge Worker },
190*a71a9546SAutomerger Merge Worker };
191*a71a9546SAutomerger Merge Worker
_init(void)192*a71a9546SAutomerger Merge Worker void _init(void)
193*a71a9546SAutomerger Merge Worker {
194*a71a9546SAutomerger Merge Worker xtables_register_targets(tproxy_tg_reg, ARRAY_SIZE(tproxy_tg_reg));
195*a71a9546SAutomerger Merge Worker }
196