From 43d3939602975060c7f9a5f3c69ce8b1fa4109d2 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Wed, 6 Feb 2013 15:06:59 +0100 Subject: [PATCH] miniupnpd: Implement get_src_for_route_to() for *BSD Also modify get_src_for_route_to() to return the network interface index --- miniupnpd/Changelog.txt | 1 + miniupnpd/Makefile | 21 ++++--- miniupnpd/bsd/getroute.c | 122 +++++++++++++++++++++++++++++++++++++ miniupnpd/getroute.h | 7 ++- miniupnpd/linux/getroute.c | 24 +++++--- miniupnpd/minissdp.c | 7 ++- miniupnpd/testgetroute.c | 13 +++- 7 files changed, 170 insertions(+), 25 deletions(-) create mode 100644 miniupnpd/bsd/getroute.c diff --git a/miniupnpd/Changelog.txt b/miniupnpd/Changelog.txt index 1378342..daaf3e9 100644 --- a/miniupnpd/Changelog.txt +++ b/miniupnpd/Changelog.txt @@ -1,6 +1,7 @@ $Id: Changelog.txt,v 1.325 2013/02/06 13:14:50 nanard Exp $ 2013/02/06: + Implement get_src_for_route_to() for *BSD fix 2 potential memory leaks in GetListOfPortMappings() 2013/01/29: diff --git a/miniupnpd/Makefile b/miniupnpd/Makefile index a82e5e3..3192942 100644 --- a/miniupnpd/Makefile +++ b/miniupnpd/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.71 2012/09/20 12:45:59 nanard Exp $ +# $Id: Makefile,v 1.73 2013/02/06 13:11:45 nanard Exp $ # MiniUPnP project # http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ # Author: Thomas Bernard @@ -81,9 +81,9 @@ STDOBJS = miniupnpd.o upnphttp.o upnpdescgen.o upnpsoap.o \ options.o upnppermissions.o minissdp.o natpmp.o \ upnpevents.o upnputils.o getconnstatus.o \ upnppinhole.o -BSDOBJS = bsd/getifstats.o bsd/ifacewatcher.o -SUNOSOBJS = solaris/getifstats.o bsd/ifacewatcher.o -MACOBJS = mac/getifstats.o bsd/ifacewatcher.o +BSDOBJS = bsd/getifstats.o bsd/ifacewatcher.o bsd/getroute.o +SUNOSOBJS = solaris/getifstats.o bsd/ifacewatcher.o bsd/getroute.o +MACOBJS = mac/getifstats.o bsd/ifacewatcher.o bsd/getroute.o PFOBJS = pf/obsdrdr.o pf/pfpinhole.o IPFOBJS = ipf/ipfrdr.o IPFWOBJS = ipfw/ipfwrdr.o ipfw/ipfwaux.o @@ -93,12 +93,15 @@ ALLOBJS = $(STDOBJS) $(MISCOBJS) .if $(OSNAME) == "SunOS" ALLOBJS += $(SUNOSOBJS) TESTGETIFSTATSOBJS = testgetifstats.o solaris/getifstats.o +TESTGETROUTEOBJS = testgetroute.o upnputils.o bsd/getroute.o .elif $(OSNAME) == "Darwin" ALLOBJS += $(MACOBJS) TESTGETIFSTATSOBJS = testgetifstats.o mac/getifstats.o +TESTGETROUTEOBJS = testgetroute.o upnputils.o bsd/getroute.o .else ALLOBJS += $(BSDOBJS) TESTGETIFSTATSOBJS = testgetifstats.o bsd/getifstats.o +TESTGETROUTEOBJS = testgetroute.o upnputils.o bsd/getroute.o .endif .if $(FWNAME) == "pf" @@ -116,7 +119,7 @@ MINIUPNPDCTLOBJS = miniupnpdctl.o EXECUTABLES = miniupnpd testupnpdescgen testgetifstats \ testupnppermissions miniupnpdctl \ - testgetifaddr + testgetifaddr testgetroute .if $(OSNAME) == "Darwin" LIBS = .else @@ -139,7 +142,7 @@ clean: $(RM) $(STDOBJS) $(BSDOBJS) $(SUNOSOBJS) $(MACOBJS) $(EXECUTABLES) \ testupnpdescgen.o \ $(MISCOBJS) config.h testgetifstats.o testupnppermissions.o \ - miniupnpdctl.o testgetifaddr.o \ + miniupnpdctl.o testgetifaddr.o testgetroute.o \ $(PFOBJS) $(IPFOBJS) $(IPFWOBJS) install: miniupnpd genuuid @@ -169,7 +172,8 @@ genuuid: depend: config.h mkdep $(ALLOBJS:.o=.c) testupnpdescgen.c testgetifstats.c \ - testupnppermissions.c miniupnpdctl.c testgetifaddr.c + testupnppermissions.c miniupnpdctl.c testgetifaddr.c \ + testgetroute.c miniupnpd: config.h $(ALLOBJS) $(CC) $(CFLAGS) -o $@ $(ALLOBJS) $(LIBS) @@ -192,6 +196,9 @@ testgetifaddr: config.h $(TESTGETIFADDROBJS) testupnppermissions: config.h $(TESTUPNPPERMISSIONSOBJS) $(CC) $(CFLAGS) -o $@ $(TESTUPNPPERMISSIONSOBJS) +testgetroute: config.h $(TESTGETROUTEOBJS) + $(CC) $(CFLAGS) -o $@ $(TESTGETROUTEOBJS) + # gmake : # $(CC) $(CFLAGS) -o $@ $^ # BSDmake : diff --git a/miniupnpd/bsd/getroute.c b/miniupnpd/bsd/getroute.c new file mode 100644 index 0000000..e72f716 --- /dev/null +++ b/miniupnpd/bsd/getroute.c @@ -0,0 +1,122 @@ +/* $Id: getroute.c,v 1.3 2013/02/06 13:11:45 nanard Exp $ */ +/* MiniUPnP project + * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * (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 +#include +#include +#include +#include +#ifdef AF_LINK +#include +#endif + +#include "../config.h" +#include "../upnputils.h" + + +int +get_src_for_route_to(const struct sockaddr * dst, + void * src, size_t * src_len, + int * index) +{ + int found = 0; + int s; + int l, i; + char * p; + struct sockaddr * sa; + struct { + struct rt_msghdr m_rtm; + char m_space[512]; + } m_rtmsg; +#define rtm m_rtmsg.m_rtm + + if(dst == NULL) + return -1; +#ifdef __APPLE__ + if(dst->sa_family == AF_INET6) { + syslog(LOG_ERR, "Sorry, get_src_for_route_to() is known to fail with IPV6 on OS X..."); + return -1; + } +#endif + s = socket(PF_ROUTE, SOCK_RAW, dst->sa_family); + if(s < 0) { + syslog(LOG_ERR, "socket(PF_ROUTE) failed : %m"); + return -1; + } + memset(&rtm, 0, sizeof(rtm)); + rtm.rtm_type = RTM_GET; + rtm.rtm_flags = RTF_UP; + rtm.rtm_version = RTM_VERSION; + rtm.rtm_seq = 1; + rtm.rtm_addrs = RTA_DST; /* destination address */ + memcpy(m_rtmsg.m_space, dst, sizeof(struct sockaddr)); + rtm.rtm_msglen = sizeof(struct rt_msghdr) + sizeof(struct sockaddr); + if(write(s, &m_rtmsg, rtm.rtm_msglen) < 0) { + syslog(LOG_ERR, "write: %m"); + close(s); + return -1; + } + + do { + l = read(s, &m_rtmsg, sizeof(m_rtmsg)); + if(l<0) { + syslog(LOG_ERR, "read: %m"); + close(s); + return -1; + } + syslog(LOG_DEBUG, "read l=%d seq=%d pid=%d", + l, rtm.rtm_seq, rtm.rtm_pid); + } while(l > 0 && (rtm.rtm_pid != getpid() || rtm.rtm_seq != 1)); + close(s); + p = m_rtmsg.m_space; + if(rtm.rtm_addrs) { + for(i=1; i<0x8000; i <<= 1) { + if(i & rtm.rtm_addrs) { + char tmp[256] = { 0 }; + sa = (struct sockaddr *)p; + sockaddr_to_string(sa, tmp, sizeof(tmp)); + syslog(LOG_DEBUG, "type=%d sa_len=%d sa_family=%d %s", + i, sa->sa_len, sa->sa_family, tmp); + if((i == RTA_DST || i == RTA_GATEWAY) && + (src_len && src)) { + size_t len = 0; + void * paddr = NULL; + if(sa->sa_family == AF_INET) { + paddr = &((struct sockaddr_in *)sa)->sin_addr; + len = sizeof(struct in_addr); + } else if(sa->sa_family == AF_INET6) { + paddr = &((struct sockaddr_in6 *)sa)->sin6_addr; + len = sizeof(struct in6_addr); + } + if(paddr) { + if(*src_len < len) { + syslog(LOG_WARNING, "cannot copy src. %u<%u", + (unsigned)*src_len, (unsigned)len); + return -1; + } + memcpy(src, paddr, len); + *src_len = len; + found = 1; + } + } +#ifdef AF_LINK + if(sa->sa_family == AF_LINK) { + struct sockaddr_dl * sdl = (struct sockaddr_dl *)sa; + if(index) + *index = sdl->sdl_index; + } +#endif + p += sa->sa_len; + } + } + } + return found ? 0 : -1; +} + diff --git a/miniupnpd/getroute.h b/miniupnpd/getroute.h index a556efd..86d0496 100644 --- a/miniupnpd/getroute.h +++ b/miniupnpd/getroute.h @@ -1,7 +1,7 @@ -/* $Id: getroute.h,v 1.1 2012/06/23 22:59:07 nanard Exp $ */ +/* $Id: getroute.h,v 1.3 2013/02/06 10:50:04 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 */ @@ -10,7 +10,8 @@ int get_src_for_route_to(const struct sockaddr * dst, - void * src, size_t * src_len); + void * src, size_t * src_len, + int * index); #endif diff --git a/miniupnpd/linux/getroute.c b/miniupnpd/linux/getroute.c index a472010..e6386d0 100644 --- a/miniupnpd/linux/getroute.c +++ b/miniupnpd/linux/getroute.c @@ -1,7 +1,7 @@ -/* $Id: getroute.c,v 1.3 2012/10/23 12:24:33 nanard Exp $ */ +/* $Id: getroute.c,v 1.4 2013/02/06 10:50:04 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 */ @@ -23,7 +23,8 @@ int get_src_for_route_to(const struct sockaddr * dst, - void * src, size_t * src_len) + void * src, size_t * src_len, + int * index) { int fd = -1; struct nlmsghdr *h; @@ -141,13 +142,18 @@ get_src_for_route_to(const struct sockaddr * dst, for(rta = RTM_RTA(NLMSG_DATA((h))); RTA_OK(rta, len); rta = RTA_NEXT(rta,len)) { unsigned char * data = RTA_DATA(rta); if(rta->rta_type == RTA_PREFSRC) { - if(*src_len < RTA_PAYLOAD(rta)) { - syslog(LOG_WARNING, "cannot copy src: %u<%lu", - (unsigned)*src_len, RTA_PAYLOAD(rta)); - goto error; + if(src_len && src) { + if(*src_len < RTA_PAYLOAD(rta)) { + syslog(LOG_WARNING, "cannot copy src: %u<%lu", + (unsigned)*src_len, RTA_PAYLOAD(rta)); + goto error; + } + *src_len = RTA_PAYLOAD(rta); + memcpy(src, data, RTA_PAYLOAD(rta)); } - *src_len = RTA_PAYLOAD(rta); - memcpy(src, data, RTA_PAYLOAD(rta)); + } else if(rta->rta_type == RTA_OIF) { + if(index) + memcpy(index, data, sizeof(int)); } } close(fd); diff --git a/miniupnpd/minissdp.c b/miniupnpd/minissdp.c index 2caeaf3..aec1057 100644 --- a/miniupnpd/minissdp.c +++ b/miniupnpd/minissdp.c @@ -1,7 +1,7 @@ -/* $Id: minissdp.c,v 1.43 2012/10/03 15:21:48 nanard Exp $ */ +/* $Id: minissdp.c,v 1.44 2013/02/06 10:50:04 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 */ @@ -617,12 +617,13 @@ ProcessSSDPData(int s, const char *bufr, int n, { /* IPv6 address with brackets */ #ifdef UPNP_STRICT + int index; struct in6_addr addr6; size_t addr6_len = sizeof(addr6); /* retrieve the IPv6 address which * will be used locally to reach sender */ memset(&addr6, 0, sizeof(addr6)); - if(get_src_for_route_to (sender, &addr6, &addr6_len) < 0) { + if(get_src_for_route_to (sender, &addr6, &addr6_len, &index) < 0) { syslog(LOG_WARNING, "get_src_for_route_to() failed, using %s", ipv6_addr_for_http_with_brackets); announced_host = ipv6_addr_for_http_with_brackets; } else { diff --git a/miniupnpd/testgetroute.c b/miniupnpd/testgetroute.c index c144e9b..1afab64 100644 --- a/miniupnpd/testgetroute.c +++ b/miniupnpd/testgetroute.c @@ -1,7 +1,7 @@ -/* $Id: testgetroute.c,v 1.3 2012/10/23 12:24:33 nanard Exp $ */ +/* $Id: testgetroute.c,v 1.5 2013/02/06 12:07:36 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 */ @@ -15,12 +15,15 @@ #include "getroute.h" #include "upnputils.h" +#include "upnpglobalvars.h" #ifndef LOG_PERROR /* solaris does not define LOG_PERROR */ #define LOG_PERROR 0 #endif +struct lan_addr_list lan_addrs; + int main(int argc, char ** argv) { @@ -30,6 +33,7 @@ main(int argc, char ** argv) void * src; size_t src_len; int r; + int index = -1; memset(&dst4, 0, sizeof(dst4)); memset(&dst6, 0, sizeof(dst6)); @@ -71,12 +75,15 @@ main(int argc, char ** argv) } if (dst) { - r = get_src_for_route_to (dst, src, &src_len); + syslog(LOG_DEBUG, "calling get_src_for_route_to(%p, %p, %p(%u), %p)", + dst, src, &src_len, (unsigned)src_len, &index); + r = get_src_for_route_to (dst, src, &src_len, &index); syslog(LOG_DEBUG, "get_src_for_route_to() returned %d", r); if(r >= 0) { char src_str[128]; sockaddr_to_string(dst, src_str, sizeof(src_str)); syslog(LOG_DEBUG, "src=%s", src_str); + syslog(LOG_DEBUG, "index=%d", index); } } closelog();