[hipl-dev] [Merge] lp:~christian-roeller/hipl/whitelisting into lp:hipl

  • From: Christian Röller <christian.roeller@xxxxxxxxxxxxxx>
  • To: mp+72408@xxxxxxxxxxxxxxxxxx
  • Date: Mon, 22 Aug 2011 11:47:44 -0000

Christian Röller has proposed merging lp:~christian-roeller/hipl/whitelisting 
into lp:hipl.

Requested reviews:
  Diego Biurrun (diego-biurrun)
  Stefan Götz (stefan.goetz)

For more details, see:
https://code.launchpad.net/~christian-roeller/hipl/whitelisting/+merge/72408

Change in the whitelisting of hipl:

The problem with the current whitelisting fuction is, that it only considers 
the interface-indexes. So when you for instance want to whitelist your eth0 
interface, but there are also alias-interfaces for this interface on your 
machine, then a change for this alias-interfaces would also trigger an update, 
because these interfaces have the same interface-index for the kernel.

To have a more concrete possibility to whitelist interfaces, I extend the 
whitelist-structure with the interface-label. So that when you now whitelist 
your interface eth0, only changes on this interface would trigger an update and 
not for the alias-interfaces.

I did this by just checking for every incoming NEWADDR netlinkevent, if the 
corresponding label for this address is whitelisted or not.

So please have a look and just tell if you are fine with this...
-- 
https://code.launchpad.net/~christian-roeller/hipl/whitelisting/+merge/72408
Your team HIPL core team is subscribed to branch lp:hipl.
=== modified file 'hipd/netdev.c'
--- hipd/netdev.c       2011-08-15 14:11:56 +0000
+++ hipd/netdev.c       2011-08-22 11:47:21 +0000
@@ -97,19 +97,28 @@
  * size array.
  * Free slots are signaled by the value -1.
  */
-static int hip_netdev_white_list[HIP_NETDEV_MAX_WHITE_LIST];
-static int hip_netdev_white_list_count = 0;
+struct hip_netdev_whiteliste_entry {
+    unsigned int if_index;
+    char         if_label[IF_NAMESIZE];
+};
+static struct hip_netdev_whiteliste_entry 
hip_netdev_white_list[HIP_NETDEV_MAX_WHITE_LIST];
+static unsigned int                       hip_netdev_white_list_count = 0;
 
 /**
- * Add a network interface index number to the list of white listed
+ * Add a network interface index number plus label to the list of white listed
  * network interfaces.
  *
  * @param if_index the network interface index to be white listed
+ * @param device_name the network interface label to be white listed
  */
