diff options
author | Alexander V. Chernikov <melifaro@FreeBSD.org> | 2015-05-19 18:29:13 +0000 |
---|---|---|
committer | Alexander V. Chernikov <melifaro@FreeBSD.org> | 2015-05-19 18:29:13 +0000 |
commit | 8755aff6c9610af543b991f65612316b032ec893 (patch) | |
tree | 035b5e329874b03eb20134d5da5df5d80b953e7d | |
parent | 4ec5fcbe09a494aeff0ca06adcda55ea6d330064 (diff) | |
download | src-8755aff6c9610af543b991f65612316b032ec893.tar.gz src-8755aff6c9610af543b991f65612316b032ec893.zip |
Bring back support for checking tables via "ipfw -n".
Currently we have different table key types which can easily interfere
with each other (numbers and IPv4 address, interface names and hostnames,
flows and hostnames/addresses).
This conflicts are solved by [auto-]creating _typed_ tables, so after
table is created, only keys of given type can be inserted to that table.
ipfw(8) consults with kernel about key/value type for particular table so
it knows key/value interpretation.
However, we have 2 cases (adding entries to non-existing table and
parsing configuration file via `ipfw -n`) when kernel is unable to
provide us table info we need. Fix the latter case by partially importing
old `table_fill_xentry()` parse function responsible for guessing key type.
Sponsored by: Yandex LLC
Notes
Notes:
svn path=/head/; revision=283118
-rw-r--r-- | sbin/ipfw/tables.c | 98 |
1 files changed, 80 insertions, 18 deletions
diff --git a/sbin/ipfw/tables.c b/sbin/ipfw/tables.c index 594c28d17867..b3473fc15575 100644 --- a/sbin/ipfw/tables.c +++ b/sbin/ipfw/tables.c @@ -1310,6 +1310,63 @@ tentry_fill_key_type(char *arg, ipfw_obj_tentry *tentry, uint8_t type, tentry->masklen = masklen; } +/* + * Tries to guess table key type. + * This procedure is used in legacy table auto-create + * code AND in `ipfw -n` ruleset checking. + * + * Imported from old table_fill_xentry() parse code. + */ +static int +guess_key_type(char *key, uint8_t *ptype) +{ + char *p; + struct in6_addr addr; + uint32_t kv; + + if (ishexnumber(*key) != 0 || *key == ':') { + /* Remove / if exists */ + if ((p = strchr(key, '/')) != NULL) + *p = '\0'; + + if ((inet_pton(AF_INET, key, &addr) == 1) || + (inet_pton(AF_INET6, key, &addr) == 1)) { + *ptype = IPFW_TABLE_CIDR; + if (p != NULL) + *p = '/'; + return (0); + } else { + /* Port or any other key */ + /* Skip non-base 10 entries like 'fa1' */ + kv = strtol(key, &p, 10); + if (*p == '\0') { + *ptype = IPFW_TABLE_NUMBER; + return (0); + } else if ((p != key) && (*p == '.')) { + /* + * Warn on IPv4 address strings + * which are "valid" for inet_aton() but not + * in inet_pton(). + * + * Typical examples: '10.5' or '10.0.0.05' + */ + return (1); + } + } + } + + if (strchr(key, '.') == NULL) { + *ptype = IPFW_TABLE_INTERFACE; + return (0); + } + + if (lookup_host(key, (struct in_addr *)&addr) != 0) + return (1); + + *ptype = IPFW_TABLE_CIDR; + return (0); +} + static void tentry_fill_key(ipfw_obj_header *oh, ipfw_obj_tentry *tent, char *key, int add, uint8_t *ptype, uint32_t *pvmask, ipfw_xtable_info *xi) @@ -1317,7 +1374,6 @@ tentry_fill_key(ipfw_obj_header *oh, ipfw_obj_tentry *tent, char *key, uint8_t type, tflags; uint32_t vmask; int error; - char *del; type = 0; tflags = 0; @@ -1329,10 +1385,24 @@ tentry_fill_key(ipfw_obj_header *oh, ipfw_obj_tentry *tent, char *key, error = 0; if (error == 0) { - /* Table found. */ - type = xi->type; - tflags = xi->tflags; - vmask = xi->vmask; + if (co.test_only == 0) { + /* Table found */ + type = xi->type; + tflags = xi->tflags; + vmask = xi->vmask; + } else { + /* + * we're running `ipfw -n` + * Compability layer: try to guess key type + * before failing. + */ + if (guess_key_type(key, &type) != 0) { + /* Inknown key */ + errx(EX_USAGE, "Cannot guess " + "key '%s' type", key); + } + vmask = IPFW_VTYPE_LEGACY; + } } else { if (error != ESRCH) errx(EX_OSERR, "Error requesting table %s info", @@ -1341,24 +1411,16 @@ tentry_fill_key(ipfw_obj_header *oh, ipfw_obj_tentry *tent, char *key, errx(EX_DATAERR, "Table %s does not exist", oh->ntlv.name); /* - * Table does not exist. - * Compability layer: try to interpret data as ADDR - * before failing. + * Table does not exist + * Compability layer: try to guess key type before failing. */ - if ((del = strchr(key, '/')) != NULL) - *del = '\0'; - if (inet_pton(AF_INET, key, &tent->k.addr6) == 1 || - inet_pton(AF_INET6, key, &tent->k.addr6) == 1) { - /* OK Prepare and send */ - type = IPFW_TABLE_ADDR; - vmask = IPFW_VTYPE_LEGACY; - } else { + if (guess_key_type(key, &type) != 0) { /* Inknown key */ errx(EX_USAGE, "Table %s does not exist, cannot guess " "key '%s' type", oh->ntlv.name, key); } - if (del != NULL) - *del = '/'; + + vmask = IPFW_VTYPE_LEGACY; } tentry_fill_key_type(key, tent, type, tflags); |