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