libip6t_HL.c revision 60358d73482620aeafc34f38df36e462875fd244
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>\n"
28"  --hl-dec value		Decrement HL by <value>\n"
29"  --hl-inc value		Increment HL by <value>\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	u_int8_t 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	value = atoi(optarg);
54
55	switch (c) {
56
57		case '1':
58			info->mode = IP6T_HL_SET;
59			break;
60
61		case '2':
62			if (value == 0) {
63				exit_error(PARAMETER_PROBLEM,
64					"HL: decreasing by 0?");
65			}
66
67			info->mode = IP6T_HL_DEC;
68			break;
69
70		case '3':
71			if (value == 0) {
72				exit_error(PARAMETER_PROBLEM,
73					"HL: increasing by 0?");
74			}
75
76			info->mode = IP6T_HL_INC;
77			break;
78
79		default:
80			return 0;
81
82	}
83
84	info->hop_limit = value;
85	*flags |= IP6T_HL_USED;
86
87	return 1;
88}
89
90static void final_check(unsigned int flags)
91{
92	if (!(flags & IP6T_HL_USED))
93		exit_error(PARAMETER_PROBLEM,
94				"HL: You must specify an action");
95}
96
97static void save(const struct ip6t_ip6 *ip,
98		const struct ip6t_entry_target *target)
99{
100	const struct ip6t_HL_info *info =
101		(struct ip6t_HL_info *) target->data;
102
103	switch (info->mode) {
104		case IP6T_HL_SET:
105			printf("--hl-set ");
106			break;
107		case IP6T_HL_DEC:
108			printf("--hl-dec ");
109			break;
110
111		case IP6T_HL_INC:
112			printf("--hl-inc ");
113			break;
114	}
115	printf("%u ", info->hop_limit);
116}
117
118static void print(const struct ip6t_ip6 *ip,
119		const struct ip6t_entry_target *target, int numeric)
120{
121	const struct ip6t_HL_info *info =
122		(struct ip6t_HL_info *) target->data;
123
124	printf("HL ");
125	switch (info->mode) {
126		case IP6T_HL_SET:
127			printf("set to ");
128			break;
129		case IP6T_HL_DEC:
130			printf("decrement by ");
131			break;
132		case IP6T_HL_INC:
133			printf("increment by ");
134			break;
135	}
136	printf("%u ", info->hop_limit);
137}
138
139static struct option opts[] = {
140	{ "hl-set", 1, 0, '1' },
141	{ "hl-dec", 1, 0, '2' },
142	{ "hl-inc", 1, 0, '3' },
143	{ 0 }
144};
145
146static
147struct ip6tables_target HL = { NULL,
148	"HL",
149	IPTABLES_VERSION,
150	IP6T_ALIGN(sizeof(struct ip6t_HL_info)),
151	IP6T_ALIGN(sizeof(struct ip6t_HL_info)),
152	&help,
153	&init,
154	&parse,
155	&final_check,
156	&print,
157	&save,
158	opts
159};
160
161void _init(void)
162{
163	register_target6(&HL);
164}
165