svn commit: r268347 - in projects/ipfw: sbin/ipfw sys/netinet sys/netpfil/ipfw
Alexander V. Chernikov
melifaro at FreeBSD.org
Sun Jul 6 23:26:36 UTC 2014
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,
};
More information about the svn-src-projects
mailing list