| /* | 
 |  * IPv6 Hop Limit Target module | 
 |  * Maciej Soltysiak <solt@dns.toxicfilms.tv> | 
 |  * Based on HW's ttl target | 
 |  * This program is distributed under the terms of GNU GPL | 
 |  */ | 
 |  | 
 | #include <getopt.h> | 
 | #include <stdio.h> | 
 | #include <string.h> | 
 | #include <stdlib.h> | 
 | #include <xtables.h> | 
 |  | 
 | #include <linux/netfilter_ipv6/ip6t_HL.h> | 
 |  | 
 | #define IP6T_HL_USED	1 | 
 |  | 
 | static void HL_help(void) | 
 | { | 
 | 	printf( | 
 | "HL target options\n" | 
 | "  --hl-set value		Set HL to <value 0-255>\n" | 
 | "  --hl-dec value		Decrement HL by <value 1-255>\n" | 
 | "  --hl-inc value		Increment HL by <value 1-255>\n"); | 
 | } | 
 |  | 
 | static int HL_parse(int c, char **argv, int invert, unsigned int *flags, | 
 |                     const void *entry, struct xt_entry_target **target) | 
 | { | 
 | 	struct ip6t_HL_info *info = (struct ip6t_HL_info *) (*target)->data; | 
 | 	unsigned int value; | 
 |  | 
 | 	if (*flags & IP6T_HL_USED) { | 
 | 		xtables_error(PARAMETER_PROBLEM, | 
 | 				"Can't specify HL option twice"); | 
 | 	} | 
 |  | 
 | 	if (!optarg)  | 
 | 		xtables_error(PARAMETER_PROBLEM, | 
 | 				"HL: You must specify a value"); | 
 |  | 
 | 	if (xtables_check_inverse(optarg, &invert, NULL, 0)) | 
 | 		xtables_error(PARAMETER_PROBLEM, | 
 | 				"HL: unexpected `!'"); | 
 | 	 | 
 | 	if (!xtables_strtoui(optarg, NULL, &value, 0, UINT8_MAX)) | 
 | 		xtables_error(PARAMETER_PROBLEM, | 
 | 		           "HL: Expected value between 0 and 255"); | 
 |  | 
 | 	switch (c) { | 
 |  | 
 | 		case '1': | 
 | 			info->mode = IP6T_HL_SET; | 
 | 			break; | 
 |  | 
 | 		case '2': | 
 | 			if (value == 0) { | 
 | 				xtables_error(PARAMETER_PROBLEM, | 
 | 					"HL: decreasing by 0?"); | 
 | 			} | 
 |  | 
 | 			info->mode = IP6T_HL_DEC; | 
 | 			break; | 
 |  | 
 | 		case '3': | 
 | 			if (value == 0) { | 
 | 				xtables_error(PARAMETER_PROBLEM, | 
 | 					"HL: increasing by 0?"); | 
 | 			} | 
 |  | 
 | 			info->mode = IP6T_HL_INC; | 
 | 			break; | 
 |  | 
 | 		default: | 
 | 			return 0; | 
 |  | 
 | 	} | 
 | 	 | 
 | 	info->hop_limit = value; | 
 | 	*flags |= IP6T_HL_USED; | 
 |  | 
 | 	return 1; | 
 | } | 
 |  | 
 | static void HL_check(unsigned int flags) | 
 | { | 
 | 	if (!(flags & IP6T_HL_USED)) | 
 | 		xtables_error(PARAMETER_PROBLEM, | 
 | 				"HL: You must specify an action"); | 
 | } | 
 |  | 
 | static void HL_save(const void *ip, const struct xt_entry_target *target) | 
 | { | 
 | 	const struct ip6t_HL_info *info =  | 
 | 		(struct ip6t_HL_info *) target->data; | 
 |  | 
 | 	switch (info->mode) { | 
 | 		case IP6T_HL_SET: | 
 | 			printf("--hl-set "); | 
 | 			break; | 
 | 		case IP6T_HL_DEC: | 
 | 			printf("--hl-dec "); | 
 | 			break; | 
 |  | 
 | 		case IP6T_HL_INC: | 
 | 			printf("--hl-inc "); | 
 | 			break; | 
 | 	} | 
 | 	printf("%u ", info->hop_limit); | 
 | } | 
 |  | 
 | static void HL_print(const void *ip, const struct xt_entry_target *target, | 
 |                      int numeric) | 
 | { | 
 | 	const struct ip6t_HL_info *info = | 
 | 		(struct ip6t_HL_info *) target->data; | 
 |  | 
 | 	printf("HL "); | 
 | 	switch (info->mode) { | 
 | 		case IP6T_HL_SET: | 
 | 			printf("set to "); | 
 | 			break; | 
 | 		case IP6T_HL_DEC: | 
 | 			printf("decrement by "); | 
 | 			break; | 
 | 		case IP6T_HL_INC: | 
 | 			printf("increment by "); | 
 | 			break; | 
 | 	} | 
 | 	printf("%u ", info->hop_limit); | 
 | } | 
 |  | 
 | static const struct option HL_opts[] = { | 
 | 	{ "hl-set", 1, NULL, '1' }, | 
 | 	{ "hl-dec", 1, NULL, '2' }, | 
 | 	{ "hl-inc", 1, NULL, '3' }, | 
 | 	{ .name = NULL } | 
 | }; | 
 |  | 
 | static struct xtables_target hl_tg6_reg = { | 
 | 	.name 		= "HL", | 
 | 	.version	= XTABLES_VERSION, | 
 | 	.family		= NFPROTO_IPV6, | 
 | 	.size		= XT_ALIGN(sizeof(struct ip6t_HL_info)), | 
 | 	.userspacesize	= XT_ALIGN(sizeof(struct ip6t_HL_info)), | 
 | 	.help		= HL_help, | 
 | 	.parse		= HL_parse, | 
 | 	.final_check	= HL_check, | 
 | 	.print		= HL_print, | 
 | 	.save		= HL_save, | 
 | 	.extra_opts	= HL_opts, | 
 | }; | 
 |  | 
 | void _init(void) | 
 | { | 
 | 	xtables_register_target(&hl_tg6_reg); | 
 | } |