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