Add missing and or-flush options to "ipfw table <NAME> create"

command to simplify firewall reloading.

The `missing` option suppresses EEXIST error code, but does check that
existing table has the same parameters as new one. The `or-flush` option
implies `missing` option and additionally does flush for table if it
is already exist.

Submitted by:	lev
MFC after:	2 weeks
Differential Revision:	https://reviews.freebsd.org/D18339
This commit is contained in:
Andrey V. Elsukov 2019-05-24 11:06:24 +00:00
parent 2b32abd2b1
commit 05ab1ef64e
3 changed files with 45 additions and 7 deletions

View File

@ -1,7 +1,7 @@
.\" .\"
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd April 21, 2019 .Dd May 24, 2019
.Dt IPFW 8 .Dt IPFW 8
.Os .Os
.Sh NAME .Sh NAME
@ -2138,7 +2138,7 @@ The following creation options are supported:
.Bl -tag -width indent .Bl -tag -width indent
.It Ar create-options : Ar create-option | create-options .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 | .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 .It Cm type
Table key type. Table key type.
.It Cm valtype .It Cm valtype
@ -2149,6 +2149,13 @@ Table algorithm to use (see below).
Maximum number of items that may be inserted into table. Maximum number of items that may be inserted into table.
.It Cm locked .It Cm locked
Restrict any table modifications. 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 .El
.Pp .Pp
Some of these options may be modified later via Some of these options may be modified later via

View File

@ -264,6 +264,9 @@ enum tokens {
TOK_UNLOCK, TOK_UNLOCK,
TOK_VLIST, TOK_VLIST,
TOK_OLIST, TOK_OLIST,
TOK_MISSING,
TOK_ORFLUSH,
TOK_OPTIONAL,
/* NAT64 tokens */ /* NAT64 tokens */
TOK_NAT64STL, TOK_NAT64STL,

View File

@ -327,6 +327,8 @@ static struct _s_x tablenewcmds[] = {
{ "algo", TOK_ALGO }, { "algo", TOK_ALGO },
{ "limit", TOK_LIMIT }, { "limit", TOK_LIMIT },
{ "locked", TOK_LOCK }, { "locked", TOK_LOCK },
{ "missing", TOK_MISSING },
{ "or-flush", TOK_ORFLUSH },
{ NULL, 0 } { NULL, 0 }
}; };
@ -389,19 +391,19 @@ table_print_type(char *tbuf, size_t size, uint8_t type, uint8_t tflags)
* Creates new table * Creates new table
* *
* ipfw table NAME create [ type { addr | iface | number | flow } ] * ipfw table NAME create [ type { addr | iface | number | flow } ]
* [ algo algoname ] * [ algo algoname ] [missing] [or-flush]
*/ */
static void static void
table_create(ipfw_obj_header *oh, int ac, char *av[]) table_create(ipfw_obj_header *oh, int ac, char *av[])
{ {
ipfw_xtable_info xi; ipfw_xtable_info xi, xie;
int error, tcmd, val; int error, missing, orflush, tcmd, val;
uint32_t fset, fclear; uint32_t fset, fclear;
char *e, *p; char *e, *p;
char tbuf[128]; char tbuf[128];
missing = orflush = 0;
memset(&xi, 0, sizeof(xi)); memset(&xi, 0, sizeof(xi));
while (ac > 0) { while (ac > 0) {
tcmd = get_token(tablenewcmds, *av, "option"); tcmd = get_token(tablenewcmds, *av, "option");
ac--; av++; ac--; av++;
@ -457,6 +459,12 @@ table_create(ipfw_obj_header *oh, int ac, char *av[])
case TOK_LOCK: case TOK_LOCK:
xi.flags |= IPFW_TGFLAGS_LOCKED; xi.flags |= IPFW_TGFLAGS_LOCKED;
break; break;
case TOK_ORFLUSH:
orflush = 1;
/* FALLTHROUGH */
case TOK_MISSING:
missing = 1;
break;
} }
} }
@ -466,8 +474,28 @@ table_create(ipfw_obj_header *oh, int ac, char *av[])
if (xi.vmask == 0) if (xi.vmask == 0)
xi.vmask = IPFW_VTYPE_LEGACY; 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"); 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");
} }
/* /*