Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/azatoth/minidlna.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/getifaddr.c')
-rw-r--r--src/getifaddr.c205
1 files changed, 164 insertions, 41 deletions
diff --git a/src/getifaddr.c b/src/getifaddr.c
index f0cbdfc..4aeb92b 100644
--- a/src/getifaddr.c
+++ b/src/getifaddr.c
@@ -1,4 +1,4 @@
-/* $Id: getifaddr.c,v 1.14 2011/05/02 23:50:52 jmaggard Exp $ */
+/* $Id$ */
/* MiniUPnP project
* http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
*
@@ -43,19 +43,82 @@
#include <sys/sockio.h>
#endif
+#include "config.h"
+#if HAVE_GETIFADDRS
+#include <ifaddrs.h>
+#ifdef __linux__
+#ifndef AF_LINK
+#define AF_LINK AF_INET
+#endif
+#else
+#include <net/if_dl.h>
+#endif
+#endif
#include "getifaddr.h"
#include "log.h"
+static uint32_t
+get_netmask(struct sockaddr_in *netmask)
+{
+ uint32_t mask;
+ int i;
+
+ if (!netmask)
+ return 0;
+ mask = ntohl(netmask->sin_addr.s_addr);
+ for (i = 0; i < 32; i++)
+ {
+ if ((mask >> i) & 1)
+ break;
+ }
+ mask = 32 - i;
+
+ return mask;
+}
+
int
getifaddr(const char * ifname, char * buf, int len)
{
/* SIOCGIFADDR struct ifreq * */
+ uint32_t mask = 0;
+ int i;
+#if HAVE_GETIFADDRS
+ struct ifaddrs *ifap, *p;
+ struct sockaddr_in *addr_in;
+
+ if( getifaddrs(&ifap) != 0 )
+ {
+ DPRINTF(E_ERROR, L_GENERAL, "getifaddrs(): %s\n", strerror(errno));
+ return -1;
+ }
+ for( p = ifap; p != NULL; p = p->ifa_next )
+ {
+ if( p->ifa_addr->sa_family == AF_INET )
+ {
+ if( strcmp(p->ifa_name, ifname) != 0 )
+ continue;
+ addr_in = (struct sockaddr_in *)p->ifa_addr;
+ if(!inet_ntop(AF_INET, &addr_in->sin_addr, buf, len))
+ {
+ DPRINTF(E_ERROR, L_GENERAL, "inet_ntop(): %s\n", strerror(errno));
+ break;
+ }
+ addr_in = (struct sockaddr_in *)p->ifa_netmask;
+ mask = get_netmask(addr_in);
+ break;
+ }
+ }
+ freeifaddrs(ifap);
+ if( !p )
+ {
+ DPRINTF(E_ERROR, L_GENERAL, "Network interface %s not found\n", ifname);
+ return -1;
+ }
+#else
int s;
struct ifreq ifr;
int ifrlen;
struct sockaddr_in * addr;
- uint32_t mask;
- int i;
ifrlen = sizeof(ifr);
s = socket(PF_INET, SOCK_DGRAM, 0);
@@ -81,22 +144,17 @@ getifaddr(const char * ifname, char * buf, int len)
if(ioctl(s, SIOCGIFNETMASK, &ifr, &ifrlen) == 0)
{
addr = (struct sockaddr_in *)&ifr.ifr_netmask;
- mask = ntohl(addr->sin_addr.s_addr);
- for (i = 0; i < 32; i++)
- {
- if ((mask >> i) & 1)
- break;
- }
- mask = 32 - i;
- if (mask)
- {
- i = strlen(buf);
- snprintf(buf+i, len-i, "/%u", mask);
- }
+ mask = get_netmask(addr);
}
else
DPRINTF(E_ERROR, L_GENERAL, "ioctl(s, SIOCGIFNETMASK, ...): %s\n", strerror(errno));
close(s);
+#endif
+ if (mask)
+ {
+ i = strlen(buf);
+ snprintf(buf+i, len-i, "/%u", mask);
+ }
return 0;
}
@@ -104,12 +162,42 @@ int
getsysaddr(char * buf, int len)
{
int i;
+ uint32_t mask = 0;
+ int ret = -1;
+#if HAVE_GETIFADDRS
+ struct ifaddrs *ifap, *p;
+ struct sockaddr_in *addr_in;
+ uint8_t a;
+
+ if( getifaddrs(&ifap) != 0 )
+ {
+ DPRINTF(E_ERROR, L_GENERAL, "getifaddrs(): %s\n", strerror(errno));
+ return -1;
+ }
+ for( p = ifap; p != NULL; p = p->ifa_next )
+ {
+ if (p->ifa_addr->sa_family == AF_INET)
+ {
+ addr_in = (struct sockaddr_in *)p->ifa_addr;
+ a = (htonl(addr_in->sin_addr.s_addr) >> 0x18) & 0xFF;
+ if( a == 127 )
+ continue;
+ if(!inet_ntop(AF_INET, &addr_in->sin_addr, buf, len))
+ {
+ DPRINTF(E_ERROR, L_GENERAL, "inet_ntop(): %s\n", strerror(errno));
+ break;
+ }
+ addr_in = (struct sockaddr_in *)p->ifa_netmask;
+ mask = get_netmask(addr_in);
+ ret = 0;
+ break;
+ }
+ }
+ freeifaddrs(ifap);
+#else
int s = socket(PF_INET, SOCK_STREAM, 0);
struct sockaddr_in addr;
struct ifreq ifr;
- uint32_t mask;
- int ret = -1;
-
for (i=1; i > 0; i++)
{
ifr.ifr_ifindex = i;
@@ -128,24 +216,19 @@ getsysaddr(char * buf, int len)
close(s);
break;
}
- ret = 0;
-
memcpy(&addr, &ifr.ifr_netmask, sizeof(addr));
- mask = ntohl(addr.sin_addr.s_addr);
- for (i = 0; i < 32; i++)
- {
- if ((mask >> i) & 1)
- break;
- }
- mask = 32 - i;
- if (mask)
- {
- i = strlen(buf);
- snprintf(buf+i, len-i, "/%u", mask);
- }
+ mask = get_netmask(&addr);
+ ret = 0;
break;
}
close(s);
+#endif
+
+ if (mask)
+ {
+ i = strlen(buf);
+ snprintf(buf+i, len-i, "/%u", mask);
+ }
return(ret);
}
@@ -153,11 +236,55 @@ getsysaddr(char * buf, int len)
int
getsyshwaddr(char * buf, int len)
{
- struct if_nameindex *ifaces, *if_idx;
unsigned char mac[6];
+ int ret = -1;
+#if HAVE_GETIFADDRS
+ struct ifaddrs *ifap, *p;
+ struct sockaddr_in *addr_in;
+ uint8_t a;
+
+ if( getifaddrs(&ifap) != 0 )
+ {
+ DPRINTF(E_ERROR, L_GENERAL, "getifaddrs(): %s\n", strerror(errno));
+ return -1;
+ }
+ for( p = ifap; p != NULL; p = p->ifa_next )
+ {
+ if (p->ifa_addr->sa_family == AF_LINK)
+ {
+ addr_in = (struct sockaddr_in *)p->ifa_addr;
+ a = (htonl(addr_in->sin_addr.s_addr) >> 0x18) & 0xFF;
+ if( a == 127 )
+ continue;
+#ifdef __linux__
+ struct ifreq ifr;
+ int fd;
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if( fd < 0 )
+ continue;
+ strncpy(ifr.ifr_name, p->ifa_name, IFNAMSIZ);
+ if( ioctl(fd, SIOCGIFHWADDR, &ifr) < 0 )
+ {
+ close(fd);
+ continue;
+ }
+ memcpy(mac, ifr.ifr_hwaddr.sa_data, 6);
+#else
+ struct sockaddr_dl *sdl;
+ sdl = (struct sockaddr_dl*)p->ifa_addr;
+ memcpy(mac, LLADDR(sdl), sdl->sdl_alen);
+#endif
+ if( MACADDR_IS_ZERO(mac) )
+ continue;
+ ret = 0;
+ break;
+ }
+ }
+ freeifaddrs(ifap);
+#else
+ struct if_nameindex *ifaces, *if_idx;
struct ifreq ifr;
int fd;
- int ret = -1;
memset(&mac, '\0', sizeof(mac));
/* Get the spatially unique node identifier */
@@ -180,25 +307,21 @@ getsyshwaddr(char * buf, int len)
continue;
if( MACADDR_IS_ZERO(ifr.ifr_hwaddr.sa_data) )
continue;
+ memcpy(mac, ifr.ifr_hwaddr.sa_data, 6);
ret = 0;
break;
}
if_freenameindex(ifaces);
close(fd);
-
+#endif
if(ret == 0)
{
if(len > 12)
- {
- memmove(mac, ifr.ifr_hwaddr.sa_data, 6);
sprintf(buf, "%02x%02x%02x%02x%02x%02x",
mac[0]&0xFF, mac[1]&0xFF, mac[2]&0xFF,
mac[3]&0xFF, mac[4]&0xFF, mac[5]&0xFF);
- }
else if(len == 6)
- {
- memmove(buf, ifr.ifr_hwaddr.sa_data, 6);
- }
+ memmove(buf, mac, 6);
}
return ret;
}