libip6t_HL.c revision 46e8538e2254fcd48517067b659bcdc8ba1c3cc0
1/*
2 * IPv6 Hop Limit Target module
3 * Maciej Soltysiak <solt@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
19static void init(struct ip6t_entry_target *t, unsigned int *nfcache)
20{
21}
22
23static 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
33static 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
92static 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
99static 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
120static 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
141static 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
148static
149struct ip6tables_target HL = { NULL,
150	"HL",
151	IPTABLES_VERSION,
152	IP6T_ALIGN(sizeof(struct ip6t_HL_info)),
153	IP6T_ALIGN(sizeof(struct ip6t_HL_info)),
154	&help,
155	&init,
156	&parse,
157	&final_check,
158	&print,
159	&save,
160	opts
161};
162
163void _init(void)
164{
165	register_target6(&HL);
166}
167