libip6t_hl.c revision bbe83862a5e1baf15f7c923352d4afdf59bc70e2
1/*
2 * IPv6 Hop Limit matching module
3 * Maciej Soltysiak <solt@dns.toxicfilms.tv>
4 * Based on HW's ttl match
5 * This program is released under the terms of GNU GPL
6 * Cleanups by Stephane Ouellette <ouellettes@videotron.ca>
7 */
8
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12#include <getopt.h>
13#include <xtables.h>
14
15#include <linux/netfilter_ipv6/ip6t_hl.h>
16
17static void hl_help(void)
18{
19	printf(
20"hl match options:\n"
21"[!] --hl-eq value	Match hop limit value\n"
22"  --hl-lt value	Match HL < value\n"
23"  --hl-gt value	Match HL > value\n");
24}
25
26static int hl_parse(int c, char **argv, int invert, unsigned int *flags,
27                    const void *entry, struct xt_entry_match **match)
28{
29	struct ip6t_hl_info *info = (struct ip6t_hl_info *) (*match)->data;
30	u_int8_t value;
31
32	xtables_check_inverse(optarg, &invert, &optind, 0, argv);
33	value = atoi(optarg);
34
35	if (*flags)
36		xtables_error(PARAMETER_PROBLEM,
37				"Can't specify HL option twice");
38
39	if (!optarg)
40		xtables_error(PARAMETER_PROBLEM,
41				"hl: You must specify a value");
42	switch (c) {
43		case '2':
44			if (invert)
45				info->mode = IP6T_HL_NE;
46			else
47				info->mode = IP6T_HL_EQ;
48
49			/* is 0 allowed? */
50			info->hop_limit = value;
51			*flags = 1;
52
53			break;
54		case '3':
55			if (invert)
56				xtables_error(PARAMETER_PROBLEM,
57						"hl: unexpected `!'");
58
59			info->mode = IP6T_HL_LT;
60			info->hop_limit = value;
61			*flags = 1;
62
63			break;
64		case '4':
65			if (invert)
66				xtables_error(PARAMETER_PROBLEM,
67						"hl: unexpected `!'");
68
69			info->mode = IP6T_HL_GT;
70			info->hop_limit = value;
71			*flags = 1;
72
73			break;
74		default:
75			return 0;
76	}
77
78	return 1;
79}
80
81static void hl_check(unsigned int flags)
82{
83	if (!flags)
84		xtables_error(PARAMETER_PROBLEM,
85			"HL match: You must specify one of "
86			"`--hl-eq', `--hl-lt', `--hl-gt'");
87}
88
89static void hl_print(const void *ip, const struct xt_entry_match *match,
90                     int numeric)
91{
92	static const char *const op[] = {
93		[IP6T_HL_EQ] = "==",
94		[IP6T_HL_NE] = "!=",
95		[IP6T_HL_LT] = "<",
96		[IP6T_HL_GT] = ">" };
97
98	const struct ip6t_hl_info *info =
99		(struct ip6t_hl_info *) match->data;
100
101	printf("HL match HL %s %u ", op[info->mode], info->hop_limit);
102}
103
104static void hl_save(const void *ip, const struct xt_entry_match *match)
105{
106	static const char *const op[] = {
107		[IP6T_HL_EQ] = "--hl-eq",
108		[IP6T_HL_NE] = "! --hl-eq",
109		[IP6T_HL_LT] = "--hl-lt",
110		[IP6T_HL_GT] = "--hl-gt" };
111
112	const struct ip6t_hl_info *info =
113		(struct ip6t_hl_info *) match->data;
114
115	printf("%s %u ", op[info->mode], info->hop_limit);
116}
117
118static const struct option hl_opts[] = {
119	{ .name = "hl",    .has_arg = 1, .val = '2' },
120	{ .name = "hl-eq", .has_arg = 1, .val = '2' },
121	{ .name = "hl-lt", .has_arg = 1, .val = '3' },
122	{ .name = "hl-gt", .has_arg = 1, .val = '4' },
123	{ .name = NULL }
124};
125
126static struct xtables_match hl_mt6_reg = {
127	.name          = "hl",
128	.version       = XTABLES_VERSION,
129	.family        = NFPROTO_IPV6,
130	.size          = XT_ALIGN(sizeof(struct ip6t_hl_info)),
131	.userspacesize = XT_ALIGN(sizeof(struct ip6t_hl_info)),
132	.help          = hl_help,
133	.parse         = hl_parse,
134	.final_check   = hl_check,
135	.print         = hl_print,
136	.save          = hl_save,
137	.extra_opts    = hl_opts,
138};
139
140
141void _init(void)
142{
143	xtables_register_match(&hl_mt6_reg);
144}
145