• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Shared library add-on to ip6tables to add mobility header support. */
2 /*
3  * Copyright (C)2006 USAGI/WIDE Project
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Author:
10  *	Masahide NAKAMURA @USAGI <masahide.nakamura.cz@hitachi.com>
11  *
12  * Based on libip6t_{icmpv6,udp}.c
13  */
14 #include <stdint.h>
15 #include <stdio.h>
16 #include <string.h>
17 #include <stdlib.h>
18 #include <xtables.h>
19 #include <linux/netfilter_ipv6/ip6t_mh.h>
20 #include <linux/netfilter_ipv6/ip6_tables.h>
21 
22 enum {
23 	O_MH_TYPE = 0,
24 };
25 
26 struct mh_name {
27 	const char *name;
28 	uint8_t type;
29 };
30 
31 static const struct mh_name mh_names[] = {
32 	{ "binding-refresh-request", 0, },
33 	/* Alias */ { "brr", 0, },
34 	{ "home-test-init", 1, },
35 	/* Alias */ { "hoti", 1, },
36 	{ "careof-test-init", 2, },
37 	/* Alias */ { "coti", 2, },
38 	{ "home-test", 3, },
39 	/* Alias */ { "hot", 3, },
40 	{ "careof-test", 4, },
41 	/* Alias */ { "cot", 4, },
42 	{ "binding-update", 5, },
43 	/* Alias */ { "bu", 5, },
44 	{ "binding-acknowledgement", 6, },
45 	/* Alias */ { "ba", 6, },
46 	{ "binding-error", 7, },
47 	/* Alias */ { "be", 7, },
48 };
49 
print_types_all(void)50 static void print_types_all(void)
51 {
52 	unsigned int i;
53 	printf("Valid MH types:");
54 
55 	for (i = 0; i < ARRAY_SIZE(mh_names); ++i) {
56 		if (i && mh_names[i].type == mh_names[i-1].type)
57 			printf(" (%s)", mh_names[i].name);
58 		else
59 			printf("\n%s", mh_names[i].name);
60 	}
61 	printf("\n");
62 }
63 
mh_help(void)64 static void mh_help(void)
65 {
66 	printf(
67 "mh match options:\n"
68 "[!] --mh-type type[:type]	match mh type\n");
69 	print_types_all();
70 }
71 
mh_init(struct xt_entry_match * m)72 static void mh_init(struct xt_entry_match *m)
73 {
74 	struct ip6t_mh *mhinfo = (struct ip6t_mh *)m->data;
75 
76 	mhinfo->types[1] = 0xFF;
77 }
78 
name_to_type(const char * name)79 static unsigned int name_to_type(const char *name)
80 {
81 	int namelen = strlen(name);
82 	static const unsigned int limit = ARRAY_SIZE(mh_names);
83 	unsigned int match = limit;
84 	unsigned int i;
85 
86 	for (i = 0; i < limit; i++) {
87 		if (strncasecmp(mh_names[i].name, name, namelen) == 0) {
88 			int len = strlen(mh_names[i].name);
89 			if (match == limit || len == namelen)
90 				match = i;
91 		}
92 	}
93 
94 	if (match != limit) {
95 		return mh_names[match].type;
96 	} else {
97 		unsigned int number;
98 
99 		if (!xtables_strtoui(name, NULL, &number, 0, UINT8_MAX))
100 			xtables_error(PARAMETER_PROBLEM,
101 				      "Invalid MH type `%s'", name);
102 		return number;
103 	}
104 }
105 
parse_mh_types(const char * mhtype,uint8_t * types)106 static void parse_mh_types(const char *mhtype, uint8_t *types)
107 {
108 	char *buffer;
109 	char *cp;
110 
111 	buffer = xtables_strdup(mhtype);
112 	if ((cp = strchr(buffer, ':')) == NULL)
113 		types[0] = types[1] = name_to_type(buffer);
114 	else {
115 		*cp = '\0';
116 		cp++;
117 
118 		types[0] = buffer[0] ? name_to_type(buffer) : 0;
119 		types[1] = cp[0] ? name_to_type(cp) : 0xFF;
120 
121 		if (types[0] > types[1])
122 			xtables_error(PARAMETER_PROBLEM,
123 				   "Invalid MH type range (min > max)");
124 	}
125 	free(buffer);
126 }
127 
mh_parse(struct xt_option_call * cb)128 static void mh_parse(struct xt_option_call *cb)
129 {
130 	struct ip6t_mh *mhinfo = cb->data;
131 
132 	xtables_option_parse(cb);
133 	parse_mh_types(cb->arg, mhinfo->types);
134 	if (cb->invert)
135 		mhinfo->invflags |= IP6T_MH_INV_TYPE;
136 }
137 
type_to_name(uint8_t type)138 static const char *type_to_name(uint8_t type)
139 {
140 	unsigned int i;
141 
142 	for (i = 0; i < ARRAY_SIZE(mh_names); ++i)
143 		if (mh_names[i].type == type)
144 			return mh_names[i].name;
145 
146 	return NULL;
147 }
148 
print_type(uint8_t type,int numeric)149 static void print_type(uint8_t type, int numeric)
150 {
151 	const char *name;
152 	if (numeric || !(name = type_to_name(type)))
153 		printf("%u", type);
154 	else
155 		printf("%s", name);
156 }
157 
skip_types_match(uint8_t min,uint8_t max,bool inv)158 static bool skip_types_match(uint8_t min, uint8_t max, bool inv)
159 {
160 	return min == 0 && max == UINT8_MAX && !inv;
161 }
162 
print_types(uint8_t min,uint8_t max,int invert,int numeric)163 static void print_types(uint8_t min, uint8_t max, int invert, int numeric)
164 {
165 	const char *inv = invert ? "!" : "";
166 
167 	if (!skip_types_match(min, max, invert)) {
168 		printf(" ");
169 		if (min == max) {
170 			printf("%s", inv);
171 			print_type(min, numeric);
172 		} else {
173 			printf("%s", inv);
174 			print_type(min, numeric);
175 			printf(":");
176 			print_type(max, numeric);
177 		}
178 	}
179 }
180 
mh_print(const void * ip,const struct xt_entry_match * match,int numeric)181 static void mh_print(const void *ip, const struct xt_entry_match *match,
182                      int numeric)
183 {
184 	const struct ip6t_mh *mhinfo = (struct ip6t_mh *)match->data;
185 
186 	printf(" mh");
187 	print_types(mhinfo->types[0], mhinfo->types[1],
188 		    mhinfo->invflags & IP6T_MH_INV_TYPE,
189 		    numeric);
190 	if (mhinfo->invflags & ~IP6T_MH_INV_MASK)
191 		printf(" Unknown invflags: 0x%X",
192 		       mhinfo->invflags & ~IP6T_MH_INV_MASK);
193 }
194 
mh_save(const void * ip,const struct xt_entry_match * match)195 static void mh_save(const void *ip, const struct xt_entry_match *match)
196 {
197 	const struct ip6t_mh *mhinfo = (struct ip6t_mh *)match->data;
198 	bool inv_type = mhinfo->invflags & IP6T_MH_INV_TYPE;
199 
200 	if (skip_types_match(mhinfo->types[0], mhinfo->types[1], inv_type))
201 		return;
202 
203 	if (inv_type)
204 		printf(" !");
205 
206 	if (mhinfo->types[0] != mhinfo->types[1])
207 		printf(" --mh-type %u:%u", mhinfo->types[0], mhinfo->types[1]);
208 	else
209 		printf(" --mh-type %u", mhinfo->types[0]);
210 }
211 
mh_xlate(struct xt_xlate * xl,const struct xt_xlate_mt_params * params)212 static int mh_xlate(struct xt_xlate *xl,
213 		    const struct xt_xlate_mt_params *params)
214 {
215 	const struct ip6t_mh *mhinfo = (struct ip6t_mh *)params->match->data;
216 	bool inv_type = mhinfo->invflags & IP6T_MH_INV_TYPE;
217 
218 	if (skip_types_match(mhinfo->types[0], mhinfo->types[1], inv_type)) {
219 		xt_xlate_add(xl, "exthdr mh exists");
220 		return 1;
221 	}
222 
223 	if (mhinfo->types[0] != mhinfo->types[1])
224 		xt_xlate_add(xl, "mh type %s%u-%u",
225 			     mhinfo->invflags & IP6T_MH_INV_TYPE ? "!= " : "",
226 			     mhinfo->types[0], mhinfo->types[1]);
227 	else
228 		xt_xlate_add(xl, "mh type %s%u",
229 			     mhinfo->invflags & IP6T_MH_INV_TYPE ? "!= " : "",
230 			     mhinfo->types[0]);
231 
232 	return 1;
233 }
234 
235 static const struct xt_option_entry mh_opts[] = {
236 	{.name = "mh-type", .id = O_MH_TYPE, .type = XTTYPE_STRING,
237 	 .flags = XTOPT_INVERT},
238 	XTOPT_TABLEEND,
239 };
240 
241 static struct xtables_match mh_mt6_reg = {
242 	.name		= "mh",
243 	.version	= XTABLES_VERSION,
244 	.family		= NFPROTO_IPV6,
245 	.size		= XT_ALIGN(sizeof(struct ip6t_mh)),
246 	.userspacesize	= XT_ALIGN(sizeof(struct ip6t_mh)),
247 	.help		= mh_help,
248 	.init		= mh_init,
249 	.x6_parse	= mh_parse,
250 	.print		= mh_print,
251 	.save		= mh_save,
252 	.x6_options	= mh_opts,
253 	.xlate		= mh_xlate,
254 };
255 
_init(void)256 void _init(void)
257 {
258 	xtables_register_match(&mh_mt6_reg);
259 }
260