aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander V. Chernikov <melifaro@FreeBSD.org>2015-05-19 18:29:13 +0000
committerAlexander V. Chernikov <melifaro@FreeBSD.org>2015-05-19 18:29:13 +0000
commit8755aff6c9610af543b991f65612316b032ec893 (patch)
tree035b5e329874b03eb20134d5da5df5d80b953e7d
parent4ec5fcbe09a494aeff0ca06adcda55ea6d330064 (diff)
downloadsrc-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.c98
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);