Home | History | Annotate | Download | only in extensions
      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