Index: sbin/ipfw/ipfw.8 =================================================================== --- sbin/ipfw/ipfw.8 +++ sbin/ipfw/ipfw.8 @@ -1,7 +1,7 @@ .\" .\" $FreeBSD$ .\" -.Dd November 13, 2018 +.Dd November 27, 2018 .Dt IPFW 8 .Os .Sh NAME @@ -2119,7 +2119,7 @@ .Bl -tag -width indent .It Ar create-options : Ar create-option | create-options .It Ar create-option : Cm type Ar table-type | Cm valtype Ar value-mask | Cm algo Ar algo-desc | -.Cm limit Ar number | Cm locked +.Cm limit Ar number | Cm locked | Cm missing | Cm or-flush .It Cm type Table key type. .It Cm valtype @@ -2130,6 +2130,12 @@ Maximum number of items that may be inserted into table. .It Cm locked Restrict any table modifications. +.It Cm missing +Don't fail if table already exists and has exactly same options as new one. +.It Cm or-flush +Flush existing table with same name instead of returning error. Implies +.Cm missing +so existing tabel must be compatible with new one. .El .Pp Some of these options may be modified later via Index: sbin/ipfw/ipfw2.h =================================================================== --- sbin/ipfw/ipfw2.h +++ sbin/ipfw/ipfw2.h @@ -264,6 +264,9 @@ TOK_UNLOCK, TOK_VLIST, TOK_OLIST, + TOK_MISSING, + TOK_ORFLUSH, + TOK_OPTIONAL, /* NAT64 tokens */ TOK_NAT64STL, Index: sbin/ipfw/tables.c =================================================================== --- sbin/ipfw/tables.c +++ sbin/ipfw/tables.c @@ -326,6 +326,8 @@ { "algo", TOK_ALGO }, { "limit", TOK_LIMIT }, { "locked", TOK_LOCK }, + { "missing", TOK_MISSING }, + { "or-flush", TOK_ORFLUSH }, { NULL, 0 } }; @@ -388,16 +390,18 @@ * Creates new table * * ipfw table NAME create [ type { addr | iface | number | flow } ] - * [ algo algoname ] + * [ algo algoname ] [missing] [or-flush] */ static void table_create(ipfw_obj_header *oh, int ac, char *av[]) { - ipfw_xtable_info xi; + ipfw_xtable_info xi, xie; int error, tcmd, val; uint32_t fset, fclear; char *e, *p; char tbuf[128]; + int missing = 0; + int flush = 0; memset(&xi, 0, sizeof(xi)); @@ -456,6 +460,13 @@ case TOK_LOCK: xi.flags |= IPFW_TGFLAGS_LOCKED; break; + case TOK_MISSING: + missing = 1; + break; + case TOK_ORFLUSH: + missing = 1; + flush = 1; + break; } } @@ -465,8 +476,30 @@ if (xi.vmask == 0) xi.vmask = IPFW_VTYPE_LEGACY; - if ((error = table_do_create(oh, &xi)) != 0) + error = table_do_create(oh, &xi); + + if (error == 0) + return; + + if (errno != EEXIST || !missing) err(EX_OSERR, "Table creation failed"); + + /* Check that existing table as same we try to create */ + if (table_get_info(oh, &xie) != 0) + err(EX_OSERR, "Existing table check failed"); + + if (xi.limit != xie.limit || + xi.type != xie.type || + xi.tflags != xie.tflags || + xi.vmask != xie.vmask || + (xi.algoname[0] != '\0' && strcmp(xi.algoname, xie.algoname) != 0) || + xi.flags != xie.flags) + err(EX_OSERR, "Existing table is incompatible with created one"); + + /* Flush existing table if instructed so */ + if (flush != 0) + if (table_flush(oh) != 0) + err(EX_OSERR, "Table flush on creation failed"); } /*