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 */