libxt_TEE.c revision 8532c70fd182057b440b41f013d8021a95bd72b2
1/* 2 * "TEE" target extension for iptables 3 * Copyright © Sebastian Claßen <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 27enum { 28 FLAG_GATEWAY = 1 << 0, 29 FLAG_OIF = 1 << 1, 30}; 31 32static const struct option tee_tg_opts[] = { 33 {.name = "gateway", .has_arg = true, .val = 'g'}, 34 {.name = "oif", .has_arg = true, .val = 'o'}, 35 {NULL}, 36}; 37 38static void tee_tg_help(void) 39{ 40 printf( 41"TEE target options:\n" 42" --gateway IPADDR Route packet via the gateway given by address\n" 43" --oif NAME Include oif in route calculation\n" 44"\n"); 45} 46 47static int tee_tg_parse(int c, char **argv, int invert, unsigned int *flags, 48 const void *entry, struct xt_entry_target **target) 49{ 50 struct xt_tee_tginfo *info = (void *)(*target)->data; 51 const struct in_addr *ia; 52 53 switch (c) { 54 case 'g': 55 if (*flags & FLAG_GATEWAY) 56 xtables_error(PARAMETER_PROBLEM, 57 "Cannot specify --gateway more than once"); 58 59 ia = xtables_numeric_to_ipaddr(optarg); 60 if (ia == NULL) 61 xtables_error(PARAMETER_PROBLEM, 62 "Invalid IP address %s", optarg); 63 64 memcpy(&info->gw, ia, sizeof(*ia)); 65 *flags |= FLAG_GATEWAY; 66 return true; 67 case 'o': 68 if (*flags & FLAG_OIF) 69 xtables_error(PARAMETER_PROBLEM, 70 "Cannot specify --oif more than once"); 71 if (strlen(optarg) >= sizeof(info->oif)) 72 xtables_error(PARAMETER_PROBLEM, 73 "oif name too long"); 74 strcpy(info->oif, optarg); 75 *flags |= FLAG_OIF; 76 return true; 77 } 78 79 return false; 80} 81 82static int tee_tg6_parse(int c, char **argv, int invert, unsigned int *flags, 83 const void *entry, struct xt_entry_target **target) 84{ 85 struct xt_tee_tginfo *info = (void *)(*target)->data; 86 const struct in6_addr *ia; 87 88 switch (c) { 89 case 'g': 90 if (*flags & FLAG_GATEWAY) 91 xtables_error(PARAMETER_PROBLEM, 92 "Cannot specify --gateway more than once"); 93 94 ia = xtables_numeric_to_ip6addr(optarg); 95 if (ia == NULL) 96 xtables_error(PARAMETER_PROBLEM, 97 "Invalid IP address %s", optarg); 98 99 memcpy(&info->gw, ia, sizeof(*ia)); 100 *flags |= FLAG_GATEWAY; 101 return true; 102 case 'o': 103 if (*flags & FLAG_OIF) 104 xtables_error(PARAMETER_PROBLEM, 105 "Cannot specify --oif more than once"); 106 if (strlen(optarg) >= sizeof(info->oif)) 107 xtables_error(PARAMETER_PROBLEM, 108 "oif name too long"); 109 strcpy(info->oif, optarg); 110 *flags |= FLAG_OIF; 111 return true; 112 } 113 114 return false; 115} 116 117static void tee_tg_check(unsigned int flags) 118{ 119 if (flags == 0) 120 xtables_error(PARAMETER_PROBLEM, "TEE target: " 121 "--gateway parameter required"); 122} 123 124static void tee_tg_print(const void *ip, const struct xt_entry_target *target, 125 int numeric) 126{ 127 const struct xt_tee_tginfo *info = (const void *)target->data; 128 129 if (numeric) 130 printf("TEE gw:%s ", xtables_ipaddr_to_numeric(&info->gw.in)); 131 else 132 printf("TEE gw:%s ", xtables_ipaddr_to_anyname(&info->gw.in)); 133 if (*info->oif != '\0') 134 printf("oif=%s ", info->oif); 135} 136 137static void tee_tg6_print(const void *ip, const struct xt_entry_target *target, 138 int numeric) 139{ 140 const struct xt_tee_tginfo *info = (const void *)target->data; 141 142 if (numeric) 143 printf("TEE gw:%s ", xtables_ip6addr_to_numeric(&info->gw.in6)); 144 else 145 printf("TEE gw:%s ", xtables_ip6addr_to_anyname(&info->gw.in6)); 146 if (*info->oif != '\0') 147 printf("oif=%s ", info->oif); 148} 149 150static void tee_tg_save(const void *ip, const struct xt_entry_target *target) 151{ 152 const struct xt_tee_tginfo *info = (const void *)target->data; 153 154 printf("--gateway %s ", xtables_ipaddr_to_numeric(&info->gw.in)); 155 if (*info->oif != '\0') 156 printf("--oif %s ", info->oif); 157} 158 159static void tee_tg6_save(const void *ip, const struct xt_entry_target *target) 160{ 161 const struct xt_tee_tginfo *info = (const void *)target->data; 162 163 printf("--gateway %s ", xtables_ip6addr_to_numeric(&info->gw.in6)); 164 if (*info->oif != '\0') 165 printf("--oif %s ", info->oif); 166} 167 168static struct xtables_target tee_tg_reg = { 169 .name = "TEE", 170 .version = XTABLES_VERSION, 171 .revision = 1, 172 .family = NFPROTO_IPV4, 173 .size = XT_ALIGN(sizeof(struct xt_tee_tginfo)), 174 .userspacesize = XT_ALIGN(sizeof(struct xt_tee_tginfo)), 175 .help = tee_tg_help, 176 .parse = tee_tg_parse, 177 .final_check = tee_tg_check, 178 .print = tee_tg_print, 179 .save = tee_tg_save, 180 .extra_opts = tee_tg_opts, 181}; 182 183static struct xtables_target tee_tg6_reg = { 184 .name = "TEE", 185 .version = XTABLES_VERSION, 186 .revision = 1, 187 .family = NFPROTO_IPV6, 188 .size = XT_ALIGN(sizeof(struct xt_tee_tginfo)), 189 .userspacesize = XT_ALIGN(sizeof(struct xt_tee_tginfo)), 190 .help = tee_tg_help, 191 .parse = tee_tg6_parse, 192 .final_check = tee_tg_check, 193 .print = tee_tg6_print, 194 .save = tee_tg6_save, 195 .extra_opts = tee_tg_opts, 196}; 197 198static __attribute__((constructor)) void tee_tg_ldr(void) 199{ 200 xtables_register_target(&tee_tg_reg); 201 xtables_register_target(&tee_tg6_reg); 202} 203