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:
parent
829c056260
commit
89b980b89f
5 changed files with 266 additions and 218 deletions
|
@ -407,31 +407,21 @@ static int get_ifindex(const char *name)
|
||||||
return ifr.ifr_ifindex;
|
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;
|
struct ifaddrs *tmp;
|
||||||
int err = -ENOENT;
|
int error = -ENOENT;
|
||||||
char name[IF_NAMESIZE];
|
|
||||||
|
|
||||||
if (!if_indextoname(ifindex, name))
|
for (tmp = if_address; tmp; tmp = tmp->ifa_next) {
|
||||||
return -EINVAL;
|
if (tmp->ifa_addr &&
|
||||||
|
!strncmp(tmp->ifa_name, if_name, IF_NAMESIZE) &&
|
||||||
|
tmp->ifa_addr->sa_family == family) {
|
||||||
|
|
||||||
if (getifaddrs(&ifaddr) < 0) {
|
switch (family) {
|
||||||
err = -errno;
|
case AF_INET: {
|
||||||
fprintf(stderr, "Cannot get addresses err %d/%s",
|
struct sockaddr_in *in4 =
|
||||||
err, strerror(-err));
|
(struct sockaddr_in *)tmp->ifa_addr;
|
||||||
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;
|
|
||||||
if (in4->sin_addr.s_addr == INADDR_ANY)
|
if (in4->sin_addr.s_addr == INADDR_ANY)
|
||||||
continue;
|
continue;
|
||||||
if ((in4->sin_addr.s_addr & IN_CLASSB_NET) ==
|
if ((in4->sin_addr.s_addr & IN_CLASSB_NET) ==
|
||||||
|
@ -439,29 +429,51 @@ static int get_address(int ifindex, int family, void *address)
|
||||||
continue;
|
continue;
|
||||||
memcpy(address, &in4->sin_addr,
|
memcpy(address, &in4->sin_addr,
|
||||||
sizeof(struct in_addr));
|
sizeof(struct in_addr));
|
||||||
} else if (family == AF_INET6) {
|
error = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
case AF_INET6: {
|
||||||
struct sockaddr_in6 *in6 =
|
struct sockaddr_in6 *in6 =
|
||||||
(struct sockaddr_in6 *)ifa->ifa_addr;
|
(struct sockaddr_in6 *)tmp->ifa_addr;
|
||||||
if (memcmp(&in6->sin6_addr, &in6addr_any,
|
if (!memcmp(&in6->sin6_addr, &in6addr_any,
|
||||||
sizeof(struct in6_addr)) == 0)
|
sizeof(struct in6_addr)))
|
||||||
continue;
|
continue;
|
||||||
if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr))
|
if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
memcpy(address, &in6->sin6_addr,
|
memcpy(address, &in6->sin6_addr,
|
||||||
sizeof(struct in6_addr));
|
sizeof(struct in6_addr));
|
||||||
} else {
|
error = 0;
|
||||||
err = -EINVAL;
|
goto out;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
error = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = 0;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
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;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1669,7 +1681,12 @@ int main(int argc, char**argv)
|
||||||
exit(-EINVAL);
|
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,
|
printf("Binding to %s\n", inet_ntop(family, address,
|
||||||
addr_buf, sizeof(addr_buf)));
|
addr_buf, sizeof(addr_buf)));
|
||||||
|
|
|
@ -303,56 +303,21 @@ 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;
|
struct ifaddrs *tmp;
|
||||||
int sk, err;
|
int error = -ENOENT;
|
||||||
|
|
||||||
if (!name)
|
for (tmp = if_address; tmp; tmp = tmp->ifa_next) {
|
||||||
return -1;
|
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);
|
switch (family) {
|
||||||
if (sk < 0)
|
case AF_INET: {
|
||||||
return -1;
|
struct sockaddr_in *in4 =
|
||||||
|
(struct sockaddr_in *)tmp->ifa_addr;
|
||||||
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;
|
|
||||||
if (in4->sin_addr.s_addr == INADDR_ANY)
|
if (in4->sin_addr.s_addr == INADDR_ANY)
|
||||||
continue;
|
continue;
|
||||||
if ((in4->sin_addr.s_addr & IN_CLASSB_NET) ==
|
if ((in4->sin_addr.s_addr & IN_CLASSB_NET) ==
|
||||||
|
@ -360,29 +325,51 @@ static int get_address(int ifindex, int family, void *address)
|
||||||
continue;
|
continue;
|
||||||
memcpy(address, &in4->sin_addr,
|
memcpy(address, &in4->sin_addr,
|
||||||
sizeof(struct in_addr));
|
sizeof(struct in_addr));
|
||||||
} else if (family == AF_INET6) {
|
error = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
case AF_INET6: {
|
||||||
struct sockaddr_in6 *in6 =
|
struct sockaddr_in6 *in6 =
|
||||||
(struct sockaddr_in6 *)ifa->ifa_addr;
|
(struct sockaddr_in6 *)tmp->ifa_addr;
|
||||||
if (memcmp(&in6->sin6_addr, &in6addr_any,
|
if (!memcmp(&in6->sin6_addr, &in6addr_any,
|
||||||
sizeof(struct in6_addr)) == 0)
|
sizeof(struct in6_addr)))
|
||||||
continue;
|
continue;
|
||||||
if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr))
|
if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
memcpy(address, &in6->sin6_addr,
|
memcpy(address, &in6->sin6_addr,
|
||||||
sizeof(struct in6_addr));
|
sizeof(struct in6_addr));
|
||||||
} else {
|
error = 0;
|
||||||
err = -EINVAL;
|
goto out;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
error = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = 0;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
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;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -686,7 +673,7 @@ int main(int argc, char**argv)
|
||||||
const char *target = NULL, *interface = NULL, *source = NULL;
|
const char *target = NULL, *interface = NULL, *source = NULL;
|
||||||
fd_set rfds;
|
fd_set rfds;
|
||||||
struct timeval tv = {};
|
struct timeval tv = {};
|
||||||
int ifindex = -1, on, port;
|
int on, port;
|
||||||
void *address = NULL;
|
void *address = NULL;
|
||||||
session_t dst;
|
session_t dst;
|
||||||
struct client_data user_data;
|
struct client_data user_data;
|
||||||
|
@ -810,14 +797,13 @@ int main(int argc, char**argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!source) {
|
if (!source) {
|
||||||
ifindex = get_ifindex(interface);
|
ret = get_address(interface, family, address);
|
||||||
if (ifindex < 0) {
|
if (ret < 0) {
|
||||||
printf("Invalid interface %s\n", interface);
|
printf("Cannot find suitable source address "
|
||||||
exit(-EINVAL);
|
"for interface %s [%d/%s]\n",
|
||||||
|
interface, ret, strerror(-ret));
|
||||||
}
|
}
|
||||||
|
|
||||||
get_address(ifindex, family, address);
|
|
||||||
|
|
||||||
printf("Binding to %s\n", inet_ntop(family, address,
|
printf("Binding to %s\n", inet_ntop(family, address,
|
||||||
addr_buf, sizeof(addr_buf)));
|
addr_buf, sizeof(addr_buf)));
|
||||||
}
|
}
|
||||||
|
@ -830,6 +816,8 @@ int main(int argc, char**argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
on = 1;
|
on = 1;
|
||||||
|
|
||||||
|
if (family == AF_INET6) {
|
||||||
#ifdef IPV6_RECVPKTINFO
|
#ifdef IPV6_RECVPKTINFO
|
||||||
if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
|
if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on,
|
||||||
sizeof(on)) < 0) {
|
sizeof(on)) < 0) {
|
||||||
|
@ -837,7 +825,9 @@ int main(int argc, char**argv)
|
||||||
if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &on,
|
if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &on,
|
||||||
sizeof(on)) < 0) {
|
sizeof(on)) < 0) {
|
||||||
#endif /* IPV6_RECVPKTINFO */
|
#endif /* IPV6_RECVPKTINFO */
|
||||||
printf("setsockopt IPV6_PKTINFO: %s\n", strerror(errno));
|
printf("setsockopt IPV6_PKTINFO: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
signal(SIGINT, signal_handler);
|
signal(SIGINT, signal_handler);
|
||||||
|
|
|
@ -129,31 +129,21 @@ static int bind_device(int fd, const char *interface, void *addr, int len)
|
||||||
return ret;
|
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;
|
struct ifaddrs *tmp;
|
||||||
int err = -ENOENT;
|
int error = -ENOENT;
|
||||||
char name[IF_NAMESIZE];
|
|
||||||
|
|
||||||
if (!if_indextoname(ifindex, name))
|
for (tmp = if_address; tmp; tmp = tmp->ifa_next) {
|
||||||
return -EINVAL;
|
if (tmp->ifa_addr &&
|
||||||
|
!strncmp(tmp->ifa_name, if_name, IF_NAMESIZE) &&
|
||||||
|
tmp->ifa_addr->sa_family == family) {
|
||||||
|
|
||||||
if (getifaddrs(&ifaddr) < 0) {
|
switch (family) {
|
||||||
err = -errno;
|
case AF_INET: {
|
||||||
fprintf(stderr, "Cannot get addresses err %d/%s",
|
struct sockaddr_in *in4 =
|
||||||
err, strerror(-err));
|
(struct sockaddr_in *)tmp->ifa_addr;
|
||||||
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;
|
|
||||||
if (in4->sin_addr.s_addr == INADDR_ANY)
|
if (in4->sin_addr.s_addr == INADDR_ANY)
|
||||||
continue;
|
continue;
|
||||||
if ((in4->sin_addr.s_addr & IN_CLASSB_NET) ==
|
if ((in4->sin_addr.s_addr & IN_CLASSB_NET) ==
|
||||||
|
@ -161,29 +151,51 @@ static int get_address(int ifindex, int family, void *address)
|
||||||
continue;
|
continue;
|
||||||
memcpy(address, &in4->sin_addr,
|
memcpy(address, &in4->sin_addr,
|
||||||
sizeof(struct in_addr));
|
sizeof(struct in_addr));
|
||||||
} else if (family == AF_INET6) {
|
error = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
case AF_INET6: {
|
||||||
struct sockaddr_in6 *in6 =
|
struct sockaddr_in6 *in6 =
|
||||||
(struct sockaddr_in6 *)ifa->ifa_addr;
|
(struct sockaddr_in6 *)tmp->ifa_addr;
|
||||||
if (memcmp(&in6->sin6_addr, &in6addr_any,
|
if (!memcmp(&in6->sin6_addr, &in6addr_any,
|
||||||
sizeof(struct in6_addr)) == 0)
|
sizeof(struct in6_addr)))
|
||||||
continue;
|
continue;
|
||||||
if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr))
|
if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
memcpy(address, &in6->sin6_addr,
|
memcpy(address, &in6->sin6_addr,
|
||||||
sizeof(struct in6_addr));
|
sizeof(struct in6_addr));
|
||||||
} else {
|
error = 0;
|
||||||
err = -EINVAL;
|
goto out;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
error = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = 0;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
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;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -544,7 +556,7 @@ int main(int argc, char**argv)
|
||||||
* we can listen correct addresses. We do not want to listen
|
* we can listen correct addresses. We do not want to listen
|
||||||
* link local addresses in this test.
|
* 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",
|
printf("IPv4: binding to %s\n",
|
||||||
inet_ntop(AF_INET, &addr4_recv.sin_addr,
|
inet_ntop(AF_INET, &addr4_recv.sin_addr,
|
||||||
addr_buf, sizeof(addr_buf)));
|
addr_buf, sizeof(addr_buf)));
|
||||||
|
@ -553,7 +565,7 @@ int main(int argc, char**argv)
|
||||||
addr6_recv.sin6_port = htons(SERVER_PORT);
|
addr6_recv.sin6_port = htons(SERVER_PORT);
|
||||||
|
|
||||||
/* Bind to global unicast address instead of ll address */
|
/* 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",
|
printf("IPv6: binding to %s\n",
|
||||||
inet_ntop(AF_INET6, &addr6_recv.sin6_addr,
|
inet_ntop(AF_INET6, &addr6_recv.sin6_addr,
|
||||||
addr_buf, sizeof(addr_buf)));
|
addr_buf, sizeof(addr_buf)));
|
||||||
|
|
|
@ -302,31 +302,21 @@ static int get_ifindex(const char *name)
|
||||||
return ifr.ifr_ifindex;
|
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;
|
struct ifaddrs *tmp;
|
||||||
int err = -ENOENT;
|
int error = -ENOENT;
|
||||||
char name[IF_NAMESIZE];
|
|
||||||
|
|
||||||
if (!if_indextoname(ifindex, name))
|
for (tmp = if_address; tmp; tmp = tmp->ifa_next) {
|
||||||
return -EINVAL;
|
if (tmp->ifa_addr &&
|
||||||
|
!strncmp(tmp->ifa_name, if_name, IF_NAMESIZE) &&
|
||||||
|
tmp->ifa_addr->sa_family == family) {
|
||||||
|
|
||||||
if (getifaddrs(&ifaddr) < 0) {
|
switch (family) {
|
||||||
err = -errno;
|
case AF_INET: {
|
||||||
fprintf(stderr, "Cannot get addresses err %d/%s",
|
struct sockaddr_in *in4 =
|
||||||
err, strerror(-err));
|
(struct sockaddr_in *)tmp->ifa_addr;
|
||||||
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;
|
|
||||||
if (in4->sin_addr.s_addr == INADDR_ANY)
|
if (in4->sin_addr.s_addr == INADDR_ANY)
|
||||||
continue;
|
continue;
|
||||||
if ((in4->sin_addr.s_addr & IN_CLASSB_NET) ==
|
if ((in4->sin_addr.s_addr & IN_CLASSB_NET) ==
|
||||||
|
@ -334,29 +324,51 @@ static int get_address(int ifindex, int family, void *address)
|
||||||
continue;
|
continue;
|
||||||
memcpy(address, &in4->sin_addr,
|
memcpy(address, &in4->sin_addr,
|
||||||
sizeof(struct in_addr));
|
sizeof(struct in_addr));
|
||||||
} else if (family == AF_INET6) {
|
error = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
case AF_INET6: {
|
||||||
struct sockaddr_in6 *in6 =
|
struct sockaddr_in6 *in6 =
|
||||||
(struct sockaddr_in6 *)ifa->ifa_addr;
|
(struct sockaddr_in6 *)tmp->ifa_addr;
|
||||||
if (memcmp(&in6->sin6_addr, &in6addr_any,
|
if (!memcmp(&in6->sin6_addr, &in6addr_any,
|
||||||
sizeof(struct in6_addr)) == 0)
|
sizeof(struct in6_addr)))
|
||||||
continue;
|
continue;
|
||||||
if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr))
|
if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
memcpy(address, &in6->sin6_addr,
|
memcpy(address, &in6->sin6_addr,
|
||||||
sizeof(struct in6_addr));
|
sizeof(struct in6_addr));
|
||||||
} else {
|
error = 0;
|
||||||
err = -EINVAL;
|
goto out;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
error = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = 0;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
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;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -480,7 +492,12 @@ int main(int argc, char**argv)
|
||||||
exit(-EINVAL);
|
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,
|
printf("Binding to %s\n", inet_ntop(family, address,
|
||||||
addr_buf, sizeof(addr_buf)));
|
addr_buf, sizeof(addr_buf)));
|
||||||
|
|
|
@ -204,31 +204,21 @@ static int join_mc_group(int sock, int ifindex, int family, void *addr,
|
||||||
return ret;
|
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;
|
struct ifaddrs *tmp;
|
||||||
int err = -ENOENT;
|
int error = -ENOENT;
|
||||||
char name[IF_NAMESIZE];
|
|
||||||
|
|
||||||
if (!if_indextoname(ifindex, name))
|
for (tmp = if_address; tmp; tmp = tmp->ifa_next) {
|
||||||
return -EINVAL;
|
if (tmp->ifa_addr &&
|
||||||
|
!strncmp(tmp->ifa_name, if_name, IF_NAMESIZE) &&
|
||||||
|
tmp->ifa_addr->sa_family == family) {
|
||||||
|
|
||||||
if (getifaddrs(&ifaddr) < 0) {
|
switch (family) {
|
||||||
err = -errno;
|
case AF_INET: {
|
||||||
fprintf(stderr, "Cannot get addresses err %d/%s",
|
struct sockaddr_in *in4 =
|
||||||
err, strerror(-err));
|
(struct sockaddr_in *)tmp->ifa_addr;
|
||||||
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;
|
|
||||||
if (in4->sin_addr.s_addr == INADDR_ANY)
|
if (in4->sin_addr.s_addr == INADDR_ANY)
|
||||||
continue;
|
continue;
|
||||||
if ((in4->sin_addr.s_addr & IN_CLASSB_NET) ==
|
if ((in4->sin_addr.s_addr & IN_CLASSB_NET) ==
|
||||||
|
@ -236,29 +226,51 @@ static int get_address(int ifindex, int family, void *address)
|
||||||
continue;
|
continue;
|
||||||
memcpy(address, &in4->sin_addr,
|
memcpy(address, &in4->sin_addr,
|
||||||
sizeof(struct in_addr));
|
sizeof(struct in_addr));
|
||||||
} else if (family == AF_INET6) {
|
error = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
case AF_INET6: {
|
||||||
struct sockaddr_in6 *in6 =
|
struct sockaddr_in6 *in6 =
|
||||||
(struct sockaddr_in6 *)ifa->ifa_addr;
|
(struct sockaddr_in6 *)tmp->ifa_addr;
|
||||||
if (memcmp(&in6->sin6_addr, &in6addr_any,
|
if (!memcmp(&in6->sin6_addr, &in6addr_any,
|
||||||
sizeof(struct in6_addr)) == 0)
|
sizeof(struct in6_addr)))
|
||||||
continue;
|
continue;
|
||||||
if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr))
|
if (IN6_IS_ADDR_LINKLOCAL(&in6->sin6_addr))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
memcpy(address, &in6->sin6_addr,
|
memcpy(address, &in6->sin6_addr,
|
||||||
sizeof(struct in6_addr));
|
sizeof(struct in6_addr));
|
||||||
} else {
|
error = 0;
|
||||||
err = -EINVAL;
|
goto out;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
error = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = 0;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
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;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,7 +327,7 @@ int main(int argc, char**argv)
|
||||||
* we can listen correct addresses. We do not want to listen
|
* we can listen correct addresses. We do not want to listen
|
||||||
* link local addresses in this test.
|
* 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",
|
printf("IPv4: binding to %s\n",
|
||||||
inet_ntop(AF_INET, &addr4_recv.sin_addr,
|
inet_ntop(AF_INET, &addr4_recv.sin_addr,
|
||||||
addr_buf, sizeof(addr_buf)));
|
addr_buf, sizeof(addr_buf)));
|
||||||
|
@ -324,7 +336,7 @@ int main(int argc, char**argv)
|
||||||
addr6_recv.sin6_port = htons(SERVER_PORT);
|
addr6_recv.sin6_port = htons(SERVER_PORT);
|
||||||
|
|
||||||
/* Bind to global unicast address instead of ll address */
|
/* 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",
|
printf("IPv6: binding to %s\n",
|
||||||
inet_ntop(AF_INET6, &addr6_recv.sin6_addr,
|
inet_ntop(AF_INET6, &addr6_recv.sin6_addr,
|
||||||
addr_buf, sizeof(addr_buf)));
|
addr_buf, sizeof(addr_buf)));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue