libxt_TPROXY.c revision 9e152fa9f1283ce4f4274cf251b2b2e69bbdfee6
1/* 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 <stdint.h> 9#include <stdio.h> 10#include <string.h> 11#include <stdlib.h> 12#include <limits.h> 13 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 = 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, 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, uint16_t *portp) 41{ 42 unsigned int lport; 43 44 if (xtables_strtoui(s, NULL, &lport, 0, UINT16_MAX)) 45 *portp = htons(lport); 46 else 47 xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--on-port", s); 48} 49 50static void parse_tproxy_laddr(const char *s, union nf_inet_addr *addrp, 51 unsigned int nfproto) 52{ 53 struct in6_addr *laddr6 = NULL; 54 struct in_addr *laddr4 = NULL; 55 56 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); 70} 71 72static void parse_tproxy_mark(char *s, uint32_t *markp, uint32_t *maskp) 73{ 74 unsigned int value, mask = UINT32_MAX; 75 char *end; 76 77 if (!xtables_strtoui(s, &end, &value, 0, UINT32_MAX)) 78 xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--tproxy-mark", s); 79 if (*end == '/') 80 if (!xtables_strtoui(end + 1, &end, &mask, 0, UINT32_MAX)) 81 xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--tproxy-mark", s); 82 if (*end != '\0') 83 xtables_param_act(XTF_BAD_VALUE, "TPROXY", "--tproxy-mark", s); 84 85 *markp = value; 86 *maskp = mask; 87} 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{ 92 struct xt_tproxy_target_info *info = (void *)(*target)->data; 93 94 switch (c) { 95 case '1': 96 xtables_param_act(XTF_ONLY_ONCE, "TPROXY", "--on-port", *flags & PARAM_ONPORT); 97 xtables_param_act(XTF_NO_INVERT, "TPROXY", "--on-port", invert); 98 parse_tproxy_lport(optarg, &info->lport); 99 *flags |= PARAM_ONPORT; 100 return 1; 101 case '2': 102 xtables_param_act(XTF_ONLY_ONCE, "TPROXY", "--on-ip", *flags & PARAM_ONIP); 103 xtables_param_act(XTF_NO_INVERT, "TPROXY", "--on-ip", invert); 104 parse_tproxy_laddr(optarg, (void *)&info->laddr, NFPROTO_IPV4); 105 *flags |= PARAM_ONIP; 106 return 1; 107 case '3': 108 xtables_param_act(XTF_ONLY_ONCE, "TPROXY", "--tproxy-mark", *flags & PARAM_MARK); 109 xtables_param_act(XTF_NO_INVERT, "TPROXY", "--tproxy-mark", invert); 110 parse_tproxy_mark(optarg, &info->mark_value, &info->mark_mask); 111 *flags |= PARAM_MARK; 112 return 1; 113 } 114 115 return 0; 116} 117 118static 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 161static void tproxy_tg_check(unsigned int flags) 162{ 163 if (!(flags & PARAM_ONPORT)) 164 xtables_error(PARAMETER_PROBLEM, 165 "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", 173 xtables_ipaddr_to_numeric((const struct in_addr *)&info->laddr), 174 ntohs(info->lport), (unsigned int)info->mark_value, 175 (unsigned int)info->mark_mask); 176} 177 178static 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 204static 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 ", 210 xtables_ipaddr_to_numeric((const struct in_addr *)&info->laddr)); 211 printf("--tproxy-mark 0x%x/0x%x ", 212 (unsigned int)info->mark_value, (unsigned int)info->mark_mask); 213} 214 215static 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 }, 282}; 283 284void _init(void) 285{ 286 xtables_register_targets(tproxy_tg_reg, ARRAY_SIZE(tproxy_tg_reg)); 287} 288