diff options
author | Alexander V. Chernikov <melifaro@FreeBSD.org> | 2014-08-01 15:17:46 +0000 |
---|---|---|
committer | Alexander V. Chernikov <melifaro@FreeBSD.org> | 2014-08-01 15:17:46 +0000 |
commit | 4c0c07a5521fca479d04726beb4f7c38914461f4 (patch) | |
tree | 1039246d324a5e4fb33337aa1b6f3cc96b2763d2 /sbin | |
parent | 95c3c1e25f9601f1d9b40ea13f518be8c33c7d0f (diff) | |
download | src-4c0c07a5521fca479d04726beb4f7c38914461f4.tar.gz src-4c0c07a5521fca479d04726beb4f7c38914461f4.zip |
* 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.
Notes
Notes:
svn path=/projects/ipfw/; revision=269386
Diffstat (limited to 'sbin')
-rw-r--r-- | sbin/ipfw/ipfw2.c | 8 | ||||
-rw-r--r-- | sbin/ipfw/ipfw2.h | 2 | ||||
-rw-r--r-- | sbin/ipfw/tables.c | 42 |
3 files changed, 41 insertions, 11 deletions
diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c index a31451b5d41c..4595b04f3713 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 1ed2ee8062ff..ff9bc5b52e0c 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 f94ca72c2934..e36def6adfdf 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 |