]> git.proxmox.com Git - mirror_kronosnet.git/commitdiff
[access lists] automatically add and remove point to point access lists
authorFabio M. Di Nitto <fdinitto@redhat.com>
Thu, 14 Feb 2019 05:32:42 +0000 (06:32 +0100)
committerFabio M. Di Nitto <fdinitto@redhat.com>
Fri, 1 Mar 2019 08:15:43 +0000 (09:15 +0100)
those are not used just yet.

Signed-off-by: Fabio M. Di Nitto <fdinitto@redhat.com>
libknet/links.c
libknet/links_acl.c
libknet/links_acl.h
libknet/tests/int_links_acl.c

index 9348c55018d2507d758b7203f304948b803eded4..06ca28744b48e00ca170781e7b052b4fb07dcc24 100644 (file)
 #include "transports.h"
 #include "host.h"
 #include "threads_common.h"
+#include "links_acl.h"
+
+static void _link_del_all_acl(knet_handle_t knet_h, int sock)
+{
+       check_rmall(&knet_h->knet_transport_fd_tracker[sock].match_entry);
+}
+
+static int _link_add_default_acl(knet_handle_t knet_h, struct knet_link *kh_link)
+{
+       int err = -1;
+
+       switch(transport_get_proto(knet_h, kh_link->transport_type)) {
+               case LOOPBACK:
+                       /*
+                        * loopback does not require access lists
+                        */
+                       err = 0;
+                       break;
+               case IP_PROTO:
+                       err = ipcheck_addip(&knet_h->knet_transport_fd_tracker[kh_link->outsock].match_entry,
+                                           &kh_link->dst_addr, &kh_link->dst_addr, CHECK_TYPE_ADDRESS, CHECK_ACCEPT);
+                       break;
+               default:
+                       break;
+       }
+
+       return err;
+}
+
+static int _link_rm_default_acl(knet_handle_t knet_h, struct knet_link *kh_link)
+{
+       int err = -1;
+
+       switch(transport_get_proto(knet_h, kh_link->transport_type)) {
+               case LOOPBACK:
+                       /*
+                        * loopback does not require access lists
+                        */
+                       err = 0;
+                       break;
+               case IP_PROTO:
+                       err = ipcheck_rmip(&knet_h->knet_transport_fd_tracker[kh_link->outsock].match_entry,
+                                          &kh_link->dst_addr, &kh_link->dst_addr, CHECK_TYPE_ADDRESS, CHECK_ACCEPT);
+                       break;
+               default:
+                       break;
+       }
+
+       return err;
+}
 
 int _link_updown(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t link_id,
                 unsigned int enabled, unsigned int connected)
@@ -247,6 +297,21 @@ int knet_link_set_config(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t l
                err = -1;
                goto exit_unlock;
        }
+
+       /*
+        * we can only configure default access lists if we know both endpoints
+        */
+       if (link->dynamic == KNET_LINK_STATIC) {
+               log_debug(knet_h, KNET_SUB_LINK, "Configuring default access lists for host: %u link: %u",
+                         host_id, link_id);
+               if (_link_add_default_acl(knet_h, link) < 0) {
+                       log_warn(knet_h, KNET_SUB_LINK, "Failed to configure default access lists for host: %u link: %u", host_id, link_id);
+                       savederrno = errno;
+                       err = -1;
+                       goto exit_unlock;
+               }
+       }
+
        link->configured = 1;
        log_debug(knet_h, KNET_SUB_LINK, "host: %u link: %u is configured",
                  host_id, link_id);
