net: tools: Refactor resolving of the source IP address

The function that resolves the source IP address we need to
use when sending a test network IP packet in Linux host is
refactored a bit. No functionality changes here.

Change-Id: I0f9bc79a9a7f01b382116b969739d7ad3f671751
Signed-off-by: Jukka Rissanen <jukka.rissanen@linux.intel.com>
This commit is contained in:
Jukka Rissanen 2015-10-23 12:37:07 +03:00 committed by Anas Nashif
commit 89b980b89f
5 changed files with 266 additions and 218 deletions

View file

@ -407,61 +407,73 @@ static int get_ifindex(const char *name)
return ifr.ifr_ifindex;
}
static int get_address(int ifindex, int family, void *address)
static int find_address(int family, struct ifaddrs *if_address,
const char *if_name, void *address)
{
struct ifaddrs *ifaddr, *ifa;
int err = -ENOENT;
char name[IF_NAMESIZE];
struct ifaddrs *tmp;
int error = -ENOENT;
if (!if_indextoname(ifindex, name))
return -EINVAL;
for (tmp = if_address; tmp; tmp = tmp->ifa_next) {
if (tmp->ifa_addr &&
!strncmp(tmp->ifa_name, if_name, IF_NAMESIZE) &&
tmp->ifa_addr->sa_family == family) {
if (getifaddrs(&ifaddr) < 0) {
err = -errno;
fprintf(stderr, "Cannot get addresses err %d/%s",
err, strerror(-err));
return err;
}
for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
if (!ifa->ifa_addr)
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;
switch (family) {
case AF_INET: {
struct sockaddr_in *in4 =
(struct sockaddr_in *)tmp->ifa_addr;
if (in4->sin_addr.s_addr == INADDR_ANY)
continue;
if ((in4->sin_addr.s_addr & IN_CLASSB_NET) ==
((in_addr_t) 0xa9fe0000))
((in_addr_t)0xa9fe0000))
continue;
memcpy(address, &in4->sin_addr,
sizeof(struct in_addr));
} else if (family == AF_INET6) {
sizeof(struct in_addr));
error = 0;
goto out;
}
case AF_INET6: {
struct sockaddr_in6 *in6 =
(struct sockaddr_in6 *)ifa->ifa_addr;
if (memcmp(&in6->sin6_addr, &in6addr_any,
sizeof(struct in6_addr)) == 0)
(struct sockaddr_in6 *)tmp->ifa_addr;
if (!memcmp(&in6->sin6_addr, &in6addr_any,
sizeof(struct in6_addr)))
continue;
if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr))
continue;
memcpy(address, &in6->sin6_addr,
sizeof(struct in6_addr));
} else {
err = -EINVAL;
sizeof(struct in6_addr));
error = 0;
goto out;
}
default:
error = -EINVAL;
goto out;
}
err = 0;
break;
}
}
out:
freeifaddrs(ifaddr);
return error;
}
static int get_address(const char *if_name, int family, void *address)
{
struct ifaddrs *if_address;
int err;
if (getifaddrs(&if_address) < 0) {
err = -errno;
fprintf(stderr, "Cannot get interface addresses for "
"interface %s error %d/%s",
if_name, err, strerror(-err));
return err;
}
err = find_address(family, if_address, if_name, address);
freeifaddrs(if_address);
return err;
}
@ -1669,7 +1681,12 @@ int main(int argc, char**argv)
exit(-EINVAL);
}
get_address(ifindex, family, address);
ret = get_address(interface, family, address);
if (ret < 0) {
printf("Cannot find suitable source address "
"for interface %s [%d/%s]\n",
interface, ret, strerror(-ret));
}
printf("Binding to %s\n", inet_ntop(family, address,
addr_buf, sizeof(addr_buf)));

View file

