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