@@ -364,6 +429,7 @@ int knet_link_clear_config(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t
        int savederrno = 0, err = 0;
        struct knet_host *host;
        struct knet_link *link;
+       int sock;
 
        if (!knet_h) {
                errno = EINVAL;
@@ -410,6 +476,28 @@ int knet_link_clear_config(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t
                goto exit_unlock;
        }
 
+       /*
+        * remove well known access lists here.
+        * After the transport has done clearing the config,
+        * then we can remove any leftover access lists if the link
+        * is no longer in use.
+        */
+       if (link->dynamic == KNET_LINK_STATIC) {
+               if (_link_rm_default_acl(knet_h, link) < 0) {
+                       err = -1;
+                       savederrno = EBUSY;
+                       log_err(knet_h, KNET_SUB_LINK, "Host %u link %u: unable to remove default access list",
+                               host_id, link_id);
+                       goto exit_unlock;
+               }
+       }
+
+       /*
+        * cache it for later as we don't know if the transport
+        * will clear link info during clear_config.
+        */
+       sock = link->outsock;
+
        if ((transport_link_clear_config(knet_h, link) < 0)  &&
            (errno != EBUSY)) {
                savederrno = errno;
@@ -417,6 +505,14 @@ int knet_link_clear_config(knet_handle_t knet_h, knet_node_id_t host_id, uint8_t
                goto exit_unlock;
        }
 
+       /*
+        * remove any other access lists when the socket is no
+        * longer in use by the transport.
+        */
+       if (knet_h->knet_transport_fd_tracker[sock].transport == KNET_MAX_TRANSPORTS) {
+               _link_del_all_acl(knet_h, sock);
+       }
+
        memset(link, 0, sizeof(struct knet_link));
        link->link_id = link_id;
 
index 36474ee5fe4a667ddc9f2faaf8df4f9d06af7cae..bbd5d1a4d68042972b0fb608623cc614bb534901 100644 (file)
@@ -148,7 +148,7 @@ int ipcheck_validate(struct acl_match_entry **match_entry_head, struct sockaddr_
  * Routines to manuipulate access lists
  */
 
-void ipcheck_clear(struct acl_match_entry **match_entry_head)
+void check_rmall(struct acl_match_entry **match_entry_head)
 {
        struct acl_match_entry *next_match_entry;
        struct acl_match_entry *match_entry = *match_entry_head;
@@ -161,6 +161,62 @@ void ipcheck_clear(struct acl_match_entry **match_entry_head)
        *match_entry_head = NULL;
 }
 
+static struct acl_match_entry *ipcheck_findmatch(struct acl_match_entry **match_entry_head,
+                                                struct sockaddr_storage *ip1, struct sockaddr_storage *ip2,
+                                                check_type_t type, check_acceptreject_t acceptreject)
+{
+       struct acl_match_entry *match_entry = *match_entry_head;
+
+       while (match_entry) {
+               if ((!memcmp(&match_entry->addr1, ip1, sizeof(struct sockaddr_storage))) &&
+                   (!memcmp(&match_entry->addr2, ip2, sizeof(struct sockaddr_storage))) &&
+                   (match_entry->type == type) &&
+                   (match_entry->acceptreject == acceptreject)) {
+                       return match_entry;
+               }
+               match_entry = match_entry->next;
+       }
+
+       return NULL;
+}
+
+int ipcheck_rmip(struct acl_match_entry **match_entry_head,
+                struct sockaddr_storage *ip1, struct sockaddr_storage *ip2,
+                check_type_t type, check_acceptreject_t acceptreject)
+{
+       struct acl_match_entry *next_match_entry = NULL;
+       struct acl_match_entry *rm_match_entry;
+       struct acl_match_entry *match_entry = *match_entry_head;
+
+       rm_match_entry = ipcheck_findmatch(match_entry_head, ip1, ip2, type, acceptreject);
+       if (!rm_match_entry) {
+               return -1;
+       }
+
+       while (match_entry) {
+               next_match_entry = match_entry->next;
+               /*
+                * we are removing the list head, be careful
+                */
+               if (rm_match_entry == match_entry) {
+                       *match_entry_head = next_match_entry;
+                       free(match_entry);
+                       break;
+               }
+               /*
+                * the next one is the one we need to remove
+                */
+               if (rm_match_entry == next_match_entry) {
+                       match_entry->next = next_match_entry->next;
+                       free(next_match_entry);
+                       break;
+               }
+               match_entry = next_match_entry;
+       }
+
+       return 0;
+}
+
 int ipcheck_addip(struct acl_match_entry **match_entry_head,
                  struct sockaddr_storage *ip1, struct sockaddr_storage *ip2,
                  check_type_t type, check_acceptreject_t acceptreject)
@@ -180,6 +236,10 @@ int ipcheck_addip(struct acl_match_entry **match_entry_head,
            (ip1->ss_family != ip2->ss_family))
                return -1;
 
+       if (ipcheck_findmatch(match_entry_head, ip1, ip2, type, acceptreject) != NULL) {
+               return -1;
+       }
+
        new_match_entry = malloc(sizeof(struct acl_match_entry));
        if (!new_match_entry)
                return -1;
index cb4703b54153184b5a3f395388cbbb0bcff77c4b..658926676e83812a71648b97650769105f0122e9 100644 (file)
 
 int ipcheck_validate(struct acl_match_entry **match_entry_head, struct sockaddr_storage *checkip);
 
-void ipcheck_clear(struct acl_match_entry **match_entry_head);
-
 int ipcheck_addip(struct acl_match_entry **match_entry_head,
                  struct sockaddr_storage *ip1, struct sockaddr_storage *ip2,
                  check_type_t type, check_acceptreject_t acceptreject);
 
+int ipcheck_rmip(struct acl_match_entry **match_entry_head,
+                 struct sockaddr_storage *ip1, struct sockaddr_storage *ip2,
+                 check_type_t type, check_acceptreject_t acceptreject);
+
+void check_rmall(struct acl_match_entry **match_entry_head);
 #endif
index a958bd02a61e749536aa1cbfb8d642bfe6787a4b..ac14559e7c0e5fed848ecb96355c251ab318d128 100644 (file)
@@ -106,8 +106,8 @@ static int load_file(void)
        struct sockaddr_storage addr1;
        struct sockaddr_storage addr2;
 
-       ipcheck_clear(&match_entry_v4);
-       ipcheck_clear(&match_entry_v6);
+       check_rmall(&match_entry_v4);
+       check_rmall(&match_entry_v6);
 
        filterfile = fopen("int_links_acl.txt", "r");
        if (!filterfile) {
@@ -203,7 +203,7 @@ int main(int argc, char *argv[])
                }
        }
 
-       ipcheck_clear(&match_entry_v4);
-       ipcheck_clear(&match_entry_v6);
+       check_rmall(&match_entry_v4);
+       check_rmall(&match_entry_v6);
        return 0;
 }