* Add IP_FW_TABLE_XMODIFY opcode
* Since there seems to be lack of consensus on strict value typing, remove non-default value types. Use userland-only "value format type" to print values. Kernel changes: * Add IP_FW_XMODIFY to permit table run-time modifications. Currently we support changing limit and value format type. Userland changes: * Support IP_FW_XMODIFY opcode. * Support specifying value format type (ftype) in tablble create/modify req * Fine-print value type/value format type.
This commit is contained in:
parent
28ea4fa355
commit
adf3b2b9d8
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/ipfw/; revision=269706
@ -215,6 +215,7 @@ enum tokens {
|
|||||||
TOK_LIST,
|
TOK_LIST,
|
||||||
TOK_INFO,
|
TOK_INFO,
|
||||||
TOK_DETAIL,
|
TOK_DETAIL,
|
||||||
|
TOK_MODIFY,
|
||||||
TOK_FLUSH,
|
TOK_FLUSH,
|
||||||
TOK_SWAP,
|
TOK_SWAP,
|
||||||
TOK_ADD,
|
TOK_ADD,
|
||||||
@ -222,6 +223,7 @@ enum tokens {
|
|||||||
TOK_VALTYPE,
|
TOK_VALTYPE,
|
||||||
TOK_ALGO,
|
TOK_ALGO,
|
||||||
TOK_TALIST,
|
TOK_TALIST,
|
||||||
|
TOK_FTYPE,
|
||||||
};
|
};
|
||||||
/*
|
/*
|
||||||
* the following macro returns an error message if we run out of
|
* the following macro returns an error message if we run out of
|
||||||
|
@ -54,9 +54,11 @@ static void table_modify_record(ipfw_obj_header *oh, int ac, char *av[],
|
|||||||
static int table_flush(ipfw_obj_header *oh);
|
static int table_flush(ipfw_obj_header *oh);
|
||||||
static int table_destroy(ipfw_obj_header *oh);
|
static int table_destroy(ipfw_obj_header *oh);
|
||||||
static int table_do_create(ipfw_obj_header *oh, ipfw_xtable_info *i);
|
static int table_do_create(ipfw_obj_header *oh, ipfw_xtable_info *i);
|
||||||
static void table_create(ipfw_obj_header *oh, int ac, char *av[]);
|
static int table_do_modify(ipfw_obj_header *oh, ipfw_xtable_info *i);
|
||||||
static void table_lookup(ipfw_obj_header *oh, int ac, char *av[]);
|
|
||||||
static int table_do_swap(ipfw_obj_header *oh, char *second);
|
static int table_do_swap(ipfw_obj_header *oh, char *second);
|
||||||
|
static void table_create(ipfw_obj_header *oh, int ac, char *av[]);
|
||||||
|
static void table_modify(ipfw_obj_header *oh, int ac, char *av[]);
|
||||||
|
static void table_lookup(ipfw_obj_header *oh, int ac, char *av[]);
|
||||||
static int table_swap(ipfw_obj_header *oh, char *second);
|
static int table_swap(ipfw_obj_header *oh, char *second);
|
||||||
static int table_get_info(ipfw_obj_header *oh, ipfw_xtable_info *i);
|
static int table_get_info(ipfw_obj_header *oh, ipfw_xtable_info *i);
|
||||||
static int table_show_info(ipfw_xtable_info *i, void *arg);
|
static int table_show_info(ipfw_xtable_info *i, void *arg);
|
||||||
@ -90,18 +92,23 @@ static struct _s_x tabletypes[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static struct _s_x tablevaltypes[] = {
|
static struct _s_x tablevaltypes[] = {
|
||||||
{ "dscp", IPFW_VTYPE_DSCP },
|
|
||||||
{ "ip", IPFW_VTYPE_IP },
|
|
||||||
{ "number", IPFW_VTYPE_U32 },
|
{ "number", IPFW_VTYPE_U32 },
|
||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct _s_x tablefvaltypes[] = {
|
||||||
|
{ "ip", IPFW_VFTYPE_IP },
|
||||||
|
{ "number", IPFW_VFTYPE_U32 },
|
||||||
|
{ NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
static struct _s_x tablecmds[] = {
|
static struct _s_x tablecmds[] = {
|
||||||
{ "add", TOK_ADD },
|
{ "add", TOK_ADD },
|
||||||
{ "delete", TOK_DEL },
|
{ "delete", TOK_DEL },
|
||||||
{ "create", TOK_CREATE },
|
{ "create", TOK_CREATE },
|
||||||
{ "destroy", TOK_DESTROY },
|
{ "destroy", TOK_DESTROY },
|
||||||
{ "flush", TOK_FLUSH },
|
{ "flush", TOK_FLUSH },
|
||||||
|
{ "modify", TOK_MODIFY },
|
||||||
{ "swap", TOK_SWAP },
|
{ "swap", TOK_SWAP },
|
||||||
{ "info", TOK_INFO },
|
{ "info", TOK_INFO },
|
||||||
{ "detail", TOK_DETAIL },
|
{ "detail", TOK_DETAIL },
|
||||||
@ -192,6 +199,10 @@ ipfw_table_handler(int ac, char *av[])
|
|||||||
ac--; av++;
|
ac--; av++;
|
||||||
table_create(&oh, ac, av);
|
table_create(&oh, ac, av);
|
||||||
break;
|
break;
|
||||||
|
case TOK_MODIFY:
|
||||||
|
ac--; av++;
|
||||||
|
table_modify(&oh, ac, av);
|
||||||
|
break;
|
||||||
case TOK_DESTROY:
|
case TOK_DESTROY:
|
||||||
if (table_destroy(&oh) != 0)
|
if (table_destroy(&oh) != 0)
|
||||||
err(EX_OSERR, "failed to destroy table %s", tablename);
|
err(EX_OSERR, "failed to destroy table %s", tablename);
|
||||||
@ -265,6 +276,7 @@ table_fill_objheader(ipfw_obj_header *oh, ipfw_xtable_info *i)
|
|||||||
|
|
||||||
static struct _s_x tablenewcmds[] = {
|
static struct _s_x tablenewcmds[] = {
|
||||||
{ "type", TOK_TYPE },
|
{ "type", TOK_TYPE },
|
||||||
|
{ "ftype", TOK_FTYPE },
|
||||||
{ "valtype", TOK_VALTYPE },
|
{ "valtype", TOK_VALTYPE },
|
||||||
{ "algo", TOK_ALGO },
|
{ "algo", TOK_ALGO },
|
||||||
{ "limit", TOK_LIMIT },
|
{ "limit", TOK_LIMIT },
|
||||||
@ -330,8 +342,6 @@ table_print_type(char *tbuf, size_t size, uint8_t type, uint8_t tflags)
|
|||||||
* ipfw table NAME create [ type { cidr | iface | u32 } ]
|
* ipfw table NAME create [ type { cidr | iface | u32 } ]
|
||||||
* [ valtype { number | ip | dscp } ]
|
* [ valtype { number | ip | dscp } ]
|
||||||
* [ algo algoname ]
|
* [ algo algoname ]
|
||||||
*
|
|
||||||
* Request: [ ipfw_obj_header ipfw_xtable_info ]
|
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
table_create(ipfw_obj_header *oh, int ac, char *av[])
|
table_create(ipfw_obj_header *oh, int ac, char *av[])
|
||||||
@ -394,6 +404,18 @@ table_create(ipfw_obj_header *oh, int ac, char *av[])
|
|||||||
errx(EX_USAGE, "Unknown value type: %s. Supported: %s",
|
errx(EX_USAGE, "Unknown value type: %s. Supported: %s",
|
||||||
*av, tbuf);
|
*av, tbuf);
|
||||||
break;
|
break;
|
||||||
|
case TOK_FTYPE:
|
||||||
|
NEED1("table value format type required");
|
||||||
|
val = match_token(tablefvaltypes, *av);
|
||||||
|
if (val != -1) {
|
||||||
|
xi.vftype = val;
|
||||||
|
ac--; av++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
concat_tokens(tbuf, sizeof(tbuf), tablefvaltypes, ", ");
|
||||||
|
errx(EX_USAGE, "Unknown format type: %s. Supported: %s",
|
||||||
|
*av, tbuf);
|
||||||
|
break;
|
||||||
case TOK_ALGO:
|
case TOK_ALGO:
|
||||||
NEED1("table algorithm name required");
|
NEED1("table algorithm name required");
|
||||||
if (strlen(*av) > sizeof(xi.algoname))
|
if (strlen(*av) > sizeof(xi.algoname))
|
||||||
@ -430,6 +452,79 @@ table_do_create(ipfw_obj_header *oh, ipfw_xtable_info *i)
|
|||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modifies existing table
|
||||||
|
*
|
||||||
|
* ipfw table NAME modify [ limit number ] [ ftype { number | ip } ]
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
table_modify(ipfw_obj_header *oh, int ac, char *av[])
|
||||||
|
{
|
||||||
|
ipfw_xtable_info xi;
|
||||||
|
int error, tcmd, val;
|
||||||
|
size_t sz;
|
||||||
|
char tbuf[128];
|
||||||
|
|
||||||
|
sz = sizeof(tbuf);
|
||||||
|
memset(&xi, 0, sizeof(xi));
|
||||||
|
|
||||||
|
/* Set some defaults to preserve compability */
|
||||||
|
xi.type = IPFW_TABLE_CIDR;
|
||||||
|
xi.vtype = IPFW_VTYPE_U32;
|
||||||
|
|
||||||
|
while (ac > 0) {
|
||||||
|
if ((tcmd = match_token(tablenewcmds, *av)) == -1)
|
||||||
|
errx(EX_USAGE, "unknown option: %s", *av);
|
||||||
|
ac--; av++;
|
||||||
|
|
||||||
|
switch (tcmd) {
|
||||||
|
case TOK_LIMIT:
|
||||||
|
NEED1("limit value required");
|
||||||
|
xi.limit = strtol(*av, NULL, 10);
|
||||||
|
xi.mflags |= IPFW_TMFLAGS_LIMIT;
|
||||||
|
ac--; av++;
|
||||||
|
break;
|
||||||
|
case TOK_FTYPE:
|
||||||
|
NEED1("table value format type required");
|
||||||
|
val = match_token(tablefvaltypes, *av);
|
||||||
|
if (val != -1) {
|
||||||
|
xi.vftype = val;
|
||||||
|
xi.mflags |= IPFW_TMFLAGS_FTYPE;
|
||||||
|
ac--; av++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
concat_tokens(tbuf, sizeof(tbuf), tablefvaltypes, ", ");
|
||||||
|
errx(EX_USAGE, "Unknown value type: %s. Supported: %s",
|
||||||
|
*av, tbuf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((error = table_do_modify(oh, &xi)) != 0)
|
||||||
|
err(EX_OSERR, "Table modification failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modifies existing table.
|
||||||
|
*
|
||||||
|
* Request: [ ipfw_obj_header ipfw_xtable_info ]
|
||||||
|
*
|
||||||
|
* Returns 0 on success.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
table_do_modify(ipfw_obj_header *oh, ipfw_xtable_info *i)
|
||||||
|
{
|
||||||
|
char tbuf[sizeof(ipfw_obj_header) + sizeof(ipfw_xtable_info)];
|
||||||
|
int error;
|
||||||
|
|
||||||
|
memcpy(tbuf, oh, sizeof(*oh));
|
||||||
|
memcpy(tbuf + sizeof(*oh), i, sizeof(*i));
|
||||||
|
oh = (ipfw_obj_header *)tbuf;
|
||||||
|
|
||||||
|
error = do_set3(IP_FW_TABLE_XMODIFY, &oh->opheader, sizeof(tbuf));
|
||||||
|
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Destroys given table specified by @oh->ntlv.
|
* Destroys given table specified by @oh->ntlv.
|
||||||
* Returns 0 on success.
|
* Returns 0 on success.
|
||||||
@ -584,19 +679,25 @@ table_show_tainfo(ipfw_xtable_info *i, struct ta_cldata *d,
|
|||||||
static int
|
static int
|
||||||
table_show_info(ipfw_xtable_info *i, void *arg)
|
table_show_info(ipfw_xtable_info *i, void *arg)
|
||||||
{
|
{
|
||||||
const char *vtype;
|
const char *vtype, *vftype;
|
||||||
ipfw_ta_tinfo *tainfo;
|
ipfw_ta_tinfo *tainfo;
|
||||||
int afdata, afitem;
|
int afdata, afitem;
|
||||||
struct ta_cldata d;
|
struct ta_cldata d;
|
||||||
char ttype[64];
|
char ttype[64], tvtype[64];
|
||||||
|
|
||||||
table_print_type(ttype, sizeof(ttype), i->type, i->tflags);
|
table_print_type(ttype, sizeof(ttype), i->type, i->tflags);
|
||||||
if ((vtype = match_value(tablevaltypes, i->vtype)) == NULL)
|
if ((vtype = match_value(tablevaltypes, i->vtype)) == NULL)
|
||||||
vtype = "unknown";
|
vtype = "unknown";
|
||||||
|
if ((vftype = match_value(tablefvaltypes, i->vftype)) == NULL)
|
||||||
|
vftype = "unknown";
|
||||||
|
if (strcmp(vtype, vftype) != 0)
|
||||||
|
snprintf(tvtype, sizeof(tvtype), "%s(%s)", vtype, vftype);
|
||||||
|
else
|
||||||
|
snprintf(tvtype, sizeof(tvtype), "%s", vtype);
|
||||||
|
|
||||||
printf("--- table(%s), set(%u) ---\n", i->tablename, i->set);
|
printf("--- table(%s), set(%u) ---\n", i->tablename, i->set);
|
||||||
printf(" kindex: %d, type: %s\n", i->kidx, ttype);
|
printf(" kindex: %d, type: %s\n", i->kidx, ttype);
|
||||||
printf(" valtype: %s, references: %u\n", vtype, i->refcnt);
|
printf(" valtype: %s, references: %u\n", tvtype, i->refcnt);
|
||||||
printf(" algorithm: %s\n", i->algoname);
|
printf(" algorithm: %s\n", i->algoname);
|
||||||
printf(" items: %u, size: %u\n", i->count, i->size);
|
printf(" items: %u, size: %u\n", i->count, i->size);
|
||||||
if (i->limit > 0)
|
if (i->limit > 0)
|
||||||
@ -1092,9 +1193,22 @@ static void
|
|||||||
tentry_fill_value(ipfw_obj_header *oh, ipfw_obj_tentry *tent, char *arg,
|
tentry_fill_value(ipfw_obj_header *oh, ipfw_obj_tentry *tent, char *arg,
|
||||||
uint8_t type, uint8_t vtype)
|
uint8_t type, uint8_t vtype)
|
||||||
{
|
{
|
||||||
int code;
|
uint32_t val;
|
||||||
char *p;
|
char *p;
|
||||||
|
|
||||||
|
/* Try to interpret as number first */
|
||||||
|
tent->value = strtoul(arg, &p, 0);
|
||||||
|
if (*p == '\0')
|
||||||
|
return;
|
||||||
|
if (inet_pton(AF_INET, arg, &val) == 1) {
|
||||||
|
tent->value = ntohl(val);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* Try hostname */
|
||||||
|
if (lookup_host(arg, (struct in_addr *)&tent->value) == 0)
|
||||||
|
return;
|
||||||
|
errx(EX_OSERR, "Unable to parse value %s", arg);
|
||||||
|
#if 0
|
||||||
switch (vtype) {
|
switch (vtype) {
|
||||||
case IPFW_VTYPE_U32:
|
case IPFW_VTYPE_U32:
|
||||||
tent->value = strtoul(arg, &p, 0);
|
tent->value = strtoul(arg, &p, 0);
|
||||||
@ -1122,6 +1236,7 @@ tentry_fill_value(ipfw_obj_header *oh, ipfw_obj_tentry *tent, char *arg,
|
|||||||
default:
|
default:
|
||||||
errx(EX_OSERR, "Unsupported format type %d", vtype);
|
errx(EX_OSERR, "Unsupported format type %d", vtype);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1250,7 +1365,7 @@ table_show_entry(ipfw_xtable_info *i, ipfw_obj_tentry *tent)
|
|||||||
|
|
||||||
tval = tent->value;
|
tval = tent->value;
|
||||||
|
|
||||||
if (co.do_value_as_ip) {
|
if (co.do_value_as_ip || i->vftype == IPFW_VFTYPE_IP) {
|
||||||
tval = htonl(tval);
|
tval = htonl(tval);
|
||||||
inet_ntop(AF_INET, &tval, pval, sizeof(pval));
|
inet_ntop(AF_INET, &tval, pval, sizeof(pval));
|
||||||
} else
|
} else
|
||||||
|
@ -83,7 +83,7 @@ typedef struct _ip_fw3_opheader {
|
|||||||
#define IP_FW_TABLE_XINFO 93 /* request info for one table */
|
#define IP_FW_TABLE_XINFO 93 /* request info for one table */
|
||||||
#define IP_FW_TABLE_XFLUSH 94 /* flush table data */
|
#define IP_FW_TABLE_XFLUSH 94 /* flush table data */
|
||||||
#define IP_FW_TABLE_XCREATE 95 /* create new table */
|
#define IP_FW_TABLE_XCREATE 95 /* create new table */
|
||||||
//#define IP_FW_TABLE_XMODIFY 96 /* modify existing table */
|
#define IP_FW_TABLE_XMODIFY 96 /* modify existing table */
|
||||||
#define IP_FW_XGET 97 /* Retrieve configuration */
|
#define IP_FW_XGET 97 /* Retrieve configuration */
|
||||||
#define IP_FW_XADD 98 /* add rule */
|
#define IP_FW_XADD 98 /* add rule */
|
||||||
#define IP_FW_XDEL 99 /* del rule */
|
#define IP_FW_XDEL 99 /* del rule */
|
||||||
@ -686,9 +686,12 @@ struct _ipfw_dyn_rule {
|
|||||||
#define IPFW_TABLE_FLOW 4 /* Table for holding flow data */
|
#define IPFW_TABLE_FLOW 4 /* Table for holding flow data */
|
||||||
#define IPFW_TABLE_MAXTYPE 4 /* Maximum valid number */
|
#define IPFW_TABLE_MAXTYPE 4 /* Maximum valid number */
|
||||||
|
|
||||||
|
/* Value types */
|
||||||
#define IPFW_VTYPE_U32 1 /* Skipto/tablearg integer */
|
#define IPFW_VTYPE_U32 1 /* Skipto/tablearg integer */
|
||||||
#define IPFW_VTYPE_IP 2 /* Nexthop IP address */
|
|
||||||
#define IPFW_VTYPE_DSCP 3 /* DiffServ codepoints */
|
/* Value format types */
|
||||||
|
#define IPFW_VFTYPE_U32 0 /* Skipto/tablearg integer */
|
||||||
|
#define IPFW_VFTYPE_IP 1 /* Nexthop IP address */
|
||||||
|
|
||||||
typedef struct _ipfw_table_entry {
|
typedef struct _ipfw_table_entry {
|
||||||
in_addr_t addr; /* network address */
|
in_addr_t addr; /* network address */
|
||||||
@ -844,15 +847,16 @@ typedef struct _ipfw_ta_tinfo {
|
|||||||
typedef struct _ipfw_xtable_info {
|
typedef struct _ipfw_xtable_info {
|
||||||
uint8_t type; /* table type (cidr,iface,..) */
|
uint8_t type; /* table type (cidr,iface,..) */
|
||||||
uint8_t tflags; /* type flags */
|
uint8_t tflags; /* type flags */
|
||||||
uint8_t ftype; /* table value format type */
|
uint8_t vtype; /* value type (u32) */
|
||||||
uint8_t vtype; /* value type */
|
uint8_t vftype; /* value format type (ip,number)*/
|
||||||
|
uint16_t mflags; /* modification flags */
|
||||||
|
uint16_t spare;
|
||||||
uint32_t set; /* set table is in */
|
uint32_t set; /* set table is in */
|
||||||
uint32_t kidx; /* kernel index */
|
uint32_t kidx; /* kernel index */
|
||||||
uint32_t refcnt; /* number of references */
|
uint32_t refcnt; /* number of references */
|
||||||
uint32_t count; /* Number of records */
|
uint32_t count; /* Number of records */
|
||||||
uint32_t size; /* Total size of records(export)*/
|
uint32_t size; /* Total size of records(export)*/
|
||||||
uint32_t limit; /* Max number of records */
|
uint32_t limit; /* Max number of records */
|
||||||
uint32_t spare;
|
|
||||||
char tablename[64]; /* table name */
|
char tablename[64]; /* table name */
|
||||||
char algoname[64]; /* algorithm name */
|
char algoname[64]; /* algorithm name */
|
||||||
ipfw_ta_tinfo ta_info; /* additional algo stats */
|
ipfw_ta_tinfo ta_info; /* additional algo stats */
|
||||||
@ -862,6 +866,8 @@ typedef struct _ipfw_xtable_info {
|
|||||||
#define IPFW_TFFLAG_SRCPORT 0x04
|
#define IPFW_TFFLAG_SRCPORT 0x04
|
||||||
#define IPFW_TFFLAG_DSTPORT 0x08
|
#define IPFW_TFFLAG_DSTPORT 0x08
|
||||||
#define IPFW_TFFLAG_PROTO 0x10
|
#define IPFW_TFFLAG_PROTO 0x10
|
||||||
|
#define IPFW_TMFLAGS_FTYPE 0x01 /* Change ftype field */
|
||||||
|
#define IPFW_TMFLAGS_LIMIT 0x02 /* Change limit value */
|
||||||
|
|
||||||
typedef struct _ipfw_iface_info {
|
typedef struct _ipfw_iface_info {
|
||||||
char ifname[64]; /* interface name */
|
char ifname[64]; /* interface name */
|
||||||
|
@ -2321,6 +2321,10 @@ ipfw_ctl3(struct sockopt *sopt)
|
|||||||
error = ipfw_flush_table(chain, op3, &sdata);
|
error = ipfw_flush_table(chain, op3, &sdata);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IP_FW_TABLE_XMODIFY:
|
||||||
|
error = ipfw_modify_table(chain, op3, &sdata);
|
||||||
|
break;
|
||||||
|
|
||||||
case IP_FW_TABLE_XINFO:
|
case IP_FW_TABLE_XINFO:
|
||||||
error = ipfw_describe_table(chain, &sdata);
|
error = ipfw_describe_table(chain, &sdata);
|
||||||
break;
|
break;
|
||||||
|
@ -73,12 +73,16 @@ __FBSDID("$FreeBSD$");
|
|||||||
*/
|
*/
|
||||||
struct table_config {
|
struct table_config {
|
||||||
struct named_object no;
|
struct named_object no;
|
||||||
uint8_t vtype; /* format table type */
|
uint8_t vtype; /* value type */
|
||||||
uint8_t linked; /* 1 if already linked */
|
uint8_t vftype; /* value format type */
|
||||||
uint8_t tflags; /* type flags */
|
uint8_t tflags; /* type flags */
|
||||||
uint8_t ochanged; /* used by set swapping */
|
uint8_t spare0;
|
||||||
uint32_t count; /* Number of records */
|
uint32_t count; /* Number of records */
|
||||||
uint32_t limit; /* Max number of records */
|
uint32_t limit; /* Max number of records */
|
||||||
|
uint8_t linked; /* 1 if already linked */
|
||||||
|
uint8_t ochanged; /* used by set swapping */
|
||||||
|
uint16_t spare1;
|
||||||
|
uint32_t spare2;
|
||||||
uint32_t ocount; /* used by set swapping */
|
uint32_t ocount; /* used by set swapping */
|
||||||
uint64_t gencnt; /* generation count */
|
uint64_t gencnt; /* generation count */
|
||||||
char tablename[64]; /* table name */
|
char tablename[64]; /* table name */
|
||||||
@ -168,7 +172,7 @@ add_table_entry(struct ip_fw_chain *ch, struct tid_info *ti,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Try to exit early on limit hit */
|
/* Try to exit early on limit hit */
|
||||||
if (tc->limit != 0 && tc->count == tc->limit &&
|
if (tc->limit != 0 && tc->count >= tc->limit &&
|
||||||
(tei->flags & TEI_FLAGS_UPDATE) == 0) {
|
(tei->flags & TEI_FLAGS_UPDATE) == 0) {
|
||||||
IPFW_UH_WUNLOCK(ch);
|
IPFW_UH_WUNLOCK(ch);
|
||||||
return (EFBIG);
|
return (EFBIG);
|
||||||
@ -239,7 +243,7 @@ add_table_entry(struct ip_fw_chain *ch, struct tid_info *ti,
|
|||||||
tc->no.refcnt--;
|
tc->no.refcnt--;
|
||||||
|
|
||||||
/* Check limit before adding */
|
/* Check limit before adding */
|
||||||
if (tc->limit != 0 && tc->count == tc->limit) {
|
if (tc->limit != 0 && tc->count >= tc->limit) {
|
||||||
if ((tei->flags & TEI_FLAGS_UPDATE) == 0) {
|
if ((tei->flags & TEI_FLAGS_UPDATE) == 0) {
|
||||||
IPFW_UH_WUNLOCK(ch);
|
IPFW_UH_WUNLOCK(ch);
|
||||||
ta->flush_entry(ch, tei, &ta_buf);
|
ta->flush_entry(ch, tei, &ta_buf);
|
||||||
@ -1334,6 +1338,56 @@ ipfw_dump_table_v0(struct ip_fw_chain *ch, struct sockopt_data *sd)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modifies existing table.
|
||||||
|
* Data layout (v0)(current):
|
||||||
|
* Request: [ ipfw_obj_header ipfw_xtable_info ]
|
||||||
|
*
|
||||||
|
* Returns 0 on success
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
ipfw_modify_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||||
|
struct sockopt_data *sd)
|
||||||
|
{
|
||||||
|
struct _ipfw_obj_header *oh;
|
||||||
|
ipfw_xtable_info *i;
|
||||||
|
char *tname;
|
||||||
|
struct tid_info ti;
|
||||||
|
struct namedobj_instance *ni;
|
||||||
|
struct table_config *tc;
|
||||||
|
|
||||||
|
if (sd->valsize != sizeof(*oh) + sizeof(ipfw_xtable_info))
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
|
oh = (struct _ipfw_obj_header *)sd->kbuf;
|
||||||
|
i = (ipfw_xtable_info *)(oh + 1);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verify user-supplied strings.
|
||||||
|
* Check for null-terminated/zero-length strings/
|
||||||
|
*/
|
||||||
|
tname = oh->ntlv.name;
|
||||||
|
if (ipfw_check_table_name(tname) != 0)
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
|
objheader_to_ti(oh, &ti);
|
||||||
|
ti.type = i->type;
|
||||||
|
|
||||||
|
IPFW_UH_WLOCK(ch);
|
||||||
|
ni = CHAIN_TO_NI(ch);
|
||||||
|
if ((tc = find_table(ni, &ti)) == NULL) {
|
||||||
|
IPFW_UH_WUNLOCK(ch);
|
||||||
|
return (ESRCH);
|
||||||
|
}
|
||||||
|
if ((i->mflags & IPFW_TMFLAGS_FTYPE) != 0)
|
||||||
|
tc->vftype = i->vftype;
|
||||||
|
if ((i->mflags & IPFW_TMFLAGS_LIMIT) != 0)
|
||||||
|
tc->limit = i->limit;
|
||||||
|
IPFW_UH_WUNLOCK(ch);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Creates new table.
|
* Creates new table.
|
||||||
* Data layout (v0)(current):
|
* Data layout (v0)(current):
|
||||||
@ -1415,6 +1469,7 @@ create_table_internal(struct ip_fw_chain *ch, struct tid_info *ti,
|
|||||||
if (tc == NULL)
|
if (tc == NULL)
|
||||||
return (ENOMEM);
|
return (ENOMEM);
|
||||||
|
|
||||||
|
tc->vftype = i->vftype;
|
||||||
tc->limit = i->limit;
|
tc->limit = i->limit;
|
||||||
|
|
||||||
IPFW_UH_WLOCK(ch);
|
IPFW_UH_WLOCK(ch);
|
||||||
@ -1498,6 +1553,7 @@ export_table_info(struct ip_fw_chain *ch, struct table_config *tc,
|
|||||||
i->type = tc->no.type;
|
i->type = tc->no.type;
|
||||||
i->tflags = tc->tflags;
|
i->tflags = tc->tflags;
|
||||||
i->vtype = tc->vtype;
|
i->vtype = tc->vtype;
|
||||||
|
i->vftype = tc->vftype;
|
||||||
i->set = tc->no.set;
|
i->set = tc->no.set;
|
||||||
i->kidx = tc->no.kidx;
|
i->kidx = tc->no.kidx;
|
||||||
i->refcnt = tc->no.refcnt;
|
i->refcnt = tc->no.refcnt;
|
||||||
|
@ -146,6 +146,8 @@ int ipfw_find_table_entry(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
|||||||
struct sockopt_data *sd);
|
struct sockopt_data *sd);
|
||||||
int ipfw_create_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
int ipfw_create_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||||
struct sockopt_data *sd);
|
struct sockopt_data *sd);
|
||||||
|
int ipfw_modify_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||||
|
struct sockopt_data *sd);
|
||||||
int ipfw_manage_table_ent(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
int ipfw_manage_table_ent(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||||
struct sockopt_data *sd);
|
struct sockopt_data *sd);
|
||||||
int ipfw_flush_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
int ipfw_flush_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||||
|
Loading…
Reference in New Issue
Block a user