Date: Sun, 6 Jul 2014 23:26:35 +0000 (UTC) From: "Alexander V. Chernikov" <melifaro@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r268347 - in projects/ipfw: sbin/ipfw sys/netinet sys/netpfil/ipfw Message-ID: <201407062326.s66NQZMA087851@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: melifaro Date: Sun Jul 6 23:26:34 2014 New Revision: 268347 URL: http://svnweb.freebsd.org/changeset/base/268347 Log: * Prepare to pass other dynamic states via ipfw_dump_config() Kernel changes: * Change dump format for dynamic states: each state is now stored inside ipfw_obj_dyntlv last dynamic state is indicated by IPFW_DF_LAST flag * Do not perform sooptcopyout() for !SOPT_GET requests. Userland changes: * Introduce foreach_state() function handler to ease work with different states passed by ipfw_dump_config(). Modified: projects/ipfw/sbin/ipfw/ipfw2.c projects/ipfw/sys/netinet/ip_fw.h projects/ipfw/sys/netpfil/ipfw/ip_fw_dynamic.c projects/ipfw/sys/netpfil/ipfw/ip_fw_private.h projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c projects/ipfw/sys/netpfil/ipfw/ip_fw_table_algo.c Modified: projects/ipfw/sbin/ipfw/ipfw2.c ============================================================================== --- projects/ipfw/sbin/ipfw/ipfw2.c Sun Jul 6 23:24:06 2014 (r268346) +++ projects/ipfw/sbin/ipfw/ipfw2.c Sun Jul 6 23:26:34 2014 (r268347) @@ -64,6 +64,7 @@ struct format_opts { uint32_t flags; /* request flags */ uint32_t first; /* first rule to request */ uint32_t last; /* last rule to request */ + uint32_t dcnt; /* number of dynamic states */ ipfw_obj_ctlv *tstate; /* table state data */ }; @@ -2161,13 +2162,85 @@ ipfw_sysctl_handler(char *av[], int whic } } +typedef void state_cb(struct cmdline_opts *co, struct format_opts *fo, + void *arg, void *state); + +static void +prepare_format_dyn(struct cmdline_opts *co, struct format_opts *fo, + void *arg, void *_state) +{ + ipfw_dyn_rule *d; + int width; + uint8_t set; + + d = (ipfw_dyn_rule *)_state; + /* Count _ALL_ states */ + fo->dcnt++; + + if (co->use_set) { + /* skip states from another set */ + bcopy((char *)&d->rule + sizeof(uint16_t), &set, + sizeof(uint8_t)); + if (set != co->use_set - 1) + return; + } + + width = pr_u64(NULL, &d->pcnt, 0); + if (width > fo->pcwidth) + fo->pcwidth = width; + + width = pr_u64(NULL, &d->bcnt, 0); + if (width > fo->bcwidth) + fo->bcwidth = width; +} + +static int +foreach_state(struct cmdline_opts *co, struct format_opts *fo, + caddr_t base, size_t sz, state_cb dyn_bc, void *dyn_arg) +{ + int ttype; + state_cb *fptr; + void *farg; + ipfw_obj_tlv *tlv; + ipfw_obj_ctlv *ctlv; + + fptr = NULL; + ttype = 0; + + while (sz > 0) { + ctlv = (ipfw_obj_ctlv *)base; + switch (ctlv->head.type) { + case IPFW_TLV_DYNSTATE_LIST: + base += sizeof(*ctlv); + sz -= sizeof(*ctlv); + ttype = IPFW_TLV_DYN_ENT; + fptr = dyn_bc; + farg = dyn_arg; + break; + default: + return (sz); + } + + while (sz > 0) { + tlv = (ipfw_obj_tlv *)base; + if (tlv->type != ttype) + break; + + fptr(co, fo, farg, tlv + 1); + sz -= tlv->length; + base += tlv->length; + } + } + + return (sz); +} + static void prepare_format_opts(struct cmdline_opts *co, struct format_opts *fo, - struct ip_fw *r, ipfw_dyn_rule *d, int rcnt, int dcnt) + struct ip_fw *r, int rcnt, caddr_t base, size_t sz) { int bcwidth, pcwidth, width; int n; - uint32_t set; #define NEXT(r) ((struct ip_fw *)((char *)r + RULESIZE(r))) bcwidth = 0; @@ -2189,31 +2262,16 @@ prepare_format_opts(struct cmdline_opts bcwidth = width; } } - if (co->do_dynamic && dcnt > 0) { - for (n = 0; n < dcnt; n++, d++) { - if (co->use_set) { - /* skip rules from another set */ - bcopy((char *)&d->rule + sizeof(uint16_t), - &set, sizeof(uint8_t)); - if (set != co->use_set - 1) - continue; - } - width = pr_u64(NULL, &d->pcnt, 0); - if (width > pcwidth) - pcwidth = width; - - width = pr_u64(NULL, &d->bcnt, 0); - if (width > bcwidth) - bcwidth = width; - } - } - fo->bcwidth = bcwidth; fo->pcwidth = pcwidth; + + fo->dcnt = 0; + if (co->do_dynamic && sz > 0) + sz = foreach_state(co, fo, base, sz, prepare_format_dyn, NULL); } static int -ipfw_list_static_range(struct cmdline_opts *co, struct format_opts *fo, +list_static_range(struct cmdline_opts *co, struct format_opts *fo, struct buf_pr *bp, struct ip_fw *r, int rcnt) { int n, seen; @@ -2234,35 +2292,42 @@ ipfw_list_static_range(struct cmdline_op } static void -ipfw_list_dyn_range(struct cmdline_opts *co, struct format_opts *fo, - struct buf_pr *bp, ipfw_dyn_rule *d, int dcnt, int objsize) +list_dyn_state(struct cmdline_opts *co, struct format_opts *fo, + void *_arg, void *_state) { - int n; - uint8_t set; uint16_t rulenum; + uint8_t set; + ipfw_dyn_rule *d; + struct buf_pr *bp; - for (n = 0; n < dcnt; n++) { - bcopy(&d->rule, &rulenum, sizeof(rulenum)); - if (rulenum > fo->last) - break; - if (co->use_set) { - bcopy((char *)&d->rule + sizeof(uint16_t), - &set, sizeof(uint8_t)); - if (set != co->use_set - 1) { - d = (ipfw_dyn_rule *)((caddr_t)d + objsize); - continue; - } - } - if (rulenum >= fo->first) { - show_dyn_state(co, fo, bp, d); - printf("%s\n", bp->buf); - bp_flush(bp); - } + d = (ipfw_dyn_rule *)_state; + bp = (struct buf_pr *)_arg; - d = (ipfw_dyn_rule *)((caddr_t)d + objsize); + bcopy(&d->rule, &rulenum, sizeof(rulenum)); + if (rulenum > fo->last) + return; + if (co->use_set) { + bcopy((char *)&d->rule + sizeof(uint16_t), + &set, sizeof(uint8_t)); + if (set != co->use_set - 1) + return; + } + if (rulenum >= fo->first) { + show_dyn_state(co, fo, bp, d); + printf("%s\n", bp->buf); + bp_flush(bp); } } +static int +list_dyn_range(struct cmdline_opts *co, struct format_opts *fo, + struct buf_pr *bp, caddr_t base, size_t sz) +{ + + sz = foreach_state(co, fo, base, sz, list_dyn_state, bp); + return (sz); +} + void ipfw_list(int ac, char *av[], int show_counters) { @@ -2325,13 +2390,14 @@ ipfw_show_config(struct cmdline_opts *co ipfw_cfg_lheader *cfg, size_t sz, int ac, char *av[]) { struct ip_fw *rbase; - ipfw_dyn_rule *dynbase; - int rcnt, dcnt; + caddr_t dynbase; + size_t dynsz; + int rcnt; int exitval = EX_OK; int lac; char **lav; char *endptr; - size_t dobjsz, read; + size_t read; struct buf_pr bp; ipfw_obj_ctlv *ctlv, *tstate; @@ -2341,7 +2407,7 @@ ipfw_show_config(struct cmdline_opts *co tstate = NULL; rbase = NULL; dynbase = NULL; - dobjsz = 0; + dynsz = 0; read = 0; ctlv = (ipfw_obj_ctlv *)(cfg + 1); @@ -2365,26 +2431,23 @@ ipfw_show_config(struct cmdline_opts *co } if ((cfg->flags & IPFW_CFG_GET_STATES) && (read != sz)) { - /* We may have some dynamic rules */ - read += sizeof(ipfw_obj_ctlv); - dobjsz = ctlv->objsize; - dcnt = (sz - read) / dobjsz; - if (dcnt != 0) - dynbase = (ipfw_dyn_rule *)(ctlv + 1); + /* We may have some dynamic states */ + dynbase = (caddr_t)ctlv; + dynsz = sz - read; } - prepare_format_opts(co, fo, rbase, dynbase, rcnt, dcnt); + prepare_format_opts(co, fo, rbase, rcnt, dynbase, dynsz); bp_alloc(&bp, 4096); /* if no rule numbers were specified, list all rules */ if (ac == 0) { fo->first = 0; fo->last = IPFW_DEFAULT_RULE; - ipfw_list_static_range(co, fo, &bp, rbase, rcnt); + list_static_range(co, fo, &bp, rbase, rcnt); - if (co->do_dynamic && dcnt) { - printf("## Dynamic rules (%d):\n", dcnt); - ipfw_list_dyn_range(co, fo, &bp, dynbase, dcnt, dobjsz); + if (co->do_dynamic && dynsz > 0) { + printf("## Dynamic rules (%d):\n", fo->dcnt); + list_dyn_range(co, fo, &bp, dynbase, dynsz); } bp_free(&bp); @@ -2403,7 +2466,7 @@ ipfw_show_config(struct cmdline_opts *co continue; } - if (ipfw_list_static_range(co, fo, &bp, rbase, rcnt) == 0) { + if (list_static_range(co, fo, &bp, rbase, rcnt) == 0) { /* give precedence to other error(s) */ if (exitval == EX_OK) exitval = EX_UNAVAILABLE; @@ -2415,7 +2478,7 @@ ipfw_show_config(struct cmdline_opts *co } } - if (co->do_dynamic && dcnt > 0) { + if (co->do_dynamic && dynsz > 0) { printf("## Dynamic rules:\n"); for (lac = ac, lav = av; lac != 0; lac--) { fo->last = fo->first = strtoul(*lav++, &endptr, 10); @@ -2424,7 +2487,7 @@ ipfw_show_config(struct cmdline_opts *co if (*endptr) /* already warned */ continue; - ipfw_list_dyn_range(co, fo, &bp, dynbase, dcnt, dobjsz); + list_dyn_range(co, fo, &bp, dynbase, dynsz); } } Modified: projects/ipfw/sys/netinet/ip_fw.h ============================================================================== --- projects/ipfw/sys/netinet/ip_fw.h Sun Jul 6 23:24:06 2014 (r268346) +++ projects/ipfw/sys/netinet/ip_fw.h Sun Jul 6 23:26:34 2014 (r268347) @@ -695,8 +695,9 @@ typedef struct _ipfw_obj_tlv { #define IPFW_TLV_TBL_NAME 1 #define IPFW_TLV_TBLNAME_LIST 2 #define IPFW_TLV_RULE_LIST 3 -#define IPFW_TLV_STATE_LIST 4 +#define IPFW_TLV_DYNSTATE_LIST 4 #define IPFW_TLV_TBL_ENT 5 +#define IPFW_TLV_DYN_ENT 6 /* Object name TLV */ typedef struct _ipfw_obj_ntlv { @@ -726,6 +727,12 @@ typedef struct _ipfw_obj_tentry { } ipfw_obj_tentry; #define IPFW_TF_UPDATE 0x01 /* Update record if exists */ +typedef struct _ipfw_obj_dyntlv { + ipfw_obj_tlv head; + ipfw_dyn_rule state; +} ipfw_obj_dyntlv; +#define IPFW_DF_LAST 0x01 /* Last state in chain */ + /* Containter TLVs */ typedef struct _ipfw_obj_ctlv { ipfw_obj_tlv head; /* TLV header */ Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_dynamic.c ============================================================================== --- projects/ipfw/sys/netpfil/ipfw/ip_fw_dynamic.c Sun Jul 6 23:24:06 2014 (r268346) +++ projects/ipfw/sys/netpfil/ipfw/ip_fw_dynamic.c Sun Jul 6 23:26:34 2014 (r268347) @@ -1444,7 +1444,7 @@ sysctl_ipfw_dyn_count(SYSCTL_HANDLER_ARG #endif /* - * Returns number of dynamic rules. + * Returns size of dynamic states in legacy format */ int ipfw_dyn_len(void) @@ -1454,6 +1454,17 @@ ipfw_dyn_len(void) (DYN_COUNT * sizeof(ipfw_dyn_rule)); } +/* + * Returns number of dynamic states. + * Used by dump format v1 (current). + */ +int +ipfw_dyn_get_count(void) +{ + + return (V_ipfw_dyn_v == NULL) ? 0 : DYN_COUNT; +} + static void export_dyn_rule(ipfw_dyn_rule *src, ipfw_dyn_rule *dst) { @@ -1479,15 +1490,18 @@ export_dyn_rule(ipfw_dyn_rule *src, ipfw /* * Fills int buffer given by @sd with dynamic states. + * Used by dump format v1 (current). * * Returns 0 on success. */ int ipfw_dump_states(struct ip_fw_chain *chain, struct sockopt_data *sd) { - ipfw_dyn_rule *p, *dst, *last = NULL; + ipfw_dyn_rule *p; + ipfw_obj_dyntlv *dst, *last; ipfw_obj_ctlv *ctlv; int i; + size_t sz; if (V_ipfw_dyn_v == NULL) return (0); @@ -1497,33 +1511,36 @@ ipfw_dump_states(struct ip_fw_chain *cha ctlv = (ipfw_obj_ctlv *)ipfw_get_sopt_space(sd, sizeof(*ctlv)); if (ctlv == NULL) return (ENOMEM); - ctlv->head.type = IPFW_TLV_TBLNAME_LIST; - ctlv->objsize = sizeof(ipfw_dyn_rule); + sz = sizeof(ipfw_obj_dyntlv); + ctlv->head.type = IPFW_TLV_DYNSTATE_LIST; + ctlv->objsize = sz; + last = NULL; for (i = 0 ; i < V_curr_dyn_buckets; i++) { IPFW_BUCK_LOCK(i); for (p = V_ipfw_dyn_v[i].head ; p != NULL; p = p->next) { - dst = (ipfw_dyn_rule *)ipfw_get_sopt_space(sd, - sizeof(*dst)); + dst = (ipfw_obj_dyntlv *)ipfw_get_sopt_space(sd, sz); if (dst == NULL) { IPFW_BUCK_UNLOCK(i); return (ENOMEM); } - export_dyn_rule(p, dst); + export_dyn_rule(p, &dst->state); + dst->head.length = sz; + dst->head.type = IPFW_TLV_DYN_ENT; last = dst; } IPFW_BUCK_UNLOCK(i); } if (last != NULL) /* mark last dynamic rule */ - bzero(&last->next, sizeof(last)); + last->head.flags = IPFW_DF_LAST; return (0); } /* - * Fill given buffer with dynamic states. + * Fill given buffer with dynamic states (legacy format). * IPFW_UH_RLOCK has to be held while calling. */ void Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_private.h ============================================================================== --- projects/ipfw/sys/netpfil/ipfw/ip_fw_private.h Sun Jul 6 23:24:06 2014 (r268346) +++ projects/ipfw/sys/netpfil/ipfw/ip_fw_private.h Sun Jul 6 23:26:34 2014 (r268347) @@ -194,6 +194,7 @@ int ipfw_dump_states(struct ip_fw_chain void ipfw_dyn_init(struct ip_fw_chain *); /* per-vnet initialization */ void ipfw_dyn_uninit(int); /* per-vnet deinitialization */ int ipfw_dyn_len(void); +int ipfw_dyn_get_count(void); /* common variables */ VNET_DECLARE(int, fw_one_pass); Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c ============================================================================== --- projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c Sun Jul 6 23:24:06 2014 (r268346) +++ projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c Sun Jul 6 23:26:34 2014 (r268347) @@ -1201,9 +1201,8 @@ dump_config(struct ip_fw_chain *chain, s sz += da.rsize + sizeof(ipfw_obj_ctlv); } - if (hdr->flags & IPFW_CFG_GET_STATES) { - sz += ipfw_dyn_len(); - } + if (hdr->flags & IPFW_CFG_GET_STATES) + sz += ipfw_dyn_get_count() * sizeof(ipfw_obj_dyntlv); /* Fill header anyway */ hdr->size = sz; @@ -1916,8 +1915,11 @@ ipfw_flush_sopt_data(struct sockopt_data if (sd->koff == 0) return (0); - if ((error = sooptcopyout(sd->sopt, sd->kbuf, sd->koff)) != 0) - return (error); + if (sd->sopt->sopt_dir == SOPT_GET) { + error = sooptcopyout(sd->sopt, sd->kbuf, sd->koff); + if (error != 0) + return (error); + } memset(sd->kbuf, 0, sd->ksize); sd->ktotal += sd->koff; Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_table_algo.c ============================================================================== --- projects/ipfw/sys/netpfil/ipfw/ip_fw_table_algo.c Sun Jul 6 23:24:06 2014 (r268346) +++ projects/ipfw/sys/netpfil/ipfw/ip_fw_table_algo.c Sun Jul 6 23:26:34 2014 (r268347) @@ -800,13 +800,13 @@ struct table_algo radix_iface = { .name = "radix_iface", .lookup = ta_lookup_iface, .init = ta_init_iface, - .destroy = ta_destroy_iface, + .destroy = ta_destroy_iface, .prepare_add = ta_prepare_add_iface, .prepare_del = ta_prepare_del_iface, .add = ta_add_iface, .del = ta_del_iface, .flush_entry = ta_flush_iface_entry, - .foreach = ta_foreach_iface, + .foreach = ta_foreach_iface, .dump_tentry = ta_dump_iface_tentry, .find_tentry = ta_find_iface_tentry, };
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201407062326.s66NQZMA087851>