diff options
author | Tobias Brunner <tobias@strongswan.org> | 2012-09-14 16:43:08 +0200 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2012-09-21 18:16:26 +0200 |
commit | 940e1b0f66dc04b0853414c1f4c45fa3f6e33bdd (patch) | |
tree | 230fbd0a377abcb5592036b8b30ed3341e412d6e /src | |
parent | 645d7a5ef32b03d137d21b2dc73fdb6d528d65dc (diff) | |
download | strongswan-940e1b0f66dc04b0853414c1f4c45fa3f6e33bdd.tar.bz2 strongswan-940e1b0f66dc04b0853414c1f4c45fa3f6e33bdd.tar.xz |
Filter ignored interfaces in kernel interfaces (for events, address enumeration, etc.)
Diffstat (limited to 'src')
-rw-r--r-- | src/libhydra/kernel/kernel_interface.h | 3 | ||||
-rw-r--r-- | src/libhydra/kernel/kernel_net.h | 3 | ||||
-rw-r--r-- | src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c | 118 | ||||
-rw-r--r-- | src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c | 71 |
4 files changed, 134 insertions, 61 deletions
diff --git a/src/libhydra/kernel/kernel_interface.h b/src/libhydra/kernel/kernel_interface.h index 842b51102..dce3ef222 100644 --- a/src/libhydra/kernel/kernel_interface.h +++ b/src/libhydra/kernel/kernel_interface.h @@ -305,7 +305,8 @@ struct kernel_interface_t { host_t* (*get_nexthop)(kernel_interface_t *this, host_t *dest, host_t *src); /** - * Get the interface name of a local address. + * Get the interface name of a local address. Interfaces that are down or + * ignored by config are not considered. * * @param host address to get interface name from * @param name allocated interface name (optional) diff --git a/src/libhydra/kernel/kernel_net.h b/src/libhydra/kernel/kernel_net.h index 4edd8da04..1f56bf8ab 100644 --- a/src/libhydra/kernel/kernel_net.h +++ b/src/libhydra/kernel/kernel_net.h @@ -65,7 +65,8 @@ struct kernel_net_t { host_t* (*get_nexthop)(kernel_net_t *this, host_t *dest, host_t *src); /** - * Get the interface name of a local address. + * Get the interface name of a local address. Interfaces that are down or + * ignored by config are not considered. * * @param host address to get interface name from * @param name allocated interface name (optional) diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c index 2180b9008..09a850667 100644 --- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c +++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c @@ -110,6 +110,9 @@ struct iface_entry_t { /** list of addresses as host_t */ linked_list_t *addrs; + + /** TRUE if usable by config */ + bool usable; }; /** @@ -121,6 +124,22 @@ static void iface_entry_destroy(iface_entry_t *this) free(this); } +/** + * find an interface entry by index + */ +static bool iface_entry_by_index(iface_entry_t *this, int *ifindex) +{ + return this->ifindex == *ifindex; +} + +/** + * check if an interface is up and usable + */ +static inline bool iface_entry_up_and_usable(iface_entry_t *iface) +{ + return iface->usable && (iface->flags & IFF_UP) == IFF_UP; +} + typedef struct route_entry_t route_entry_t; /** @@ -486,6 +505,10 @@ static host_t *get_interface_address(private_kernel_netlink_net_t *this, { if (iface->ifindex == ifindex) { + if (!iface->usable) + { /* ignore interfaces excluded by config */ + break; + } addrs = iface->addrs->create_enumerator(iface->addrs); while (addrs->enumerate(addrs, &addr)) { @@ -558,6 +581,22 @@ static void fire_roam_event(private_kernel_netlink_net_t *this, bool address) } /** + * check if an interface with a given index is up and usable + */ +static bool is_interface_up_and_usable(private_kernel_netlink_net_t *this, + int index) +{ + iface_entry_t *iface; + + if (this->ifaces->find_first(this->ifaces, (void*)iface_entry_by_index, + (void**)&iface, &index) == SUCCESS) + { + return iface_entry_up_and_usable(iface); + } + return FALSE; +} + +/** * process RTM_NEWLINK/RTM_DELLINK from kernel */ static void process_link(private_kernel_netlink_net_t *this, @@ -606,12 +645,14 @@ static void process_link(private_kernel_netlink_net_t *this, entry = malloc_thing(iface_entry_t); entry->ifindex = msg->ifi_index; entry->flags = 0; + entry->usable = hydra->kernel_interface->is_interface_usable( + hydra->kernel_interface, name); entry->addrs = linked_list_create(); this->ifaces->insert_last(this->ifaces, entry); } strncpy(entry->ifname, name, IFNAMSIZ); entry->ifname[IFNAMSIZ-1] = '\0'; - if (event) + if (event && entry->usable) { if (!(entry->flags & IFF_UP) && (msg->ifi_flags & IFF_UP)) { @@ -634,7 +675,7 @@ static void process_link(private_kernel_netlink_net_t *this, { if (current->ifindex == msg->ifi_index) { - if (event) + if (event && current->usable) { update = TRUE; DBG1(DBG_KNL, "interface %s deleted", current->ifname); @@ -727,7 +768,7 @@ static void process_addr(private_kernel_netlink_net_t *this, if (hdr->nlmsg_type == RTM_DELADDR) { iface->addrs->remove_at(iface->addrs, addrs); - if (!addr->virtual) + if (!addr->virtual && iface->usable) { changed = TRUE; DBG1(DBG_KNL, "%H disappeared from %s", @@ -757,7 +798,7 @@ static void process_addr(private_kernel_netlink_net_t *this, addr->scope = msg->ifa_scope; iface->addrs->insert_last(iface->addrs, addr); - if (event) + if (event && iface->usable) { DBG1(DBG_KNL, "%H appeared on %s", host, iface->ifname); } @@ -767,6 +808,10 @@ static void process_addr(private_kernel_netlink_net_t *this, { update = TRUE; } + if (!iface->usable) + { /* ignore events for interfaces excluded by config */ + update = changed = FALSE; + } break; } } @@ -830,20 +875,26 @@ static void process_route(private_kernel_netlink_net_t *this, struct nlmsghdr *h } rta = RTA_NEXT(rta, rtasize); } + this->mutex->lock(this->mutex); + if (rta_oif && !is_interface_up_and_usable(this, rta_oif)) + { /* ignore route changes for interfaces that are ignored or down */ + this->mutex->unlock(this->mutex); + DESTROY_IF(host); + return; + } if (!host && rta_oif) { host = get_interface_address(this, rta_oif, msg->rtm_family, NULL); } if (host) { - this->mutex->lock(this->mutex); if (!get_vip_refcount(this, host)) { /* ignore routes added for virtual IPs */ fire_roam_event(this, FALSE); } - this->mutex->unlock(this->mutex); host->destroy(host); } + this->mutex->unlock(this->mutex); } /** @@ -970,6 +1021,10 @@ static enumerator_t *create_iface_enumerator(iface_entry_t *iface, static bool filter_interfaces(address_enumerator_t *data, iface_entry_t** in, iface_entry_t** out) { + if (!(*in)->usable) + { /* skip interfaces excluded by config */ + return FALSE; + } if (!data->include_loopback && ((*in)->flags & IFF_LOOPBACK)) { /* ignore loopback devices */ return FALSE; @@ -1007,7 +1062,7 @@ METHOD(kernel_net_t, get_interface_name, bool, enumerator_t *ifaces, *addrs; iface_entry_t *iface; addr_entry_t *addr; - bool found = FALSE; + bool found = FALSE, ignored = FALSE; if (ip->is_anyaddr(ip)) { @@ -1024,6 +1079,11 @@ METHOD(kernel_net_t, get_interface_name, bool, if (ip->ip_equals(ip, addr->ip)) { found = TRUE; + if (!iface->usable) + { + ignored = TRUE; + break; + } if (name) { *name = strdup(iface->ifname); @@ -1040,15 +1100,18 @@ METHOD(kernel_net_t, get_interface_name, bool, ifaces->destroy(ifaces); this->mutex->unlock(this->mutex); - if (!found) - { - DBG2(DBG_KNL, "%H is not a local address", ip); - } - else if (name) + if (!ignored) { - DBG2(DBG_KNL, "%H is on interface %s", ip, *name); + if (!found) + { + DBG2(DBG_KNL, "%H is not a local address", ip); + } + else if (name) + { + DBG2(DBG_KNL, "%H is on interface %s", ip, *name); + } } - return found; + return found && !ignored; } /** @@ -1083,29 +1146,6 @@ static int get_interface_index(private_kernel_netlink_net_t *this, char* name) } /** - * Check if an interface with a given index is up - */ -static bool is_interface_up(private_kernel_netlink_net_t *this, int index) -{ - enumerator_t *ifaces; - iface_entry_t *iface; - /* default to TRUE for interface we do not monitor (e.g. lo) */ - bool up = TRUE; - - ifaces = this->ifaces->create_enumerator(this->ifaces); - while (ifaces->enumerate(ifaces, &iface)) - { - if (iface->ifindex == index) - { - up = iface->flags & IFF_UP; - break; - } - } - ifaces->destroy(ifaces); - return up; -} - -/** * check if an address (chunk) addr is in subnet (net with net_len net bits) */ static bool addr_in_subnet(chunk_t addr, chunk_t net, int net_len) @@ -1303,7 +1343,7 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest, { /* route is from our own ipsec routing table */ continue; } - if (route->oif && !is_interface_up(this, route->oif)) + if (route->oif && !is_interface_up_and_usable(this, route->oif)) { /* interface is down */ continue; } @@ -1830,7 +1870,7 @@ static status_t init_address_list(private_kernel_netlink_net_t *this) ifaces = this->ifaces->create_enumerator(this->ifaces); while (ifaces->enumerate(ifaces, &iface)) { - if (iface->flags & IFF_UP) + if (iface_entry_up_and_usable(iface)) { DBG2(DBG_KNL, " %s", iface->ifname); addrs = iface->addrs->create_enumerator(iface->addrs); diff --git a/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c b/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c index d46c019eb..0095c6630 100644 --- a/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c +++ b/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c @@ -85,6 +85,9 @@ struct iface_entry_t { /** list of addresses as host_t */ linked_list_t *addrs; + + /** TRUE if usable by config */ + bool usable; }; /** @@ -96,6 +99,14 @@ static void iface_entry_destroy(iface_entry_t *this) free(this); } +/** + * check if an interface is up and usable + */ +static inline bool iface_entry_up_and_usable(iface_entry_t *iface) +{ + return iface->usable && (iface->flags & IFF_UP) == IFF_UP; +} + typedef struct private_kernel_pfroute_net_t private_kernel_pfroute_net_t; @@ -229,7 +240,7 @@ static void process_addr(private_kernel_pfroute_net_t *this, if (ifa->ifam_type == RTM_DELADDR) { iface->addrs->remove_at(iface->addrs, addrs); - if (!addr->virtual) + if (!addr->virtual && iface->usable) { changed = TRUE; DBG1(DBG_KNL, "%H disappeared from %s", @@ -253,10 +264,13 @@ static void process_addr(private_kernel_pfroute_net_t *this, addr->virtual = FALSE; addr->refcount = 1; iface->addrs->insert_last(iface->addrs, addr); - DBG1(DBG_KNL, "%H appeared on %s", host, iface->ifname); + if (iface->usable) + { + DBG1(DBG_KNL, "%H appeared on %s", host, iface->ifname); + } } - if (changed && (iface->flags & IFF_UP)) + if (changed && iface_entry_up_and_usable(iface)) { roam = TRUE; } @@ -290,15 +304,18 @@ static void process_link(private_kernel_pfroute_net_t *this, { if (iface->ifindex == msg->ifm_index) { - if (!(iface->flags & IFF_UP) && (msg->ifm_flags & IFF_UP)) - { - roam = TRUE; - DBG1(DBG_KNL, "interface %s activated", iface->ifname); - } - else if ((iface->flags & IFF_UP) && !(msg->ifm_flags & IFF_UP)) + if (iface->usable) { - roam = TRUE; - DBG1(DBG_KNL, "interface %s deactivated", iface->ifname); + if (!(iface->flags & IFF_UP) && (msg->ifm_flags & IFF_UP)) + { + roam = TRUE; + DBG1(DBG_KNL, "interface %s activated", iface->ifname); + } + else if ((iface->flags & IFF_UP) && !(msg->ifm_flags & IFF_UP)) + { + roam = TRUE; + DBG1(DBG_KNL, "interface %s deactivated", iface->ifname); + } } iface->flags = msg->ifm_flags; break; @@ -441,6 +458,10 @@ static enumerator_t *create_iface_enumerator(iface_entry_t *iface, static bool filter_interfaces(address_enumerator_t *data, iface_entry_t** in, iface_entry_t** out) { + if (!(*in)->usable) + { /* skip interfaces excluded by config */ + return FALSE; + } if (!data->include_loopback && ((*in)->flags & IFF_LOOPBACK)) { /* ignore loopback devices */ return FALSE; @@ -478,7 +499,7 @@ METHOD(kernel_net_t, get_interface_name, bool, enumerator_t *ifaces, *addrs; iface_entry_t *iface; addr_entry_t *addr; - bool found = FALSE; + bool found = FALSE, ignored = FALSE; if (ip->is_anyaddr(ip)) { @@ -495,6 +516,11 @@ METHOD(kernel_net_t, get_interface_name, bool, if (ip->ip_equals(ip, addr->ip)) { found = TRUE; + if (!iface->usable) + { + ignored = TRUE; + break; + } if (name) { *name = strdup(iface->ifname); @@ -511,15 +537,18 @@ METHOD(kernel_net_t, get_interface_name, bool, ifaces->destroy(ifaces); this->mutex->unlock(this->mutex); - if (!found) + if (!ignored) { - DBG2(DBG_KNL, "%H is not a local address", ip); - } - else if (name) - { - DBG2(DBG_KNL, "%H is on interface %s", ip, *name); + if (!found) + { + DBG2(DBG_KNL, "%H is not a local address", ip); + } + else if (name) + { + DBG2(DBG_KNL, "%H is on interface %s", ip, *name); + } } - return found; + return found && !ignored; } METHOD(kernel_net_t, get_source_addr, host_t*, @@ -609,6 +638,8 @@ static status_t init_address_list(private_kernel_pfroute_net_t *this) iface->ifindex = if_nametoindex(ifa->ifa_name); iface->flags = ifa->ifa_flags; iface->addrs = linked_list_create(); + iface->usable = hydra->kernel_interface->is_interface_usable( + hydra->kernel_interface, ifa->ifa_name); this->ifaces->insert_last(this->ifaces, iface); } @@ -628,7 +659,7 @@ static status_t init_address_list(private_kernel_pfroute_net_t *this) ifaces = this->ifaces->create_enumerator(this->ifaces); while (ifaces->enumerate(ifaces, &iface)) { - if (iface->flags & IFF_UP) + if (iface->usable && iface->flags & IFF_UP) { DBG2(DBG_KNL, " %s", iface->ifname); addrs = iface->addrs->create_enumerator(iface->addrs); |