-static void hip_netdev_white_list_add_index(int if_index)
+static void hip_netdev_white_list_add_index_and_name(const unsigned int 
if_index,
+                                                     const char *const 
device_name)
 {
     if (hip_netdev_white_list_count < HIP_NETDEV_MAX_WHITE_LIST) {
-        hip_netdev_white_list[hip_netdev_white_list_count++] = if_index;
+        hip_netdev_white_list[hip_netdev_white_list_count].if_index = if_index;
+        strncpy(hip_netdev_white_list[hip_netdev_white_list_count].if_label,
+                device_name, sizeof(hip_netdev_white_list[0].if_label) - 1);
+        hip_netdev_white_list_count++;
     } else {
         /* We should NEVER run out of white list slots!!! */
         HIP_DIE("Error: ran out of space for white listed interfaces!\n");
@@ -117,17 +126,22 @@
 }
 
 /**
- * Test if the given network interface index is white listed.
+ * Test if the given network interface index plus label is white listed.
  *
  * @param if_index the index of the network interface to be tested
+ * @param device_name the label of the network interface to be tested
  * @return 1 if the index is whitelisted or zero otherwise
  */
-static int hip_netdev_is_in_white_list(int if_index)
+static int hip_netdev_is_in_white_list(const unsigned int if_index,
+                                       const char *const device_name)
 {
-    int i = 0;
-    for (i = 0; i < hip_netdev_white_list_count; i++) {
-        if (hip_netdev_white_list[i] == if_index) {
-            return 1;
+    if (hip_netdev_white_list_count > 0) {
+        for (unsigned int i = 0; i < hip_netdev_white_list_count; i++) {
+            if (hip_netdev_white_list[i].if_index == if_index &&
+                !strncmp(hip_netdev_white_list[i].if_label,
+                         device_name, 
sizeof(hip_netdev_white_list[0].if_label))) {
+                return 1;
+            }
         }
     }
     return 0;
@@ -146,19 +160,18 @@
     int          sock = 0;
     int          ret  = 0;
 
-    strncpy(ifr.ifr_name, device_name, IF_NAMESIZE);
+    strncpy(ifr.ifr_name, device_name, sizeof(ifr.ifr_name) - 1);
     sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
 
     if (ioctl(sock, SIOCGIFINDEX, &ifr) == 0) {
         ret = 1;
-        hip_netdev_white_list_add_index(ifr.ifr_ifindex);
+        hip_netdev_white_list_add_index_and_name(ifr.ifr_ifindex, device_name);
         HIP_DEBUG("Adding device <%s> to white list with index <%i>.\n",
                   device_name,
                   ifr.ifr_ifindex);
     } else {
         ret = 0;
     }
-
     if (sock) {
         close(sock);
     }
@@ -632,7 +645,7 @@
         HIP_IFEL(!(if_index = if_nametoindex(g_iface->ifa_name)),
                  -1, "if_nametoindex failed\n");
         /* Check if our interface is in the whitelist */
-        if ((hip_netdev_white_list_count > 0) && 
(!hip_netdev_is_in_white_list(if_index))) {
+        if ((!hip_netdev_is_in_white_list(if_index, g_iface->ifa_name))) {
             continue;
         }
 
@@ -1120,6 +1133,40 @@
 }
 
 /**
+ * Gives you the interface label for a given IPv4 or IPv6 address.
+ *
+ * @param addr address for which you want to know the label
+ * @param label pointer where the function stores the label
+ * @return zero on success, one on error and write the label in param label
+ * if the given address exists in the system
+ */
+int hip_find_label_for_address(const struct sockaddr *const addr,
+                               char *const label)
+{
+    int             res = 1;
+    struct ifaddrs *myaddrs, *ifa = NULL;
+
+    getifaddrs(&myaddrs);
+    for (ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+        if (ifa->ifa_addr == NULL ||
+            (ifa->ifa_addr->sa_family != AF_INET &&
+             ifa->ifa_addr->sa_family != AF_INET6)) {
+            continue;
+        }
+
+        if (!memcmp(addr, ifa->ifa_addr, sizeof(addr))) {
+            if (strlen(ifa->ifa_name) <= sizeof(label) - 1) {
+                strncpy(label, ifa->ifa_name, sizeof(label) - 1);
+                res = 0;
+            }
+            break;
+        }
+    }
+    freeifaddrs(myaddrs);
+    return res;
+}
+
+/**
  * Netlink event handler. Handles IPsec acquire messages (triggering
  * of base exchange) and updates the cache of local addresses when
  * address changes occur.
@@ -1165,11 +1212,6 @@
             rta = IFA_RTA(ifa);
             l   = msg->nlmsg_len - NLMSG_LENGTH(sizeof(*ifa));
 
-            /* Check if our interface is in the whitelist */
-            if ((hip_netdev_white_list_count > 0) &&
-                (!hip_netdev_is_in_white_list(ifindex))) {
-                continue;
-            }
 
             if ((ifa->ifa_family != AF_INET) &&
                 (ifa->ifa_family != AF_INET6)) {
@@ -1211,6 +1253,17 @@
                 HIP_DEBUG("Unknown addr family in addr\n");
             }
 
+            /* find interface label for address and check if it is whitelisted 
or not */
+            if (is_add) {
+                char label[IF_NAMESIZE];
+                if (!hip_find_label_for_address(addr, label) &&
+                    !hip_netdev_is_in_white_list(ifa->ifa_index, label)) {
+                    HIP_DEBUG("Interface:<%s> is not whitelisted\n", label);
+                    continue;
+                }
+            }
+
+
             /* Trying to add an existing address or deleting a non-existing
              * address */
             exists = hip_exists_address_in_list(addr, ifa->ifa_index);

=== modified file 'hipd/netdev.h'
--- hipd/netdev.h       2011-05-18 15:12:07 +0000
+++ hipd/netdev.h       2011-08-22 11:47:21 +0000
@@ -56,4 +56,7 @@
 int hip_map_id_to_addr(const hip_hit_t *hit, const hip_lsi_t *lsi,
                        struct in6_addr *addr);
 
+int hip_find_label_for_address(const struct sockaddr *const addr,
+                               char *const label);
+
 #endif /* HIP_HIPD_NETDEV_H */

Other related posts: