diff options
Diffstat (limited to 'zebra/zebra_pbr.c')
| -rw-r--r-- | zebra/zebra_pbr.c | 384 |
1 files changed, 366 insertions, 18 deletions
diff --git a/zebra/zebra_pbr.c b/zebra/zebra_pbr.c index 4b93168846..27daa2d807 100644 --- a/zebra/zebra_pbr.c +++ b/zebra/zebra_pbr.c @@ -50,16 +50,22 @@ uint32_t zebra_pbr_rules_hash_key(void *arg) uint32_t key; rule = (struct zebra_pbr_rule *)arg; - key = jhash_3words(rule->seq, rule->priority, rule->action.table, - prefix_hash_key(&rule->filter.src_ip)); + key = jhash_3words(rule->rule.seq, rule->rule.priority, + rule->rule.action.table, + prefix_hash_key(&rule->rule.filter.src_ip)); if (rule->ifp) key = jhash_1word(rule->ifp->ifindex, key); else key = jhash_1word(0, key); - return jhash_3words(rule->filter.src_port, rule->filter.dst_port, - prefix_hash_key(&rule->filter.dst_ip), - jhash_1word(rule->unique, key)); + if (rule->rule.filter.fwmark) + key = jhash_1word(rule->rule.filter.fwmark, key); + else + key = jhash_1word(0, key); + return jhash_3words(rule->rule.filter.src_port, + rule->rule.filter.dst_port, + prefix_hash_key(&rule->rule.filter.dst_ip), + jhash_1word(rule->rule.unique, key)); } int zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2) @@ -69,28 +75,31 @@ int zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2) r1 = (const struct zebra_pbr_rule *)arg1; r2 = (const struct zebra_pbr_rule *)arg2; - if (r1->seq != r2->seq) + if (r1->rule.seq != r2->rule.seq) return 0; - if (r1->priority != r2->priority) + if (r1->rule.priority != r2->rule.priority) return 0; - if (r1->unique != r2->unique) + if (r1->rule.unique != r2->rule.unique) return 0; - if (r1->action.table != r2->action.table) + if (r1->rule.action.table != r2->rule.action.table) return 0; - if (r1->filter.src_port != r2->filter.src_port) + if (r1->rule.filter.src_port != r2->rule.filter.src_port) return 0; - if (r1->filter.dst_port != r2->filter.dst_port) + if (r1->rule.filter.dst_port != r2->rule.filter.dst_port) return 0; - if (!prefix_same(&r1->filter.src_ip, &r2->filter.src_ip)) + if (r1->rule.filter.fwmark != r2->rule.filter.fwmark) return 0; - if (!prefix_same(&r1->filter.dst_ip, &r2->filter.dst_ip)) + if (!prefix_same(&r1->rule.filter.src_ip, &r2->rule.filter.src_ip)) + return 0; + + if (!prefix_same(&r1->rule.filter.dst_ip, &r2->rule.filter.dst_ip)) return 0; if (r1->ifp != r2->ifp) @@ -99,17 +108,17 @@ int zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2) return 1; } -struct pbr_unique_lookup { +struct pbr_rule_unique_lookup { struct zebra_pbr_rule *rule; uint32_t unique; }; static int pbr_rule_lookup_unique_walker(struct hash_backet *b, void *data) { - struct pbr_unique_lookup *pul = data; + struct pbr_rule_unique_lookup *pul = data; struct zebra_pbr_rule *rule = b->data; - if (pul->unique == rule->unique) { + if (pul->unique == rule->rule.unique) { pul->rule = rule; return HASHWALK_ABORT; } @@ -120,7 +129,7 @@ static int pbr_rule_lookup_unique_walker(struct hash_backet *b, void *data) static struct zebra_pbr_rule *pbr_rule_lookup_unique(struct zebra_ns *zns, uint32_t unique) { - struct pbr_unique_lookup pul; + struct pbr_rule_unique_lookup pul; pul.unique = unique; pul.rule = NULL; @@ -129,6 +138,126 @@ 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_HASH_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; +} + +void zebra_pbr_iptable_free(void *arg) +{ + struct zebra_pbr_iptable *iptable; + + iptable = (struct zebra_pbr_iptable *)arg; + + XFREE(MTYPE_TMP, iptable); +} + +uint32_t zebra_pbr_iptable_hash_key(void *arg) +{ + struct zebra_pbr_iptable *iptable = (struct zebra_pbr_iptable *)arg; + uint32_t *pnt = (uint32_t *)&(iptable->ipset_name); + uint32_t key; + + key = jhash2(pnt, ZEBRA_IPSET_NAME_HASH_SIZE, + 0x63ab42de); + key = jhash_1word(iptable->fwmark, key); + return jhash_3words(iptable->filter_bm, iptable->type, + iptable->unique, key); +} + +int zebra_pbr_iptable_hash_equal(const void *arg1, const void *arg2) +{ + const struct zebra_pbr_iptable *r1, *r2; + + r1 = (const struct zebra_pbr_iptable *)arg1; + r2 = (const struct zebra_pbr_iptable *)arg2; + + if (r1->type != r2->type) + return 0; + if (r1->unique != r2->unique) + return 0; + if (r1->filter_bm != r2->filter_bm) + return 0; + if (r1->fwmark != r2->fwmark) + return 0; + if (r1->action != r2->action) + return 0; + if (strncmp(r1->ipset_name, r2->ipset_name, + ZEBRA_IPSET_NAME_SIZE)) + return 0; + return 1; +} + static void *pbr_rule_alloc_intern(void *arg) { struct zebra_pbr_rule *zpr; @@ -146,7 +275,7 @@ static void *pbr_rule_alloc_intern(void *arg) void zebra_pbr_add_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule) { struct zebra_pbr_rule *unique = - pbr_rule_lookup_unique(zns, rule->unique); + pbr_rule_lookup_unique(zns, rule->rule.unique); (void)hash_get(zns->rules_hash, rule, pbr_rule_alloc_intern); kernel_add_pbr_rule(rule); @@ -194,6 +323,162 @@ 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 Entry being deleted we know nothing about", + __PRETTY_FUNCTION__); +} + +struct pbr_ipset_name_lookup { + struct zebra_pbr_ipset *ipset; + char ipset_name[ZEBRA_IPSET_NAME_SIZE]; +}; + +static int zebra_pbr_ipset_pername_walkcb(struct hash_backet *backet, void *arg) +{ + struct pbr_ipset_name_lookup *pinl = + (struct pbr_ipset_name_lookup *)arg; + struct zebra_pbr_ipset *zpi = (struct zebra_pbr_ipset *)backet->data; + + if (!strncmp(pinl->ipset_name, zpi->ipset_name, + ZEBRA_IPSET_NAME_SIZE)) { + pinl->ipset = zpi; + return HASHWALK_ABORT; + } + return HASHWALK_CONTINUE; +} + +struct zebra_pbr_ipset *zebra_pbr_lookup_ipset_pername(struct zebra_ns *zns, + char *ipsetname) +{ + struct pbr_ipset_name_lookup pinl; + struct pbr_ipset_name_lookup *ptr = &pinl; + + if (!ipsetname) + return NULL; + memset(ptr, 0, sizeof(struct pbr_ipset_name_lookup)); + snprintf((char *)ptr->ipset_name, ZEBRA_IPSET_NAME_SIZE, "%s", + ipsetname); + hash_walk(zns->ipset_hash, zebra_pbr_ipset_pername_walkcb, ptr); + return ptr->ipset; +} + +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_entry_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__); +} + +static void *pbr_iptable_alloc_intern(void *arg) +{ + struct zebra_pbr_iptable *zpi; + struct zebra_pbr_iptable *new; + + zpi = (struct zebra_pbr_iptable *)arg; + + new = XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_iptable)); + + memcpy(new, zpi, sizeof(*zpi)); + + return new; +} + +void zebra_pbr_add_iptable(struct zebra_ns *zns, + struct zebra_pbr_iptable *iptable) +{ + (void)hash_get(zns->iptable_hash, iptable, + pbr_iptable_alloc_intern); + /* TODO call netlink layer */ +} + +void zebra_pbr_del_iptable(struct zebra_ns *zns, + struct zebra_pbr_iptable *iptable) +{ + struct zebra_pbr_ipset_entry *lookup; + + lookup = hash_lookup(zns->iptable_hash, iptable); + /* TODO: + * - call netlink layer + * - detach from iptable list + */ + if (lookup) + XFREE(MTYPE_TMP, lookup); + else + zlog_warn("%s: IPTable being deleted we know nothing about", + __PRETTY_FUNCTION__); +} + /* * Handle success or failure of rule (un)install in the kernel. */ @@ -215,6 +500,69 @@ void kernel_pbr_rule_add_del_status(struct zebra_pbr_rule *rule, } /* + * Handle success or failure of ipset (un)install in the kernel. + */ +void kernel_pbr_ipset_add_del_status(struct zebra_pbr_ipset *ipset, + enum southbound_results res) +{ + switch (res) { + case SOUTHBOUND_INSTALL_SUCCESS: + zsend_ipset_notify_owner(ipset, ZAPI_IPSET_INSTALLED); + break; + case SOUTHBOUND_INSTALL_FAILURE: + zsend_ipset_notify_owner(ipset, ZAPI_IPSET_FAIL_INSTALL); + break; + case SOUTHBOUND_DELETE_SUCCESS: + case SOUTHBOUND_DELETE_FAILURE: + /* TODO : handling of delete event */ + break; + } +} + +/* + * Handle success or failure of ipset (un)install in the kernel. + */ +void kernel_pbr_ipset_entry_add_del_status( + struct zebra_pbr_ipset_entry *ipset, + enum southbound_results res) +{ + switch (res) { + case SOUTHBOUND_INSTALL_SUCCESS: + zsend_ipset_entry_notify_owner(ipset, + ZAPI_IPSET_ENTRY_INSTALLED); + break; + case SOUTHBOUND_INSTALL_FAILURE: + zsend_ipset_entry_notify_owner(ipset, + ZAPI_IPSET_ENTRY_FAIL_INSTALL); + break; + case SOUTHBOUND_DELETE_SUCCESS: + case SOUTHBOUND_DELETE_FAILURE: + /* TODO : handling of delete event */ + break; + } +} + +/* + * Handle success or failure of ipset (un)install in the kernel. + */ +void kernel_pbr_iptable_add_del_status(struct zebra_pbr_iptable *iptable, + enum southbound_results res) +{ + switch (res) { + case SOUTHBOUND_INSTALL_SUCCESS: + zsend_iptable_notify_owner(iptable, ZAPI_IPTABLE_INSTALLED); + break; + case SOUTHBOUND_INSTALL_FAILURE: + zsend_iptable_notify_owner(iptable, ZAPI_IPTABLE_FAIL_INSTALL); + break; + case SOUTHBOUND_DELETE_SUCCESS: + case SOUTHBOUND_DELETE_FAILURE: + /* TODO : handling of delete event */ + break; + } +} + +/* * Handle rule delete notification from kernel. */ int kernel_pbr_rule_del(struct zebra_pbr_rule *rule) |
