xref: /aosp_15_r20/external/iptables/extensions/libxt_icmp.h (revision a71a954618bbadd4a345637e5edcf36eec826889)
1 static const struct xt_icmp_names {
2 	const char *name;
3 	uint8_t type;
4 	uint8_t code_min, code_max;
5 } icmp_codes[] = {
6 	{ "any", 0xFF, 0, 0xFF },
7 	{ "echo-reply", 0, 0, 0xFF },
8 	/* Alias */ { "pong", 0, 0, 0xFF },
9 
10 	{ "destination-unreachable", 3, 0, 0xFF },
11 	{   "network-unreachable", 3, 0, 0 },
12 	{   "host-unreachable", 3, 1, 1 },
13 	{   "protocol-unreachable", 3, 2, 2 },
14 	{   "port-unreachable", 3, 3, 3 },
15 	{   "fragmentation-needed", 3, 4, 4 },
16 	{   "source-route-failed", 3, 5, 5 },
17 	{   "network-unknown", 3, 6, 6 },
18 	{   "host-unknown", 3, 7, 7 },
19 	{   "network-prohibited", 3, 9, 9 },
20 	{   "host-prohibited", 3, 10, 10 },
21 	{   "TOS-network-unreachable", 3, 11, 11 },
22 	{   "TOS-host-unreachable", 3, 12, 12 },
23 	{   "communication-prohibited", 3, 13, 13 },
24 	{   "host-precedence-violation", 3, 14, 14 },
25 	{   "precedence-cutoff", 3, 15, 15 },
26 
27 	{ "source-quench", 4, 0, 0xFF },
28 
29 	{ "redirect", 5, 0, 0xFF },
30 	{   "network-redirect", 5, 0, 0 },
31 	{   "host-redirect", 5, 1, 1 },
32 	{   "TOS-network-redirect", 5, 2, 2 },
33 	{   "TOS-host-redirect", 5, 3, 3 },
34 
35 	{ "echo-request", 8, 0, 0xFF },
36 	/* Alias */ { "ping", 8, 0, 0xFF },
37 
38 	{ "router-advertisement", 9, 0, 0xFF },
39 
40 	{ "router-solicitation", 10, 0, 0xFF },
41 
42 	{ "time-exceeded", 11, 0, 0xFF },
43 	/* Alias */ { "ttl-exceeded", 11, 0, 0xFF },
44 	{   "ttl-zero-during-transit", 11, 0, 0 },
45 	{   "ttl-zero-during-reassembly", 11, 1, 1 },
46 
47 	{ "parameter-problem", 12, 0, 0xFF },
48 	{   "ip-header-bad", 12, 0, 0 },
49 	{   "required-option-missing", 12, 1, 1 },
50 
51 	{ "timestamp-request", 13, 0, 0xFF },
52 
53 	{ "timestamp-reply", 14, 0, 0xFF },
54 
55 	{ "address-mask-request", 17, 0, 0xFF },
56 
57 	{ "address-mask-reply", 18, 0, 0xFF }
58 }, icmpv6_codes[] = {
59 	{ "destination-unreachable", 1, 0, 0xFF },
60 	{   "no-route", 1, 0, 0 },
61 	{   "communication-prohibited", 1, 1, 1 },
62 	{   "beyond-scope", 1, 2, 2 },
63 	{   "address-unreachable", 1, 3, 3 },
64 	{   "port-unreachable", 1, 4, 4 },
65 	{   "failed-policy", 1, 5, 5 },
66 	{   "reject-route", 1, 6, 6 },
67 
68 	{ "packet-too-big", 2, 0, 0xFF },
69 
70 	{ "time-exceeded", 3, 0, 0xFF },
71 	/* Alias */ { "ttl-exceeded", 3, 0, 0xFF },
72 	{   "ttl-zero-during-transit", 3, 0, 0 },
73 	{   "ttl-zero-during-reassembly", 3, 1, 1 },
74 
75 	{ "parameter-problem", 4, 0, 0xFF },
76 	{   "bad-header", 4, 0, 0 },
77 	{   "unknown-header-type", 4, 1, 1 },
78 	{   "unknown-option", 4, 2, 2 },
79 
80 	{ "echo-request", 128, 0, 0xFF },
81 	/* Alias */ { "ping", 128, 0, 0xFF },
82 
83 	{ "echo-reply", 129, 0, 0xFF },
84 	/* Alias */ { "pong", 129, 0, 0xFF },
85 
86 	{ "mld-listener-query", 130, 0, 0xFF },
87 
88 	{ "mld-listener-report", 131, 0, 0xFF },
89 
90 	{ "mld-listener-done", 132, 0, 0xFF },
91 	/* Alias */ { "mld-listener-reduction", 132, 0, 0xFF },
92 
93 	{ "router-solicitation", 133, 0, 0xFF },
94 
95 	{ "router-advertisement", 134, 0, 0xFF },
96 
97 	{ "neighbour-solicitation", 135, 0, 0xFF },
98 	/* Alias */ { "neighbor-solicitation", 135, 0, 0xFF },
99 
100 	{ "neighbour-advertisement", 136, 0, 0xFF },
101 	/* Alias */ { "neighbor-advertisement", 136, 0, 0xFF },
102 
103 	{ "redirect", 137, 0, 0xFF },
104 }, igmp_types[] = {
105 	{ "membership-query", 0x11 },
106 	{ "membership-report-v1", 0x12 },
107 	{ "membership-report-v2", 0x16 },
108 	{ "leave-group", 0x17 },
109 	{ "membership-report-v3", 0x22 },
110 };
111 
parse_range(const char * str,unsigned int res[])112 static inline char *parse_range(const char *str, unsigned int res[])
113 {
114 	char *next;
115 
116 	if (!xtables_strtoui(str, &next, &res[0], 0, 255))
117 		return NULL;
118 
119 	res[1] = res[0];
120 	if (*next == ':') {
121 		str = next + 1;
122 		if (!xtables_strtoui(str, &next, &res[1], 0, 255))
123 			return NULL;
124 	}
125 
126 	return next;
127 }
128 
129 static void
__parse_icmp(const struct xt_icmp_names codes[],size_t n_codes,const char * codes_name,const char * fmtstring,uint8_t type[],uint8_t code[])130 __parse_icmp(const struct xt_icmp_names codes[], size_t n_codes,
131 	     const char *codes_name, const char *fmtstring,
132 	     uint8_t type[], uint8_t code[])
133 {
134 	unsigned int match = n_codes;
135 	unsigned int i, number[2];
136 
137 	for (i = 0; i < n_codes; i++) {
138 		if (strncasecmp(codes[i].name, fmtstring, strlen(fmtstring)))
139 			continue;
140 		if (match != n_codes)
141 			xtables_error(PARAMETER_PROBLEM,
142 				      "Ambiguous %s type `%s': `%s' or `%s'?",
143 				      codes_name, fmtstring, codes[match].name,
144 				      codes[i].name);
145 		match = i;
146 	}
147 
148 	if (match < n_codes) {
149 		type[0] = type[1] = codes[match].type;
150 		if (code) {
151 			code[0] = codes[match].code_min;
152 			code[1] = codes[match].code_max;
153 		}
154 	} else {
155 		char *next = parse_range(fmtstring, number);
156 		if (!next)
157 			xtables_error(PARAMETER_PROBLEM, "Unknown %s type `%s'",
158 				      codes_name, fmtstring);
159 		type[0] = (uint8_t) number[0];
160 		type[1] = (uint8_t) number[1];
161 		switch (*next) {
162 		case 0:
163 			if (code) {
164 				code[0] = 0;
165 				code[1] = 255;
166 			}
167 			return;
168 		case '/':
169 			if (!code)
170 				break;
171 
172 			next = parse_range(next + 1, number);
173 			if (!next)
174 				xtables_error(PARAMETER_PROBLEM,
175 					      "Unknown %s code `%s'",
176 					      codes_name, fmtstring);
177 			code[0] = (uint8_t) number[0];
178 			code[1] = (uint8_t) number[1];
179 			if (!*next)
180 				break;
181 		/* fallthrough */
182 		default:
183 			xtables_error(PARAMETER_PROBLEM,
184 				      "unknown character %c", *next);
185 		}
186 	}
187 }
188 
189 static inline void
__ipt_parse_icmp(const struct xt_icmp_names * codes,size_t n_codes,const char * codes_name,const char * fmtstr,uint8_t * type,uint8_t code[])190 __ipt_parse_icmp(const struct xt_icmp_names *codes, size_t n_codes,
191 		 const char *codes_name, const char *fmtstr,
192 		 uint8_t *type, uint8_t code[])
193 {
194 	uint8_t types[2];
195 
196 	__parse_icmp(codes, n_codes, codes_name, fmtstr, types, code);
197 	if (types[1] != types[0])
198 		xtables_error(PARAMETER_PROBLEM,
199 			      "%s type range not supported", codes_name);
200 	*type = types[0];
201 }
202 
203 static inline void
ipt_parse_icmp(const char * str,uint8_t * type,uint8_t code[])204 ipt_parse_icmp(const char *str, uint8_t *type, uint8_t code[])
205 {
206 	__ipt_parse_icmp(icmp_codes, ARRAY_SIZE(icmp_codes),
207 			 "ICMP", str, type, code);
208 }
209 
210 static inline void
ipt_parse_icmpv6(const char * str,uint8_t * type,uint8_t code[])211 ipt_parse_icmpv6(const char *str, uint8_t *type, uint8_t code[])
212 {
213 	__ipt_parse_icmp(icmpv6_codes, ARRAY_SIZE(icmpv6_codes),
214 			 "ICMPv6", str, type, code);
215 }
216 
217 static inline void
ebt_parse_icmp(const char * str,uint8_t type[],uint8_t code[])218 ebt_parse_icmp(const char *str, uint8_t type[], uint8_t code[])
219 {
220 	__parse_icmp(icmp_codes, ARRAY_SIZE(icmp_codes),
221 		     "ICMP", str, type, code);
222 }
223 
224 static inline void
ebt_parse_icmpv6(const char * str,uint8_t type[],uint8_t code[])225 ebt_parse_icmpv6(const char *str, uint8_t type[], uint8_t code[])
226 {
227 	__parse_icmp(icmpv6_codes, ARRAY_SIZE(icmpv6_codes),
228 		     "ICMPv6", str, type, code);
229 }
230 
231 static inline void
ebt_parse_igmp(const char * str,uint8_t type[])232 ebt_parse_igmp(const char *str, uint8_t type[])
233 {
234 	__parse_icmp(igmp_types, ARRAY_SIZE(igmp_types),
235 		     "IGMP", str, type, NULL);
236 }
237 
xt_print_icmp_types(const struct xt_icmp_names * _icmp_codes,unsigned int n_codes)238 static void xt_print_icmp_types(const struct xt_icmp_names *_icmp_codes,
239 				unsigned int n_codes)
240 {
241 	unsigned int i;
242 
243 	for (i = 0; i < n_codes; ++i) {
244 		if (i && _icmp_codes[i].type == _icmp_codes[i-1].type) {
245 			if (_icmp_codes[i].code_min == _icmp_codes[i-1].code_min
246 			    && (_icmp_codes[i].code_max
247 				== _icmp_codes[i-1].code_max))
248 				printf(" (%s)", _icmp_codes[i].name);
249 			else
250 				printf("\n   %s", _icmp_codes[i].name);
251 		}
252 		else
253 			printf("\n%s", _icmp_codes[i].name);
254 	}
255 	printf("\n");
256 }
257