From 961e1c35d35c926fbd6ac69773e98b31453a4f27 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Sat, 23 Mar 2013 11:50:57 +0100 Subject: [PATCH] miniupnpd: autodetect LAN interface netmask instead of defaulting to /24 Fix #23 --- miniupnpd/Changelog.txt | 5 ++++- miniupnpd/getconnstatus.c | 6 +++--- miniupnpd/getifaddr.c | 27 +++++++++++++++++++++------ miniupnpd/getifaddr.h | 9 ++++++--- miniupnpd/miniupnpd.c | 11 ++++++----- miniupnpd/natpmp.c | 6 +++--- miniupnpd/testgetifaddr.c | 13 ++++++++----- miniupnpd/upnpdescgen.c | 6 +++--- miniupnpd/upnpsoap.c | 8 ++++---- 9 files changed, 58 insertions(+), 33 deletions(-) diff --git a/miniupnpd/Changelog.txt b/miniupnpd/Changelog.txt index d7aa96c..e12f48c 100644 --- a/miniupnpd/Changelog.txt +++ b/miniupnpd/Changelog.txt @@ -1,4 +1,7 @@ -$Id: Changelog.txt,v 1.331 2013/02/11 10:37:06 nanard Exp $ +$Id: Changelog.txt,v 1.332 2013/03/23 10:46:53 nanard Exp $ + +2013/03/23: + autodetect LAN interface netmask instead of defaulting to /24 2013/02/11: Use $(DESTDIR) in Makefile.linux. diff --git a/miniupnpd/getconnstatus.c b/miniupnpd/getconnstatus.c index 2b36e80..332784c 100644 --- a/miniupnpd/getconnstatus.c +++ b/miniupnpd/getconnstatus.c @@ -1,7 +1,7 @@ -/* $Id: getconnstatus.c,v 1.4 2011/05/23 20:22:41 nanard Exp $ */ +/* $Id: getconnstatus.c,v 1.6 2013/03/23 10:46:54 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2011 Thomas Bernard + * (c) 2011-2013 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -35,7 +35,7 @@ get_wan_connection_status(const char * ifname) /* we need a better implementation here. * I'm afraid it should be device specific */ - r = getifaddr(ifname, addr, INET_ADDRSTRLEN); + r = getifaddr(ifname, addr, INET_ADDRSTRLEN, NULL, NULL); return (r < 0) ? STATUS_DISCONNECTED : STATUS_CONNECTED; } diff --git a/miniupnpd/getifaddr.c b/miniupnpd/getifaddr.c index c86034d..2090d55 100644 --- a/miniupnpd/getifaddr.c +++ b/miniupnpd/getifaddr.c @@ -1,7 +1,7 @@ -/* $Id: getifaddr.c,v 1.14 2012/02/07 11:05:07 nanard Exp $ */ +/* $Id: getifaddr.c,v 1.16 2013/03/23 10:46:54 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2011 Thomas Bernard + * (c) 2006-2013 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -26,7 +26,8 @@ #endif int -getifaddr(const char * ifname, char * buf, int len) +getifaddr(const char * ifname, char * buf, int len, + struct in_addr * addr, struct in_addr * mask) { #ifndef USE_GETIFADDRS /* use ioctl SIOCGIFADDR. Works only for ip v4 */ @@ -34,7 +35,7 @@ getifaddr(const char * ifname, char * buf, int len) int s; struct ifreq ifr; int ifrlen; - struct sockaddr_in * addr; + struct sockaddr_in * ifaddr; ifrlen = sizeof(ifr); if(!ifname || ifname[0]=='\0') @@ -52,13 +53,25 @@ getifaddr(const char * ifname, char * buf, int len) close(s); return -1; } - addr = (struct sockaddr_in *)&ifr.ifr_addr; - if(!inet_ntop(AF_INET, &addr->sin_addr, buf, len)) + ifaddr = (struct sockaddr_in *)&ifr.ifr_addr; + if(addr) *addr = ifaddr->sin_addr; + if(!inet_ntop(AF_INET, &ifaddr->sin_addr, buf, len)) { syslog(LOG_ERR, "inet_ntop(): %m"); close(s); return -1; } + if(mask) + { + strncpy(ifr.ifr_name, ifname, IFNAMSIZ); + if(ioctl(s, SIOCGIFNETMASK, &ifr, &ifrlen) < 0) + { + syslog(LOG_ERR, "ioctl(s, SIOCGIFNETMASK, ...): %m"); + close(s); + return -1; + } + *mask = ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr; + } close(s); #else /* ifndef USE_GETIFADDRS */ /* Works for all address families (both ip v4 and ip v6) */ @@ -85,6 +98,8 @@ getifaddr(const char * ifname, char * buf, int len) inet_ntop(ife->ifa_addr->sa_family, &((struct sockaddr_in *)ife->ifa_addr)->sin_addr, 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; /* case AF_INET6: diff --git a/miniupnpd/getifaddr.h b/miniupnpd/getifaddr.h index 471f9e2..77f77e8 100644 --- a/miniupnpd/getifaddr.h +++ b/miniupnpd/getifaddr.h @@ -1,19 +1,22 @@ -/* $Id: getifaddr.h,v 1.5 2011/05/15 08:59:27 nanard Exp $ */ +/* $Id: getifaddr.h,v 1.8 2013/03/23 10:46:54 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2011 Thomas Bernard + * (c) 2006-2013 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ #ifndef GETIFADDR_H_INCLUDED #define GETIFADDR_H_INCLUDED +struct in_addr; + /* getifaddr() * take a network interface name and write the * ip v4 address as text in the buffer * returns: 0 success, -1 failure */ int -getifaddr(const char * ifname, char * buf, int len); +getifaddr(const char * ifname, char * buf, int len, + struct in_addr * addr, struct in_addr * mask); /* find a non link local IP v6 address for the interface. * if ifname is NULL, look for all interfaces */ diff --git a/miniupnpd/miniupnpd.c b/miniupnpd/miniupnpd.c index 050d8db..b1c2a07 100644 --- a/miniupnpd/miniupnpd.c +++ b/miniupnpd/miniupnpd.c @@ -1,4 +1,4 @@ -/* $Id: miniupnpd.c,v 1.173 2013/02/06 10:50:04 nanard Exp $ */ +/* $Id: miniupnpd.c,v 1.174 2013/03/23 10:46:54 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2013 Thomas Bernard @@ -561,7 +561,8 @@ parselanaddr(struct lan_addr_s * lan_addr, const char * str) /* not starting with a digit : suppose it is an interface name */ memcpy(lan_addr->ifname, str, n); lan_addr->ifname[n] = '\0'; - if(getifaddr(lan_addr->ifname, lan_addr->str, sizeof(lan_addr->str)) < 0) + if(getifaddr(lan_addr->ifname, lan_addr->str, sizeof(lan_addr->str), + &lan_addr->addr, &lan_addr->mask) < 0) goto parselan_error; } else @@ -570,9 +571,9 @@ parselanaddr(struct lan_addr_s * lan_addr, const char * str) goto parselan_error; memcpy(lan_addr->str, str, n); lan_addr->str[n] = '\0'; + if(!inet_aton(lan_addr->str, &lan_addr->addr)) + goto parselan_error; } - if(!inet_aton(lan_addr->str, &lan_addr->addr)) - goto parselan_error; if(*p == '/') { const char * q = ++p; @@ -598,7 +599,7 @@ parselanaddr(struct lan_addr_s * lan_addr, const char * str) lan_addr->mask.s_addr = htonl(nbits ? (0xffffffffu << (32 - nbits)) : 0); } } - else + else if(lan_addr->mask.s_addr == 0) { /* by default, networks are /24 */ lan_addr->mask.s_addr = htonl(0xffffff00u); diff --git a/miniupnpd/natpmp.c b/miniupnpd/natpmp.c index c596781..2add04a 100644 --- a/miniupnpd/natpmp.c +++ b/miniupnpd/natpmp.c @@ -1,6 +1,6 @@ -/* $Id: natpmp.c,v 1.32 2012/05/27 22:36:03 nanard Exp $ */ +/* $Id: natpmp.c,v 1.33 2013/03/23 10:46:55 nanard Exp $ */ /* MiniUPnP project - * (c) 2007-2012 Thomas Bernard + * (c) 2007-2013 Thomas Bernard * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -96,7 +96,7 @@ static void FillPublicAddressResponse(unsigned char * resp, in_addr_t senderaddr if(!ext_if_name || ext_if_name[0]=='\0') { resp[3] = 3; /* Network Failure (e.g. NAT box itself * has not obtained a DHCP lease) */ - } else if(getifaddr(ext_if_name, tmp, INET_ADDRSTRLEN) < 0) { + } else if(getifaddr(ext_if_name, tmp, INET_ADDRSTRLEN, NULL, NULL) < 0) { syslog(LOG_ERR, "Failed to get IP for interface %s", ext_if_name); resp[3] = 3; /* Network Failure (e.g. NAT box itself * has not obtained a DHCP lease) */ diff --git a/miniupnpd/testgetifaddr.c b/miniupnpd/testgetifaddr.c index ff23b5d..7bc9b92 100644 --- a/miniupnpd/testgetifaddr.c +++ b/miniupnpd/testgetifaddr.c @@ -1,11 +1,12 @@ -/* $Id: testgetifaddr.c,v 1.4 2012/03/05 20:36:17 nanard Exp $ */ +/* $Id: testgetifaddr.c,v 1.6 2013/03/23 10:46:55 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2011 Thomas Bernard + * (c) 2006-2013 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ #include #include +#include #include "getifaddr.h" #if defined(__sun) @@ -14,17 +15,19 @@ #endif int main(int argc, char * * argv) { - char addr[64]; + char str_addr[64]; + struct in_addr addr; + struct in_addr mask; if(argc < 2) { fprintf(stderr, "Usage:\t%s interface_name\n", argv[0]); return 1; } openlog("testgetifaddr", LOG_CONS|LOG_PERROR, LOG_USER); - if(getifaddr(argv[1], addr, sizeof(addr)) < 0) { + if(getifaddr(argv[1], str_addr, sizeof(str_addr), &addr, &mask) < 0) { fprintf(stderr, "Cannot get address for interface %s.\n", argv[1]); return 1; } - printf("Interface %s has IP address %s.\n", argv[1], addr); + printf("Interface %s has IP address %s.\n", argv[1], str_addr); return 0; } diff --git a/miniupnpd/upnpdescgen.c b/miniupnpd/upnpdescgen.c index d13f74c..754e06d 100644 --- a/miniupnpd/upnpdescgen.c +++ b/miniupnpd/upnpdescgen.c @@ -1,7 +1,7 @@ -/* $Id: upnpdescgen.c,v 1.71 2012/10/04 22:08:08 nanard Exp $ */ +/* $Id: upnpdescgen.c,v 1.72 2013/03/23 10:46:55 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2012 Thomas Bernard + * (c) 2006-2013 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -1198,7 +1198,7 @@ genEventVars(int * len, const struct serviceDesc * s, const char * servns) str = strcat_str(str, len, &tmplen, use_ext_ip_addr); else { char ext_ip_addr[INET_ADDRSTRLEN]; - if(getifaddr(ext_if_name, ext_ip_addr, INET_ADDRSTRLEN) < 0) { + if(getifaddr(ext_if_name, ext_ip_addr, INET_ADDRSTRLEN, NULL, NULL) < 0) { str = strcat_str(str, len, &tmplen, "0.0.0.0"); } else { str = strcat_str(str, len, &tmplen, ext_ip_addr); diff --git a/miniupnpd/upnpsoap.c b/miniupnpd/upnpsoap.c index 0157f72..b563927 100644 --- a/miniupnpd/upnpsoap.c +++ b/miniupnpd/upnpsoap.c @@ -1,7 +1,7 @@ -/* $Id: upnpsoap.c,v 1.114 2013/02/06 12:40:25 nanard Exp $ */ +/* $Id: upnpsoap.c,v 1.115 2013/03/23 10:46:56 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2012 Thomas Bernard + * (c) 2006-2013 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -191,7 +191,7 @@ GetCommonLinkProperties(struct upnphttp * h, const char * action) if(upstream_bitrate == 0) upstream_bitrate = data.baudrate; } } - if(getifaddr(ext_if_name, ext_ip_addr, INET_ADDRSTRLEN) < 0) { + if(getifaddr(ext_if_name, ext_ip_addr, INET_ADDRSTRLEN, NULL, NULL) < 0) { status = "Down"; } bodylen = snprintf(body, sizeof(body), resp, @@ -269,7 +269,7 @@ GetExternalIPAddress(struct upnphttp * h, const char * action) { strncpy(ext_ip_addr, use_ext_ip_addr, INET_ADDRSTRLEN); } - else if(getifaddr(ext_if_name, ext_ip_addr, INET_ADDRSTRLEN) < 0) + else if(getifaddr(ext_if_name, ext_ip_addr, INET_ADDRSTRLEN, NULL, NULL) < 0) { syslog(LOG_ERR, "Failed to get ip address for interface %s", ext_if_name);