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 struct xtables_target tee_tg_reg = { 96 .name = "TEE", 97 .version = XTABLES_VERSION, 98 .revision = 1, 99 .family = NFPROTO_IPV4, 100 .size = XT_ALIGN(sizeof(struct xt_tee_tginfo)), 101 .userspacesize = XT_ALIGN(sizeof(struct xt_tee_tginfo)), 102 .help = tee_tg_help, 103 .print = tee_tg_print, 104 .save = tee_tg_save, 105 .x6_parse = xtables_option_parse, 106 .x6_options = tee_tg_opts, 107 }; 108 109 static struct xtables_target tee_tg6_reg = { 110 .name = "TEE", 111 .version = XTABLES_VERSION, 112 .revision = 1, 113 .family = NFPROTO_IPV6, 114 .size = XT_ALIGN(sizeof(struct xt_tee_tginfo)), 115 .userspacesize = XT_ALIGN(sizeof(struct xt_tee_tginfo)), 116 .help = tee_tg_help, 117 .print = tee_tg6_print, 118 .save = tee_tg6_save, 119 .x6_parse = xtables_option_parse, 120 .x6_options = tee_tg_opts, 121 }; 122 123 void _init(void) 124 { 125 xtables_register_target(&tee_tg_reg); 126 xtables_register_target(&tee_tg6_reg); 127 } 128