summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilippe Guibert <philippe.guibert@6wind.com>2018-03-12 09:23:48 +0100
committerPhilippe Guibert <philippe.guibert@6wind.com>2018-04-16 14:40:43 +0200
commit7abd6c4fa0331bc6a416c69080218457f9efc90f (patch)
treed6e0fdfceebd71c106b608fc66d9b24df40c3228
parentzebra: pbr rule structure is being added fwmark tag (diff)
downloadfrr-7abd6c4fa0331bc6a416c69080218457f9efc90f.tar.xz
frr-7abd6c4fa0331bc6a416c69080218457f9efc90f.zip
zebra: add IPTABLE_ADD and IPTABLE_DEL commands in zapi
Those messages permit a remote daemon to configure an iptable entry. A structure is defined that maps to an iptable entry. More specifically, this structure proposes to associate fwmark, and a table ID. Adding to the configuration, the initialisation of iptables hash list is done into zebra netnamespace. Also a hook for notifying the sender that the iptables has been correctly set is done. Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
-rw-r--r--lib/zclient.h15
-rw-r--r--zebra/zebra_ns.c9
-rw-r--r--zebra/zebra_ns.h2
-rw-r--r--zebra/zebra_pbr.c104
-rw-r--r--zebra/zebra_pbr.h41
-rw-r--r--zebra/zserv.c56
-rw-r--r--zebra/zserv.h4
7 files changed, 231 insertions, 0 deletions
diff --git a/lib/zclient.h b/lib/zclient.h
index b8896f6b9..2cdcefd5e 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -52,6 +52,12 @@
*/
#define ZEBRA_IPSET_NAME_SIZE 32
+/* IPTable action is defined by two values: either
+ * forward or drop
+ */
+#define ZEBRA_IPTABLES_FORWARD 0
+#define ZEBRA_IPTABLES_DROP 1
+
extern struct sockaddr_storage zclient_addr;
extern socklen_t zclient_addr_len;
@@ -146,6 +152,9 @@ typedef enum {
ZEBRA_IPSET_ENTRY_DELETE,
ZEBRA_IPSET_NOTIFY_OWNER,
ZEBRA_IPSET_ENTRY_NOTIFY_OWNER,
+ ZEBRA_IPTABLE_ADD,
+ ZEBRA_IPTABLE_DELETE,
+ ZEBRA_IPTABLE_NOTIFY_OWNER,
} zebra_message_types_t;
struct redist_proto {
@@ -409,6 +418,12 @@ enum zapi_ipset_entry_notify_owner {
ZAPI_IPSET_ENTRY_REMOVED,
};
+enum zapi_iptable_notify_owner {
+ ZAPI_IPTABLE_FAIL_INSTALL,
+ ZAPI_IPTABLE_INSTALLED,
+ ZAPI_IPTABLE_REMOVED,
+};
+
/* Zebra MAC types */
#define ZEBRA_MACIP_TYPE_STICKY 0x01 /* Sticky MAC*/
#define ZEBRA_MACIP_TYPE_GW 0x02 /* gateway (SVI) mac*/
diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c
index f2a459cbb..5c62e366a 100644
--- a/zebra/zebra_ns.c
+++ b/zebra/zebra_ns.c
@@ -148,6 +148,12 @@ int zebra_ns_enable(ns_id_t ns_id, void **info)
hash_create_size(8, zebra_pbr_ipset_entry_hash_key,
zebra_pbr_ipset_entry_hash_equal,
"IPset Hash Entry");
+
+ zns->iptable_hash =
+ hash_create_size(8, zebra_pbr_iptable_hash_key,
+ zebra_pbr_iptable_hash_equal,
+ "IPtable Hash Entry");
+
#if defined(HAVE_RTADV)
rtadv_init(zns);
#endif
@@ -261,6 +267,9 @@ int zebra_ns_disable(ns_id_t ns_id, void **info)
hash_clean(zns->ipset_entry_hash,
zebra_pbr_ipset_entry_free),
hash_free(zns->ipset_entry_hash);
+ hash_clean(zns->iptable_hash,
+ zebra_pbr_iptable_free);
+ hash_free(zns->iptable_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 c37010105..fbf88ae6e 100644
--- a/zebra/zebra_ns.h
+++ b/zebra/zebra_ns.h
@@ -77,6 +77,8 @@ struct zebra_ns {
struct hash *ipset_entry_hash;
+ struct hash *iptable_hash;
+
/* Back pointer */
struct ns *ns;
};
diff --git a/zebra/zebra_pbr.c b/zebra/zebra_pbr.c
index dd6e16bb7..42b3f37da 100644
--- a/zebra/zebra_pbr.c
+++ b/zebra/zebra_pbr.c
@@ -211,6 +211,51 @@ int zebra_pbr_ipset_entry_hash_equal(const void *arg1, const void *arg2)
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;
@@ -383,6 +428,45 @@ void zebra_pbr_del_ipset_entry(struct zebra_ns *zns,
__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.
*/
@@ -447,6 +531,26 @@ void kernel_pbr_ipset_entry_add_del_status(
}
/*
+ * 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)
diff --git a/zebra/zebra_pbr.h b/zebra/zebra_pbr.h
index 9f25c6f43..6de33ee2e 100644
--- a/zebra/zebra_pbr.h
+++ b/zebra/zebra_pbr.h
@@ -148,6 +148,35 @@ struct zebra_pbr_ipset_entry {
struct zebra_pbr_ipset *backpointer;
};
+/*
+ * An IPTables Action
+ *
+ * This is a filter mapped on ipset entries
+ */
+struct zebra_pbr_iptable {
+ /*
+ * Originating zclient sock fd, so we can know who to send
+ * back to.
+ */
+ int sock;
+
+ uint32_t unique;
+
+ /* include ipset type
+ */
+ uint32_t type;
+
+ /* include which IP is to be filtered
+ */
+ uint32_t filter_bm;
+
+ uint32_t fwmark;
+
+ uint32_t action;
+
+ char ipset_name[ZEBRA_IPSET_NAME_SIZE];
+};
+
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,
@@ -161,6 +190,11 @@ void zebra_pbr_add_ipset_entry(struct zebra_ns *zns,
void zebra_pbr_del_ipset_entry(struct zebra_ns *zns,
struct zebra_pbr_ipset_entry *ipset);
+void zebra_pbr_add_iptable(struct zebra_ns *zns,
+ struct zebra_pbr_iptable *iptable);
+void zebra_pbr_del_iptable(struct zebra_ns *zns,
+ struct zebra_pbr_iptable *iptable);
+
/*
* Install specified rule for a specific interface.
* It is possible that the user-defined sequence number and the one in the
@@ -196,6 +230,9 @@ extern void kernel_pbr_ipset_entry_add_del_status(
struct zebra_pbr_ipset_entry *ipset,
enum southbound_results res);
+extern void kernel_pbr_iptable_add_del_status(struct zebra_pbr_iptable *iptable,
+ enum southbound_results res);
+
/*
* Handle rule delete notification from kernel.
*/
@@ -220,4 +257,8 @@ 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);
+extern void zebra_pbr_iptable_free(void *arg);
+extern uint32_t zebra_pbr_iptable_hash_key(void *arg);
+extern int zebra_pbr_iptable_hash_equal(const void *arg1, const void *arg2);
+
#endif /* _ZEBRA_PBR_H */
diff --git a/zebra/zserv.c b/zebra/zserv.c
index 4d9898ae2..b7bce1f56 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -817,6 +817,35 @@ void zsend_ipset_entry_notify_owner(
zebra_server_send_message(client, s);
}
+void zsend_iptable_notify_owner(struct zebra_pbr_iptable *iptable,
+ enum zapi_iptable_notify_owner note)
+{
+ struct listnode *node;
+ struct zserv *client;
+ struct stream *s;
+
+ if (IS_ZEBRA_DEBUG_PACKET)
+ zlog_debug("%s: Notifying %u", __PRETTY_FUNCTION__,
+ iptable->unique);
+
+ for (ALL_LIST_ELEMENTS_RO(zebrad.client_list, node, client)) {
+ if (iptable->sock == client->sock)
+ break;
+ }
+
+ if (!client)
+ return;
+
+ s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+
+ zclient_create_header(s, ZEBRA_IPTABLE_NOTIFY_OWNER, VRF_DEFAULT);
+ stream_put(s, &note, sizeof(note));
+ stream_putl(s, iptable->unique);
+ stream_putw_at(s, 0, stream_get_endp(s));
+
+ zebra_server_send_message(client, s);
+}
+
/* Router-id is updated. Send ZEBRA_ROUTER_ID_ADD to client. */
int zsend_router_id_update(struct zserv *client, struct prefix *p,
vrf_id_t vrf_id)
@@ -2854,6 +2883,31 @@ stream_failure:
return;
}
+static inline void zread_iptable(ZAPI_HANDLER_ARGS)
+{
+ struct zebra_pbr_iptable zpi;
+ struct stream *s;
+
+ s = msg;
+
+ memset(&zpi, 0, sizeof(zpi));
+
+ zpi.sock = client->sock;
+ STREAM_GETL(s, zpi.unique);
+ STREAM_GETL(s, zpi.type);
+ STREAM_GETL(s, zpi.filter_bm);
+ STREAM_GETL(s, zpi.action);
+ STREAM_GETL(s, zpi.fwmark);
+ STREAM_GET(&zpi.ipset_name, s,
+ ZEBRA_IPSET_NAME_SIZE);
+
+ if (hdr->command == ZEBRA_IPTABLE_ADD)
+ zebra_pbr_add_iptable(zvrf->zns, &zpi);
+ else
+ zebra_pbr_del_iptable(zvrf->zns, &zpi);
+stream_failure:
+ return;
+}
void (*zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
[ZEBRA_ROUTER_ID_ADD] = zread_router_id_add,
@@ -2919,6 +2973,8 @@ void (*zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
[ZEBRA_IPSET_DESTROY] = zread_ipset,
[ZEBRA_IPSET_ENTRY_ADD] = zread_ipset_entry,
[ZEBRA_IPSET_ENTRY_DELETE] = zread_ipset_entry,
+ [ZEBRA_IPTABLE_ADD] = zread_iptable,
+ [ZEBRA_IPTABLE_DELETE] = zread_iptable,
};
static inline void zserv_handle_commands(struct zserv *client,
diff --git a/zebra/zserv.h b/zebra/zserv.h
index e66c1811c..f68e87956 100644
--- a/zebra/zserv.h
+++ b/zebra/zserv.h
@@ -190,6 +190,7 @@ extern int zsend_route_notify_owner(struct route_entry *re, struct prefix *p,
struct zebra_pbr_rule;
struct zebra_pbr_ipset;
struct zebra_pbr_ipset_entry;
+struct zebra_pbr_iptable;
extern void zsend_rule_notify_owner(struct zebra_pbr_rule *rule,
enum zapi_rule_notify_owner note);
extern void zsend_ipset_notify_owner(
@@ -198,6 +199,9 @@ extern void zsend_ipset_notify_owner(
extern void zsend_ipset_entry_notify_owner(
struct zebra_pbr_ipset_entry *ipset,
enum zapi_ipset_entry_notify_owner note);
+extern void zsend_iptable_notify_owner(
+ struct zebra_pbr_iptable *iptable,
+ enum zapi_iptable_notify_owner note);
extern void zserv_nexthop_num_warn(const char *, const struct prefix *,
const unsigned int);