@ -303,86 +303,73 @@ static inline void reverse(unsigned char *buf, int len)
}
}
static int get_ifindex(const char *name)
static int find_address(int family, struct ifaddrs *if_address,
const char *if_name, void *address)
{
struct ifreq ifr;
int sk, err;
struct ifaddrs *tmp;
int error = -ENOENT;
if (!name)
return -1;
for (tmp = if_address; tmp; tmp = tmp->ifa_next) {
if (tmp->ifa_addr &&
!strncmp(tmp->ifa_name, if_name, IF_NAMESIZE) &&
tmp->ifa_addr->sa_family == family) {
sk = socket(PF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
if (sk < 0)
return -1;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name) - 1);
err = ioctl(sk, SIOCGIFINDEX, &ifr);
close(sk);
if (err < 0)
return -1;
return ifr.ifr_ifindex;
}
static int get_address(int ifindex, int family, void *address)
{
struct ifaddrs *ifaddr, *ifa;
int err = -ENOENT;
char name[IF_NAMESIZE];
if (!if_indextoname(ifindex, name))
return -EINVAL;
if (getifaddrs(&ifaddr) < 0) {
err = -errno;
fprintf(stderr, "Cannot get addresses err %d/%s",
err, strerror(-err));
return err;
}
for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
if (!ifa->ifa_addr)
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;
switch (family) {
case AF_INET: {
struct sockaddr_in *in4 =
(struct sockaddr_in *)tmp->ifa_addr;
if (in4->sin_addr.s_addr == INADDR_ANY)
continue;
if ((in4->sin_addr.s_addr & IN_CLASSB_NET) ==
((in_addr_t) 0xa9fe0000))
((in_addr_t)0xa9fe0000))
continue;
memcpy(address, &in4->sin_addr,
sizeof(struct in_addr));
} else if (family == AF_INET6) {
sizeof(struct in_addr));
error = 0;
goto out;
}
case AF_INET6: {
struct sockaddr_in6 *in6 =
(struct sockaddr_in6 *)ifa->ifa_addr;
if (memcmp(&in6->sin6_addr, &in6addr_any,
sizeof(struct in6_addr)) == 0)
(struct sockaddr_in6 *)tmp->ifa_addr;
if (!memcmp(&in6->sin6_addr, &in6addr_any,
sizeof(struct in6_addr)))
continue;
if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr))
continue;
memcpy(address, &in6->sin6_addr,
sizeof(struct in6_addr));
} else {
err = -EINVAL;
sizeof(struct in6_addr));
error = 0;
goto out;
}
default:
error = -EINVAL;
goto out;
}
err = 0;
break;
}
}
out:
freeifaddrs(ifaddr);
return error;
}
static int get_address(const char *if_name, int family, void *address)
{
struct ifaddrs *if_address;
int err;
if (getifaddrs(&if_address) < 0) {
err = -errno;
fprintf(stderr, "Cannot get interface addresses for "
"interface %s error %d/%s",
if_name, err, strerror(-err));
return err;
}
err = find_address(family, if_address, if_name, address);
freeifaddrs(if_address);
return err;
}
@ -686,7 +673,7 @@ int main(int argc, char**argv)
const char *target = NULL, *interface = NULL, *source = NULL;
fd_set rfds;
struct timeval tv = {};
int ifindex = -1, on, port;
int on, port;
void *address = NULL;
session_t dst;
struct client_data user_data;
@ -810,14 +797,13 @@ int main(int argc, char**argv)
}
if (!source) {
ifindex = get_ifindex(interface);
if (ifindex < 0) {
printf("Invalid interface %s\n", interface);
exit(-EINVAL);
ret = get_address(interface, family, address);
if (ret < 0) {
printf("Cannot find suitable source address "
"for interface %s [%d/%s]\n",
interface, ret, strerror(-ret));
}
get_address(ifindex, family, address);
printf("Binding to %s\n", inet_ntop(family, address,
addr_buf, sizeof(addr_buf)));
}
@ -830,14 +816,18 @@ int main(int argc, char**argv)
}
on = 1;
if (family == AF_INET6) {
#ifdef IPV6_RECVPKTINFO
if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
sizeof(on) ) < 0) {
if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
sizeof(on)) < 0) {
#else /* IPV6_RECVPKTINFO */
if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &on,
sizeof(on) ) < 0) {
if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &on,
sizeof(on)) < 0) {
#endif /* IPV6_RECVPKTINFO */
printf("setsockopt IPV6_PKTINFO: %s\n", strerror(errno));
printf("setsockopt IPV6_PKTINFO: %s\n",
strerror(errno));
}
}
signal(SIGINT, signal_handler);

View file

@ -129,61 +129,73 @@ static int bind_device(int fd, const char *interface, void *addr, int len)
return ret;
}
static int get_address(int ifindex, int family, void *address)
static int find_address(int family, struct ifaddrs *if_address,
const char *if_name, void *address)
{
struct ifaddrs *ifaddr, *ifa;
int err = -ENOENT;
char name[IF_NAMESIZE];
struct ifaddrs *tmp;
int error = -ENOENT;
if (!if_indextoname(ifindex, name))
return -EINVAL;
for (tmp = if_address; tmp; tmp = tmp->ifa_next) {
if (tmp->ifa_addr &&
!strncmp(tmp->ifa_name, if_name, IF_NAMESIZE) &&
tmp->ifa_addr->sa_family == family) {
if (getifaddrs(&ifaddr) < 0) {
err = -errno;
fprintf(stderr, "Cannot get addresses err %d/%s",
err, strerror(-err));
return err;
}
for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
if (!ifa->ifa_addr)
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;
switch (family) {
case AF_INET: {
struct sockaddr_in *in4 =
(struct sockaddr_in *)tmp->ifa_addr;
if (in4->sin_addr.s_addr == INADDR_ANY)
continue;
if ((in4->sin_addr.s_addr & IN_CLASSB_NET) ==
((in_addr_t) 0xa9fe0000))
((in_addr_t)0xa9fe0000))
continue;
memcpy(address, &in4->sin_addr,
sizeof(struct in_addr));
} else if (family == AF_INET6) {
sizeof(struct in_addr));
error = 0;
goto out;
}
case AF_INET6: {
struct sockaddr_in6 *in6 =
(struct sockaddr_in6 *)ifa->ifa_addr;
if (memcmp(&in6->sin6_addr, &in6addr_any,
sizeof(struct in6_addr)) == 0)
(struct sockaddr_in6 *)tmp->ifa_addr;
if (!memcmp(&in6->sin6_addr, &in6addr_any,
sizeof(struct in6_addr)))
continue;
if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr))
continue;
memcpy(address, &in6->sin6_addr,
sizeof(struct in6_addr));
} else {
err = -EINVAL;
sizeof(struct in6_addr));
error = 0;
goto out;
}
default:
error = -EINVAL;
goto out;
}
err = 0;
break;
}
}
out:
freeifaddrs(ifaddr);
return error;
}
static int get_address(const char *if_name, int family, void *address)
{
struct ifaddrs *if_address;
int err;
if (getifaddrs(&if_address) < 0) {
err = -errno;
fprintf(stderr, "Cannot get interface addresses for "
"interface %s error %d/%s",
if_name, err, strerror(-err));
return err;
}
err = find_address(family, if_address, if_name, address);
freeifaddrs(if_address);
return err;
}
@ -544,7 +556,7 @@ int main(int argc, char**argv)
* we can listen correct addresses. We do not want to listen
* link local addresses in this test.
*/
get_address(ifindex, AF_INET, &addr4_recv.sin_addr);
get_address(interface, AF_INET, &addr4_recv.sin_addr);
printf("IPv4: binding to %s\n",
inet_ntop(AF_INET, &addr4_recv.sin_addr,
addr_buf, sizeof(addr_buf)));
@ -553,7 +565,7 @@ int main(int argc, char**argv)
addr6_recv.sin6_port = htons(SERVER_PORT);
/* Bind to global unicast address instead of ll address */
get_address(ifindex, AF_INET6, &addr6_recv.sin6_addr);
get_address(interface, AF_INET6, &addr6_recv.sin6_addr);
printf("IPv6: binding to %s\n",
inet_ntop(AF_INET6, &addr6_recv.sin6_addr,
addr_buf, sizeof(addr_buf)));

View file

@ -302,61 +302,73 @@ static int get_ifindex(const char *name)
return ifr.ifr_ifindex;
}
static int get_address(int ifindex, int family, void *address)
static int find_address(int family, struct ifaddrs *if_address,
const char *if_name, void *address)
{
struct ifaddrs *ifaddr, *ifa;
int err = -ENOENT;
char name[IF_NAMESIZE];
struct ifaddrs *tmp;
int error = -ENOENT;
if (!if_indextoname(ifindex, name))
return -EINVAL;
for (tmp = if_address; tmp; tmp = tmp->ifa_next) {
if (tmp->ifa_addr &&
!strncmp(tmp->ifa_name, if_name, IF_NAMESIZE) &&
tmp->ifa_addr->sa_family == family) {
if (getifaddrs(&ifaddr) < 0) {
err = -errno;
fprintf(stderr, "Cannot get addresses err %d/%s",
err, strerror(-err));
return err;
}
for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
if (!ifa->ifa_addr)
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;
switch (family) {
case AF_INET: {
struct sockaddr_in *in4 =
(struct sockaddr_in *)tmp->ifa_addr;
if (in4->sin_addr.s_addr == INADDR_ANY)
continue;
if ((in4->sin_addr.s_addr & IN_CLASSB_NET) ==
((in_addr_t) 0xa9fe0000))
((in_addr_t)0xa9fe0000))
continue;
memcpy(address, &in4->sin_addr,
sizeof(struct in_addr));
} else if (family == AF_INET6) {
sizeof(struct in_addr));
error = 0;
goto out;
}
case AF_INET6: {
struct sockaddr_in6 *in6 =
(struct sockaddr_in6 *)ifa->ifa_addr;
if (memcmp(&in6->sin6_addr, &in6addr_any,
sizeof(struct in6_addr)) == 0)
(struct sockaddr_in6 *)tmp->ifa_addr;
if (!memcmp(&in6->sin6_addr, &in6addr_any,
sizeof(struct in6_addr)))
continue;
if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr))
continue;
memcpy(address, &in6->sin6_addr,
sizeof(struct in6_addr));
} else {
err = -EINVAL;
sizeof(struct in6_addr));
error = 0;
goto out;
}
default:
error = -EINVAL;
goto out;
}
err = 0;
break;
}
}
out:
freeifaddrs(ifaddr);
return error;
}
static int get_address(const char *if_name, int family, void *address)
{
struct ifaddrs *if_address;
int err;
if (getifaddrs(&if_address) < 0) {
err = -errno;
fprintf(stderr, "Cannot get interface addresses for "
"interface %s error %d/%s",
if_name, err, strerror(-err));
return err;
}
err = find_address(family, if_address, if_name, address);
freeifaddrs(if_address);
return err;
}
@ -480,7 +492,12 @@ int main(int argc, char**argv)
exit(-EINVAL);
}
get_address(ifindex, family, address);
ret = get_address(interface, family, address);
if (ret < 0) {
printf("Cannot find suitable source address "
"for interface %s [%d/%s]\n",
interface, ret, strerror(-ret));
}
printf("Binding to %s\n", inet_ntop(family, address,
addr_buf, sizeof(addr_buf)));

View file

@ -204,61 +204,73 @@ static int join_mc_group(int sock, int ifindex, int family, void *addr,
return ret;
}
static int get_address(int ifindex, int family, void *address)
static int find_address(int family, struct ifaddrs *if_address,
const char *if_name, void *address)
{
struct ifaddrs *ifaddr, *ifa;
int err = -ENOENT;
char name[IF_NAMESIZE];
struct ifaddrs *tmp;
int error = -ENOENT;
if (!if_indextoname(ifindex, name))
return -EINVAL;
for (tmp = if_address; tmp; tmp = tmp->ifa_next) {
if (tmp->ifa_addr &&
!strncmp(tmp->ifa_name, if_name, IF_NAMESIZE) &&
tmp->ifa_addr->sa_family == family) {
if (getifaddrs(&ifaddr) < 0) {
err = -errno;
fprintf(stderr, "Cannot get addresses err %d/%s",
err, strerror(-err));
return err;
}
for (ifa = ifaddr; ifa; ifa = ifa->ifa_next) {
if (!ifa->ifa_addr)
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;
switch (family) {
case AF_INET: {
struct sockaddr_in *in4 =
(struct sockaddr_in *)tmp->ifa_addr;
if (in4->sin_addr.s_addr == INADDR_ANY)
continue;
if ((in4->sin_addr.s_addr & IN_CLASSB_NET) ==
((in_addr_t) 0xa9fe0000))
((in_addr_t)0xa9fe0000))
continue;
memcpy(address, &in4->sin_addr,
sizeof(struct in_addr));
} else if (family == AF_INET6) {
sizeof(struct in_addr));
error = 0;
goto out;
}
case AF_INET6: {
struct sockaddr_in6 *in6 =
(struct sockaddr_in6 *)ifa->ifa_addr;
if (memcmp(&in6->sin6_addr, &in6addr_any,
sizeof(struct in6_addr)) == 0)
(struct sockaddr_in6 *)tmp->ifa_addr;
if (!memcmp(&in6->sin6_addr, &in6addr_any,
sizeof(struct in6_addr)))
continue;
if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr))
continue;
memcpy(address, &in6->sin6_addr,
sizeof(struct in6_addr));
} else {
err = -EINVAL;
sizeof(struct in6_addr));
error = 0;
goto out;
}
default:
error = -EINVAL;
goto out;
}
err = 0;
break;
}
}
out:
freeifaddrs(ifaddr);
return error;
}
static int get_address(const char *if_name, int family, void *address)
{
struct ifaddrs *if_address;
int err;
if (getifaddrs(&if_address) < 0) {
err = -errno;
fprintf(stderr, "Cannot get interface addresses for "
"interface %s error %d/%s",
if_name, err, strerror(-err));
return err;
}
err = find_address(family, if_address, if_name, address);
freeifaddrs(if_address);
return err;
}
@ -315,7 +327,7 @@ int main(int argc, char**argv)
* we can listen correct addresses. We do not want to listen
* link local addresses in this test.
*/
get_address(ifindex, AF_INET, &addr4_recv.sin_addr);
get_address(interface, AF_INET, &addr4_recv.sin_addr);
printf("IPv4: binding to %s\n",
inet_ntop(AF_INET, &addr4_recv.sin_addr,
addr_buf, sizeof(addr_buf)));
@ -324,7 +336,7 @@ int main(int argc, char**argv)
addr6_recv.sin6_port = htons(SERVER_PORT);
/* Bind to global unicast address instead of ll address */
get_address(ifindex, AF_INET6, &addr6_recv.sin6_addr);
get_address(interface, AF_INET6, &addr6_recv.sin6_addr);
printf("IPv6: binding to %s\n",
inet_ntop(AF_INET6, &addr6_recv.sin6_addr,
addr_buf, sizeof(addr_buf)));