1 /*
2 * Argument parser
3 * Copyright © Jan Engelhardt, 2011
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or (at your option) any later version.
9 */
10 #include <ctype.h>
11 #include <errno.h>
12 #include <getopt.h>
13 #include <limits.h>
14 #include <netdb.h>
15 #include <stdbool.h>
16 #include <stdint.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <syslog.h>
21 #include <arpa/inet.h>
22 #include <netinet/ip.h>
23 #include "xtables.h"
24 #ifndef IPTOS_NORMALSVC
25 # define IPTOS_NORMALSVC 0
26 #endif
27
28 #define XTOPT_MKPTR(cb) \
29 ((void *)((char *)(cb)->data + (cb)->entry->ptroff))
30
31 /**
32 * Simple key-value pairs for syslog levels
33 */
34 struct syslog_level {
35 char name[8];
36 uint8_t level;
37 };
38
39 struct tos_value_mask {
40 uint8_t value, mask;
41 };
42
43 static const size_t xtopt_psize[] = {
44 /*
45 * All types not listed here, and thus essentially being initialized to
46 * zero have zero on purpose.
47 */
48 [XTTYPE_UINT8] = sizeof(uint8_t),
49 [XTTYPE_UINT16] = sizeof(uint16_t),
50 [XTTYPE_UINT32] = sizeof(uint32_t),
51 [XTTYPE_UINT64] = sizeof(uint64_t),
52 [XTTYPE_UINT8RC] = sizeof(uint8_t[2]),
53 [XTTYPE_UINT16RC] = sizeof(uint16_t[2]),
54 [XTTYPE_UINT32RC] = sizeof(uint32_t[2]),
55 [XTTYPE_UINT64RC] = sizeof(uint64_t[2]),
56 [XTTYPE_DOUBLE] = sizeof(double),
57 [XTTYPE_STRING] = -1,
58 [XTTYPE_SYSLOGLEVEL] = sizeof(uint8_t),
59 [XTTYPE_HOST] = sizeof(union nf_inet_addr),
60 [XTTYPE_HOSTMASK] = sizeof(union nf_inet_addr),
61 [XTTYPE_PROTOCOL] = sizeof(uint8_t),
62 [XTTYPE_PORT] = sizeof(uint16_t),
63 [XTTYPE_PORTRC] = sizeof(uint16_t[2]),
64 [XTTYPE_PLENMASK] = sizeof(union nf_inet_addr),
65 [XTTYPE_ETHERMAC] = sizeof(uint8_t[6]),
66 };
67
68 /**
69 * Creates getopt options from the x6-style option map, and assigns each a
70 * getopt id.
71 */
72 struct option *
xtables_options_xfrm(struct option * orig_opts,struct option * oldopts,const struct xt_option_entry * entry,unsigned int * offset)73 xtables_options_xfrm(struct option *orig_opts, struct option *oldopts,
74 const struct xt_option_entry *entry, unsigned int *offset)
75 {
76 unsigned int num_orig, num_old = 0, num_new, i;
77 struct option *merge, *mp;
78
79 if (entry == NULL)
80 return oldopts;
81 for (num_orig = 0; orig_opts[num_orig].name != NULL; ++num_orig)
82 ;
83 if (oldopts != NULL)
84 for (num_old = 0; oldopts[num_old].name != NULL; ++num_old)
85 ;
86 for (num_new = 0; entry[num_new].name != NULL; ++num_new)
87 ;
88
89 /*
90 * Since @oldopts also has @orig_opts already (and does so at the
91 * start), skip these entries.
92 */
93 if (oldopts != NULL) {
94 oldopts += num_orig;
95 num_old -= num_orig;
96 }
97
98 merge = malloc(sizeof(*mp) * (num_orig + num_old + num_new + 1));
99 if (merge == NULL)
100 return NULL;
101
102 /* Let the base options -[ADI...] have precedence over everything */
103 memcpy(merge, orig_opts, sizeof(*mp) * num_orig);
104 mp = merge + num_orig;
105
106 /* Second, the new options */
107 xt_params->option_offset += XT_OPTION_OFFSET_SCALE;
108 *offset = xt_params->option_offset;
109
110 for (i = 0; i < num_new; ++i, ++mp, ++entry) {
111 mp->name = entry->name;
112 mp->has_arg = entry->type != XTTYPE_NONE;
113 mp->flag = NULL;
114 mp->val = entry->id + *offset;
115 }
116
117 /* Third, the old options */
118 if (oldopts != NULL) {
119 memcpy(mp, oldopts, sizeof(*mp) * num_old);
120 mp += num_old;
121 }
122 xtables_free_opts(0);
123
124 /* Clear trailing entry */
125 memset(mp, 0, sizeof(*mp));
126 return merge;
127 }
128
129 /**
130 * Give the upper limit for a certain type.
131 */
xtopt_max_by_type(enum xt_option_type type)132 static uintmax_t xtopt_max_by_type(enum xt_option_type type)
133 {
134 switch (type) {
135 case XTTYPE_UINT8:
136 case XTTYPE_UINT8RC:
137 return UINT8_MAX;
138 case XTTYPE_UINT16:
139 case XTTYPE_UINT16RC:
140 return UINT16_MAX;
141 case XTTYPE_UINT32:
142 case XTTYPE_UINT32RC:
143 return UINT32_MAX;
144 case XTTYPE_UINT64:
145 case XTTYPE_UINT64RC:
146 return UINT64_MAX;
147 default:
148 return 0;
149 }
150 }
151
152 /**
153 * Return the size of a single entity based upon a type - predominantly an
154 * XTTYPE_UINT*RC type.
155 */
xtopt_esize_by_type(enum xt_option_type type)156 static size_t xtopt_esize_by_type(enum xt_option_type type)
157 {
158 switch (type) {
159 case XTTYPE_UINT8RC:
160 return xtopt_psize[XTTYPE_UINT8];
161 case XTTYPE_UINT16RC:
162 return xtopt_psize[XTTYPE_UINT16];
163 case XTTYPE_UINT32RC:
164 return xtopt_psize[XTTYPE_UINT32];
165 case XTTYPE_UINT64RC:
166 return xtopt_psize[XTTYPE_UINT64];
167 default:
168 return xtopt_psize[type];
169 }
170 }
171
172 /**
173 * Require a simple integer.
174 */
xtopt_parse_int(struct xt_option_call * cb)175 static void xtopt_parse_int(struct xt_option_call *cb)
176 {
177 const struct xt_option_entry *entry = cb->entry;
178 uintmax_t lmin = 0, lmax = xtopt_max_by_type(entry->type);
179 uintmax_t value;
180
181 if (cb->entry->min != 0)
182 lmin = cb->entry->min;
183 if (cb->entry->max != 0)
184 lmax = cb->entry->max;
185
186 if (!xtables_strtoul(cb->arg, NULL, &value, lmin, lmax))
187 xt_params->exit_err(PARAMETER_PROBLEM,
188 "%s: bad value for option \"--%s\", "
189 "or out of range (%ju-%ju).\n",
190 cb->ext_name, entry->name, lmin, lmax);
191
192 if (entry->type == XTTYPE_UINT8) {
193 cb->val.u8 = value;
194 if (entry->flags & XTOPT_PUT)
195 *(uint8_t *)XTOPT_MKPTR(cb) = cb->val.u8;
196 } else if (entry->type == XTTYPE_UINT16) {
197 cb->val.u16 = value;
198 if (entry->flags & XTOPT_PUT)
199 *(uint16_t *)XTOPT_MKPTR(cb) = cb->val.u16;
200 } else if (entry->type == XTTYPE_UINT32) {
201 cb->val.u32 = value;
202 if (entry->flags & XTOPT_PUT)
203 *(uint32_t *)XTOPT_MKPTR(cb) = cb->val.u32;
204 } else if (entry->type == XTTYPE_UINT64) {
205 cb->val.u64 = value;
206 if (entry->flags & XTOPT_PUT)
207 *(uint64_t *)XTOPT_MKPTR(cb) = cb->val.u64;
208 }
209 }
210
211 /**
212 * Require a simple floating point number.
213 */
xtopt_parse_float(struct xt_option_call * cb)214 static void xtopt_parse_float(struct xt_option_call *cb)
215 {
216 const struct xt_option_entry *entry = cb->entry;
217 double value;
218 char *end;
219
220 value = strtod(cb->arg, &end);
221 if (end == cb->arg || *end != '\0' ||
222 (entry->min != entry->max &&
223 (value < entry->min || value > entry->max)))
224 xt_params->exit_err(PARAMETER_PROBLEM,
225 "%s: bad value for option \"--%s\", "
226 "or out of range (%u-%u).\n",
227 cb->ext_name, entry->name, entry->min, entry->max);
228
229 cb->val.dbl = value;
230 if (entry->flags & XTOPT_PUT)
231 *(double *)XTOPT_MKPTR(cb) = cb->val.dbl;
232 }
233
234 /**
235 * Copy the parsed value to the appropriate entry in cb->val.
236 */
xtopt_mint_value_to_cb(struct xt_option_call * cb,uintmax_t value)237 static void xtopt_mint_value_to_cb(struct xt_option_call *cb, uintmax_t value)
238 {
239 const struct xt_option_entry *entry = cb->entry;
240
241 if (cb->nvals >= ARRAY_SIZE(cb->val.u32_range))
242 return;
243 if (entry->type == XTTYPE_UINT8RC)
244 cb->val.u8_range[cb->nvals] = value;
245 else if (entry->type == XTTYPE_UINT16RC)
246 cb->val.u16_range[cb->nvals] = value;
247 else if (entry->type == XTTYPE_UINT32RC)
248 cb->val.u32_range[cb->nvals] = value;
249 else if (entry->type == XTTYPE_UINT64RC)
250 cb->val.u64_range[cb->nvals] = value;
251 }
252
253 /**
254 * Copy the parsed value to the data area, using appropriate type access.
255 */
xtopt_mint_value_to_ptr(struct xt_option_call * cb,void ** datap,uintmax_t value)256 static void xtopt_mint_value_to_ptr(struct xt_option_call *cb, void **datap,
257 uintmax_t value)
258 {
259 const struct xt_option_entry *entry = cb->entry;
260 void *data = *datap;
261
262 if (!(entry->flags & XTOPT_PUT))
263 return;
264 if (entry->type == XTTYPE_UINT8RC)
265 *(uint8_t *)data = value;
266 else if (entry->type == XTTYPE_UINT16RC)
267 *(uint16_t *)data = value;
268 else if (entry->type == XTTYPE_UINT32RC)
269 *(uint32_t *)data = value;
270 else if (entry->type == XTTYPE_UINT64RC)
271 *(uint64_t *)data = value;
272 data += xtopt_esize_by_type(entry->type);
273 *datap = data;
274 }
275
276 /**
277 * Multiple integer parse routine.
278 *
279 * This function is capable of parsing any number of fields. Only the first
280 * two values from the string will be put into @cb however (and as such,
281 * @cb->val.uXX_range is just that large) to cater for the few extensions that
282 * do not have a range[2] field, but {min, max}, and which cannot use
283 * XTOPT_POINTER.
284 */
xtopt_parse_mint(struct xt_option_call * cb)285 static void xtopt_parse_mint(struct xt_option_call *cb)
286 {
287 const struct xt_option_entry *entry = cb->entry;
288 const char *arg;
289 size_t esize = xtopt_esize_by_type(entry->type);
290 const uintmax_t lmax = xtopt_max_by_type(entry->type);
291 void *put = XTOPT_MKPTR(cb);
292 unsigned int maxiter;
293 uintmax_t value;
294 char *end = "";
295 char sep = ':';
296
297 maxiter = entry->size / esize;
298 if (maxiter == 0)
299 maxiter = ARRAY_SIZE(cb->val.u32_range);
300 if (entry->size % esize != 0)
301 xt_params->exit_err(OTHER_PROBLEM, "%s: memory block does "
302 "not have proper size\n", __func__);
303
304 cb->nvals = 0;
305 for (arg = cb->arg, end = (char *)arg; ; arg = end + 1) {
306 if (cb->nvals == maxiter)
307 xt_params->exit_err(PARAMETER_PROBLEM, "%s: Too many "
308 "components for option \"--%s\" (max: %u)\n",
309 cb->ext_name, entry->name, maxiter);
310 if (*arg == '\0' || *arg == sep) {
311 /* Default range components when field not spec'd. */
312 end = (char *)arg;
313 value = (cb->nvals == 1) ? lmax : 0;
314 } else {
315 if (!xtables_strtoul(arg, &end, &value, 0, lmax))
316 xt_params->exit_err(PARAMETER_PROBLEM,
317 "%s: bad value for option \"--%s\" near "
318 "\"%s\", or out of range (0-%ju).\n",
319 cb->ext_name, entry->name, arg, lmax);
320 if (*end != '\0' && *end != sep)
321 xt_params->exit_err(PARAMETER_PROBLEM,
322 "%s: Argument to \"--%s\" has "
323 "unexpected characters near \"%s\".\n",
324 cb->ext_name, entry->name, end);
325 }
326 xtopt_mint_value_to_cb(cb, value);
327 ++cb->nvals;
328 xtopt_mint_value_to_ptr(cb, &put, value);
329 if (*end == '\0')
330 break;
331 }
332 }
333
xtopt_parse_string(struct xt_option_call * cb)334 static void xtopt_parse_string(struct xt_option_call *cb)
335 {
336 const struct xt_option_entry *entry = cb->entry;
337 size_t z = strlen(cb->arg);
338 char *p;
339
340 if (entry->min != 0 && z < entry->min)
341 xt_params->exit_err(PARAMETER_PROBLEM,
342 "Argument must have a minimum length of "
343 "%u characters\n", entry->min);
344 if (entry->max != 0 && z > entry->max)
345 xt_params->exit_err(PARAMETER_PROBLEM,
346 "Argument must have a maximum length of "
347 "%u characters\n", entry->max);
348 if (!(entry->flags & XTOPT_PUT))
349 return;
350 if (z >= entry->size)
351 z = entry->size - 1;
352 p = XTOPT_MKPTR(cb);
353 strncpy(p, cb->arg, z);
354 p[z] = '\0';
355 }
356
357 static const struct tos_symbol_info {
358 unsigned char value;
359 const char *name;
360 } tos_symbol_names[] = {
361 {IPTOS_LOWDELAY, "Minimize-Delay"},
362 {IPTOS_THROUGHPUT, "Maximize-Throughput"},
363 {IPTOS_RELIABILITY, "Maximize-Reliability"},
364 {IPTOS_MINCOST, "Minimize-Cost"},
365 {IPTOS_NORMALSVC, "Normal-Service"},
366 {},
367 };
368
369 /*
370 * tos_parse_numeric - parse a string like "15/255"
371 *
372 * @str: input string
373 * @tvm: (value/mask) tuple
374 * @max: maximum allowed value (must be pow(2,some_int)-1)
375 */
tos_parse_numeric(const char * str,struct xt_option_call * cb,unsigned int max)376 static bool tos_parse_numeric(const char *str, struct xt_option_call *cb,
377 unsigned int max)
378 {
379 unsigned int value;
380 char *end;
381
382 xtables_strtoui(str, &end, &value, 0, max);
383 cb->val.tos_value = value;
384 cb->val.tos_mask = max;
385
386 if (*end == '/') {
387 const char *p = end + 1;
388
389 if (!xtables_strtoui(p, &end, &value, 0, max))
390 xtables_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"",
391 str);
392 cb->val.tos_mask = value;
393 }
394
395 if (*end != '\0')
396 xtables_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"", str);
397 return true;
398 }
399
400 /**
401 * @str: input string
402 * @tvm: (value/mask) tuple
403 * @def_mask: mask to force when a symbolic name is used
404 */
xtopt_parse_tosmask(struct xt_option_call * cb)405 static void xtopt_parse_tosmask(struct xt_option_call *cb)
406 {
407 const struct tos_symbol_info *symbol;
408 char *tmp;
409
410 if (xtables_strtoui(cb->arg, &tmp, NULL, 0, UINT8_MAX)) {
411 tos_parse_numeric(cb->arg, cb, UINT8_MAX);
412 return;
413 }
414 /*
415 * This is our way we deal with different defaults
416 * for different revisions.
417 */
418 cb->val.tos_mask = cb->entry->max;
419 for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol)
420 if (strcasecmp(cb->arg, symbol->name) == 0) {
421 cb->val.tos_value = symbol->value;
422 return;
423 }
424
425 xtables_error(PARAMETER_PROBLEM, "Symbolic name \"%s\" is unknown",
426 cb->arg);
427 }
428
429 /**
430 * Validate the input for being conformant to "mark[/mask]".
431 */
xtopt_parse_markmask(struct xt_option_call * cb)432 static void xtopt_parse_markmask(struct xt_option_call *cb)
433 {
434 xtables_parse_mark_mask(cb, &cb->val.mark, &cb->val.mask);
435 }
436
xtopt_sysloglvl_compare(const void * a,const void * b)437 static int xtopt_sysloglvl_compare(const void *a, const void *b)
438 {
439 const char *name = a;
440 const struct syslog_level *entry = b;
441
442 return strcmp(name, entry->name);
443 }
444
xtopt_parse_sysloglevel(struct xt_option_call * cb)445 static void xtopt_parse_sysloglevel(struct xt_option_call *cb)
446 {
447 static const struct syslog_level log_names[] = { /* must be sorted */
448 {"alert", LOG_ALERT},
449 {"crit", LOG_CRIT},
450 {"debug", LOG_DEBUG},
451 {"emerg", LOG_EMERG},
452 {"error", LOG_ERR}, /* deprecated */
453 {"info", LOG_INFO},
454 {"notice", LOG_NOTICE},
455 {"panic", LOG_EMERG}, /* deprecated */
456 {"warning", LOG_WARNING},
457 };
458 const struct syslog_level *e;
459 unsigned int num = 0;
460
461 if (!xtables_strtoui(cb->arg, NULL, &num, 0, 7)) {
462 e = bsearch(cb->arg, log_names, ARRAY_SIZE(log_names),
463 sizeof(*log_names), xtopt_sysloglvl_compare);
464 if (e == NULL)
465 xt_params->exit_err(PARAMETER_PROBLEM,
466 "log level \"%s\" unknown\n", cb->arg);
467 num = e->level;
468 }
469 cb->val.syslog_level = num;
470 if (cb->entry->flags & XTOPT_PUT)
471 *(uint8_t *)XTOPT_MKPTR(cb) = num;
472 }
473
xtables_sa_host(const void * sa,unsigned int afproto)474 static void *xtables_sa_host(const void *sa, unsigned int afproto)
475 {
476 if (afproto == AF_INET6)
477 return &((struct sockaddr_in6 *)sa)->sin6_addr;
478 else if (afproto == AF_INET)
479 return &((struct sockaddr_in *)sa)->sin_addr;
480 return (void *)sa;
481 }
482
xtables_sa_hostlen(unsigned int afproto)483 static socklen_t xtables_sa_hostlen(unsigned int afproto)
484 {
485 if (afproto == AF_INET6)
486 return sizeof(struct in6_addr);
487 else if (afproto == AF_INET)
488 return sizeof(struct in_addr);
489 return 0;
490 }
491
492 /**
493 * Accepts: a hostname (DNS), or a single inetaddr - without any mask. The
494 * result is stored in @cb->val.haddr. Additionally, @cb->val.hmask and
495 * @cb->val.hlen are set for completeness to the appropriate values.
496 */
xtopt_parse_host(struct xt_option_call * cb)497 static void xtopt_parse_host(struct xt_option_call *cb)
498 {
499 struct addrinfo hints = {.ai_family = afinfo->family};
500 unsigned int adcount = 0;
501 struct addrinfo *res, *p;
502 int ret;
503
504 ret = getaddrinfo(cb->arg, NULL, &hints, &res);
505 if (ret != 0)
506 xt_params->exit_err(PARAMETER_PROBLEM,
507 "getaddrinfo: %s\n", gai_strerror(ret));
508
509 memset(&cb->val.hmask, 0xFF, sizeof(cb->val.hmask));
510 cb->val.hlen = (afinfo->family == NFPROTO_IPV4) ? 32 : 128;
511
512 for (p = res; p != NULL; p = p->ai_next) {
513 if (adcount == 0) {
514 memset(&cb->val.haddr, 0, sizeof(cb->val.haddr));
515 memcpy(&cb->val.haddr,
516 xtables_sa_host(p->ai_addr, p->ai_family),
517 xtables_sa_hostlen(p->ai_family));
518 ++adcount;
519 continue;
520 }
521 if (memcmp(&cb->val.haddr,
522 xtables_sa_host(p->ai_addr, p->ai_family),
523 xtables_sa_hostlen(p->ai_family)) != 0)
524 xt_params->exit_err(PARAMETER_PROBLEM,
525 "%s resolves to more than one address\n",
526 cb->arg);
527 }
528
529 freeaddrinfo(res);
530 if (cb->entry->flags & XTOPT_PUT)
531 /* Validation in xtables_option_metavalidate */
532 memcpy(XTOPT_MKPTR(cb), &cb->val.haddr,
533 sizeof(cb->val.haddr));
534 }
535
536 /**
537 * @name: port name, or number as a string (e.g. "http" or "80")
538 *
539 * Resolve a port name to a number. Returns the port number in integral
540 * form on success, or <0 on error. (errno will not be set.)
541 */
xtables_getportbyname(const char * name)542 static int xtables_getportbyname(const char *name)
543 {
544 struct addrinfo *res = NULL, *p;
545 int ret;
546
547 ret = getaddrinfo(NULL, name, NULL, &res);
548 if (ret != 0)
549 return -1;
550 ret = -1;
551 for (p = res; p != NULL; p = p->ai_next) {
552 if (p->ai_family == AF_INET6) {
553 ret = ((struct sockaddr_in6 *)p->ai_addr)->sin6_port;
554 break;
555 } else if (p->ai_family == AF_INET) {
556 ret = ((struct sockaddr_in *)p->ai_addr)->sin_port;
557 break;
558 }
559 }
560 freeaddrinfo(res);
561 if (ret < 0)
562 return ret;
563 return ntohs(ret);
564 }
565
566 /**
567 * Validate and parse a protocol specification (number or name) by use of
568 * /etc/protocols and put the result into @cb->val.protocol.
569 */
xtopt_parse_protocol(struct xt_option_call * cb)570 static void xtopt_parse_protocol(struct xt_option_call *cb)
571 {
572 cb->val.protocol = xtables_parse_protocol(cb->arg);
573 if (cb->entry->flags & XTOPT_PUT)
574 *(uint8_t *)XTOPT_MKPTR(cb) = cb->val.protocol;
575 }
576
577 /**
578 * Validate and parse a port specification and put the result into
579 * @cb->val.port.
580 */
xtopt_parse_port(struct xt_option_call * cb)581 static void xtopt_parse_port(struct xt_option_call *cb)
582 {
583 const struct xt_option_entry *entry = cb->entry;
584 int ret;
585
586 ret = xtables_getportbyname(cb->arg);
587 if (ret < 0)
588 xt_params->exit_err(PARAMETER_PROBLEM,
589 "Port \"%s\" does not resolve to anything.\n",
590 cb->arg);
591 if (entry->flags & XTOPT_NBO)
592 ret = htons(ret);
593 cb->val.port = ret;
594 if (entry->flags & XTOPT_PUT)
595 *(uint16_t *)XTOPT_MKPTR(cb) = cb->val.port;
596 }
597
xtopt_parse_mport(struct xt_option_call * cb)598 static void xtopt_parse_mport(struct xt_option_call *cb)
599 {
600 static const size_t esize = sizeof(uint16_t);
601 const struct xt_option_entry *entry = cb->entry;
602 char *lo_arg, *wp_arg, *arg;
603 unsigned int maxiter;
604 int value;
605
606 wp_arg = lo_arg = xtables_strdup(cb->arg);
607
608 maxiter = entry->size / esize;
609 if (maxiter == 0)
610 maxiter = 2; /* ARRAY_SIZE(cb->val.port_range) */
611 if (entry->size % esize != 0)
612 xt_params->exit_err(OTHER_PROBLEM, "%s: memory block does "
613 "not have proper size\n", __func__);
614
615 cb->val.port_range[0] = 0;
616 cb->val.port_range[1] = UINT16_MAX;
617 cb->nvals = 0;
618
619 while ((arg = strsep(&wp_arg, ":")) != NULL) {
620 if (cb->nvals == maxiter)
621 xt_params->exit_err(PARAMETER_PROBLEM, "%s: Too many "
622 "components for option \"--%s\" (max: %u)\n",
623 cb->ext_name, entry->name, maxiter);
624 if (*arg == '\0') {
625 ++cb->nvals;
626 continue;
627 }
628
629 value = xtables_getportbyname(arg);
630 if (value < 0)
631 xt_params->exit_err(PARAMETER_PROBLEM,
632 "Port \"%s\" does not resolve to "
633 "anything.\n", arg);
634 if (entry->flags & XTOPT_NBO)
635 value = htons(value);
636 if (cb->nvals < ARRAY_SIZE(cb->val.port_range))
637 cb->val.port_range[cb->nvals] = value;
638 ++cb->nvals;
639 }
640
641 if (cb->nvals == 1) {
642 cb->val.port_range[1] = cb->val.port_range[0];
643 ++cb->nvals;
644 }
645 if (entry->flags & XTOPT_PUT)
646 memcpy(XTOPT_MKPTR(cb), cb->val.port_range, sizeof(uint16_t) *
647 (cb->nvals <= maxiter ? cb->nvals : maxiter));
648 free(lo_arg);
649 }
650
xtopt_parse_mask(struct xt_option_call * cb)651 static int xtopt_parse_mask(struct xt_option_call *cb)
652 {
653 struct addrinfo hints = {.ai_family = afinfo->family,
654 .ai_flags = AI_NUMERICHOST };
655 struct addrinfo *res;
656 int ret;
657
658 ret = getaddrinfo(cb->arg, NULL, &hints, &res);
659 if (ret != 0)
660 return 0;
661
662 memcpy(&cb->val.hmask, xtables_sa_host(res->ai_addr, res->ai_family),
663 xtables_sa_hostlen(res->ai_family));
664
665 switch(afinfo->family) {
666 case AF_INET:
667 cb->val.hlen = xtables_ipmask_to_cidr(&cb->val.hmask.in);
668 break;
669 case AF_INET6:
670 cb->val.hlen = xtables_ip6mask_to_cidr(&cb->val.hmask.in6);
671 break;
672 }
673
674 freeaddrinfo(res);
675 return 1;
676 }
677
678 /**
679 * Parse an integer and ensure it is within the address family's prefix length
680 * limits. The result is stored in @cb->val.hlen.
681 */
xtopt_parse_plen(struct xt_option_call * cb)682 static void xtopt_parse_plen(struct xt_option_call *cb)
683 {
684 const struct xt_option_entry *entry = cb->entry;
685 unsigned int prefix_len = 128; /* happiness is a warm gcc */
686
687 cb->val.hlen = (afinfo->family == NFPROTO_IPV4) ? 32 : 128;
688 if (!xtables_strtoui(cb->arg, NULL, &prefix_len, 0, cb->val.hlen)) {
689 /* Is this mask expressed in full format? e.g. 255.255.255.0 */
690 if (xtopt_parse_mask(cb))
691 return;
692
693 xt_params->exit_err(PARAMETER_PROBLEM,
694 "%s: bad value for option \"--%s\", "
695 "neither a valid network mask "
696 "nor valid CIDR (%u-%u).\n",
697 cb->ext_name, entry->name, 0, cb->val.hlen);
698 }
699 cb->val.hlen = prefix_len;
700 }
701
702 /**
703 * Reuse xtopt_parse_plen for testing the integer. Afterwards convert this to
704 * a bitmask, and make it available through @cb->val.hmask (hlen remains
705 * valid). If %XTOPT_PUT is used, hmask will be copied to the target area.
706 */
xtopt_parse_plenmask(struct xt_option_call * cb)707 static void xtopt_parse_plenmask(struct xt_option_call *cb)
708 {
709 const struct xt_option_entry *entry = cb->entry;
710 uint32_t *mask = cb->val.hmask.all;
711
712 xtopt_parse_plen(cb);
713
714 memset(mask, 0xFF, sizeof(union nf_inet_addr));
715 /* This shifting is AF-independent. */
716 if (cb->val.hlen == 0) {
717 mask[0] = mask[1] = mask[2] = mask[3] = 0;
718 } else if (cb->val.hlen <= 32) {
719 mask[0] <<= 32 - cb->val.hlen;
720 mask[1] = mask[2] = mask[3] = 0;
721 } else if (cb->val.hlen <= 64) {
722 mask[1] <<= 32 - (cb->val.hlen - 32);
723 mask[2] = mask[3] = 0;
724 } else if (cb->val.hlen <= 96) {
725 mask[2] <<= 32 - (cb->val.hlen - 64);
726 mask[3] = 0;
727 } else if (cb->val.hlen <= 128) {
728 mask[3] <<= 32 - (cb->val.hlen - 96);
729 }
730 mask[0] = htonl(mask[0]);
731 mask[1] = htonl(mask[1]);
732 mask[2] = htonl(mask[2]);
733 mask[3] = htonl(mask[3]);
734 if (entry->flags & XTOPT_PUT)
735 memcpy(XTOPT_MKPTR(cb), mask, sizeof(union nf_inet_addr));
736 }
737
xtopt_parse_hostmask(struct xt_option_call * cb)738 static void xtopt_parse_hostmask(struct xt_option_call *cb)
739 {
740 const char *orig_arg = cb->arg;
741 char *work, *p;
742
743 if (strchr(cb->arg, '/') == NULL) {
744 xtopt_parse_host(cb);
745 return;
746 }
747 work = xtables_strdup(orig_arg);
748 p = strchr(work, '/'); /* by def this can't be NULL now */
749 *p++ = '\0';
750 /*
751 * Because xtopt_parse_host and xtopt_parse_plenmask would store
752 * different things in the same target area, XTTYPE_HOSTMASK must
753 * disallow XTOPT_PUT, which it does by forcing its absence,
754 * cf. not being listed in xtopt_psize.
755 */
756 cb->arg = work;
757 xtopt_parse_host(cb);
758 cb->arg = p;
759 xtopt_parse_plenmask(cb);
760 cb->arg = orig_arg;
761 free(work);
762 }
763
xtopt_parse_ethermac(struct xt_option_call * cb)764 static void xtopt_parse_ethermac(struct xt_option_call *cb)
765 {
766 const char *arg = cb->arg;
767 unsigned int i;
768 char *end;
769
770 for (i = 0; i < ARRAY_SIZE(cb->val.ethermac) - 1; ++i) {
771 cb->val.ethermac[i] = strtoul(arg, &end, 16);
772 if (*end != ':' || end - arg > 2)
773 goto out;
774 arg = end + 1;
775 }
776 i = ARRAY_SIZE(cb->val.ethermac) - 1;
777 cb->val.ethermac[i] = strtoul(arg, &end, 16);
778 if (*end != '\0' || end - arg > 2)
779 goto out;
780 if (cb->entry->flags & XTOPT_PUT)
781 memcpy(XTOPT_MKPTR(cb), cb->val.ethermac,
782 sizeof(cb->val.ethermac));
783 return;
784 out:
785 xt_params->exit_err(PARAMETER_PROBLEM, "Invalid MAC address specified.");
786 }
787
788 static void (*const xtopt_subparse[])(struct xt_option_call *) = {
789 [XTTYPE_UINT8] = xtopt_parse_int,
790 [XTTYPE_UINT16] = xtopt_parse_int,
791 [XTTYPE_UINT32] = xtopt_parse_int,
792 [XTTYPE_UINT64] = xtopt_parse_int,
793 [XTTYPE_UINT8RC] = xtopt_parse_mint,
794 [XTTYPE_UINT16RC] = xtopt_parse_mint,
795 [XTTYPE_UINT32RC] = xtopt_parse_mint,
796 [XTTYPE_UINT64RC] = xtopt_parse_mint,
797 [XTTYPE_DOUBLE] = xtopt_parse_float,
798 [XTTYPE_STRING] = xtopt_parse_string,
799 [XTTYPE_TOSMASK] = xtopt_parse_tosmask,
800 [XTTYPE_MARKMASK32] = xtopt_parse_markmask,
801 [XTTYPE_SYSLOGLEVEL] = xtopt_parse_sysloglevel,
802 [XTTYPE_HOST] = xtopt_parse_host,
803 [XTTYPE_HOSTMASK] = xtopt_parse_hostmask,
804 [XTTYPE_PROTOCOL] = xtopt_parse_protocol,
805 [XTTYPE_PORT] = xtopt_parse_port,
806 [XTTYPE_PORTRC] = xtopt_parse_mport,
807 [XTTYPE_PLEN] = xtopt_parse_plen,
808 [XTTYPE_PLENMASK] = xtopt_parse_plenmask,
809 [XTTYPE_ETHERMAC] = xtopt_parse_ethermac,
810 };
811
812 /**
813 * The master option parsing routine. May be used for the ".x6_parse"
814 * function pointer in extensions if fully automatic parsing is desired.
815 * It may be also called manually from a custom x6_parse function.
816 */
xtables_option_parse(struct xt_option_call * cb)817 void xtables_option_parse(struct xt_option_call *cb)
818 {
819 const struct xt_option_entry *entry = cb->entry;
820 unsigned int eflag = 1 << cb->entry->id;
821
822 /*
823 * With {.id = P_FOO, .excl = P_FOO} we can have simple double-use
824 * prevention. Though it turned out that this is too much typing (most
825 * of the options are one-time use only), so now we also have
826 * %XTOPT_MULTI.
827 */
828 if ((!(entry->flags & XTOPT_MULTI) || (entry->excl & eflag)) &&
829 cb->xflags & eflag)
830 xt_params->exit_err(PARAMETER_PROBLEM,
831 "%s: option \"--%s\" can only be used once.\n",
832 cb->ext_name, cb->entry->name);
833 if (cb->invert && !(entry->flags & XTOPT_INVERT))
834 xt_params->exit_err(PARAMETER_PROBLEM,
835 "%s: option \"--%s\" cannot be inverted.\n",
836 cb->ext_name, entry->name);
837 if (entry->type != XTTYPE_NONE && optarg == NULL)
838 xt_params->exit_err(PARAMETER_PROBLEM,
839 "%s: option \"--%s\" requires an argument.\n",
840 cb->ext_name, entry->name);
841 /*
842 * Fill in fallback value for "nvals", in case an extension (as it
843 * happened with libxt_conntrack.2) tries to read it, despite not using
844 * a *RC option type.
845 */
846 cb->nvals = 1;
847 if (entry->type < ARRAY_SIZE(xtopt_subparse) &&
848 xtopt_subparse[entry->type] != NULL)
849 xtopt_subparse[entry->type](cb);
850 /* Exclusion with other flags tested later in finalize. */
851 cb->xflags |= 1 << entry->id;
852 }
853
854 /**
855 * Verifies that an extension's option map descriptor is valid, and ought to
856 * be called right after the extension has been loaded, and before option
857 * merging/xfrm.
858 */
xtables_option_metavalidate(const char * name,const struct xt_option_entry * entry)859 void xtables_option_metavalidate(const char *name,
860 const struct xt_option_entry *entry)
861 {
862 for (; entry->name != NULL; ++entry) {
863 if (entry->id >= CHAR_BIT * sizeof(unsigned int) ||
864 entry->id >= XT_OPTION_OFFSET_SCALE)
865 xt_params->exit_err(OTHER_PROBLEM,
866 "Extension %s uses invalid ID %u\n",
867 name, entry->id);
868 if (!(entry->flags & XTOPT_PUT)) {
869 if (entry->ptroff != 0)
870 xt_params->exit_err(OTHER_PROBLEM,
871 "%s: ptroff for \"--%s\" is non-"
872 "zero but no XTOPT_PUT is specified. "
873 "Oversight?", name, entry->name);
874 continue;
875 }
876 if (entry->type >= ARRAY_SIZE(xtopt_psize) ||
877 xtopt_psize[entry->type] == 0)
878 xt_params->exit_err(OTHER_PROBLEM,
879 "%s: entry type of option \"--%s\" cannot be "
880 "combined with XTOPT_PUT\n",
881 name, entry->name);
882 if (xtopt_psize[entry->type] != -1 &&
883 xtopt_psize[entry->type] != entry->size)
884 xt_params->exit_err(OTHER_PROBLEM,
885 "%s: option \"--%s\" points to a memory block "
886 "of wrong size (expected %zu, got %zu)\n",
887 name, entry->name,
888 xtopt_psize[entry->type], entry->size);
889 }
890 }
891
892 /**
893 * Find an option entry by its id.
894 */
895 static const struct xt_option_entry *
xtables_option_lookup(const struct xt_option_entry * entry,unsigned int id)896 xtables_option_lookup(const struct xt_option_entry *entry, unsigned int id)
897 {
898 for (; entry->name != NULL; ++entry)
899 if (entry->id == id)
900 return entry;
901 return NULL;
902 }
903
904 /**
905 * @c: getopt id (i.e. with offset)
906 * @fw: struct ipt_entry or ip6t_entry
907 *
908 * Dispatch arguments to the appropriate parse function, based upon the
909 * extension's choice of API.
910 */
xtables_option_tpcall(unsigned int c,char ** argv,bool invert,struct xtables_target * t,void * fw)911 void xtables_option_tpcall(unsigned int c, char **argv, bool invert,
912 struct xtables_target *t, void *fw)
913 {
914 struct xt_option_call cb;
915
916 if (t->x6_parse == NULL) {
917 if (t->parse != NULL)
918 t->parse(c - t->option_offset, argv, invert,
919 &t->tflags, fw, &t->t);
920 return;
921 }
922
923 c -= t->option_offset;
924 cb.entry = xtables_option_lookup(t->x6_options, c);
925 if (cb.entry == NULL)
926 xtables_error(OTHER_PROBLEM,
927 "Extension does not know id %u", c);
928 cb.arg = optarg;
929 cb.invert = invert;
930 cb.ext_name = t->name;
931 cb.data = t->t->data;
932 cb.xflags = t->tflags;
933 cb.target = &t->t;
934 cb.xt_entry = fw;
935 cb.udata = t->udata;
936 t->x6_parse(&cb);
937 t->tflags = cb.xflags;
938 }
939
940 /**
941 * @c: getopt id (i.e. with offset)
942 * @fw: struct ipt_entry or ip6t_entry
943 *
944 * Dispatch arguments to the appropriate parse function, based upon the
945 * extension's choice of API.
946 */
xtables_option_mpcall(unsigned int c,char ** argv,bool invert,struct xtables_match * m,void * fw)947 void xtables_option_mpcall(unsigned int c, char **argv, bool invert,
948 struct xtables_match *m, void *fw)
949 {
950 struct xt_option_call cb;
951
952 if (m->x6_parse == NULL) {
953 if (m->parse != NULL)
954 m->parse(c - m->option_offset, argv, invert,
955 &m->mflags, fw, &m->m);
956 return;
957 }
958
959 c -= m->option_offset;
960 cb.entry = xtables_option_lookup(m->x6_options, c);
961 if (cb.entry == NULL)
962 xtables_error(OTHER_PROBLEM,
963 "Extension does not know id %u", c);
964 cb.arg = optarg;
965 cb.invert = invert;
966 cb.ext_name = m->name;
967 cb.data = m->m->data;
968 cb.xflags = m->mflags;
969 cb.match = &m->m;
970 cb.xt_entry = fw;
971 cb.udata = m->udata;
972 m->x6_parse(&cb);
973 m->mflags = cb.xflags;
974 }
975
976 /**
977 * @name: name of extension
978 * @entry: current option (from all ext's entries) being validated
979 * @xflags: flags the extension has collected
980 * @i: conflicting option (id) to test for
981 */
982 static void
xtables_option_fcheck2(const char * name,const struct xt_option_entry * entry,const struct xt_option_entry * other,unsigned int xflags)983 xtables_option_fcheck2(const char *name, const struct xt_option_entry *entry,
984 const struct xt_option_entry *other,
985 unsigned int xflags)
986 {
987 unsigned int ef = 1 << entry->id, of = 1 << other->id;
988
989 if (entry->also & of && !(xflags & of))
990 xt_params->exit_err(PARAMETER_PROBLEM,
991 "%s: option \"--%s\" also requires \"--%s\".\n",
992 name, entry->name, other->name);
993
994 if (!(entry->excl & of))
995 /* Use of entry does not collide with other option, good. */
996 return;
997 if ((xflags & (ef | of)) != (ef | of))
998 /* Conflicting options were not used. */
999 return;
1000
1001 xt_params->exit_err(PARAMETER_PROBLEM,
1002 "%s: option \"--%s\" cannot be used together with \"--%s\".\n",
1003 name, entry->name, other->name);
1004 }
1005
1006 /**
1007 * @name: name of extension
1008 * @xflags: accumulated flags
1009 * @entry: extension's option table
1010 *
1011 * Check that all option constraints have been met. This effectively replaces
1012 * ->final_check of the older API.
1013 */
xtables_options_fcheck(const char * name,unsigned int xflags,const struct xt_option_entry * table)1014 void xtables_options_fcheck(const char *name, unsigned int xflags,
1015 const struct xt_option_entry *table)
1016 {
1017 const struct xt_option_entry *entry, *other;
1018 unsigned int i;
1019
1020 for (entry = table; entry->name != NULL; ++entry) {
1021 if (entry->flags & XTOPT_MAND &&
1022 !(xflags & (1 << entry->id)))
1023 xt_params->exit_err(PARAMETER_PROBLEM,
1024 "%s: option \"--%s\" must be specified\n",
1025 name, entry->name);
1026 if (!(xflags & (1 << entry->id)))
1027 /* Not required, not specified, thus skip. */
1028 continue;
1029
1030 for (i = 0; i < CHAR_BIT * sizeof(entry->id); ++i) {
1031 if (entry->id == i)
1032 /*
1033 * Avoid conflict with self. Multi-use check
1034 * was done earlier in xtables_option_parse.
1035 */
1036 continue;
1037 other = xtables_option_lookup(table, i);
1038 if (other == NULL)
1039 continue;
1040 xtables_option_fcheck2(name, entry, other, xflags);
1041 }
1042 }
1043 }
1044
1045 /**
1046 * Dispatch arguments to the appropriate final_check function, based upon the
1047 * extension's choice of API.
1048 */
xtables_option_tfcall(struct xtables_target * t)1049 void xtables_option_tfcall(struct xtables_target *t)
1050 {
1051 if (t->x6_fcheck != NULL) {
1052 struct xt_fcheck_call cb;
1053
1054 cb.ext_name = t->name;
1055 cb.data = t->t->data;
1056 cb.xflags = t->tflags;
1057 cb.udata = t->udata;
1058 t->x6_fcheck(&cb);
1059 } else if (t->final_check != NULL) {
1060 t->final_check(t->tflags);
1061 }
1062 if (t->x6_options != NULL)
1063 xtables_options_fcheck(t->name, t->tflags, t->x6_options);
1064 }
1065
1066 /**
1067 * Dispatch arguments to the appropriate final_check function, based upon the
1068 * extension's choice of API.
1069 */
xtables_option_mfcall(struct xtables_match * m)1070 void xtables_option_mfcall(struct xtables_match *m)
1071 {
1072 if (m->x6_fcheck != NULL) {
1073 struct xt_fcheck_call cb;
1074
1075 cb.ext_name = m->name;
1076 cb.data = m->m->data;
1077 cb.xflags = m->mflags;
1078 cb.udata = m->udata;
1079 m->x6_fcheck(&cb);
1080 } else if (m->final_check != NULL) {
1081 m->final_check(m->mflags);
1082 }
1083 if (m->x6_options != NULL)
1084 xtables_options_fcheck(m->name, m->mflags, m->x6_options);
1085 }
1086
xtables_lmap_init(const char * file)1087 struct xtables_lmap *xtables_lmap_init(const char *file)
1088 {
1089 struct xtables_lmap *lmap_head = NULL, *lmap_prev = NULL, *lmap_this;
1090 char buf[512];
1091 FILE *fp;
1092 char *cur, *nxt;
1093 int id;
1094
1095 fp = fopen(file, "re");
1096 if (fp == NULL)
1097 return NULL;
1098
1099 while (fgets(buf, sizeof(buf), fp) != NULL) {
1100 cur = buf;
1101 while (isspace(*cur))
1102 ++cur;
1103 if (*cur == '#' || *cur == '\n' || *cur == '\0')
1104 continue;
1105
1106 /* iproute2 allows hex and dec format */
1107 errno = 0;
1108 id = strtoul(cur, &nxt, strncmp(cur, "0x", 2) == 0 ? 16 : 10);
1109 if (nxt == cur || errno != 0)
1110 continue;
1111
1112 /* same boundaries as in iproute2 */
1113 if (id < 0 || id > 255)
1114 continue;
1115 cur = nxt;
1116
1117 if (!isspace(*cur))
1118 continue;
1119 while (isspace(*cur))
1120 ++cur;
1121 if (*cur == '#' || *cur == '\n' || *cur == '\0')
1122 continue;
1123 nxt = cur;
1124 while (*nxt != '\0' && !isspace(*nxt))
1125 ++nxt;
1126 if (nxt == cur)
1127 continue;
1128 *nxt = '\0';
1129
1130 /* found valid data */
1131 lmap_this = malloc(sizeof(*lmap_this));
1132 if (lmap_this == NULL) {
1133 perror("malloc");
1134 goto out;
1135 }
1136 lmap_this->id = id;
1137 lmap_this->name = xtables_strdup(cur);
1138 lmap_this->next = NULL;
1139
1140 if (lmap_prev != NULL)
1141 lmap_prev->next = lmap_this;
1142 else
1143 lmap_head = lmap_this;
1144 lmap_prev = lmap_this;
1145 }
1146
1147 fclose(fp);
1148 return lmap_head;
1149 out:
1150 fclose(fp);
1151 xtables_lmap_free(lmap_head);
1152 return NULL;
1153 }
1154
xtables_lmap_free(struct xtables_lmap * head)1155 void xtables_lmap_free(struct xtables_lmap *head)
1156 {
1157 struct xtables_lmap *next;
1158
1159 for (; head != NULL; head = next) {
1160 next = head->next;
1161 free(head->name);
1162 free(head);
1163 }
1164 }
1165
xtables_lmap_name2id(const struct xtables_lmap * head,const char * name)1166 int xtables_lmap_name2id(const struct xtables_lmap *head, const char *name)
1167 {
1168 for (; head != NULL; head = head->next)
1169 if (strcmp(head->name, name) == 0)
1170 return head->id;
1171 return -1;
1172 }
1173
xtables_lmap_id2name(const struct xtables_lmap * head,int id)1174 const char *xtables_lmap_id2name(const struct xtables_lmap *head, int id)
1175 {
1176 for (; head != NULL; head = head->next)
1177 if (head->id == id)
1178 return head->name;
1179 return NULL;
1180 }
1181