miniupnpd: Implement get_src_for_route_to() for *BSD
Also modify get_src_for_route_to() to return the network interface index
This commit is contained in:
parent
dce91afe3c
commit
43d3939602
|
@ -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:
|
||||
|
|
|
@ -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 :
|
||||
|
|
|
@ -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 <stdio.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <net/if.h>
|
||||
#include <net/route.h>
|
||||
#include <netinet/in.h>
|
||||
#ifdef AF_LINK
|
||||
#include <net/if_dl.h>
|
||||
#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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,6 +142,7 @@ 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 && src) {
|
||||
if(*src_len < RTA_PAYLOAD(rta)) {
|
||||
syslog(LOG_WARNING, "cannot copy src: %u<%lu",
|
||||
(unsigned)*src_len, RTA_PAYLOAD(rta));
|
||||
|
@ -149,6 +151,10 @@ get_src_for_route_to(const struct sockaddr * dst,
|
|||
*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);
|
||||
return 0;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue