diff options
author | Jukka Rissanen <jukka.rissanen@linux.intel.com> | 2013-04-04 14:44:49 +0300 |
---|---|---|
committer | Patrik Flykt <patrik.flykt@linux.intel.com> | 2013-04-05 14:37:15 +0300 |
commit | bb147fc28a6c2bb3b81a9677af518c8e3bf6cc4e (patch) | |
tree | be0f0e97bd06c8f8aefabf791522e8e5a1eb272f | |
parent | 5b128587ec25d575a683b9a37e6ac33ce17bd760 (diff) | |
download | connman-bb147fc28a6c2bb3b81a9677af518c8e3bf6cc4e.tar.gz connman-bb147fc28a6c2bb3b81a9677af518c8e3bf6cc4e.tar.bz2 connman-bb147fc28a6c2bb3b81a9677af518c8e3bf6cc4e.zip |
inet: Get an address from a given interface and address family
The returned address is used when we need to have a listening
socket tied to specific interface and address, and do not want to
bind to any address.
-rw-r--r-- | src/connman.h | 1 | ||||
-rw-r--r-- | src/inet.c | 55 |
2 files changed, 56 insertions, 0 deletions
diff --git a/src/connman.h b/src/connman.h index e9c774e7..b63e6582 100644 --- a/src/connman.h +++ b/src/connman.h @@ -133,6 +133,7 @@ int __connman_inet_modify_address(int cmd, int flags, int index, int family, const char *peer, unsigned char prefixlen, const char *broadcast); +int __connman_inet_get_interface_address(int index, int family, void *address); #include <netinet/ip6.h> #include <netinet/icmp6.h> @@ -45,6 +45,7 @@ #include <fcntl.h> #include <linux/if_tun.h> #include <ctype.h> +#include <ifaddrs.h> #include "connman.h" @@ -2376,3 +2377,57 @@ connman_bool_t connman_inet_is_ipv6_supported() close(sk); return TRUE; } + +int __connman_inet_get_interface_address(int index, int family, void *address) +{ + struct ifaddrs *ifaddr, *ifa; + int err = -ENOENT; + char name[IF_NAMESIZE]; + + if (if_indextoname(index, name) == NULL) + return -EINVAL; + + DBG("index %d interface %s", index, name); + + if (getifaddrs(&ifaddr) < 0) { + err = -errno; + DBG("Cannot get addresses err %d/%s", err, strerror(-err)); + return err; + } + + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { + if (ifa->ifa_addr == NULL) + continue; + + if (strncmp(ifa->ifa_name, name, IF_NAMESIZE) == 0 && + ifa->ifa_addr->sa_family == family) { + if (family == AF_INET) { + struct sockaddr_in *in4 = (struct sockaddr_in *) + ifa->ifa_addr; + if (in4->sin_addr.s_addr == INADDR_ANY) + continue; + memcpy(address, &in4->sin_addr, + sizeof(struct in_addr)); + } else if (family == AF_INET6) { + struct sockaddr_in6 *in6 = + (struct sockaddr_in6 *)ifa->ifa_addr; + if (memcmp(&in6->sin6_addr, &in6addr_any, + sizeof(struct in6_addr)) == 0) + continue; + memcpy(address, &in6->sin6_addr, + sizeof(struct in6_addr)); + + } else { + err = -EINVAL; + goto out; + } + + err = 0; + break; + } + } + +out: + freeifaddrs(ifaddr); + return err; +} |