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
This commit is contained in:
parent
57bd5e2704
commit
cf1bb4659c
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user