1 /* 2 * "TEE" target extension for iptables 3 * Copyright Sebastian Claen <sebastian.classen [at] freenet.ag>, 2007 4 * Jan Engelhardt <jengelh [at] medozas de>, 2007 - 2010 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License; either 8 * version 2 of the License, or any later version, as published by the 9 * Free Software Foundation. 10 */ 11 #include <sys/socket.h> 12 #include <getopt.h> 13 #include <stdbool.h> 14 #include <stdio.h> 15 #include <stdlib.h> 16 #include <string.h> 17 18 #include <arpa/inet.h> 19 #include <net/if.h> 20 #include <netinet/in.h> 21 22 #include <xtables.h> 23 #include <linux/netfilter.h> 24 #include <linux/netfilter/x_tables.h> 25 #include <linux/netfilter/xt_TEE.h> 26 27 enum { 28 O_GATEWAY = 0, 29 O_OIF, 30 }; 31 32 #define s struct xt_tee_tginfo 33 static const struct xt_option_entry tee_tg_opts[] = { 34 {.name = "gateway", .id = O_GATEWAY, .type = XTTYPE_HOST, 35 .flags = XTOPT_MAND | XTOPT_PUT, XTOPT_POINTER(s, gw)}, 36 {.name = "oif", .id = O_OIF, .type = XTTYPE_STRING, 37 .flags = XTOPT_PUT, XTOPT_POINTER(s, oif)}, 38 XTOPT_TABLEEND, 39 }; 40 #undef s 41 42 static void tee_tg_help(void) 43 { 44 printf( 45 "TEE target options:\n" 46 " --gateway IPADDR Route packet via the gateway given by address\n" 47 " --oif NAME Include oif in route calculation\n" 48 "\n"); 49 } 50 51 static void tee_tg_print(const void *ip, const struct xt_entry_target *target, 52 int numeric) 53 { 54 const struct xt_tee_tginfo *info = (const void *)target->data; 55 56 if (numeric) 57 printf(" TEE gw:%s", xtables_ipaddr_to_numeric(&info->gw.in)); 58 else 59 printf(" TEE gw:%s", xtables_ipaddr_to_anyname(&info->gw.in)); 60 if (*info->oif != '\0') 61 printf(" oif=%s", info->oif); 62 } 63 64 static void tee_tg6_print(const void *ip, const struct xt_entry_target *target, 65 int numeric) 66 { 67 const struct xt_tee_tginfo *info = (const void *)target->data; 68 69 if (numeric) 70 printf(" TEE gw:%s", xtables_ip6addr_to_numeric(&info->gw.in6)); 71 else 72 printf(" TEE gw:%s", xtables_ip6addr_to_anyname(&info->gw.in6)); 73 if (*info->oif != '\0') 74 printf(" oif=%s", info->oif); 75 } 76 77 static void tee_tg_save(const void *ip, const struct xt_entry_target *target) 78 { 79 const struct xt_tee_tginfo *info = (const void *)target->data; 80 81 printf(" --gateway %s", xtables_ipaddr_to_numeric(&info->gw.in)); 82 if (*info->oif != '\0') 83 printf(" --oif %s", info->oif); 84 } 85 86 static void tee_tg6_save(const void *ip, const struct xt_entry_target *target) 87 { 88 const struct xt_tee_tginfo *info = (const void *)target->data; 89 90 printf(" --gateway %s", xtables_ip6addr_to_numeric(&info->gw.in6)); 91 if (*info->oif != '\0') 92 printf(" --oif %s", info->oif); 93 } 94 95 static int tee_tg_xlate(struct xt_xlate *xl, 96 const struct xt_xlate_tg_params *params) 97 { 98 const struct xt_tee_tginfo *info = (const void *)params->target->data; 99 100 if (params->numeric) 101 xt_xlate_add(xl, "dup to %s", 102 xtables_ipaddr_to_numeric(&info->gw.in)); 103 else 104 xt_xlate_add(xl, "dup to %s", 105 xtables_ipaddr_to_anyname(&info->gw.in)); 106 if (*info->oif != '\0') 107 xt_xlate_add(xl, " device %s", info->oif); 108 109 return 1; 110 } 111 112 static int tee_tg6_xlate(struct xt_xlate *xl, 113 const struct xt_xlate_tg_params *params) 114 { 115 const struct xt_tee_tginfo *info = (const void *)params->target->data; 116 117 if (params->numeric) 118 xt_xlate_add(xl, "dup to %s", 119 xtables_ip6addr_to_numeric(&info->gw.in6)); 120 else 121 xt_xlate_add(xl, "dup to %s", 122 xtables_ip6addr_to_anyname(&info->gw.in6)); 123 if (*info->oif != '\0') 124 xt_xlate_add(xl, " device %s", info->oif); 125 126 return 1; 127 } 128 129 static struct xtables_target tee_tg_reg[] = { 130 { 131 .name = "TEE", 132 .version = XTABLES_VERSION, 133 .revision = 1, 134 .family = NFPROTO_IPV4, 135 .size = XT_ALIGN(sizeof(struct xt_tee_tginfo)), 136 .userspacesize = offsetof(struct xt_tee_tginfo, priv), 137 .help = tee_tg_help, 138 .print = tee_tg_print, 139 .save = tee_tg_save, 140 .x6_parse = xtables_option_parse, 141 .x6_options = tee_tg_opts, 142 .xlate = tee_tg_xlate, 143 }, 144 { 145 .name = "TEE", 146 .version = XTABLES_VERSION, 147 .revision = 1, 148 .family = NFPROTO_IPV6, 149 .size = XT_ALIGN(sizeof(struct xt_tee_tginfo)), 150 .userspacesize = offsetof(struct xt_tee_tginfo, priv), 151 .help = tee_tg_help, 152 .print = tee_tg6_print, 153 .save = tee_tg6_save, 154 .x6_parse = xtables_option_parse, 155 .x6_options = tee_tg_opts, 156 .xlate = tee_tg6_xlate, 157 }, 158 }; 159 160 void _init(void) 161 { 162 xtables_register_targets(tee_tg_reg, ARRAY_SIZE(tee_tg_reg)); 163 } 164