From 5dc5a0e0aa5bd44eecf8a3cdff85d213607312dc Mon Sep 17 00:00:00 2001 From: "Andrey V. Elsukov" Date: Tue, 3 Nov 2015 10:21:53 +0000 Subject: [PATCH] Implement `ipfw internal olist` command to list named objects. Reviewed by: melifaro Obtained from: Yandex LLC Sponsored by: Yandex LLC --- sbin/ipfw/ipfw2.c | 41 +++++++++++++++++++ sbin/ipfw/ipfw2.h | 1 + sys/netinet/ip_fw.h | 1 + sys/netpfil/ipfw/ip_fw_private.h | 1 + sys/netpfil/ipfw/ip_fw_sockopt.c | 67 +++++++++++++++++++++++++++++--- 5 files changed, 106 insertions(+), 5 deletions(-) diff --git a/sbin/ipfw/ipfw2.c b/sbin/ipfw/ipfw2.c index bc8af9f833a6..366f77f6969f 100644 --- a/sbin/ipfw/ipfw2.c +++ b/sbin/ipfw/ipfw2.c @@ -4983,10 +4983,48 @@ ipfw_flush(int force) static struct _s_x intcmds[] = { { "talist", TOK_TALIST }, { "iflist", TOK_IFLIST }, + { "olist", TOK_OLIST }, { "vlist", TOK_VLIST }, { NULL, 0 } }; +static void +ipfw_list_objects(int ac, char *av[]) +{ + ipfw_obj_lheader req, *olh; + ipfw_obj_ntlv *ntlv; + size_t sz; + int i; + + memset(&req, 0, sizeof(req)); + sz = sizeof(req); + if (do_get3(IP_FW_DUMP_SRVOBJECTS, &req.opheader, &sz) != 0) + if (errno != ENOMEM) + return; + + sz = req.size; + if ((olh = calloc(1, sz)) == NULL) + return; + + olh->size = sz; + if (do_get3(IP_FW_DUMP_SRVOBJECTS, &olh->opheader, &sz) != 0) { + free(olh); + return; + } + + if (olh->count > 0) + printf("Objects list:\n"); + else + printf("There are no objects\n"); + ntlv = (ipfw_obj_ntlv *)(olh + 1); + for (i = 0; i < olh->count; i++) { + printf(" kidx: %4d\ttype: %2d\tname: %s\n", ntlv->idx, + ntlv->head.type, ntlv->name); + ntlv++; + } + free(olh); +} + void ipfw_internal_handler(int ac, char *av[]) { @@ -5005,6 +5043,9 @@ ipfw_internal_handler(int ac, char *av[]) case TOK_TALIST: ipfw_list_ta(ac, av); break; + case TOK_OLIST: + ipfw_list_objects(ac, av); + break; case TOK_VLIST: ipfw_list_values(ac, av); break; diff --git a/sbin/ipfw/ipfw2.h b/sbin/ipfw/ipfw2.h index 5a083216d53b..86f2a41733f5 100644 --- a/sbin/ipfw/ipfw2.h +++ b/sbin/ipfw/ipfw2.h @@ -227,6 +227,7 @@ enum tokens { TOK_LOCK, TOK_UNLOCK, TOK_VLIST, + TOK_OLIST, }; /* diff --git a/sys/netinet/ip_fw.h b/sys/netinet/ip_fw.h index d1764bbf5f1a..e52ff1a54cb3 100644 --- a/sys/netinet/ip_fw.h +++ b/sys/netinet/ip_fw.h @@ -107,6 +107,7 @@ typedef struct _ip_fw3_opheader { #define IP_FW_NAT44_XGETLOG 115 /* Get log from NAT44 instance */ #define IP_FW_DUMP_SOPTCODES 116 /* Dump available sopts/versions */ +#define IP_FW_DUMP_SRVOBJECTS 117 /* Dump existing named objects */ /* * The kernel representation of ipfw rules is made of a list of diff --git a/sys/netpfil/ipfw/ip_fw_private.h b/sys/netpfil/ipfw/ip_fw_private.h index e39b32ddc577..0950c4cfe6f5 100644 --- a/sys/netpfil/ipfw/ip_fw_private.h +++ b/sys/netpfil/ipfw/ip_fw_private.h @@ -673,6 +673,7 @@ int ipfw_objhash_free_idx(struct namedobj_instance *ni, uint16_t idx); int ipfw_objhash_alloc_idx(void *n, uint16_t *pidx); void ipfw_objhash_set_funcs(struct namedobj_instance *ni, objhash_hash_f *hash_f, objhash_cmp_f *cmp_f); +void ipfw_export_obj_ntlv(struct named_object *no, ipfw_obj_ntlv *ntlv); void ipfw_init_obj_rewriter(void); void ipfw_destroy_obj_rewriter(void); void ipfw_add_obj_rewriter(struct opcode_obj_rewrite *rw, size_t count); diff --git a/sys/netpfil/ipfw/ip_fw_sockopt.c b/sys/netpfil/ipfw/ip_fw_sockopt.c index 7ed4c1d055c3..3e2ae937be73 100644 --- a/sys/netpfil/ipfw/ip_fw_sockopt.c +++ b/sys/netpfil/ipfw/ip_fw_sockopt.c @@ -119,6 +119,8 @@ static int manage_sets(struct ip_fw_chain *chain, ip_fw3_opheader *op3, struct sockopt_data *sd); static int dump_soptcodes(struct ip_fw_chain *chain, ip_fw3_opheader *op3, struct sockopt_data *sd); +static int dump_srvobjects(struct ip_fw_chain *chain, ip_fw3_opheader *op3, + struct sockopt_data *sd); /* ctl3 handler data */ struct mtx ctl3_lock; @@ -146,6 +148,7 @@ static struct ipfw_sopt_handler scodes[] = { { IP_FW_SET_MOVE, 0, HDIR_SET, manage_sets }, { IP_FW_SET_ENABLE, 0, HDIR_SET, manage_sets }, { IP_FW_DUMP_SOPTCODES, 0, HDIR_GET, dump_soptcodes }, + { IP_FW_DUMP_SRVOBJECTS,0, HDIR_GET, dump_srvobjects }, }; static int @@ -1876,6 +1879,16 @@ struct dump_args { int rcounters; /* counters */ }; +void +ipfw_export_obj_ntlv(struct named_object *no, ipfw_obj_ntlv *ntlv) +{ + + ntlv->head.type = no->etlv; + ntlv->head.length = sizeof(*ntlv); + ntlv->idx = no->kidx; + strlcpy(ntlv->name, no->name, sizeof(ntlv->name)); +} + /* * Export named object info in instance @ni, identified by @kidx * to ipfw_obj_ntlv. TLV is allocated from @sd space. @@ -1896,11 +1909,7 @@ export_objhash_ntlv(struct namedobj_instance *ni, uint16_t kidx, if (ntlv == NULL) return (ENOMEM); - ntlv->head.type = no->etlv; - ntlv->head.length = sizeof(*ntlv); - ntlv->idx = no->kidx; - strlcpy(ntlv->name, no->name, sizeof(ntlv->name)); - + ipfw_export_obj_ntlv(no, ntlv); return (0); } @@ -2803,6 +2812,54 @@ ipfw_del_obj_rewriter(struct opcode_obj_rewrite *rw, size_t count) return (0); } +static void +export_objhash_ntlv_internal(struct namedobj_instance *ni, + struct named_object *no, void *arg) +{ + struct sockopt_data *sd; + ipfw_obj_ntlv *ntlv; + + sd = (struct sockopt_data *)arg; + ntlv = (ipfw_obj_ntlv *)ipfw_get_sopt_space(sd, sizeof(*ntlv)); + if (ntlv == NULL) + return; + ipfw_export_obj_ntlv(no, ntlv); +} + +/* + * Lists all service objects. + * Data layout (v0)(current): + * Request: [ ipfw_obj_lheader ] size = ipfw_cfg_lheader.size + * Reply: [ ipfw_obj_lheader [ ipfw_obj_ntlv x N ] (optional) ] + * Returns 0 on success + */ +static int +dump_srvobjects(struct ip_fw_chain *chain, ip_fw3_opheader *op3, + struct sockopt_data *sd) +{ + ipfw_obj_lheader *hdr; + int count; + + hdr = (ipfw_obj_lheader *)ipfw_get_sopt_header(sd, sizeof(*hdr)); + if (hdr == NULL) + return (EINVAL); + + IPFW_UH_RLOCK(chain); + count = ipfw_objhash_count(CHAIN_TO_SRV(chain)); + hdr->size = sizeof(ipfw_obj_lheader) + count * sizeof(ipfw_obj_ntlv); + if (sd->valsize < hdr->size) { + IPFW_UH_RUNLOCK(chain); + return (ENOMEM); + } + hdr->count = count; + hdr->objsize = sizeof(ipfw_obj_ntlv); + if (count > 0) + ipfw_objhash_foreach(CHAIN_TO_SRV(chain), + export_objhash_ntlv_internal, sd); + IPFW_UH_RUNLOCK(chain); + return (0); +} + /* * Compares two sopt handlers (code, version and handler ptr). * Used both as qsort() and bsearch().