Home | History | Annotate | Download | only in extensions
      1 /*
      2  * IPv6 Hop Limit Target module
      3  * Maciej Soltysiak <solt (at) dns.toxicfilms.tv>
      4  * Based on HW's ttl target
      5  * This program is distributed under the terms of GNU GPL
      6  */
      7 
      8 #include <stdio.h>
      9 #include <string.h>
     10 #include <stdlib.h>
     11 #include <getopt.h>
     12 #include <ip6tables.h>
     13 
     14 #include <linux/netfilter_ipv6/ip6_tables.h>
     15 #include <linux/netfilter_ipv6/ip6t_HL.h>
     16 
     17 #define IP6T_HL_USED	1
     18 
     19 static void init(struct ip6t_entry_target *t, unsigned int *nfcache)
     20 {
     21 }
     22 
     23 static void help(void)
     24 {
     25 	printf(
     26 "HL target v%s options\n"
     27 "  --hl-set value		Set HL to <value 0-255>\n"
     28 "  --hl-dec value		Decrement HL by <value 1-255>\n"
     29 "  --hl-inc value		Increment HL by <value 1-255>\n"
     30 , IPTABLES_VERSION);
     31 }
     32 
     33 static int parse(int c, char **argv, int invert, unsigned int *flags,
     34 		const struct ip6t_entry *entry,
     35 		struct ip6t_entry_target **target)
     36 {
     37 	struct ip6t_HL_info *info = (struct ip6t_HL_info *) (*target)->data;
     38 	unsigned int value;
     39 
     40 	if (*flags & IP6T_HL_USED) {
     41 		exit_error(PARAMETER_PROBLEM,
     42 				"Can't specify HL option twice");
     43 	}
     44 
     45 	if (!optarg)
     46 		exit_error(PARAMETER_PROBLEM,
     47 				"HL: You must specify a value");
     48 
     49 	if (check_inverse(optarg, &invert, NULL, 0))
     50 		exit_error(PARAMETER_PROBLEM,
     51 				"HL: unexpected `!'");
     52 
     53 	if (string_to_number(optarg, 0, 255, &value) == -1)
     54 		exit_error(PARAMETER_PROBLEM,
     55 		           "HL: Expected value between 0 and 255");
     56 
     57 	switch (c) {
     58 
     59 		case '1':
     60 			info->mode = IP6T_HL_SET;
     61 			break;
     62 
     63 		case '2':
     64 			if (value == 0) {
     65 				exit_error(PARAMETER_PROBLEM,
     66 					"HL: decreasing by 0?");
     67 			}
     68 
     69 			info->mode = IP6T_HL_DEC;
     70 			break;
     71 
     72 		case '3':
     73 			if (value == 0) {
     74 				exit_error(PARAMETER_PROBLEM,
     75 					"HL: increasing by 0?");
     76 			}
     77 
     78 			info->mode = IP6T_HL_INC;
     79 			break;
     80 
     81 		default:
     82 			return 0;
     83 
     84 	}
     85 
     86 	info->hop_limit = value;
     87 	*flags |= IP6T_HL_USED;
     88 
     89 	return 1;
     90 }
     91 
     92 static void final_check(unsigned int flags)
     93 {
     94 	if (!(flags & IP6T_HL_USED))
     95 		exit_error(PARAMETER_PROBLEM,
     96 				"HL: You must specify an action");
     97 }
     98 
     99 static void save(const struct ip6t_ip6 *ip,
    100 		const struct ip6t_entry_target *target)
    101 {
    102 	const struct ip6t_HL_info *info =
    103 		(struct ip6t_HL_info *) target->data;
    104 
    105 	switch (info->mode) {
    106 		case IP6T_HL_SET:
    107 			printf("--hl-set ");
    108 			break;
    109 		case IP6T_HL_DEC:
    110 			printf("--hl-dec ");
    111 			break;
    112 
    113 		case IP6T_HL_INC:
    114 			printf("--hl-inc ");
    115 			break;
    116 	}
    117 	printf("%u ", info->hop_limit);
    118 }
    119 
    120 static void print(const struct ip6t_ip6 *ip,
    121 		const struct ip6t_entry_target *target, int numeric)
    122 {
    123 	const struct ip6t_HL_info *info =
    124 		(struct ip6t_HL_info *) target->data;
    125 
    126 	printf("HL ");
    127 	switch (info->mode) {
    128 		case IP6T_HL_SET:
    129 			printf("set to ");
    130 			break;
    131 		case IP6T_HL_DEC:
    132 			printf("decrement by ");
    133 			break;
    134 		case IP6T_HL_INC:
    135 			printf("increment by ");
    136 			break;
    137 	}
    138 	printf("%u ", info->hop_limit);
    139 }
    140 
    141 static struct option opts[] = {
    142 	{ "hl-set", 1, 0, '1' },
    143 	{ "hl-dec", 1, 0, '2' },
    144 	{ "hl-inc", 1, 0, '3' },
    145 	{ 0 }
    146 };
    147 
    148 static
    149 struct ip6tables_target HL = { NULL,
    150 	.name 		= "HL",
    151 	.version	= IPTABLES_VERSION,
    152 	.size		= IP6T_ALIGN(sizeof(struct ip6t_HL_info)),
    153 	.userspacesize	= IP6T_ALIGN(sizeof(struct ip6t_HL_info)),
    154 	.help		= &help,
    155 	.init		= &init,
    156 	.parse		= &parse,
    157 	.final_check	= &final_check,
    158 	.print		= &print,
    159 	.save		= &save,
    160 	.extra_opts	= opts
    161 };
    162 
    163 void _init(void)
    164 {
    165 	register_target6(&HL);
    166 }
    167