From 85d2072eccdfcb7e8045a60d8bb939de61d1c04b Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 1 Dec 2016 20:12:22 +0100 Subject: src: support for stateful object monitoring This patch extends the event monitoring infrastructure to catch events of addition and removal of stateful objects. Signed-off-by: Pablo Neira Ayuso --- include/rule.h | 3 ++ src/netlink.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/rule.c | 25 +++++++++++ 3 files changed, 162 insertions(+) diff --git a/include/rule.h b/include/rule.h index 86c0392f..878563d9 100644 --- a/include/rule.h +++ b/include/rule.h @@ -283,7 +283,10 @@ struct obj { struct obj *obj_alloc(const struct location *loc); void obj_free(struct obj *obj); void obj_add_hash(struct obj *obj, struct table *table); +struct obj *obj_lookup(const struct table *table, const char *name, + uint32_t type); void obj_print(const struct obj *n); +void obj_print_plain(const struct obj *obj); const char *obj_type_name(uint32_t type); /** diff --git a/src/netlink.c b/src/netlink.c index 97220f45..5f478ff0 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -1923,6 +1923,19 @@ static struct nftnl_rule *netlink_rule_alloc(const struct nlmsghdr *nlh) return nlr; } +static struct nftnl_obj *netlink_obj_alloc(const struct nlmsghdr *nlh) +{ + struct nftnl_obj *nlo; + + nlo = nftnl_obj_alloc(); + if (nlo == NULL) + memory_allocation_error(); + if (nftnl_obj_nlmsg_parse(nlh, nlo) < 0) + netlink_abi_error(); + + return nlo; +} + static uint32_t netlink_msg2nftnl_of(uint32_t msg) { switch (msg) { @@ -2184,6 +2197,51 @@ out: return MNL_CB_OK; } +static int netlink_events_obj_cb(const struct nlmsghdr *nlh, int type, + struct netlink_mon_handler *monh) +{ + struct nftnl_obj *nlo; + uint32_t family; + struct obj *obj; + + nlo = netlink_obj_alloc(nlh); + + switch (monh->format) { + case NFTNL_OUTPUT_DEFAULT: + switch (type) { + case NFT_MSG_NEWOBJ: + printf("add "); + obj = netlink_delinearize_obj(monh->ctx, nlo); + if (obj == NULL) { + nftnl_obj_free(nlo); + return MNL_CB_ERROR; + } + obj_print_plain(obj); + obj_free(obj); + printf("\n"); + break; + case NFT_MSG_DELOBJ: + family = nftnl_obj_get_u32(nlo, NFTNL_OBJ_FAMILY); + printf("delete %s %s %s %s\n", + obj_type_name(nftnl_obj_get_u32(nlo, NFTNL_OBJ_TYPE)), + family2str(family), + nftnl_obj_get_str(nlo, NFTNL_OBJ_TABLE), + nftnl_obj_get_str(nlo, NFTNL_OBJ_NAME)); + break; + } + break; + case NFTNL_OUTPUT_XML: + case NFTNL_OUTPUT_JSON: + nftnl_obj_fprintf(stdout, nlo, monh->format, + netlink_msg2nftnl_of(type)); + fprintf(stdout, "\n"); + break; + } + + nftnl_obj_free(nlo); + return MNL_CB_OK; +} + static void rule_map_decompose_cb(struct set *s, void *data) { if (s->flags & NFT_SET_INTERVAL) @@ -2363,6 +2421,72 @@ static void netlink_events_cache_delsets(struct netlink_mon_handler *monh, nftnl_rule_free(nlr); } +static void netlink_events_cache_addobj(struct netlink_mon_handler *monh, + const struct nlmsghdr *nlh) +{ + struct netlink_ctx obj_tmpctx; + struct nftnl_obj *nlo; + struct table *t; + struct obj *obj; + LIST_HEAD(msgs); + + memset(&obj_tmpctx, 0, sizeof(obj_tmpctx)); + init_list_head(&obj_tmpctx.list); + init_list_head(&msgs); + obj_tmpctx.msgs = &msgs; + + nlo = netlink_obj_alloc(nlh); + obj = netlink_delinearize_obj(&obj_tmpctx, nlo); + if (obj == NULL) + goto out; + + t = table_lookup(&obj->handle); + if (t == NULL) { + fprintf(stderr, "W: Unable to cache object: table not found.\n"); + obj_free(obj); + goto out; + } + + obj_add_hash(obj, t); +out: + nftnl_obj_free(nlo); +} + +static void netlink_events_cache_delobj(struct netlink_mon_handler *monh, + const struct nlmsghdr *nlh) +{ + struct nftnl_obj *nlo; + const char *name; + struct obj *obj; + struct handle h; + struct table *t; + uint32_t type; + + nlo = netlink_obj_alloc(nlh); + h.family = nftnl_obj_get_u32(nlo, NFTNL_OBJ_FAMILY); + h.table = nftnl_obj_get_str(nlo, NFTNL_OBJ_TABLE); + + name = nftnl_obj_get_str(nlo, NFTNL_OBJ_NAME); + type = nftnl_obj_get_u32(nlo, NFTNL_OBJ_TYPE); + + t = table_lookup(&h); + if (t == NULL) { + fprintf(stderr, "W: Unable to cache object: table not found.\n"); + goto out; + } + + obj = obj_lookup(t, name, type); + if (obj == NULL) { + fprintf(stderr, "W: Unable to find object in cache\n"); + goto out; + } + + list_del(&obj->list); + obj_free(obj); +out: + nftnl_obj_free(nlo); +} + static void netlink_events_cache_update(struct netlink_mon_handler *monh, const struct nlmsghdr *nlh, int type) { @@ -2386,6 +2510,12 @@ static void netlink_events_cache_update(struct netlink_mon_handler *monh, /* there are no notification for anon-set deletion */ netlink_events_cache_delsets(monh, nlh); break; + case NFT_MSG_NEWOBJ: + netlink_events_cache_addobj(monh, nlh); + break; + case NFT_MSG_DELOBJ: + netlink_events_cache_delobj(monh, nlh); + break; } } @@ -2697,6 +2827,10 @@ static int netlink_events_cb(const struct nlmsghdr *nlh, void *data) case NFT_MSG_TRACE: ret = netlink_events_trace_cb(nlh, type, monh); break; + case NFT_MSG_NEWOBJ: + case NFT_MSG_DELOBJ: + ret = netlink_events_obj_cb(nlh, type, monh); + break; } fflush(stdout); diff --git a/src/rule.c b/src/rule.c index b97213e9..b6dc755e 100644 --- a/src/rule.c +++ b/src/rule.c @@ -1158,6 +1158,19 @@ void obj_add_hash(struct obj *obj, struct table *table) list_add_tail(&obj->list, &table->objs); } +struct obj *obj_lookup(const struct table *table, const char *name, + uint32_t type) +{ + struct obj *obj; + + list_for_each_entry(obj, &table->objs, list) { + if (!strcmp(obj->handle.obj, name) && + obj->type == type) + return obj; + } + return NULL; +} + static void obj_print_data(const struct obj *obj, struct print_fmt_options *opts) { @@ -1229,6 +1242,18 @@ void obj_print(const struct obj *obj) obj_print_declaration(obj, &opts); } +void obj_print_plain(const struct obj *obj) +{ + struct print_fmt_options opts = { + .tab = "", + .nl = " ", + .table = obj->handle.table, + .family = family2str(obj->handle.family), + }; + + obj_print_declaration(obj, &opts); +} + static int do_list_obj(struct netlink_ctx *ctx, struct cmd *cmd, uint32_t type) { struct print_fmt_options opts = { -- cgit v1.2.3