Index: head/sbin/ipfw/ipfw.8 =================================================================== --- head/sbin/ipfw/ipfw.8 +++ head/sbin/ipfw/ipfw.8 @@ -1,7 +1,7 @@ .\" .\" $FreeBSD$ .\" -.Dd April 21, 2019 +.Dd May 24, 2019 .Dt IPFW 8 .Os .Sh NAME @@ -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 +Do not 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: head/sbin/ipfw/ipfw2.h =================================================================== --- head/sbin/ipfw/ipfw2.h +++ head/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: head/sbin/ipfw/tables.c =================================================================== --- head/sbin/ipfw/tables.c +++ head/sbin/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,19 +391,19 @@ * 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; - int error, tcmd, val; + ipfw_xtable_info xi, xie; + int error, missing, orflush, tcmd, val; uint32_t fset, fclear; char *e, *p; char tbuf[128]; + missing = orflush = 0; memset(&xi, 0, sizeof(xi)); - while (ac > 0) { tcmd = get_token(tablenewcmds, *av, "option"); ac--; av++; @@ -457,6 +459,12 @@ case TOK_LOCK: xi.flags |= IPFW_TGFLAGS_LOCKED; break; + case TOK_ORFLUSH: + orflush = 1; + /* FALLTHROUGH */ + case TOK_MISSING: + missing = 1; + break; } } @@ -466,8 +474,28 @@ 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 == 0) err(EX_OSERR, "Table creation failed"); + + /* Check that existing table is the same we are trying 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) + errx(EX_DATAERR, "The existing table is not compatible " + "with one you are creating."); + + /* Flush existing table if instructed to do so */ + if (orflush != 0 && table_flush(oh) != 0) + err(EX_OSERR, "Table flush on creation failed"); } /*