getifaddr.c: prefer non-reserved over reserved addresses in `getifaddr()`
When iterating interface addresses obtained via `getifaddrs()`, don't stop at the first found IPv4 address but continue checking all IPv4 addresses and prefer to use a non-reserved one in case an interface has both reserved (private) and non-reserved (public) addresses assigned. After this fix, miniupnpd on OpenWrt is able to properly detect the external IP address of an external interface with both a private RFC1918 and a public IP assigned regardless of whether `getifaddrs()` happens to return the private or the public IPv4 address first. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
parent
a28dec3c2d
commit
95002535b3
|
@ -101,6 +101,7 @@ getifaddr(const char * ifname, char * buf, int len,
|
||||||
/* Works for all address families (both ip v4 and ip v6) */
|
/* Works for all address families (both ip v4 and ip v6) */
|
||||||
struct ifaddrs * ifap;
|
struct ifaddrs * ifap;
|
||||||
struct ifaddrs * ife;
|
struct ifaddrs * ife;
|
||||||
|
struct ifaddrs * candidate = NULL;
|
||||||
|
|
||||||
if(!ifname || ifname[0]=='\0')
|
if(!ifname || ifname[0]=='\0')
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -119,14 +120,10 @@ getifaddr(const char * ifname, char * buf, int len,
|
||||||
switch(ife->ifa_addr->sa_family)
|
switch(ife->ifa_addr->sa_family)
|
||||||
{
|
{
|
||||||
case AF_INET:
|
case AF_INET:
|
||||||
if(buf)
|
if(!candidate ||
|
||||||
{
|
(addr_is_reserved(&((struct sockaddr_in *)candidate->ifa_addr)->sin_addr) &&
|
||||||
inet_ntop(ife->ifa_addr->sa_family,
|
!addr_is_reserved(&((struct sockaddr_in *)ife->ifa_addr)->sin_addr)))
|
||||||
&((struct sockaddr_in *)ife->ifa_addr)->sin_addr,
|
candidate = ife;
|
||||||
buf, len);
|
|
||||||
}
|
|
||||||
if(addr) *addr = ((struct sockaddr_in *)ife->ifa_addr)->sin_addr;
|
|
||||||
if(mask) *mask = ((struct sockaddr_in *)ife->ifa_netmask)->sin_addr;
|
|
||||||
break;
|
break;
|
||||||
/*
|
/*
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
|
@ -136,6 +133,17 @@ getifaddr(const char * ifname, char * buf, int len,
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(candidate)
|
||||||
|
{
|
||||||
|
if(buf)
|
||||||
|
{
|
||||||
|
inet_ntop(candidate->ifa_addr->sa_family,
|
||||||
|
&((struct sockaddr_in *)candidate->ifa_addr)->sin_addr,
|
||||||
|
buf, len);
|
||||||
|
}
|
||||||
|
if(addr) *addr = ((struct sockaddr_in *)candidate->ifa_addr)->sin_addr;
|
||||||
|
if(mask) *mask = ((struct sockaddr_in *)candidate->ifa_netmask)->sin_addr;
|
||||||
|
}
|
||||||
freeifaddrs(ifap);
|
freeifaddrs(ifap);
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue