Index: ipfw/ipfw.8 =================================================================== --- ipfw/ipfw.8 +++ ipfw/ipfw.8 @@ -2138,7 +2138,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 @@ -2149,6 +2149,13 @@ 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 table must be compatible with new one. .El .Pp Some of these options may be modified later via Index: ipfw/ipfw2.h =================================================================== --- ipfw/ipfw2.h +++ ipfw/ipfw2.h @@ -264,6 +264,9 @@ TOK_UNLOCK, TOK_VLIST, TOK_OLIST, + TOK_MISSING, + TOK_ORFLUSH, + TOK_OPTIONAL, /* NAT64 tokens */ TOK_NAT64STL, Index: ipfw/tables.c =================================================================== --- ipfw/tables.c +++ ipfw/tables.c @@ -327,6 +327,8 @@ { "algo", TOK_ALGO }, { "limit", TOK_LIMIT }, { "locked", TOK_LOCK }, + { "missing", TOK_MISSING }, + { "or-flush", TOK_ORFLUSH }, { NULL, 0 } }; @@ -389,16 +391,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)); @@ -457,6 +461,13 @@ case TOK_LOCK: xi.flags |= IPFW_TGFLAGS_LOCKED; break; + case TOK_MISSING: + missing = 1; + break; + case TOK_ORFLUSH: + missing = 1; + flush = 1; + break; } } @@ -466,8 +477,29 @@ 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 to do so */ + if (flush != 0 && table_flush(oh) != 0) + err(EX_OSERR, "Table flush on creation failed"); } /*