summaryrefslogtreecommitdiffstats
path: root/sbin/ipfw
diff options
context:
space:
mode:
authormelifaro <melifaro@FreeBSD.org>2014-08-01 15:17:46 +0000
committermelifaro <melifaro@FreeBSD.org>2014-08-01 15:17:46 +0000
commit178311d9d4c0a512292c01d751831b7155819d27 (patch)
tree1039246d324a5e4fb33337aa1b6f3cc96b2763d2 /sbin/ipfw
parent6d7452f13b0a8fdccc3fb65e9e726d366c6c71b0 (diff)
downloadFreeBSD-src-178311d9d4c0a512292c01d751831b7155819d27.zip
FreeBSD-src-178311d9d4c0a512292c01d751831b7155819d27.tar.gz
* Permit limiting number of items in table.
Kernel changes: * Add TEI_FLAGS_DONTADD entry flag to indicate that insert is not possible * Support given flag in all algorithms * Add "limit" field to ipfw_xtable_info * Add actual limiting code into add_table_entry() Userland changes: * Add "limit" option as "create" table sub-option. Limit modification is currently impossible. * Print human-readable errors in table enry addition/deletion code.
Diffstat (limited to 'sbin/ipfw')
-rw-r--r--sbin/ipfw/ipfw2.c8
-rw-r--r--sbin/ipfw/ipfw2.h2
-rw-r--r--sbin/ipfw/tables.c42
3 files changed, 41 insertions, 11 deletions
diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c
index a31451b..4595b04 100644
--- a/sbin/ipfw/ipfw2.c
+++ b/sbin/ipfw/ipfw2.c
@@ -580,11 +580,12 @@ do_cmd(int optname, void *optval, uintptr_t optlen)
*
* Assumes op3 header is already embedded.
* Calls setsockopt() with IP_FW3 as kernel-visible opcode.
- * Returns 0 on success or -1 otherwise.
+ * Returns 0 on success or errno otherwise.
*/
int
do_set3(int optname, ip_fw3_opheader *op3, uintptr_t optlen)
{
+ int errno;
if (co.test_only)
return (0);
@@ -596,7 +597,10 @@ do_set3(int optname, ip_fw3_opheader *op3, uintptr_t optlen)
op3->opcode = optname;
- return (setsockopt(ipfw_socket, IPPROTO_IP, IP_FW3, op3, optlen));
+ if (setsockopt(ipfw_socket, IPPROTO_IP, IP_FW3, op3, optlen) != 0)
+ return (errno);
+
+ return (0);
}
int
diff --git a/sbin/ipfw/ipfw2.h b/sbin/ipfw/ipfw2.h
index 1ed2ee8..ff9bc5b 100644
--- a/sbin/ipfw/ipfw2.h
+++ b/sbin/ipfw/ipfw2.h
@@ -255,8 +255,6 @@ char const *match_value(struct _s_x *p, int value);
size_t concat_tokens(char *buf, size_t bufsize, struct _s_x *table,
char *delimiter);
void fill_flags(struct _s_x *flags, char *p, uint8_t *set, uint8_t *clear);
-void print_flags(char const *name, struct _s_x *list, uint8_t set,
- uint8_t clear);
void print_flags_buffer(char *buf, size_t sz, struct _s_x *list, uint8_t set);
struct _ip_fw3_opheader;
diff --git a/sbin/ipfw/tables.c b/sbin/ipfw/tables.c
index f94ca72..e36def6 100644
--- a/sbin/ipfw/tables.c
+++ b/sbin/ipfw/tables.c
@@ -251,9 +251,10 @@ table_fill_objheader(ipfw_obj_header *oh, ipfw_xtable_info *i)
}
static struct _s_x tablenewcmds[] = {
- { "type", TOK_TYPE},
+ { "type", TOK_TYPE },
{ "valtype", TOK_VALTYPE },
{ "algo", TOK_ALGO },
+ { "limit", TOK_LIMIT },
{ NULL, 0 }
};
@@ -341,6 +342,11 @@ table_create(ipfw_obj_header *oh, int ac, char *av[])
ac--; av++;
switch (tcmd) {
+ case TOK_LIMIT:
+ NEED1("limit value required");
+ xi.limit = strtol(*av, NULL, 10);
+ ac--; av++;
+ break;
case TOK_TYPE:
NEED1("table type required");
/* Type may have suboptions after ':' */
@@ -485,6 +491,8 @@ table_show_info(ipfw_xtable_info *i, void *arg)
printf(" valtype: %s, references: %u\n", vtype, i->refcnt);
printf(" algorithm: %s\n", i->algoname);
printf(" items: %u, size: %u\n", i->count, i->size);
+ if (i->limit > 0)
+ printf(" limit: %u\n", i->limit);
return (0);
}
@@ -561,8 +569,8 @@ table_modify_record(ipfw_obj_header *oh, int ac, char *av[], int add, int update
ipfw_obj_tentry tent;
ipfw_xtable_info xi;
uint8_t type, vtype;
- int cmd;
- char *texterr;
+ int cmd, error;
+ char *texterr, *etxt;
if (ac == 0)
errx(EX_USAGE, "address required");
@@ -592,14 +600,34 @@ table_modify_record(ipfw_obj_header *oh, int ac, char *av[], int add, int update
if (ac > 0)
tentry_fill_value(oh, &tent, *av, type, vtype);
cmd = IP_FW_TABLE_XADD;
- texterr = "setsockopt(IP_FW_TABLE_XADD)";
+ texterr = "Adding record failed";
} else {
cmd = IP_FW_TABLE_XDEL;
- texterr = "setsockopt(IP_FW_TABLE_XDEL)";
+ texterr = "Deleting record failed";
+ }
+
+ if ((error = table_do_modify_record(cmd, oh, &tent, update)) == 0)
+ return;
+
+ /* Try to provide more human-readable error */
+ switch (error) {
+ case EEXIST:
+ etxt = "record already exists";
+ break;
+ case EFBIG:
+ etxt = "limit hit";
+ break;
+ case ESRCH:
+ etxt = "table not found";
+ break;
+ case ENOENT:
+ etxt = "record not found";
+ break;
+ default:
+ etxt = strerror(error);
}
- if (table_do_modify_record(cmd, oh, &tent, update) != 0)
- err(EX_OSERR, "%s", texterr);
+ errx(EX_OSERR, "%s: %s", texterr, etxt);
}
static int
OpenPOWER on IntegriCloud