blob: 0f910f40504e581d0ba492bbf3fc249f8172e80a [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>
8#include <stdio.h>
9#include <string.h>
10#include <stdlib.h>
11#include <limits.h>
12
13#include <iptables.h>
14#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[] = {
19 { .name = "on-port", .has_arg = 1, .val = '1'},
20 { .name = "on-ip", .has_arg = 1, .val = '2'},
21 { .name = "tproxy-mark", .has_arg = 1, .val = '3'},
22 {NULL},
23};
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
40static void parse_tproxy_lport(const char *s, struct xt_tproxy_target_info *info)
41{
42 unsigned int lport;
43
44 if (string_to_number(s, 0, 65535, &lport) != -1)
45 info->lport = htons(lport);
46 else
47 param_act(P_BAD_VALUE, "TPROXY", "--on-port", s);
48}
49
50static void parse_tproxy_laddr(const char *s, struct xt_tproxy_target_info *info)
51{
52 struct in_addr *laddr;
53
54 if ((laddr = numeric_to_ipaddr(s)) == NULL)
55 param_act(P_BAD_VALUE, "TPROXY", "--on-ip", s);
56
57 info->laddr = laddr->s_addr;
58}
59
60static void parse_tproxy_mark(char *s, struct xt_tproxy_target_info *info)
61{
62 unsigned int value, mask = ~0U;
63 char *end;
64
65 if (!strtonum(s, &end, &value, 0, UINT_MAX))
66 param_act(P_BAD_VALUE, "TPROXY", "--tproxy-mark", s);
67 if (*end == '/')
68 if (!strtonum(end + 1, &end, &mask, 0, UINT_MAX))
69 param_act(P_BAD_VALUE, "TPROXY", "--tproxy-mark", s);
70 if (*end != '\0')
71 param_act(P_BAD_VALUE, "TPROXY", "--tproxy-mark", s);
72
73 info->mark_mask = mask;
74 info->mark_value = value;
75}
76
77static int tproxy_tg_parse(int c, char **argv, int invert, unsigned int *flags,
78 const void *entry, struct xt_entry_target **target)
79{
80 struct xt_tproxy_target_info *tproxyinfo = (void *)(*target)->data;
81
82 switch (c) {
83 case '1':
84 param_act(P_ONLY_ONCE, "TPROXY", "--on-port", *flags & PARAM_ONPORT);
85 param_act(P_NO_INVERT, "TPROXY", "--on-port", invert);
86 parse_tproxy_lport(optarg, tproxyinfo);
87 *flags |= PARAM_ONPORT;
88 return 1;
89 case '2':
90 param_act(P_ONLY_ONCE, "TPROXY", "--on-ip", *flags & PARAM_ONIP);
91 param_act(P_NO_INVERT, "TPROXY", "--on-ip", invert);
92 parse_tproxy_laddr(optarg, tproxyinfo);
93 *flags |= PARAM_ONIP;
94 return 1;
95 case '3':
96 param_act(P_ONLY_ONCE, "TPROXY", "--tproxy-mark", *flags & PARAM_MARK);
97 param_act(P_NO_INVERT, "TPROXY", "--tproxy-mark", invert);
98 parse_tproxy_mark(optarg, tproxyinfo);
99 *flags |= PARAM_MARK;
100 return 1;
101 }
102
103 return 0;
104}
105
106static void tproxy_tg_check(unsigned int flags)
107{
108 if (!(flags & PARAM_ONPORT))
109 exit_error(PARAMETER_PROBLEM,
110 "TPROXY target: Parameter --on-port is required");
111}
112
113static void tproxy_tg_print(const void *ip, const struct xt_entry_target *target,
114 int numeric)
115{
116 const struct xt_tproxy_target_info *info = (const void *)target->data;
117 printf("TPROXY redirect %s:%u mark 0x%x/0x%x",
118 ipaddr_to_numeric((const struct in_addr *)&info->laddr),
119 ntohs(info->lport), (unsigned int)info->mark_value,
120 (unsigned int)info->mark_mask);
121}
122
123static void tproxy_tg_save(const void *ip, const struct xt_entry_target *target)
124{
125 const struct xt_tproxy_target_info *info = (const void *)target->data;
126
127 printf("--on-port %u ", ntohs(info->lport));
128 printf("--on-ip %s ",
129 ipaddr_to_numeric((const struct in_addr *)&info->laddr));
130 printf("--tproxy-mark 0x%x/0x%x ",
131 (unsigned int)info->mark_value, (unsigned int)info->mark_mask);
132}
133
134static struct xtables_target tproxy_tg_reg = {
135 .name = "TPROXY",
136 .family = AF_INET,
137 .version = XTABLES_VERSION,
138 .size = XT_ALIGN(sizeof(struct xt_tproxy_target_info)),
139 .userspacesize = XT_ALIGN(sizeof(struct xt_tproxy_target_info)),
140 .help = tproxy_tg_help,
141 .parse = tproxy_tg_parse,
142 .final_check = tproxy_tg_check,
143 .print = tproxy_tg_print,
144 .save = tproxy_tg_save,
145 .extra_opts = tproxy_tg_opts,
146};
147
148void _init(void)
149{
150 xtables_register_target(&tproxy_tg_reg);
151}