From 7661461a3a2e8a6c9feb539d41ba4e454fccb037 Mon Sep 17 00:00:00 2001 From: Philippe Guibert Date: Wed, 7 Mar 2018 12:54:16 +0100 Subject: [PATCH] zebra: handle entry pointfs for ipset creation/destruction IPset and IPset entries structures are introduced. Those entries reflect the ipset structures and ipset hash sets that will be created on the kernel. Signed-off-by: Philippe Guibert --- lib/zclient.h | 12 ++++ zebra/zebra_ns.c | 14 ++++ zebra/zebra_ns.h | 4 ++ zebra/zebra_pbr.c | 158 ++++++++++++++++++++++++++++++++++++++++++++++ zebra/zebra_pbr.h | 61 ++++++++++++++++++ 5 files changed, 249 insertions(+) diff --git a/lib/zclient.h b/lib/zclient.h index e85eac73fb..a77b1c1f94 100644 --- a/lib/zclient.h +++ b/lib/zclient.h @@ -47,6 +47,11 @@ */ #define ZAPI_TCP_PATHNAME "@tcp" +/* IPset size name stands for the name of the ipset entry + * that can be created by using some zapi interfaces + */ +#define ZEBRA_IPSET_NAME_SIZE 32 + extern struct sockaddr_storage zclient_addr; extern socklen_t zclient_addr_len; @@ -367,6 +372,13 @@ enum zapi_route_notify_owner { ZAPI_ROUTE_REMOVE_FAIL, }; +enum ipset_type { + IPSET_NET_NET = 1, + IPSET_NET_PORT_NET, + IPSET_NET_PORT, + IPSET_NET +}; + enum zapi_rule_notify_owner { ZAPI_RULE_FAIL_INSTALL, ZAPI_RULE_INSTALLED, diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c index 52cf4351bc..f2a459cbb5 100644 --- a/zebra/zebra_ns.c +++ b/zebra/zebra_ns.c @@ -140,6 +140,14 @@ int zebra_ns_enable(ns_id_t ns_id, void **info) hash_create_size(8, zebra_pbr_rules_hash_key, zebra_pbr_rules_hash_equal, "Rules Hash"); + zns->ipset_hash = + hash_create_size(8, zebra_pbr_ipset_hash_key, + zebra_pbr_ipset_hash_equal, "IPset Hash"); + + zns->ipset_entry_hash = + hash_create_size(8, zebra_pbr_ipset_entry_hash_key, + zebra_pbr_ipset_entry_hash_equal, + "IPset Hash Entry"); #if defined(HAVE_RTADV) rtadv_init(zns); #endif @@ -248,6 +256,12 @@ int zebra_ns_disable(ns_id_t ns_id, void **info) hash_clean(zns->rules_hash, zebra_pbr_rules_free); hash_free(zns->rules_hash); + hash_clean(zns->ipset_hash, zebra_pbr_ipset_free); + hash_free(zns->ipset_hash); + hash_clean(zns->ipset_entry_hash, + zebra_pbr_ipset_entry_free), + hash_free(zns->ipset_entry_hash); + while (!RB_EMPTY(zebra_ns_table_head, &zns->ns_tables)) { znst = RB_ROOT(zebra_ns_table_head, &zns->ns_tables); diff --git a/zebra/zebra_ns.h b/zebra/zebra_ns.h index 66b73148d2..c370101053 100644 --- a/zebra/zebra_ns.h +++ b/zebra/zebra_ns.h @@ -73,6 +73,10 @@ struct zebra_ns { struct hash *rules_hash; + struct hash *ipset_hash; + + struct hash *ipset_entry_hash; + /* Back pointer */ struct ns *ns; }; diff --git a/zebra/zebra_pbr.c b/zebra/zebra_pbr.c index 4b93168846..1855b54371 100644 --- a/zebra/zebra_pbr.c +++ b/zebra/zebra_pbr.c @@ -129,6 +129,81 @@ static struct zebra_pbr_rule *pbr_rule_lookup_unique(struct zebra_ns *zns, return pul.rule; } +void zebra_pbr_ipset_free(void *arg) +{ + struct zebra_pbr_ipset *ipset; + + ipset = (struct zebra_pbr_ipset *)arg; + + XFREE(MTYPE_TMP, ipset); +} + +uint32_t zebra_pbr_ipset_hash_key(void *arg) +{ + struct zebra_pbr_ipset *ipset = (struct zebra_pbr_ipset *)arg; + uint32_t *pnt = (uint32_t *)ipset->ipset_name; + + return jhash2(pnt, ZEBRA_IPSET_NAME_SIZE, 0x63ab42de); +} + +int zebra_pbr_ipset_hash_equal(const void *arg1, const void *arg2) +{ + const struct zebra_pbr_ipset *r1, *r2; + + r1 = (const struct zebra_pbr_ipset *)arg1; + r2 = (const struct zebra_pbr_ipset *)arg2; + + if (r1->type != r2->type) + return 0; + if (r1->unique != r2->unique) + return 0; + if (strncmp(r1->ipset_name, r2->ipset_name, + ZEBRA_IPSET_NAME_SIZE)) + return 0; + return 1; +} + +void zebra_pbr_ipset_entry_free(void *arg) +{ + struct zebra_pbr_ipset_entry *ipset; + + ipset = (struct zebra_pbr_ipset_entry *)arg; + + XFREE(MTYPE_TMP, ipset); +} + +uint32_t zebra_pbr_ipset_entry_hash_key(void *arg) +{ + struct zebra_pbr_ipset_entry *ipset; + uint32_t key; + + ipset = (struct zebra_pbr_ipset_entry *)arg; + key = prefix_hash_key(&ipset->src); + key = jhash_1word(ipset->unique, key); + key = jhash_1word(prefix_hash_key(&ipset->dst), key); + + return key; +} + +int zebra_pbr_ipset_entry_hash_equal(const void *arg1, const void *arg2) +{ + const struct zebra_pbr_ipset_entry *r1, *r2; + + r1 = (const struct zebra_pbr_ipset_entry *)arg1; + r2 = (const struct zebra_pbr_ipset_entry *)arg2; + + if (r1->unique != r2->unique) + return 0; + + if (!prefix_same(&r1->src, &r2->src)) + return 0; + + if (!prefix_same(&r1->dst, &r2->dst)) + return 0; + + return 1; +} + static void *pbr_rule_alloc_intern(void *arg) { struct zebra_pbr_rule *zpr; @@ -194,6 +269,89 @@ void zebra_pbr_client_close_cleanup(int sock) hash_iterate(zns->rules_hash, zebra_pbr_cleanup_rules, &sock); } +static void *pbr_ipset_alloc_intern(void *arg) +{ + struct zebra_pbr_ipset *zpi; + struct zebra_pbr_ipset *new; + + zpi = (struct zebra_pbr_ipset *)arg; + + new = XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_ipset)); + + memcpy(new, zpi, sizeof(*zpi)); + + return new; +} + +void zebra_pbr_create_ipset(struct zebra_ns *zns, + struct zebra_pbr_ipset *ipset) +{ + (void)hash_get(zns->ipset_hash, ipset, pbr_ipset_alloc_intern); + /* TODO: + * - Netlink call + */ +} + +void zebra_pbr_destroy_ipset(struct zebra_ns *zns, + struct zebra_pbr_ipset *ipset) +{ + struct zebra_pbr_ipset *lookup; + + lookup = hash_lookup(zns->ipset_hash, ipset); + /* TODO: + * - Netlink destroy from kernel + * - ?? destroy ipset entries before + */ + if (lookup) + XFREE(MTYPE_TMP, lookup); + else + zlog_warn("%s: IPSet being deleted we know nothing about", + __PRETTY_FUNCTION__); +} + +static void *pbr_ipset_entry_alloc_intern(void *arg) +{ + struct zebra_pbr_ipset_entry *zpi; + struct zebra_pbr_ipset_entry *new; + + zpi = (struct zebra_pbr_ipset_entry *)arg; + + new = XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_ipset_entry)); + + memcpy(new, zpi, sizeof(*zpi)); + + return new; +} + +void zebra_pbr_add_ipset_entry(struct zebra_ns *zns, + struct zebra_pbr_ipset_entry *ipset) +{ + (void)hash_get(zns->ipset_entry_hash, ipset, + pbr_ipset_entry_alloc_intern); + /* TODO: + * - attach to ipset list + * - Netlink add to kernel + */ +} + +void zebra_pbr_del_ipset_entry(struct zebra_ns *zns, + struct zebra_pbr_ipset_entry *ipset) +{ + struct zebra_pbr_ipset_entry *lookup; + + lookup = hash_lookup(zns->ipset_hash, ipset); + /* TODO: + * - Netlink destroy + * - detach from ipset list + * - ?? if no more entres, delete ipset + */ + if (lookup) + XFREE(MTYPE_TMP, lookup); + else + zlog_warn("%s: IPSet being deleted we know nothing about", + __PRETTY_FUNCTION__); +} + /* * Handle success or failure of rule (un)install in the kernel. */ diff --git a/zebra/zebra_pbr.h b/zebra/zebra_pbr.h index f910d8e742..31e20a3078 100644 --- a/zebra/zebra_pbr.h +++ b/zebra/zebra_pbr.h @@ -31,6 +31,7 @@ #include "rt.h" + /* * A PBR filter * @@ -99,8 +100,60 @@ struct zebra_pbr_rule { struct zebra_pbr_action action; }; + +/* + * An IPSet Entry Filter + * + * This is a filter mapped on ipset entries + */ +struct zebra_pbr_ipset { + /* + * Originating zclient sock fd, so we can know who to send + * back to. + */ + int sock; + + uint32_t unique; + + /* type is encoded as uint32_t + * but value is an enum ipset_type + */ + uint32_t type; + char ipset_name[ZEBRA_IPSET_NAME_SIZE]; +}; + +/* + * An IPSet Entry Filter + * + * This is a filter mapped on ipset entries + */ +struct zebra_pbr_ipset_entry { + /* + * Originating zclient sock fd, so we can know who to send + * back to. + */ + int sock; + + uint32_t unique; + + struct prefix src; + struct prefix dst; + + uint32_t filter_bm; + + struct zebra_pbr_ipset *backpointer; +}; + void zebra_pbr_add_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule); void zebra_pbr_del_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule); +void zebra_pbr_create_ipset(struct zebra_ns *zns, + struct zebra_pbr_ipset *ipset); +void zebra_pbr_destroy_ipset(struct zebra_ns *zns, + struct zebra_pbr_ipset *ipset); +void zebra_pbr_add_ipset_entry(struct zebra_ns *zns, + struct zebra_pbr_ipset_entry *ipset); +void zebra_pbr_del_ipset_entry(struct zebra_ns *zns, + struct zebra_pbr_ipset_entry *ipset); /* * Install specified rule for a specific interface. @@ -138,4 +191,12 @@ extern void zebra_pbr_rules_free(void *arg); extern uint32_t zebra_pbr_rules_hash_key(void *arg); extern int zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2); +extern void zebra_pbr_ipset_free(void *arg); +extern uint32_t zebra_pbr_ipset_hash_key(void *arg); +extern int zebra_pbr_ipset_hash_equal(const void *arg1, const void *arg2); + +extern void zebra_pbr_ipset_entry_free(void *arg); +extern uint32_t zebra_pbr_ipset_entry_hash_key(void *arg); +extern int zebra_pbr_ipset_entry_hash_equal(const void *arg1, const void *arg2); + #endif /* _ZEBRA_PBR_H */ -- 2.39.5