From b9daf5cc27aa180b4d8fde6e32043f01125ae161 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Fri, 13 Dec 2013 12:35:36 +0100 Subject: [PATCH 001/104] testupnpdescgen.c: minor fix on getifaddr() --- miniupnpd/Makefile.linux | 17 +++++++++-------- miniupnpd/testupnpdescgen.c | 5 ++++- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/miniupnpd/Makefile.linux b/miniupnpd/Makefile.linux index 35c96ae..88f65e0 100644 --- a/miniupnpd/Makefile.linux +++ b/miniupnpd/Makefile.linux @@ -222,7 +222,7 @@ miniupnpd.o: config.h macros.h upnpglobalvars.h upnppermissions.h miniupnpd.o: miniupnpdtypes.h upnphttp.h upnpdescgen.h miniupnpdpath.h miniupnpd.o: getifaddr.h upnpsoap.h options.h minissdp.h upnpredirect.h miniupnpd.o: upnppinhole.h daemonize.h upnpevents.h natpmp.h commonrdr.h -miniupnpd.o: upnputils.h ifacewatcher.h pcpserver.h pcplearndscp.h +miniupnpd.o: upnputils.h ifacewatcher.h upnphttp.o: config.h upnphttp.h upnpdescgen.h miniupnpdpath.h upnpsoap.h upnphttp.o: upnpevents.h upnputils.h upnpdescgen.o: config.h getifaddr.h upnpredirect.h upnpdescgen.h @@ -240,26 +240,26 @@ upnpredirect.o: netfilter/iptcrdr.h commonrdr.h getifaddr.o: config.h getifaddr.h daemonize.o: daemonize.h config.h upnpglobalvars.o: config.h upnpglobalvars.h upnppermissions.h -upnpglobalvars.o: miniupnpdtypes.h pcplearndscp.h +upnpglobalvars.o: miniupnpdtypes.h upnpdescstrings.h options.o: config.h options.h upnppermissions.h upnpglobalvars.h -options.o: miniupnpdtypes.h pcplearndscp.h +options.o: miniupnpdtypes.h upnppermissions.o: config.h upnppermissions.h minissdp.o: config.h upnpdescstrings.h miniupnpdpath.h upnphttp.h minissdp.o: upnpglobalvars.h upnppermissions.h miniupnpdtypes.h minissdp.h minissdp.o: upnputils.h getroute.h codelength.h natpmp.o: macros.h config.h natpmp.h upnpglobalvars.h upnppermissions.h natpmp.o: miniupnpdtypes.h getifaddr.h upnpredirect.h commonrdr.h upnputils.h -pcpserver.o: macros.h config.h pcpserver.h pcp_msg_struct.h upnpglobalvars.h -pcpserver.o: upnpredirect.h -pcplearndscp.o: config.h pcplearndscp.h +pcpserver.o: config.h upnpevents.o: config.h upnpevents.h miniupnpdpath.h upnpglobalvars.h upnpevents.o: upnppermissions.h miniupnpdtypes.h upnpdescgen.h upnputils.h upnputils.o: config.h upnputils.h upnpglobalvars.h upnppermissions.h -upnputils.o: miniupnpdtypes.h getroute.h +upnputils.o: miniupnpdtypes.h getconnstatus.o: getconnstatus.h getifaddr.h upnppinhole.o: macros.h config.h upnpredirect.h upnpglobalvars.h upnppinhole.o: upnppermissions.h miniupnpdtypes.h upnpevents.h upnppinhole.o: netfilter/iptpinhole.h +pcplearndscp.o: config.h upnpglobalvars.h upnppermissions.h miniupnpdtypes.h +pcplearndscp.o: pcplearndscp.h linux/getifstats.o: config.h getifstats.h linux/ifacewatcher.o: config.h ifacewatcher.h config.h minissdp.h linux/ifacewatcher.o: miniupnpdtypes.h getifaddr.h upnpglobalvars.h @@ -270,7 +270,8 @@ netfilter/iptcrdr.o: config.h upnpglobalvars.h upnppermissions.h netfilter/iptcrdr.o: miniupnpdtypes.h netfilter/iptpinhole.o: config.h netfilter/iptpinhole.h upnpglobalvars.h netfilter/iptpinhole.o: upnppermissions.h config.h miniupnpdtypes.h -testupnpdescgen.o: macros.h config.h upnpdescgen.h +testupnpdescgen.o: macros.h config.h upnpdescgen.h upnpdescstrings.h +testupnpdescgen.o: getifaddr.h upnpdescgen.o: config.h getifaddr.h upnpredirect.h upnpdescgen.h upnpdescgen.o: miniupnpdpath.h upnpglobalvars.h upnppermissions.h upnpdescgen.o: miniupnpdtypes.h upnpdescstrings.h upnpurns.h getconnstatus.h diff --git a/miniupnpd/testupnpdescgen.c b/miniupnpd/testupnpdescgen.c index b838c62..c2cd028 100644 --- a/miniupnpd/testupnpdescgen.c +++ b/miniupnpd/testupnpdescgen.c @@ -17,6 +17,7 @@ #include "config.h" #include "upnpdescgen.h" #include "upnpdescstrings.h" +#include "getifaddr.h" char uuidvalue_igd[] = "uuid:12345678-0000-0000-0000-000000abcd01"; char uuidvalue_wan[] = "uuid:12345678-0000-0000-0000-000000abcd02"; @@ -42,9 +43,11 @@ int ipv6fc_firewall_enabled = 1; int ipv6fc_inbound_pinhole_allowed = 1; #endif -int getifaddr(const char * ifname, char * buf, int len) +int getifaddr(const char * ifname, char * buf, int len, struct in_addr * addr, struct in_addr * mask) { UNUSED(ifname); + UNUSED(addr); + UNUSED(mask); strncpy(buf, "1.2.3.4", len); return 0; } From 18d54e2ae073e59e65724f2af12c69ab8c16b4db Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Wed, 20 Feb 2013 17:08:07 +0100 Subject: [PATCH 002/104] miniupnpc.c: MX cannot be 0 --- miniupnpc/miniupnpc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/miniupnpc/miniupnpc.c b/miniupnpc/miniupnpc.c index d9debde..63460bf 100644 --- a/miniupnpc/miniupnpc.c +++ b/miniupnpc/miniupnpc.c @@ -560,6 +560,10 @@ upnpDiscover(int delay, const char * multicastif, *error = UPNPDISCOVER_SUCCESS; /* Calculating maximum response time in seconds */ mx = ((unsigned int)delay) / 1000u; + if(mx == 0) { + mx = 1; + delay = 1000; + } /* receiving SSDP response packet */ for(n = 0; deviceList[deviceIndex]; deviceIndex++) { From 00adeeaaad3ed35b3ec656ced7f479915756bf48 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Fri, 13 Dec 2013 14:41:21 +0100 Subject: [PATCH 003/104] typo fix --- miniupnpd/Makefile.linux | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miniupnpd/Makefile.linux b/miniupnpd/Makefile.linux index 88f65e0..f0068b4 100644 --- a/miniupnpd/Makefile.linux +++ b/miniupnpd/Makefile.linux @@ -45,7 +45,7 @@ MANINSTALLDIR = $(INSTALLPREFIX)/share/man/man8 BASEOBJS = miniupnpd.o upnphttp.o upnpdescgen.o upnpsoap.o \ upnpreplyparse.o minixml.o \ upnpredirect.o getifaddr.o daemonize.o upnpglobalvars.o \ - options.o upnppermissions.o minissdp.o natpmp.o pcpserver.o\ + options.o upnppermissions.o minissdp.o natpmp.o pcpserver.o \ upnpevents.o upnputils.o getconnstatus.o \ upnppinhole.o pcplearndscp.o From f7cb8a684892d183c953eca78d4c7fff19d6d579 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Fri, 13 Dec 2013 14:43:15 +0100 Subject: [PATCH 004/104] update .gitignore --- miniupnpd/.gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/miniupnpd/.gitignore b/miniupnpd/.gitignore index dc70043..f97b1ce 100644 --- a/miniupnpd/.gitignore +++ b/miniupnpd/.gitignore @@ -9,3 +9,6 @@ testgetifstats testupnpdescgen testupnppermissions testgetroute +netfilter/testiptcrdr +netfilter/testiptcrdr_dscp +netfilter/testiptcrdr_peer From 278f6b5e454626e4b535932a393f6d6453183c54 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Fri, 13 Dec 2013 16:57:07 +0100 Subject: [PATCH 005/104] update Changelog.txt :) --- miniupnpd/Changelog.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/miniupnpd/Changelog.txt b/miniupnpd/Changelog.txt index 5e2d2f0..4c7afc4 100644 --- a/miniupnpd/Changelog.txt +++ b/miniupnpd/Changelog.txt @@ -1,7 +1,8 @@ -$Id: Changelog.txt,v 1.345 2013/06/13 13:21:28 nanard Exp $ +$Id: Changelog.txt,v 1.346 2013/12/13 13:41:52 nanard Exp $ 2013/12/13: Make all manufacturer info configurable thanks to Leo Moll + Merge PCP support (see https://github.com/miniupnp/miniupnp) 2013/06/13: Have 3 UUID for the 3 devices (IGD, WAN Device, WAN Connection Device) From 6a8a580e6faa6e4ae974d9f8c355feb6ea8358a4 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Fri, 13 Dec 2013 16:57:42 +0100 Subject: [PATCH 006/104] Makefile: add pcpserver.o --- miniupnpd/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/miniupnpd/Makefile b/miniupnpd/Makefile index 3192942..4f085fd 100644 --- a/miniupnpd/Makefile +++ b/miniupnpd/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.73 2013/02/06 13:11:45 nanard Exp $ +# $Id: Makefile,v 1.74 2013/12/13 15:28:34 nanard Exp $ # MiniUPnP project # http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ # Author: Thomas Bernard @@ -78,7 +78,7 @@ CFLAGS += -m64 -mcmodel=medlow STDOBJS = miniupnpd.o upnphttp.o upnpdescgen.o upnpsoap.o \ upnpredirect.o getifaddr.o daemonize.o upnpglobalvars.o \ - options.o upnppermissions.o minissdp.o natpmp.o \ + options.o upnppermissions.o minissdp.o natpmp.o pcpserver.o \ upnpevents.o upnputils.o getconnstatus.o \ upnppinhole.o BSDOBJS = bsd/getifstats.o bsd/ifacewatcher.o bsd/getroute.o From 1e08e9ed4d07abf9de28fbed4c820322e2e20b7e Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Fri, 13 Dec 2013 16:59:51 +0100 Subject: [PATCH 007/104] getifaddr: more portable code (works with old OpenBSD) --- miniupnpd/getifaddr.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/miniupnpd/getifaddr.c b/miniupnpd/getifaddr.c index 2a84852..1430336 100644 --- a/miniupnpd/getifaddr.c +++ b/miniupnpd/getifaddr.c @@ -1,4 +1,4 @@ -/* $Id: getifaddr.c,v 1.17 2013/04/27 15:40:09 nanard Exp $ */ +/* $Id: getifaddr.c,v 1.19 2013/12/13 14:28:40 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2013 Thomas Bernard @@ -141,20 +141,26 @@ int getifaddr_in6(const char * ifname, struct in6_addr * addr){ switch(ife->ifa_addr->sa_family) { case AF_INET: +#if 0 addr->s6_addr32[0]=0; addr->s6_addr32[1]=0; addr->s6_addr32[2]=htonl(0xffff); addr->s6_addr32[3]=((struct sockaddr_in *)ife->ifa_addr)->sin_addr.s_addr; - //inet_ntop(ife->ifa_addr->sa_family, - // &((struct sockaddr_in *)ife->ifa_addr)->sin_addr, - // buf, len); +#endif + memset(addr->s6_addr, 0, 10); + addr->s6_addr[10] = 0xff; + addr->s6_addr[11] = 0xff; + memcpy(addr->s6_addr + 12, &(((struct sockaddr_in *)ife->ifa_addr)->sin_addr.s_addr), 4); + /*inet_ntop(ife->ifa_addr->sa_family, + &((struct sockaddr_in *)ife->ifa_addr)->sin_addr, + buf, len);*/ found = 1; break; case AF_INET6: - if(!IN6_IS_ADDR_LOOPBACK(&addr->s6_addr32) - && !IN6_IS_ADDR_LINKLOCAL(&addr->s6_addr32)) { - memcpy(addr->s6_addr32, &((struct sockaddr_in6 *)ife->ifa_addr)->sin6_addr, sizeof(addr->s6_addr32)); + if(!IN6_IS_ADDR_LOOPBACK(addr) + && !IN6_IS_ADDR_LINKLOCAL(addr)) { + memcpy(addr->s6_addr, &((struct sockaddr_in6 *)ife->ifa_addr)->sin6_addr, 16); found = 1; } break; From f774a54bac6fa6aa9d1a83228eb7cc4262b7e8a0 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Fri, 13 Dec 2013 17:01:41 +0100 Subject: [PATCH 008/104] remove C++ style comments --- miniupnpd/genconfig.sh | 6 ++-- miniupnpd/miniupnpd.c | 6 ++-- miniupnpd/natpmp.c | 4 +-- miniupnpd/options.c | 8 ++--- miniupnpd/pcp_msg_struct.h | 6 ++-- miniupnpd/pcplearndscp.h | 6 ++-- miniupnpd/pcpserver.c | 62 +++++++++++++++++++------------------- miniupnpd/pcpserver.h | 6 ++-- miniupnpd/upnpglobalvars.c | 4 +-- 9 files changed, 54 insertions(+), 54 deletions(-) diff --git a/miniupnpd/genconfig.sh b/miniupnpd/genconfig.sh index efad1f5..d4cf5d8 100755 --- a/miniupnpd/genconfig.sh +++ b/miniupnpd/genconfig.sh @@ -1,5 +1,5 @@ #! /bin/sh -# $Id: genconfig.sh,v 1.63 2013/05/03 09:30:10 nanard Exp $ +# $Id: genconfig.sh,v 1.65 2013/12/13 14:07:08 nanard Exp $ # miniupnp daemon # http://miniupnp.free.fr or http://miniupnp.tuxfamily.org/ # (c) 2006-2013 Thomas Bernard @@ -352,9 +352,9 @@ echo "/*#define PCP_PEER*/" >> ${CONFIGFILE} fi echo "#ifdef PCP_PEER" >> ${CONFIGFILE} echo "/*#define PCP_FLOWP*/" >> ${CONFIGFILE} -echo "#endif //PCP_PEER" >> ${CONFIGFILE} +echo "#endif /*PCP_PEER*/" >> ${CONFIGFILE} echo "/*#define PCP_SADSCP*/" >> ${CONFIGFILE} -echo "#endif //ENABLE_PCP" >> ${CONFIGFILE} +echo "#endif /*ENABLE_PCP*/" >> ${CONFIGFILE} echo "" >> ${CONFIGFILE} echo "/* Uncomment the following line to enable generation of" >> ${CONFIGFILE} diff --git a/miniupnpd/miniupnpd.c b/miniupnpd/miniupnpd.c index a30ce2a..42313b4 100644 --- a/miniupnpd/miniupnpd.c +++ b/miniupnpd/miniupnpd.c @@ -1,4 +1,4 @@ -/* $Id: miniupnpd.c,v 1.176 2013/06/13 13:21:29 nanard Exp $ */ +/* $Id: miniupnpd.c,v 1.178 2013/12/13 14:10:02 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2013 Thomas Bernard @@ -1837,10 +1837,10 @@ main(int argc, char * * argv) if (len < 1) continue; #ifdef ENABLE_PCP - if (msg_buff[0]==0) { // version equals to 0 -> means NAT-PMP + if (msg_buff[0]==0) { /* version equals to 0 -> means NAT-PMP */ ProcessIncomingNATPMPPacket(snatpmp[i], msg_buff, len, &senderaddr); - } else { // everything else can be PCP + } else { /* everything else can be PCP */ ProcessIncomingPCPPacket(snatpmp[i], msg_buff, len, &senderaddr); } diff --git a/miniupnpd/natpmp.c b/miniupnpd/natpmp.c index daad014..d1efd27 100644 --- a/miniupnpd/natpmp.c +++ b/miniupnpd/natpmp.c @@ -1,4 +1,4 @@ -/* $Id: natpmp.c,v 1.33 2013/03/23 10:46:55 nanard Exp $ */ +/* $Id: natpmp.c,v 1.35 2013/12/13 14:07:08 nanard Exp $ */ /* MiniUPnP project * (c) 2007-2013 Thomas Bernard * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ @@ -156,8 +156,6 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, unsigned char *req=msg_buff; /* request udp packet */ unsigned char resp[32]; /* response udp packet */ int resplen; - //struct sockaddr_in senderaddr; - //socklen_t senderaddrlen = sizeof(senderaddr); int n = len; char senderaddrstr[16]; diff --git a/miniupnpd/options.c b/miniupnpd/options.c index ce368c9..8d0de20 100644 --- a/miniupnpd/options.c +++ b/miniupnpd/options.c @@ -1,4 +1,4 @@ -/* $Id: options.c,v 1.26 2012/06/29 19:26:09 nanard Exp $ */ +/* $Id: options.c,v 1.28 2013/12/13 14:07:08 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * author: Ryan Wagoner @@ -16,7 +16,7 @@ #include "upnppermissions.h" #ifdef PCP_SADSCP #include "pcplearndscp.h" -#endif // PCP_SADSPC +#endif /* PCP_SADSPC */ #include "upnpglobalvars.h" #ifndef DISABLE_CONFIG_FILE @@ -187,7 +187,7 @@ readoptionsfile(const char * fname) } continue; } -#endif //PCP_SADSCP +#endif /* PCP_SADSCP */ if(!(equals = strchr(name, '='))) { fprintf(stderr, "parsing error file %s line %d : %s\n", @@ -303,7 +303,7 @@ freeoptions(void) dscp_values_list = NULL; num_dscp_values = 0; } -#endif //PCP_SADSCP +#endif /* PCP_SADSCP */ } #endif /* DISABLE_CONFIG_FILE */ diff --git a/miniupnpd/pcp_msg_struct.h b/miniupnpd/pcp_msg_struct.h index 3c956ea..d472b14 100644 --- a/miniupnpd/pcp_msg_struct.h +++ b/miniupnpd/pcp_msg_struct.h @@ -1,4 +1,4 @@ -/* $Id: pcp_msg_struct.h $ */ +/* $Id: pcp_msg_struct.h,v 1.2 2013/12/13 15:47:23 nanard Exp $ */ /* MiniUPnP project * Website : http://miniupnp.free.fr/ * Author : Peter Tatrai @@ -138,7 +138,7 @@ typedef enum pcp_options { #ifdef WIN32 #pragma warning (push) #pragma warning (disable:4200) -#endif // WIN32 +#endif /* WIN32 */ #pragma pack(push, 1) @@ -287,4 +287,4 @@ typedef struct pcp_filter_option { #ifdef WIN32 #pragma warning (pop) -#endif // WIN32 +#endif /* WIN32 */ diff --git a/miniupnpd/pcplearndscp.h b/miniupnpd/pcplearndscp.h index ab720ff..93fee33 100644 --- a/miniupnpd/pcplearndscp.h +++ b/miniupnpd/pcplearndscp.h @@ -1,4 +1,4 @@ -/* $Id: pcplearndscp.h $ */ +/* $Id: pcplearndscp.h,v 1.2 2013/12/13 15:47:23 nanard Exp $ */ /* MiniUPnP project * Website : http://miniupnp.free.fr/ * Author : Miroslav Bagljas @@ -44,8 +44,8 @@ struct dscp_values { -// #set_learn_dscp "Webex" 1 1 1 34 +/* #set_learn_dscp "Webex" 1 1 1 34 */ int read_learn_dscp_line(struct dscp_values *dscpvalues, char *p); -#endif // PCPLEARNDSCP_H_INCLUDED +#endif /* PCPLEARNDSCP_H_INCLUDED */ diff --git a/miniupnpd/pcpserver.c b/miniupnpd/pcpserver.c index 0253826..a580548 100644 --- a/miniupnpd/pcpserver.c +++ b/miniupnpd/pcpserver.c @@ -1,4 +1,4 @@ -/* $Id: pcpserver.c $ */ +/* $Id: pcpserver.c,v 1.2 2013/12/13 15:48:56 nanard Exp $ */ /* MiniUPnP project * Website : http://miniupnp.free.fr/ * Author : Peter Tatrai @@ -61,7 +61,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "pcp_msg_struct.h" #ifdef PCP_PEER -//TODO make this platform independent +/* TODO make this platform independent */ #include "netfilter/iptcrdr.h" #endif @@ -104,7 +104,7 @@ typedef struct pcp_info { #ifdef PCP_PEER uint16_t peer_port; const struct in6_addr *peer_ip; /* Destination IP in network order */ -#endif //PCP_PEER +#endif /* PCP_PEER */ #ifdef PCP_SADSCP /* SADSCP specific information */ @@ -232,7 +232,7 @@ static void printMAPOpcodeVersion2(pcp_map_v2_t *map_buf) syslog(LOG_DEBUG, "MAP Ext IP: \t\t %s\n", inet_ntop(AF_INET6, map_buf->ext_ip, map_addr, INET6_ADDRSTRLEN)); } -#endif //DEBUG +#endif /* DEBUG */ static int parsePCPMAP_version1(pcp_map_v1_t *map_v1, \ pcp_info_t *pcp_msg_info) @@ -303,7 +303,7 @@ static void printPEEROpcodeVersion2(pcp_peer_v2_t *peer_buf) peer_addr,INET6_ADDRSTRLEN)); syslog(LOG_DEBUG, "PEER port port: \t\t %d\n", ntohs(peer_buf->peer_port) ); } -#endif //DEBUG +#endif /* DEBUG */ /* * Function extracting information from peer_buf to pcp_msg_info @@ -352,7 +352,7 @@ static int parsePCPPEER_version2(pcp_peer_v2_t *peer_buf, \ } return 0; } -#endif //PCP_PEER +#endif /* PCP_PEER */ #ifdef PCP_SADSCP #ifdef DEBUG @@ -481,7 +481,7 @@ static int parsePCPOptions(void* pcp_buf, int* remainingSize, int* processedSize break; case PCP_OPTION_FILTER: - // TODO fully implement filter + /* TODO fully implement filter */ opt_filter = (pcp_filter_option_t*) (pcp_buf + processed); option_length = ntohs(opt_filter->len); @@ -538,7 +538,7 @@ static int parsePCPOptions(void* pcp_buf, int* remainingSize, int* processedSize break; } - // shift processed and remaining values to new values + /* shift processed and remaining values to new values */ *remainingSize = remain; *processedSize = processed; return pcp_msg_info->result_code; @@ -675,7 +675,7 @@ static int CreatePCPPeer(pcp_info_t *pcp_msg_info) return 0; } } - //Create Peer Mapping + /* Create Peer Mapping */ { char desc[64]; char peerip_s[INET_ADDRSTRLEN], extip_s[INET_ADDRSTRLEN]; @@ -724,7 +724,7 @@ static int CreatePCPPeer(pcp_info_t *pcp_msg_info) } } #endif - //TODO: add upnp function for PI + /* TODO: add upnp function for PI */ if (add_peer_redirect_rule2(ext_if_name, peerip_s, pcp_msg_info->peer_port, @@ -810,7 +810,7 @@ static void DeletePCPPeer(pcp_info_t *pcp_msg_info) pcp_msg_info->result_code = PCP_ERR_NO_RESOURCES; } } -#endif //PCP_PEER +#endif /* PCP_PEER */ static void CreatePCPMap(pcp_info_t *pcp_msg_info) { @@ -903,7 +903,7 @@ static void DeletePCPMap(pcp_info_t *pcp_msg_info) char desc[64]; unsigned int timestamp; - //iterate through all rules and delete the requested ones + /* iterate through all rules and delete the requested ones */ while(get_redirect_rule_by_index(index, 0, &eport2, iaddr2, sizeof(iaddr2), &iport2, &proto2, @@ -912,7 +912,7 @@ static void DeletePCPMap(pcp_info_t *pcp_msg_info) if(0 == strncmp(iaddr2, pcp_msg_info->senderaddrstr, sizeof(iaddr2)) && (proto2==proto) - && (0 == strncmp(desc, "PCP", 3)) //starts with PCP + && (0 == strncmp(desc, "PCP", 3)) /* starts with PCP */ && ((iport2==iport) || (iport==0))) { r = _upnp_delete_redir(eport2, proto2); @@ -984,26 +984,26 @@ static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info) #ifdef PCP_SADSCP pcp_sadscp_req_t* sadscp; #endif - // start with PCP_SUCCESS as result code, if everything is OK value will be unchanged + /* start with PCP_SUCCESS as result code, if everything is OK value will be unchanged */ pcp_msg_info->result_code = PCP_SUCCESS; remainingSize = req_size; processedSize = 0; - // discard request that exceeds maximal length, - // or that is shorter than 3 - // or that is not the multiple of 4 + /* discard request that exceeds maximal length, + or that is shorter than 3 + or that is not the multiple of 4 */ if (req_size < PCP_MIN_LEN) - return 0; //ignore msg + return 0; /* ignore msg */ if ( (req_size > PCP_MAX_LEN) || ( (req_size & 3) != 0)) { syslog(LOG_ERR, "PCP: Size of PCP packet(%d) is larger than %d bytes or " "the size is not multiple of 4.\n", req_size, PCP_MAX_LEN); pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; - return 1; // send response + return 1; /* send response */ } - //first print out info from common request header + /* first print out info from common request header */ common_req = (pcp_request_t*)req; if (parseCommonRequestHeader(common_req, pcp_msg_info) ) { @@ -1027,7 +1027,7 @@ static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info) map_v1 = (pcp_map_v1_t*)(req + processedSize); #ifdef DEBUG printMAPOpcodeVersion1(map_v1); -#endif //DEBUG +#endif /* DEBUG */ if ( parsePCPMAP_version1(map_v1, pcp_msg_info) ) { return pcp_msg_info->result_code; } @@ -1062,7 +1062,7 @@ static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info) #ifdef DEBUG printPEEROpcodeVersion1(peer_v1); -#endif //DEBUG +#endif /* DEBUG */ if ( parsePCPPEER_version1(peer_v1, pcp_msg_info) ) { return pcp_msg_info->result_code; } @@ -1085,7 +1085,7 @@ static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info) break; -#endif //PCP_PEER +#endif /* PCP_PEER */ default: pcp_msg_info->result_code = PCP_ERR_UNSUPP_OPCODE; break; @@ -1106,7 +1106,7 @@ static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info) #ifdef DEBUG printMAPOpcodeVersion2(map_v2); -#endif //DEBUG +#endif /* DEBUG */ if (parsePCPMAP_version2(map_v2, pcp_msg_info) ) { return pcp_msg_info->result_code; @@ -1142,7 +1142,7 @@ static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info) #ifdef DEBUG printPEEROpcodeVersion2(peer_v2); -#endif //DEBUG +#endif /* DEBUG */ parsePCPPEER_version2(peer_v2, pcp_msg_info); processedSize += sizeof(pcp_peer_v2_t); @@ -1165,7 +1165,7 @@ static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info) } break; -#endif //PCP_PEER +#endif /* PCP_PEER */ #ifdef PCP_SADSCP case PCP_OPCODE_SADSCP: @@ -1225,7 +1225,7 @@ static void createPCPResponse(unsigned char *response, pcp_info_t *pcp_msg_info) resp->result_code = pcp_msg_info->result_code; resp->epochtime = htonl(time(NULL) - startup_time); switch (pcp_msg_info->result_code) { - //long lifetime errors + /*long lifetime errors*/ case PCP_ERR_UNSUPP_VERSION: case PCP_ERR_NOT_AUTHORIZED: case PCP_ERR_MALFORMED_REQUEST: @@ -1286,7 +1286,7 @@ static void createPCPResponse(unsigned char *response, pcp_info_t *pcp_msg_info) (uint32_t*)pcp_msg_info->ext_ip); } } -#endif //PCP_PEER +#endif /* PCP_PEER */ #ifdef PCP_SADSCP else if (resp->r_opcode == 0x83) { /*SADSCP response*/ @@ -1296,10 +1296,10 @@ static void createPCPResponse(unsigned char *response, pcp_info_t *pcp_msg_info) sadscp_resp->a_r_dscp_value |= (pcp_msg_info->sadscp_dscp & PCP_SADSCP_MASK); memset(sadscp_resp->reserved, 0, sizeof(sadscp_resp->reserved)); } -#endif //PCP_SADSCP +#endif /* PCP_SADSCP */ } -int ProcessIncomingPCPPacket(int s, unsigned char *buff, int len, \ +int ProcessIncomingPCPPacket(int s, unsigned char *buff, int len, struct sockaddr_in *senderaddr) { pcp_info_t pcp_msg_info; @@ -1324,7 +1324,7 @@ int ProcessIncomingPCPPacket(int s, unsigned char *buff, int len, \ createPCPResponse(buff, &pcp_msg_info); if ((len&0x03)!=0) { - len = len+4-(len&0x03); //round up resp. length to multiple of 4 + len = len+4-(len&0x03); /* round up resp. length to multiple of 4 */ } len = sendto(s, buff, len, 0, diff --git a/miniupnpd/pcpserver.h b/miniupnpd/pcpserver.h index ee46fee..cc295f3 100644 --- a/miniupnpd/pcpserver.h +++ b/miniupnpd/pcpserver.h @@ -1,4 +1,4 @@ -/* $Id: pcpserver.h $ */ +/* $Id: pcpserver.h,v 1.2 2013/12/13 15:48:39 nanard Exp $ */ /* MiniUPnP project * Website : http://miniupnp.free.fr/ * Author : Peter Tatrai @@ -36,10 +36,12 @@ POSSIBILITY OF SUCH DAMAGE. #define PCP_MIN_LEN 24 #define PCP_MAX_LEN 1100 +struct sockaddr_in; + /* * returns 0 upon success 1 otherwise */ -int ProcessIncomingPCPPacket(int s, unsigned char *msg_buff, int len, \ +int ProcessIncomingPCPPacket(int s, unsigned char *msg_buff, int len, struct sockaddr_in *senderaddr); #endif /* PCPSERVER_H_INCLUDED */ diff --git a/miniupnpd/upnpglobalvars.c b/miniupnpd/upnpglobalvars.c index 2181c43..152a689 100644 --- a/miniupnpd/upnpglobalvars.c +++ b/miniupnpd/upnpglobalvars.c @@ -1,4 +1,4 @@ -/* $Id: upnpglobalvars.c,v 1.30 2013/06/13 13:21:30 nanard Exp $ */ +/* $Id: upnpglobalvars.c,v 1.32 2013/12/13 14:07:09 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2012 Thomas Bernard @@ -85,7 +85,7 @@ unsigned short nextnatpmptoclean_proto = 0; #ifdef PCP_SADSCP struct dscp_values* dscp_values_list = 0; unsigned int num_dscp_values = 0; -#endif //PCP_SADSCP +#endif /*PCP_SADSCP*/ #endif /* For automatic removal of expired rules (with LeaseDuration) */ From e2a1c4d4c9a33025ebeb8722fd51dc1ebf1e372f Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Fri, 13 Dec 2013 17:15:51 +0100 Subject: [PATCH 009/104] pcpserver.c: small code simplification --- miniupnpd/pcpserver.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/miniupnpd/pcpserver.c b/miniupnpd/pcpserver.c index a580548..1e06bdf 100644 --- a/miniupnpd/pcpserver.c +++ b/miniupnpd/pcpserver.c @@ -1323,10 +1323,7 @@ int ProcessIncomingPCPPacket(int s, unsigned char *buff, int len, createPCPResponse(buff, &pcp_msg_info); - if ((len&0x03)!=0) { - len = len+4-(len&0x03); /* round up resp. length to multiple of 4 */ - } - + len = (len + 3) & ~3; /* round up resp. length to multiple of 4 */ len = sendto(s, buff, len, 0, (struct sockaddr *)senderaddr, sizeof(struct sockaddr_in)); if( len < 0 ) { From d05abb5921d6cc359a329c43d843595033c4d4c0 Mon Sep 17 00:00:00 2001 From: Leo Moll Date: Fri, 13 Dec 2013 19:40:52 +0100 Subject: [PATCH 010/104] Added option to enable vendor configuration --- miniupnpd/genconfig.sh | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/miniupnpd/genconfig.sh b/miniupnpd/genconfig.sh index efad1f5..9fda2f7 100755 --- a/miniupnpd/genconfig.sh +++ b/miniupnpd/genconfig.sh @@ -12,6 +12,7 @@ case "$argv" in --igd2) IGD2=1 ;; --strict) STRICT=1 ;; --leasefile) LEASEFILE=1 ;; + --vendorcfg) VENDORCFG=1 ;; --pcp) PCP=1 ;; --pcp-peer) PCP=1 @@ -23,6 +24,7 @@ case "$argv" in echo " --igd2 build an IGDv2 instead of an IGDv1" echo " --strict be more strict regarding compliance with UPnP specifications" echo " --leasefile enable lease file" + echo " --vendorcfg enable configuration of manufacturer info" echo " --pcp enable PCP" echo " --pcp-peer enable PCP PEER operation" exit 1 @@ -460,8 +462,12 @@ echo "/* disable reading and parsing of config file (miniupnpd.conf) */" >> ${CO echo "/*#define DISABLE_CONFIG_FILE*/" >> ${CONFIGFILE} echo "" >> ${CONFIGFILE} -echo "/* Unable the ability to configure all manufacturer infos through miniupnpd.conf */" >> ${CONFIGFILE} -echo "/*#define ENABLE_MANUFACTURER_INFO_CONFIGURATION*/" >> ${CONFIGFILE} +echo "/* Uncomment the following line to configure all manufacturer infos through miniupnpd.conf */" >> ${CONFIGFILE} +if [ -n "$VENDORCFG" ] ; then + echo "#define ENABLE_MANUFACTURER_INFO_CONFIGURATION" >> ${CONFIGFILE} +else + echo "/*#define ENABLE_MANUFACTURER_INFO_CONFIGURATION*/" >> ${CONFIGFILE} +fi echo "" >> ${CONFIGFILE} echo "#endif" >> ${CONFIGFILE} From fa87b3aff7e1469fee28ed9efc5d172470edb756 Mon Sep 17 00:00:00 2001 From: Thomas BERNARD Date: Mon, 16 Dec 2013 13:03:54 +0100 Subject: [PATCH 011/104] miniupnpd: attempt to compile for OS X/pf --- miniupnpd/Changelog.txt | 3 +++ miniupnpd/INSTALL | 10 ++++++++++ miniupnpd/Makefile.macosx | 23 +++++++++++++++++++---- miniupnpd/genconfig.sh | 9 ++++++++- miniupnpd/pf/obsdrdr.c | 28 ++++++++++++++++++++++++++++ 5 files changed, 68 insertions(+), 5 deletions(-) diff --git a/miniupnpd/Changelog.txt b/miniupnpd/Changelog.txt index 4c7afc4..f2761ea 100644 --- a/miniupnpd/Changelog.txt +++ b/miniupnpd/Changelog.txt @@ -1,5 +1,8 @@ $Id: Changelog.txt,v 1.346 2013/12/13 13:41:52 nanard Exp $ +2013/12/16: + Attempt to compile with OS X/pf + 2013/12/13: Make all manufacturer info configurable thanks to Leo Moll Merge PCP support (see https://github.com/miniupnp/miniupnp) diff --git a/miniupnpd/INSTALL b/miniupnpd/INSTALL index e6a6fbc..92d2dd3 100644 --- a/miniupnpd/INSTALL +++ b/miniupnpd/INSTALL @@ -55,6 +55,16 @@ http://blogs.sun.com/avalon/category/IPFilter Or edit config.h after it has been generated by genconfig.sh - use 'bsdmake' or 'make -f Makefile.macosx' to build +============================== Mac OS X/pf ================================ + +Starting with Mac OS X 10.7 Lion, pf replaced ipfw as the OS X firewall. +also bsdmake is not available anymore. +Make sure you have installed the Xcode commande line tools (from the +Xcode Preferences menu or using 'xcode-select --install' command) + +You'll need to download xnu sources : https://github.com/opensource-apple/xnu +> INCLUDES="-I.../xnu/bsd -I.../xnu/libkern" make -f Makefile.macosx + ============================ Linux/netfilter ============================== To Build and install : diff --git a/miniupnpd/Makefile.macosx b/miniupnpd/Makefile.macosx index f8d2bf9..7520124 100644 --- a/miniupnpd/Makefile.macosx +++ b/miniupnpd/Makefile.macosx @@ -3,6 +3,10 @@ # Author: Thomas Bernard # This Makefile should work for MacOSX # +# To compile with pf with OS X 10.7+, you need to specify +# path to XNU bsd sources : +# INCLUDES="-I.../xnu/bsd I.../xnu/libkern" make -f Makefile.macosx +# # To install use : # $ PREFIX=/dummyinstalldir make -f Makefile.macosx install # or : @@ -10,16 +14,20 @@ # CFLAGS = -Wall -O -g3 -DDEBUG #CFLAGS = -Wall -Os -CC = gcc +#CC = gcc #better use clang ! RM = rm -f MV = mv INSTALL = install STRIP = strip +CFLAGS += -DMACOSX + # OSNAME and FWNAME are used for building OS or FW dependent code. OSNAME = $(shell uname) ARCH = $(shell uname -p) -FWNAME = ipfw +# Firewall is ipfw up to OS X 10.6 Snow Leopard +# and pf since OS X 10.7 Lion (Darwin 11.0) +FWNAME = $(shell [ `uname -r | cut -d. -f1` -ge 11 ] && echo "pf" || echo "ipfw" ) STD_OBJS = miniupnpd.o upnphttp.o upnpdescgen.o upnpsoap.o \ upnpredirect.o getifaddr.o daemonize.o upnpglobalvars.o \ @@ -27,9 +35,16 @@ STD_OBJS = miniupnpd.o upnphttp.o upnpdescgen.o upnpsoap.o \ upnpevents.o getconnstatus.o upnputils.o MAC_OBJS = mac/getifstats.o bsd/ifacewatcher.o IPFW_OBJS = ipfw/ipfwrdr.o ipfw/ipfwaux.o +PF_OBJS = pf/obsdrdr.o pf/pfpinhole.o MISC_OBJS = upnpreplyparse.o minixml.o -ALL_OBJS = $(STD_OBJS) $(MISC_OBJS) $(MAC_OBJS) $(IPFW_OBJS) +ALL_OBJS = $(STD_OBJS) $(MISC_OBJS) $(MAC_OBJS) +ifeq ($(FWNAME), ipfw) + ALL_OBJS += $(IPFW_OBJS) +else + ALL_OBJS += $(PF_OBJS) + CFLAGS += -DPF +endif TEST_UPNPDESCGEN_OBJS = testupnpdescgen.o upnpdescgen.o TEST_GETIFSTATS_OBJS = testgetifstats.o mac/getifstats.o @@ -106,5 +121,5 @@ config.h: genconfig.sh .SUFFIXES: .o .c .c.o: - $(CC) $(CFLAGS) -c -o $@ $< + $(CC) $(CFLAGS) $(INCLUDES) -c -o $@ $< # $(CC) $(CFLAGS) -c -o $(.TARGET) $(.IMPSRC) diff --git a/miniupnpd/genconfig.sh b/miniupnpd/genconfig.sh index d4cf5d8..3c2a39e 100755 --- a/miniupnpd/genconfig.sh +++ b/miniupnpd/genconfig.sh @@ -273,8 +273,15 @@ case $OS_NAME in FW=netfilter ;; Darwin) + MAJORVER=`echo $OS_VERSION | cut -d. -f1` echo "#define USE_IFACEWATCHER 1" >> ${CONFIGFILE} - FW=ipfw + # OS X switched to pf since 10.7 Lion (Darwin 11.0) + if [ $MAJORVER -ge 11 ] ; then + FW=pf + echo "#define PFRULE_INOUT_COUNTS" >> ${CONFIGFILE} + else + FW=ipfw + fi OS_URL=http://developer.apple.com/macosx ;; *) diff --git a/miniupnpd/pf/obsdrdr.c b/miniupnpd/pf/obsdrdr.c index d0287cb..04c2ddb 100644 --- a/miniupnpd/pf/obsdrdr.c +++ b/miniupnpd/pf/obsdrdr.c @@ -45,6 +45,9 @@ #ifdef __DragonFly__ #include #else +#ifdef MACOSX +#define PRIVATE 1 +#endif #include #endif #include @@ -219,9 +222,15 @@ add_redirect_rule2(const char * ifname, pcr.rule.rdr.addr.type = PF_ADDR_ADDRMASK; #endif +#ifdef MACOSX + pcr.rule.dst.xport.range.op = PF_OP_EQ; + pcr.rule.dst.xport.range.port[0] = htons(eport); + pcr.rule.dst.xport.range.port[1] = htons(eport); +#else pcr.rule.dst.port_op = PF_OP_EQ; pcr.rule.dst.port[0] = htons(eport); pcr.rule.dst.port[1] = htons(eport); +#endif #ifndef PF_NEWSTYLE pcr.rule.action = PF_RDR; #ifndef PF_ENABLE_FILTER_RULES @@ -490,8 +499,13 @@ get_redirect_rule(const char * ifname, unsigned short eport, int proto, syslog(LOG_ERR, "ioctl(dev, DIOCGETRULE): %m"); goto error; } +#ifdef MACOSX + if( (eport == ntohs(pr.rule.dst.xport.range.port[0])) + && (eport == ntohs(pr.rule.dst.xport.range.port[1])) +#else if( (eport == ntohs(pr.rule.dst.port[0])) && (eport == ntohs(pr.rule.dst.port[1])) +#endif && (pr.rule.proto == proto) ) { #ifndef PF_NEWSTYLE @@ -591,8 +605,13 @@ delete_redirect_rule(const char * ifname, unsigned short eport, int proto) syslog(LOG_ERR, "ioctl(dev, DIOCGETRULE): %m"); goto error; } +#ifdef MACOSX + if( (eport == ntohs(pr.rule.dst.xport.range.port[0])) + && (eport == ntohs(pr.rule.dst.xport.range.port[1])) +#else if( (eport == ntohs(pr.rule.dst.port[0])) && (eport == ntohs(pr.rule.dst.port[1])) +#endif && (pr.rule.proto == proto) ) { pr.action = PF_CHANGE_GET_TICKET; @@ -710,7 +729,11 @@ get_redirect_rule_by_index(int index, goto error; } *proto = pr.rule.proto; +#ifdef MACOSX + *eport = ntohs(pr.rule.dst.xport.range.port[0]); +#else *eport = ntohs(pr.rule.dst.port[0]); +#endif #ifndef PF_NEWSTYLE *iport = pr.rule.rpool.proxy_port[0]; #else @@ -822,8 +845,13 @@ get_portmappings_in_range(unsigned short startport, unsigned short endport, syslog(LOG_ERR, "ioctl(dev, DIOCGETRULE): %m"); continue; } +#ifdef MACOSX + eport = ntohs(pr.rule.dst.xport.range.port[0]); + if( (eport == ntohs(pr.rule.dst.xport.range.port[1])) +#else eport = ntohs(pr.rule.dst.port[0]); if( (eport == ntohs(pr.rule.dst.port[1])) +#endif && (pr.rule.proto == proto) && (startport <= eport) && (eport <= endport) ) { From e23c58997240a84abd8014affe9ef45cbe9c9125 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Mon, 16 Dec 2013 17:04:00 +0100 Subject: [PATCH 012/104] miniupnpd/pcpserver.c: Removed IPV6_ADDR_COPY and other simplifications --- miniupnpd/pcp_msg_struct.h | 20 ++++++++++---------- miniupnpd/pcpserver.c | 36 ++++++++++-------------------------- 2 files changed, 20 insertions(+), 36 deletions(-) diff --git a/miniupnpd/pcp_msg_struct.h b/miniupnpd/pcp_msg_struct.h index d472b14..bb557bc 100644 --- a/miniupnpd/pcp_msg_struct.h +++ b/miniupnpd/pcp_msg_struct.h @@ -1,4 +1,4 @@ -/* $Id: pcp_msg_struct.h,v 1.2 2013/12/13 15:47:23 nanard Exp $ */ +/* $Id: pcp_msg_struct.h,v 1.3 2013/12/16 16:02:19 nanard Exp $ */ /* MiniUPnP project * Website : http://miniupnp.free.fr/ * Author : Peter Tatrai @@ -148,7 +148,7 @@ typedef struct pcp_request { uint8_t r_opcode; uint16_t reserved; uint32_t req_lifetime; - uint32_t ip[4]; /* ipv4 will be represented + struct in6_addr ip; /* ipv4 will be represented by the ipv4 mapped ipv6 */ uint8_t next_data[0]; } pcp_request_t; @@ -182,7 +182,7 @@ typedef struct pcp_map_v2 { uint8_t reserved[3]; uint16_t int_port; uint16_t ext_port; - uint32_t ext_ip[4]; /* ipv4 will be represented + struct in6_addr ext_ip; /* ipv4 will be represented by the ipv4 mapped ipv6 */ uint8_t next_data[0]; } pcp_map_v2_t; @@ -193,7 +193,7 @@ typedef struct pcp_map_v1 { uint8_t reserved[3]; uint16_t int_port; uint16_t ext_port; - uint32_t ext_ip[4]; /* ipv4 will be represented + struct in6_addr ext_ip; /* ipv4 will be represented by the ipv4 mapped ipv6 */ uint8_t next_data[0]; } pcp_map_v1_t; @@ -204,11 +204,11 @@ typedef struct pcp_peer_v1 { uint8_t reserved[3]; uint16_t int_port; uint16_t ext_port; - uint32_t ext_ip[4]; /* ipv4 will be represented + struct in6_addr ext_ip; /* ipv4 will be represented by the ipv4 mapped ipv6 */ uint16_t peer_port; uint16_t reserved1; - uint32_t peer_ip[4]; + struct in6_addr peer_ip; uint8_t next_data[0]; } pcp_peer_v1_t; @@ -219,11 +219,11 @@ typedef struct pcp_peer_v2 { uint8_t reserved[3]; uint16_t int_port; uint16_t ext_port; - uint32_t ext_ip[4]; /* ipv4 will be represented + struct in6_addr ext_ip; /* ipv4 will be represented by the ipv4 mapped ipv6 */ uint16_t peer_port; uint16_t reserved1; - uint32_t peer_ip[4]; + struct in6_addr peer_ip; uint8_t next_data[0]; } pcp_peer_v2_t; @@ -254,7 +254,7 @@ typedef struct pcp_3rd_party_option{ uint8_t option; uint8_t reserved; uint16_t len; - uint32_t ip[4]; + struct in6_addr ip; uint8_t next_data[0]; } pcp_3rd_party_option_t; @@ -280,7 +280,7 @@ typedef struct pcp_filter_option { uint8_t reserved2; uint8_t prefix_len; uint16_t peer_port; - uint32_t peer_ip[4]; + struct in6_addr peer_ip; }pcp_filter_option_t; #pragma pack(pop) diff --git a/miniupnpd/pcpserver.c b/miniupnpd/pcpserver.c index 1e06bdf..78191ea 100644 --- a/miniupnpd/pcpserver.c +++ b/miniupnpd/pcpserver.c @@ -1,4 +1,4 @@ -/* $Id: pcpserver.c,v 1.2 2013/12/13 15:48:56 nanard Exp $ */ +/* $Id: pcpserver.c,v 1.4 2013/12/16 16:02:19 nanard Exp $ */ /* MiniUPnP project * Website : http://miniupnp.free.fr/ * Author : Peter Tatrai @@ -65,19 +65,6 @@ POSSIBILITY OF SUCH DAMAGE. #include "netfilter/iptcrdr.h" #endif -#define IPV6_ADDR_COPY(dest, src) \ - do { \ - (dest)[0] = (src)[0]; \ - (dest)[1] = (src)[1]; \ - (dest)[2] = (src)[2]; \ - (dest)[3] = (src)[3]; \ - } while (0) - - typedef struct options_occur { - int third_party_occur; - int pfailure_occur; -} options_occur_t; - /* server specific information */ struct pcp_server_info { uint8_t server_version; @@ -191,7 +178,7 @@ static int parseCommonRequestHeader(pcp_request_t *common_req, pcp_info_t *pcp_m pcp_msg_info->version = common_req->ver ; pcp_msg_info->opcode = common_req->r_opcode &0x7f ; pcp_msg_info->lifetime = ntohl(common_req->req_lifetime); - pcp_msg_info->int_ip = (struct in6_addr*)common_req->ip; + pcp_msg_info->int_ip = &common_req->ip; if ( (common_req->ver > this_server_info.server_version) ) { @@ -219,7 +206,7 @@ static void printMAPOpcodeVersion1(pcp_map_v1_t *map_buf) syslog(LOG_DEBUG, "MAP int port: \t\t %d\n", ntohs(map_buf->int_port) ); syslog(LOG_DEBUG, "MAP ext port: \t\t %d\n", ntohs(map_buf->ext_port) ); syslog(LOG_DEBUG, "MAP Ext IP: \t\t %s\n", inet_ntop(AF_INET6, - map_buf->ext_ip, map_addr, INET6_ADDRSTRLEN)); + &map_buf->ext_ip, map_addr, INET6_ADDRSTRLEN)); } static void printMAPOpcodeVersion2(pcp_map_v2_t *map_buf) @@ -230,7 +217,7 @@ static void printMAPOpcodeVersion2(pcp_map_v2_t *map_buf) syslog(LOG_DEBUG, "MAP int port: \t\t %d\n", ntohs(map_buf->int_port) ); syslog(LOG_DEBUG, "MAP ext port: \t\t %d\n", ntohs(map_buf->ext_port) ); syslog(LOG_DEBUG, "MAP Ext IP: \t\t %s\n", inet_ntop(AF_INET6, - map_buf->ext_ip, map_addr, INET6_ADDRSTRLEN)); + &map_buf->ext_ip, map_addr, INET6_ADDRSTRLEN)); } #endif /* DEBUG */ @@ -242,7 +229,7 @@ static int parsePCPMAP_version1(pcp_map_v1_t *map_v1, \ pcp_msg_info->int_port = ntohs(map_v1->int_port); pcp_msg_info->ext_port = ntohs(map_v1->ext_port); - pcp_msg_info->ext_ip = (struct in6_addr*)map_v1->ext_ip; + pcp_msg_info->ext_ip = &(map_v1->ext_ip); if (pcp_msg_info->protocol == 0 && pcp_msg_info->int_port !=0 ){ syslog(LOG_ERR, "PCP MAP: Protocol was ZERO, but internal port has non-ZERO value."); @@ -260,7 +247,7 @@ static int parsePCPMAP_version2(pcp_map_v2_t *map_v2, \ pcp_msg_info->int_port = ntohs(map_v2->int_port); pcp_msg_info->ext_port = ntohs(map_v2->ext_port); - pcp_msg_info->ext_ip = (struct in6_addr*)map_v2->ext_ip; + pcp_msg_info->ext_ip = &(map_v2->ext_ip); if (pcp_msg_info->protocol == 0 && pcp_msg_info->int_port !=0 ) { syslog(LOG_ERR, "PCP MAP: Protocol was ZERO, but internal port has non-ZERO value."); @@ -436,7 +423,7 @@ static int parsePCPOptions(void* pcp_buf, int* remainingSize, int* processedSize #ifdef DEBUG syslog(LOG_DEBUG, "PCP OPTION: \t Third party \n"); syslog(LOG_DEBUG, "Third PARTY IP: \t %s\n", inet_ntop(AF_INET6, - opt_3rd->ip, third_addr, INET6_ADDRSTRLEN)); + &(opt_3rd->ip), third_addr, INET6_ADDRSTRLEN)); #endif if (pcp_msg_info->thirdp_present != 0 ) { @@ -616,8 +603,7 @@ static void FillSA(struct sockaddr *sa, const struct in6_addr *in6, } else { struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa; sa6->sin6_family = AF_INET6; - IPV6_ADDR_COPY((uint32_t*)sa6->sin6_addr.s6_addr, - (uint32_t*)in6->s6_addr); + sa6->sin6_addr = *in6; sa6->sin6_port = htons(port); } } @@ -1254,15 +1240,13 @@ static void createPCPResponse(unsigned char *response, pcp_info_t *pcp_msg_info) if (resp->r_opcode == 0x81) { /* MAP response */ if (resp->ver == 1 ) { pcp_map_v1_t *mapr = (pcp_map_v1_t *)resp->next_data; - IPV6_ADDR_COPY((uint32_t*)mapr->ext_ip, - (uint32_t*)pcp_msg_info->ext_ip); + mapr->ext_ip = *pcp_msg_info->ext_ip; mapr->ext_port = htons(pcp_msg_info->ext_port); mapr->int_port = htons(pcp_msg_info->int_port); } else if (resp->ver == 2 ) { pcp_map_v2_t *mapr = (pcp_map_v2_t *)resp->next_data; - IPV6_ADDR_COPY((uint32_t*)mapr->ext_ip, - (uint32_t*)pcp_msg_info->ext_ip); + mapr->ext_ip = *pcp_msg_info->ext_ip; mapr->ext_port = htons(pcp_msg_info->ext_port); mapr->int_port = htons(pcp_msg_info->int_port); } From 4fe0fb18094a074177b6051872ed8f1e6de16f13 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Mon, 16 Dec 2013 17:04:45 +0100 Subject: [PATCH 013/104] miniupnpd/pcpserver.c: minor syntax fixes --- miniupnpd/pcpserver.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/miniupnpd/pcpserver.c b/miniupnpd/pcpserver.c index 78191ea..3d5e733 100644 --- a/miniupnpd/pcpserver.c +++ b/miniupnpd/pcpserver.c @@ -71,7 +71,7 @@ struct pcp_server_info { }; /* default server settings, highest version supported is the default */ -struct pcp_server_info this_server_info = {2}; +static struct pcp_server_info this_server_info = {2}; /* structure holding information from PCP msg*/ /* all variables are in host byte order except IP addresses */ @@ -116,7 +116,7 @@ typedef struct pcp_info { int pfailure_present; char senderaddrstr[INET_ADDRSTRLEN]; -}pcp_info_t; +} pcp_info_t; #ifdef PCP_SADSCP @@ -221,7 +221,7 @@ static void printMAPOpcodeVersion2(pcp_map_v2_t *map_buf) } #endif /* DEBUG */ -static int parsePCPMAP_version1(pcp_map_v1_t *map_v1, \ +static int parsePCPMAP_version1(pcp_map_v1_t *map_v1, pcp_info_t *pcp_msg_info) { pcp_msg_info->is_map_op = 1; @@ -239,7 +239,7 @@ static int parsePCPMAP_version1(pcp_map_v1_t *map_v1, \ return 0; } -static int parsePCPMAP_version2(pcp_map_v2_t *map_v2, \ +static int parsePCPMAP_version2(pcp_map_v2_t *map_v2, pcp_info_t *pcp_msg_info) { pcp_msg_info->is_map_op = 1; @@ -386,8 +386,8 @@ static int parseSADSCP(pcp_sadscp_req_t *sadscp, pcp_info_t *pcp_msg_info) { } #endif -static int parsePCPOptions(void* pcp_buf, int* remainingSize, int* processedSize, \ - pcp_info_t *pcp_msg_info) +static int parsePCPOptions(void* pcp_buf, int* remainingSize, + int* processedSize, pcp_info_t *pcp_msg_info) { int remain = *remainingSize; int processed = *processedSize; From a93393df44236b5e845b3ce21f76d42bd3180df3 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Tue, 14 Jan 2014 09:25:19 +0100 Subject: [PATCH 014/104] update README's to include PCP --- README | 2 +- miniupnpd/README | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/README b/README index 68abbde..405183b 100644 --- a/README +++ b/README @@ -7,7 +7,7 @@ Freecode : http://freecode.com/projects/miniupnp miniupnpc/ : MiniUPnP client - an UPnP IGD control point miniupnpd/ : MiniUPnP daemon - an implementation of a UPnP IGD - + NAT-PMP gateway + + NAT-PMP / PCP gateway minissdpd/ : SSDP managing daemon. Designed to work with miniupnpc, miniupnpd, minidlna, etc. diff --git a/miniupnpd/README b/miniupnpd/README index 0499bb0..09bd087 100644 --- a/miniupnpd/README +++ b/miniupnpd/README @@ -1,5 +1,5 @@ MiniUPnP project -(c) 2006-2012 Thomas Bernard +(c) 2006-2014 Thomas Bernard webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ github: https://github.com/miniupnp/miniupnp freecode: http://freecode.com/projects/miniupnp @@ -22,8 +22,11 @@ Support for the NAT Port Mapping Protocol (NAT-PMP) has been added. See information about NAT-PMP here : http://miniupnp.free.fr/nat-pmp.html +NAT-PMP is the precursor of Port Control Protocol (PCP). +In 2013, support for PCP has been added too. + Read the INSTALL files for instructions to compile, install and -configure miniupnpd. +configure miniupnpd on your system. Report bugs to miniupnp@free.fr on the web forum http://miniupnp.tuxfamily.org/forum/ From 3997a2ebe7b13205870d516488afd4268e050d24 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Tue, 14 Jan 2014 09:25:54 +0100 Subject: [PATCH 015/104] README: Add Peter Tatrai to thanks list --- README | 1 + 1 file changed, 1 insertion(+) diff --git a/README b/README index 405183b..96b37df 100644 --- a/README +++ b/README @@ -42,4 +42,5 @@ Thanks to : * Chiaki Ishikawa * Jardel Weyrich * Leah X. Schmidt + * Peter Tatrai * Leo Moll From 401c624bcf4da96d6b94b423952c4c99504d2974 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Tue, 14 Jan 2014 09:26:24 +0100 Subject: [PATCH 016/104] miniupnpd/INSTALL: update infos rdr-anchor lines should be removed in OpenBSD since 4.7 rephrased a bit the part about permissions --- miniupnpd/INSTALL | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/miniupnpd/INSTALL b/miniupnpd/INSTALL index 92d2dd3..f249e7d 100644 --- a/miniupnpd/INSTALL +++ b/miniupnpd/INSTALL @@ -1,5 +1,5 @@ MiniUPnP project. -(c) 2006-2013 Thomas Bernard +(c) 2006-2014 Thomas Bernard Homepage : http://miniupnp.free.fr/ Mirror: http://miniupnp.tuxfamily.org/ github: https://github.com/miniupnp/miniupnp @@ -17,7 +17,9 @@ To Build and Install : Alternatively to editing config.h, options can be passed to genconfig.sh For more details : > ./genconfig.sh -h -- add "rdr-anchor miniupnpd" and "anchor miniupnpd" lines to /etc/pf.conf +- add "rdr-anchor miniupnpd" or/and "anchor miniupnpd" lines to /etc/pf.conf + (Since OpenBSD 4.7, rdr-anchor lines are no longer used and should be + removed, leaving only the anchor lines). - some FreeBSD users reported that it is also necessary for them to explicitly allow udp traffic on 239.0.0.0/8 by adding the two following lines to /etc/pf.conf : @@ -26,7 +28,7 @@ To Build and Install : - dont forget to " pfctl -f /etc/pf.conf " - you can check your modifications are taken into accout with "pfctl -s nat" and "pfctl -s rule". Look for the "rdr-anchor miniupnpd" - and "anchor miniupnpd" lines. + (if applicable) and/or "anchor miniupnpd" lines. - install as root using : # make install or @@ -53,7 +55,7 @@ http://blogs.sun.com/avalon/category/IPFilter - To enable non standard compilation options, > ./genconfig.sh -h Or edit config.h after it has been generated by genconfig.sh -- use 'bsdmake' or 'make -f Makefile.macosx' to build +- use 'bsdmake' (if available) or 'make -f Makefile.macosx' to build ============================== Mac OS X/pf ================================ @@ -118,11 +120,11 @@ also available through command line switches. Miniupnpd supports some kind of security check for allowing or disallowing redirection to be made. The UPnP permission rules are read from the miniupnpd.conf configuration file. -When a new redirection is asked, permission rules are evaluated in top-down -order and the first permission rule matched gives the answer : redirection -allowed or denied. If no rule is matching, the redirection is allowed, so -it is a good practice to have a "catch all" deny permission rule at the end -of your mermission ruleset. +When a new redirection is requested, permission rules are evaluated in +top-down order and the first permission rule matched gives the response : +redirection allowed or denied. If no rule is matching, the redirection is +allowed, so it is a good practice to have a "catch all" deny permission +rule at the end of your permission ruleset. Sample permission ruleset : allow 4662-4672 192.168.1.34/32 4662-4672 deny 0-65535 192.168.1.34/32 0-65535 @@ -147,8 +149,8 @@ More simple, use the genuuid makefile target : > make genuuid or > make -f Makefile.linux genuuid -This target is needed by the "install" target, so it should be done -automatically. +This target is needed by the "install" target, so it is done automatically +during install. To stop the daemon use : # kill `cat /var/run/miniupnpd.pid` From 07342650920d6eacd1e6aa81529fa8305f7a502f Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Mon, 27 Jan 2014 11:09:30 +0100 Subject: [PATCH 017/104] Makefile.linux: update dependencies --- miniupnpd/Makefile.linux | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/miniupnpd/Makefile.linux b/miniupnpd/Makefile.linux index f0068b4..a9bab57 100644 --- a/miniupnpd/Makefile.linux +++ b/miniupnpd/Makefile.linux @@ -1,6 +1,6 @@ -# $Id: Makefile.linux,v 1.78 2013/05/03 09:30:33 nanard Exp $ +# $Id: Makefile.linux,v 1.81 2014/01/27 10:06:58 nanard Exp $ # MiniUPnP project -# (c) 2006-2013 Thomas Bernard +# (c) 2006-2014 Thomas Bernard # http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ # Author : Thomas Bernard # for use with GNU Make @@ -221,8 +221,8 @@ depend: config.h miniupnpd.o: config.h macros.h upnpglobalvars.h upnppermissions.h miniupnpd.o: miniupnpdtypes.h upnphttp.h upnpdescgen.h miniupnpdpath.h miniupnpd.o: getifaddr.h upnpsoap.h options.h minissdp.h upnpredirect.h -miniupnpd.o: upnppinhole.h daemonize.h upnpevents.h natpmp.h commonrdr.h -miniupnpd.o: upnputils.h ifacewatcher.h +miniupnpd.o: upnppinhole.h daemonize.h upnpevents.h natpmp.h pcpserver.h +miniupnpd.o: commonrdr.h upnputils.h ifacewatcher.h upnphttp.o: config.h upnphttp.h upnpdescgen.h miniupnpdpath.h upnpsoap.h upnphttp.o: upnpevents.h upnputils.h upnpdescgen.o: config.h getifaddr.h upnpredirect.h upnpdescgen.h @@ -249,11 +249,13 @@ minissdp.o: upnpglobalvars.h upnppermissions.h miniupnpdtypes.h minissdp.h minissdp.o: upnputils.h getroute.h codelength.h natpmp.o: macros.h config.h natpmp.h upnpglobalvars.h upnppermissions.h natpmp.o: miniupnpdtypes.h getifaddr.h upnpredirect.h commonrdr.h upnputils.h -pcpserver.o: config.h +pcpserver.o: config.h pcpserver.h macros.h upnpglobalvars.h upnppermissions.h +pcpserver.o: miniupnpdtypes.h pcplearndscp.h upnpredirect.h commonrdr.h +pcpserver.o: getifaddr.h pcp_msg_struct.h upnpevents.o: config.h upnpevents.h miniupnpdpath.h upnpglobalvars.h upnpevents.o: upnppermissions.h miniupnpdtypes.h upnpdescgen.h upnputils.h upnputils.o: config.h upnputils.h upnpglobalvars.h upnppermissions.h -upnputils.o: miniupnpdtypes.h +upnputils.o: miniupnpdtypes.h getroute.h getconnstatus.o: getconnstatus.h getifaddr.h upnppinhole.o: macros.h config.h upnpredirect.h upnpglobalvars.h upnppinhole.o: upnppermissions.h miniupnpdtypes.h upnpevents.h From 064fcd27396d100d648d57383d42d978dd17aed4 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Mon, 27 Jan 2014 12:07:54 +0100 Subject: [PATCH 018/104] miniupnpd/pcpserver.c: Removed IPV6_ADDR_COPY and other simplifications modifications that were forgotten in commit e23c58997240a84abd8014affe9ef45cbe9c9125 --- miniupnpd/pcpserver.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/miniupnpd/pcpserver.c b/miniupnpd/pcpserver.c index 3d5e733..bfae5e8 100644 --- a/miniupnpd/pcpserver.c +++ b/miniupnpd/pcpserver.c @@ -1,4 +1,4 @@ -/* $Id: pcpserver.c,v 1.4 2013/12/16 16:02:19 nanard Exp $ */ +/* $Id: pcpserver.c,v 1.5 2014/01/27 10:06:08 nanard Exp $ */ /* MiniUPnP project * Website : http://miniupnp.free.fr/ * Author : Peter Tatrai @@ -267,10 +267,10 @@ static void printPEEROpcodeVersion1(pcp_peer_v1_t *peer_buf) syslog(LOG_DEBUG, "PCP PEER: v1 Opcode specific information. \n"); syslog(LOG_DEBUG, "Protocol: \t\t %d\n",peer_buf->protocol ); syslog(LOG_DEBUG, "Internal port: \t\t %d\n", ntohs(peer_buf->int_port) ); - syslog(LOG_DEBUG, "External IP: \t\t %s\n", inet_ntop(AF_INET6, peer_buf->ext_ip, + syslog(LOG_DEBUG, "External IP: \t\t %s\n", inet_ntop(AF_INET6, &peer_buf->ext_ip, ext_addr,INET6_ADDRSTRLEN)); syslog(LOG_DEBUG, "External port port: \t\t %d\n", ntohs(peer_buf->ext_port) ); - syslog(LOG_DEBUG, "PEER IP: \t\t %s\n", inet_ntop(AF_INET6, peer_buf->peer_ip, + syslog(LOG_DEBUG, "PEER IP: \t\t %s\n", inet_ntop(AF_INET6, &peer_buf->peer_ip, peer_addr,INET6_ADDRSTRLEN)); syslog(LOG_DEBUG, "PEER port port: \t\t %d\n", ntohs(peer_buf->peer_port) ); } @@ -283,10 +283,10 @@ static void printPEEROpcodeVersion2(pcp_peer_v2_t *peer_buf) syslog(LOG_DEBUG, "PCP PEER: v2 Opcode specific information. \n"); syslog(LOG_DEBUG, "Protocol: \t\t %d\n",peer_buf->protocol ); syslog(LOG_DEBUG, "Internal port: \t\t %d\n", ntohs(peer_buf->int_port) ); - syslog(LOG_DEBUG, "External IP: \t\t %s\n", inet_ntop(AF_INET6, peer_buf->ext_ip, + syslog(LOG_DEBUG, "External IP: \t\t %s\n", inet_ntop(AF_INET6, &peer_buf->ext_ip, ext_addr,INET6_ADDRSTRLEN)); syslog(LOG_DEBUG, "External port port: \t\t %d\n", ntohs(peer_buf->ext_port) ); - syslog(LOG_DEBUG, "PEER IP: \t\t %s\n", inet_ntop(AF_INET6, peer_buf->peer_ip, + syslog(LOG_DEBUG, "PEER IP: \t\t %s\n", inet_ntop(AF_INET6, &peer_buf->peer_ip, peer_addr,INET6_ADDRSTRLEN)); syslog(LOG_DEBUG, "PEER port port: \t\t %d\n", ntohs(peer_buf->peer_port) ); } @@ -305,8 +305,8 @@ static int parsePCPPEER_version1(pcp_peer_v1_t *peer_buf, \ pcp_msg_info->ext_port = ntohs(peer_buf->ext_port); pcp_msg_info->peer_port = ntohs(peer_buf->peer_port); - pcp_msg_info->ext_ip = (struct in6_addr*)peer_buf->ext_ip; - pcp_msg_info->peer_ip = (struct in6_addr*)peer_buf->peer_ip; + pcp_msg_info->ext_ip = &peer_buf->ext_ip; + pcp_msg_info->peer_ip = &peer_buf->peer_ip; if (pcp_msg_info->protocol == 0 && pcp_msg_info->int_port !=0 ){ syslog(LOG_ERR, "PCP PEER: protocol was ZERO, but internal port has non-ZERO value."); @@ -329,8 +329,8 @@ static int parsePCPPEER_version2(pcp_peer_v2_t *peer_buf, \ pcp_msg_info->ext_port = ntohs(peer_buf->ext_port); pcp_msg_info->peer_port = ntohs(peer_buf->peer_port); - pcp_msg_info->ext_ip = (struct in6_addr*)peer_buf->ext_ip; - pcp_msg_info->peer_ip = (struct in6_addr*)peer_buf->peer_ip; + pcp_msg_info->ext_ip = &peer_buf->ext_ip; + pcp_msg_info->peer_ip = &peer_buf->peer_ip; if (pcp_msg_info->protocol == 0 && pcp_msg_info->int_port !=0 ){ syslog(LOG_ERR, "PCP PEER: protocol was ZERO, but internal port has non-ZERO value."); @@ -1258,16 +1258,14 @@ static void createPCPResponse(unsigned char *response, pcp_info_t *pcp_msg_info) peer_resp->ext_port = htons(pcp_msg_info->ext_port); peer_resp->int_port = htons(pcp_msg_info->int_port); peer_resp->peer_port = htons(pcp_msg_info->peer_port); - IPV6_ADDR_COPY((uint32_t*)peer_resp->ext_ip, - (uint32_t*)pcp_msg_info->ext_ip); + peer_resp->ext_ip = *pcp_msg_info->ext_ip; } else if (resp->ver == 2 ){ pcp_peer_v2_t* peer_resp = (pcp_peer_v2_t*)resp->next_data; peer_resp->ext_port = htons(pcp_msg_info->ext_port); peer_resp->int_port = htons(pcp_msg_info->int_port); peer_resp->peer_port = htons(pcp_msg_info->peer_port); - IPV6_ADDR_COPY((uint32_t*)peer_resp->ext_ip, - (uint32_t*)pcp_msg_info->ext_ip); + peer_resp->ext_ip = *pcp_msg_info->ext_ip; } } #endif /* PCP_PEER */ From af085e8276b65eceb97116c50d3cec6159eac40f Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Mon, 27 Jan 2014 16:27:51 +0100 Subject: [PATCH 019/104] miniupnpc: added test cases for XML parsing --- .../testreplyparse/GetSpecificPortMappingEntryReq.namevalue | 3 +++ miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.xml | 3 +++ .../testreplyparse/GetSpecificPortMappingEntryResp.namevalue | 5 +++++ miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.xml | 2 ++ 4 files changed, 13 insertions(+) create mode 100644 miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.namevalue create mode 100644 miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.xml create mode 100644 miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.namevalue create mode 100644 miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.xml diff --git a/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.namevalue b/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.namevalue new file mode 100644 index 0000000..26b169c --- /dev/null +++ b/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.namevalue @@ -0,0 +1,3 @@ +NewProtocol=UDP +NewExternalPort=12345 +NewRemoteHost= diff --git a/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.xml b/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.xml new file mode 100644 index 0000000..bbb540e --- /dev/null +++ b/miniupnpc/testreplyparse/GetSpecificPortMappingEntryReq.xml @@ -0,0 +1,3 @@ + +12345UDP + diff --git a/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.namevalue b/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.namevalue new file mode 100644 index 0000000..2189789 --- /dev/null +++ b/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.namevalue @@ -0,0 +1,5 @@ +NewInternalPort=12345 +NewInternalClient=192.168.10.110 +NewEnabled=1 +NewPortMappingDescription=libminiupnpc +NewLeaseDuration=0 diff --git a/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.xml b/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.xml new file mode 100644 index 0000000..77e8d9c --- /dev/null +++ b/miniupnpc/testreplyparse/GetSpecificPortMappingEntryResp.xml @@ -0,0 +1,2 @@ +12345192.168.10.1101libminiupnpc0 + From fd065f7c751969ae7a7a82c4e54378f9f440b9b3 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Mon, 27 Jan 2014 16:28:50 +0100 Subject: [PATCH 020/104] Makefile.mingw: removed -enable-stdcall-fixup --- miniupnpc/Makefile.mingw | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/miniupnpc/Makefile.mingw b/miniupnpc/Makefile.mingw index 5b93092..60b3f1b 100644 --- a/miniupnpc/Makefile.mingw +++ b/miniupnpc/Makefile.mingw @@ -1,7 +1,7 @@ -# $Id: Makefile.mingw,v 1.17 2012/12/02 14:12:45 nanard Exp $ +# $Id: Makefile.mingw,v 1.18 2014/01/17 09:04:01 nanard Exp $ # Miniupnp project. # http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ -# (c) 2005-2011 Thomas Bernard +# (c) 2005-2014 Thomas Bernard # This Makefile is made for MinGW # CC = gcc @@ -57,11 +57,12 @@ upnpc.o: $(CC) $(CFLAGS) -DSTATICLIB -c -o $@ $< $(CC) $(CFLAGS) -c -o dll/$@ $< +# --enable-stdcall-fixup upnpc-static: upnpc.o libminiupnpc.a - $(CC) -enable-stdcall-fixup -o $@ $^ $(LDLIBS) + $(CC) -o $@ $^ $(LDLIBS) upnpc-shared: dll/upnpc.o miniupnpc.lib - $(CC) -enable-stdcall-fixup -o $@ $^ $(LDLIBS) + $(CC) -o $@ $^ $(LDLIBS) wingenminiupnpcstrings: wingenminiupnpcstrings.o From a79cd61fc8e9979d6a98336fcea70f3de6a2628b Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Mon, 27 Jan 2014 16:29:13 +0100 Subject: [PATCH 021/104] fix miniupnpc.def --- miniupnpc/miniupnpc.def | 1 + 1 file changed, 1 insertion(+) diff --git a/miniupnpc/miniupnpc.def b/miniupnpc/miniupnpc.def index 10b9f58..3343356 100644 --- a/miniupnpc/miniupnpc.def +++ b/miniupnpc/miniupnpc.def @@ -1,5 +1,6 @@ LIBRARY ; miniupnpc library + miniupnpc EXPORTS ; miniupnpc From 223398ee0ec672c11fe129ae261fc146a24c02f7 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Mon, 27 Jan 2014 16:29:35 +0100 Subject: [PATCH 022/104] fix miniupnpc/testupnpreplyparse.c --- miniupnpc/testupnpreplyparse.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/miniupnpc/testupnpreplyparse.c b/miniupnpc/testupnpreplyparse.c index d753a20..7ba7131 100644 --- a/miniupnpc/testupnpreplyparse.c +++ b/miniupnpc/testupnpreplyparse.c @@ -1,7 +1,7 @@ -/* $Id: testupnpreplyparse.c,v 1.3 2013/05/14 20:37:36 nanard Exp $ */ +/* $Id: testupnpreplyparse.c,v 1.4 2014/01/27 11:45:19 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2013 Thomas Bernard + * (c) 2006-2014 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ #include @@ -74,7 +74,7 @@ int main(int argc, char * * argv) fclose(f); f = NULL; buffer[l] = '\0'; - if(argc >= 2) + if(argc > 2) { f = fopen(argv[2], "r"); if(!f) From 28cab3e219301bb3da3bba4317fc64b4b8ec451b Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Fri, 31 Jan 2014 14:32:00 +0100 Subject: [PATCH 023/104] miniupnpc: added argument remoteHost to UPNP_GetSpecificPortMappingEntry() increment API_VERSION to 10 --- miniupnpc/CMakeLists.txt | 4 ++-- miniupnpc/Changelog.txt | 6 +++++- miniupnpc/java/JavaBridgeTest.java | 2 +- miniupnpc/miniupnpc.h | 4 ++-- miniupnpc/miniupnpcmodule.c | 11 ++++++----- miniupnpc/upnpc.c | 4 ++-- miniupnpc/upnpcommands.c | 7 ++++--- miniupnpc/upnpcommands.h | 4 +++- 8 files changed, 25 insertions(+), 17 deletions(-) diff --git a/miniupnpc/CMakeLists.txt b/miniupnpc/CMakeLists.txt index a7744b8..bd0efa1 100644 --- a/miniupnpc/CMakeLists.txt +++ b/miniupnpc/CMakeLists.txt @@ -1,8 +1,8 @@ cmake_minimum_required (VERSION 2.6) project (miniupnpc C) -set (MINIUPNPC_VERSION 1.7) -set (MINIUPNPC_API_VERSION 9) +set (MINIUPNPC_VERSION 1.9) +set (MINIUPNPC_API_VERSION 10) if (NOT CMAKE_BUILD_TYPE) if (WIN32) diff --git a/miniupnpc/Changelog.txt b/miniupnpc/Changelog.txt index d09ba0a..2ca279d 100644 --- a/miniupnpc/Changelog.txt +++ b/miniupnpc/Changelog.txt @@ -1,6 +1,10 @@ -$Id: Changelog.txt,v 1.189 2013/10/07 10:04:55 nanard Exp $ +$Id: Changelog.txt,v 1.191 2014/01/31 13:18:24 nanard Exp $ miniUPnP client Changelog. +2014/01/31: + added argument remoteHost to UPNP_GetSpecificPortMappingEntry() + increment API_VERSION to 10 + 2013/12/09: --help and -h arguments in upnpc.c diff --git a/miniupnpc/java/JavaBridgeTest.java b/miniupnpc/java/JavaBridgeTest.java index d026dbe..a7fa56d 100644 --- a/miniupnpc/java/JavaBridgeTest.java +++ b/miniupnpc/java/JavaBridgeTest.java @@ -72,7 +72,7 @@ public class JavaBridgeTest { System.out.println("AddPortMapping() failed with code " + ret); ret = miniupnpc.UPNP_GetSpecificPortMappingEntry( urls.controlURL.getString(0), new String(data.first.servicetype), - args[0], args[1], intClient, intPort, + args[0], args[1], null, intClient, intPort, desc, enabled, leaseDuration); if (ret != MiniupnpcLibrary.UPNPCOMMAND_SUCCESS) System.out.println("GetSpecificPortMappingEntry() failed with code " + ret); diff --git a/miniupnpc/miniupnpc.h b/miniupnpc/miniupnpc.h index 6f9b63d..469c0d6 100644 --- a/miniupnpc/miniupnpc.h +++ b/miniupnpc/miniupnpc.h @@ -1,4 +1,4 @@ -/* $Id: miniupnpc.h,v 1.32 2013/02/06 14:44:42 nanard Exp $ */ +/* $Id: miniupnpc.h,v 1.34 2014/01/31 13:18:25 nanard Exp $ */ /* Project: miniupnp * http://miniupnp.free.fr/ * Author: Thomas Bernard @@ -19,7 +19,7 @@ /* versions : */ #define MINIUPNPC_VERSION "1.8" -#define MINIUPNPC_API_VERSION 9 +#define MINIUPNPC_API_VERSION 10 #ifdef __cplusplus extern "C" { diff --git a/miniupnpc/miniupnpcmodule.c b/miniupnpc/miniupnpcmodule.c index f520e8f..4654c98 100644 --- a/miniupnpc/miniupnpcmodule.c +++ b/miniupnpc/miniupnpcmodule.c @@ -1,8 +1,8 @@ -/* $Id: miniupnpcmodule.c,v 1.19 2012/01/21 13:30:32 nanard Exp $*/ +/* $Id: miniupnpcmodule.c,v 1.22 2014/01/31 13:18:25 nanard Exp $*/ /* Project : miniupnp * Author : Thomas BERNARD * website : http://miniupnp.tuxfamily.org/ - * copyright (c) 2007-2012 Thomas Bernard + * copyright (c) 2007-2014 Thomas Bernard * This software is subjet to the conditions detailed in the * provided LICENCE file. */ #include @@ -310,7 +310,7 @@ Py_END_ALLOW_THREADS } } -/* GetSpecificPortMapping(ePort, proto) +/* GetSpecificPortMapping(ePort, proto, remoteHost='') * proto = 'UDP' or 'TCP' */ static PyObject * UPnP_getspecificportmapping(UPnPObject *self, PyObject *args) @@ -318,13 +318,14 @@ UPnP_getspecificportmapping(UPnPObject *self, PyObject *args) char extPort[6]; unsigned short ePort; const char * proto; + const char * remoteHost = ""; char intClient[40]; char intPort[6]; unsigned short iPort; char desc[80]; char enabled[4]; char leaseDuration[16]; - if(!PyArg_ParseTuple(args, "Hs", &ePort, &proto)) + if(!PyArg_ParseTuple(args, "Hs|z", &ePort, &proto, &remoteHost)) return NULL; extPort[0] = '\0'; intClient[0] = '\0'; intPort[0] = '\0'; desc[0] = '\0'; enabled[0] = '\0'; leaseDuration[0] = '\0'; @@ -332,7 +333,7 @@ Py_BEGIN_ALLOW_THREADS sprintf(extPort, "%hu", ePort); UPNP_GetSpecificPortMappingEntry(self->urls.controlURL, self->data.first.servicetype, - extPort, proto, + extPort, proto, remoteHost, intClient, intPort, desc, enabled, leaseDuration); Py_END_ALLOW_THREADS diff --git a/miniupnpc/upnpc.c b/miniupnpc/upnpc.c index ff132aa..9c9979a 100644 --- a/miniupnpc/upnpc.c +++ b/miniupnpc/upnpc.c @@ -1,4 +1,4 @@ -/* $Id: upnpc.c,v 1.99 2013/02/06 12:56:41 nanard Exp $ */ +/* $Id: upnpc.c,v 1.101 2014/01/31 13:18:25 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard * Copyright (c) 2005-2013 Thomas Bernard @@ -266,7 +266,7 @@ static void SetRedirectAndTest(struct UPNPUrls * urls, r = UPNP_GetSpecificPortMappingEntry(urls->controlURL, data->first.servicetype, - eport, proto, + eport, proto, NULL/*remoteHost*/, intClient, intPort, NULL/*desc*/, NULL/*enabled*/, duration); if(r!=UPNPCOMMAND_SUCCESS) diff --git a/miniupnpc/upnpcommands.c b/miniupnpc/upnpcommands.c index 76d2d8a..ad69781 100644 --- a/miniupnpc/upnpcommands.c +++ b/miniupnpc/upnpcommands.c @@ -1,4 +1,4 @@ -/* $Id: upnpcommands.c,v 1.41 2013/12/09 08:18:23 nanard Exp $ */ +/* $Id: upnpcommands.c,v 1.42 2014/01/31 13:18:25 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard * Copyright (c) 2005-2012 Thomas Bernard @@ -578,7 +578,8 @@ LIBSPEC int UPNP_GetSpecificPortMappingEntry(const char * controlURL, const char * servicetype, const char * extPort, - const char * proto, + const char * proto, + const char * remoteHost, char * intClient, char * intPort, char * desc, @@ -597,7 +598,7 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL, GetPortMappingArgs = calloc(4, sizeof(struct UPNParg)); GetPortMappingArgs[0].elt = "NewRemoteHost"; - /* TODO : add remote host ? */ + GetPortMappingArgs[0].val = remoteHost; GetPortMappingArgs[1].elt = "NewExternalPort"; GetPortMappingArgs[1].val = extPort; GetPortMappingArgs[2].elt = "NewProtocol"; diff --git a/miniupnpc/upnpcommands.h b/miniupnpc/upnpcommands.h index ee68dfd..dc3f23f 100644 --- a/miniupnpc/upnpcommands.h +++ b/miniupnpc/upnpcommands.h @@ -1,4 +1,4 @@ -/* $Id: upnpcommands.h,v 1.23 2011/04/11 09:14:00 nanard Exp $ */ +/* $Id: upnpcommands.h,v 1.26 2014/01/31 13:18:26 nanard Exp $ */ /* Miniupnp project : http://miniupnp.free.fr/ * Author : Thomas Bernard * Copyright (c) 2005-2011 Thomas Bernard @@ -150,6 +150,7 @@ UPNP_GetPortMappingNumberOfEntries(const char* controlURL, * params : * in extPort * in proto + * in remoteHost * out intClient (16 bytes) * out intPort (6 bytes) * out desc (80 bytes) @@ -164,6 +165,7 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL, const char * servicetype, const char * extPort, const char * proto, + const char * remoteHost, char * intClient, char * intPort, char * desc, From b72a782ab0c1a22ed00b6ff686479c87d621b031 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Fri, 31 Jan 2014 14:32:26 +0100 Subject: [PATCH 024/104] VERSION 1.9 --- miniupnpc/Changelog.txt | 2 ++ miniupnpc/VERSION | 2 +- miniupnpc/apiversions.txt | 12 +++++++++++- miniupnpc/miniupnpc.h | 2 +- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/miniupnpc/Changelog.txt b/miniupnpc/Changelog.txt index 2ca279d..180015a 100644 --- a/miniupnpc/Changelog.txt +++ b/miniupnpc/Changelog.txt @@ -1,6 +1,8 @@ $Id: Changelog.txt,v 1.191 2014/01/31 13:18:24 nanard Exp $ miniUPnP client Changelog. +VERSION 1.9 : released 2014/01/31 + 2014/01/31: added argument remoteHost to UPNP_GetSpecificPortMappingEntry() increment API_VERSION to 10 diff --git a/miniupnpc/VERSION b/miniupnpc/VERSION index 6259340..2e0e38c 100644 --- a/miniupnpc/VERSION +++ b/miniupnpc/VERSION @@ -1 +1 @@ -1.8 +1.9 diff --git a/miniupnpc/apiversions.txt b/miniupnpc/apiversions.txt index bec2941..69f61c7 100644 --- a/miniupnpc/apiversions.txt +++ b/miniupnpc/apiversions.txt @@ -1,7 +1,17 @@ -$Id: apiversions.txt,v 1.2 2013/03/29 14:45:09 nanard Exp $ +$Id: apiversions.txt,v 1.3 2014/01/31 13:14:32 nanard Exp $ Differences in API between miniUPnPc versions +====================== miniUPnPc version 1.9 ====================== +API version 10 + +upnpcommands.h: + added argument remoteHost to UPNP_GetSpecificPortMappingEntry() + +miniupnpc.h: + updated macros : + #define MINIUPNPC_VERSION "1.9" + #define MINIUPNPC_API_VERSION 10 ====================== miniUPnPc version 1.8 ====================== API version 9 diff --git a/miniupnpc/miniupnpc.h b/miniupnpc/miniupnpc.h index 469c0d6..2c0e475 100644 --- a/miniupnpc/miniupnpc.h +++ b/miniupnpc/miniupnpc.h @@ -18,7 +18,7 @@ #define UPNPDISCOVER_MEMORY_ERROR (-102) /* versions : */ -#define MINIUPNPC_VERSION "1.8" +#define MINIUPNPC_VERSION "1.9" #define MINIUPNPC_API_VERSION 10 #ifdef __cplusplus From 02f137700f7b72741aa5125ea34ca6da8282163f Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Fri, 31 Jan 2014 14:58:40 +0100 Subject: [PATCH 025/104] APIVERSION = 10 --- miniupnpc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miniupnpc/Makefile b/miniupnpc/Makefile index 1bb996b..554b988 100644 --- a/miniupnpc/Makefile +++ b/miniupnpc/Makefile @@ -55,7 +55,7 @@ ifeq (SunOS, $(OS)) endif # APIVERSION is used to build SONAME -APIVERSION = 9 +APIVERSION = 10 SRCS = igd_desc_parse.c miniupnpc.c minixml.c minisoap.c miniwget.c \ upnpc.c upnpcommands.c upnpreplyparse.c testminixml.c \ From b36900b3e99503cf3dcf274d332136f4662f95c4 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Fri, 31 Jan 2014 15:19:38 +0100 Subject: [PATCH 026/104] miniupnpc/Makefile: fix clean target --- miniupnpc/Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/miniupnpc/Makefile b/miniupnpc/Makefile index 554b988..76327d0 100644 --- a/miniupnpc/Makefile +++ b/miniupnpc/Makefile @@ -3,7 +3,7 @@ # http://miniupnp.free.fr/ # http://miniupnp.tuxfamily.org/ # https://github.com/miniupnp/miniupnp -# (c) 2005-2013 Thomas Bernard +# (c) 2005-2014 Thomas Bernard # to install use : # $ make DESTDIR=/tmp/dummylocation install # or @@ -175,7 +175,8 @@ validateupnpreplyparse: testupnpreplyparse testupnpreplyparse.sh clean: $(RM) $(LIBRARY) $(SHAREDLIBRARY) $(EXECUTABLES) $(OBJS) miniupnpcstrings.h # clean python stuff - $(RM) pythonmodule pythonmodule3 validateminixml validateminiwget + $(RM) pythonmodule pythonmodule3 + $(RM) validateminixml validateminiwget validateupnpreplyparse $(RM) -r build/ dist/ #python setup.py clean # clean jnaerator stuff From ab7865ae991708212f21a9893d35763941edd1a3 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Fri, 31 Jan 2014 15:20:15 +0100 Subject: [PATCH 027/104] miniupnpc.c: translate comment from French to English :) --- miniupnpc/miniupnpc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/miniupnpc/miniupnpc.c b/miniupnpc/miniupnpc.c index 63460bf..4c1412b 100644 --- a/miniupnpc/miniupnpc.c +++ b/miniupnpc/miniupnpc.c @@ -1,8 +1,8 @@ -/* $Id: miniupnpc.c,v 1.113 2013/10/07 10:04:56 nanard Exp $ */ +/* $Id: miniupnpc.c,v 1.116 2014/01/31 14:09:03 nanard Exp $ */ /* Project : miniupnp * Web : http://miniupnp.free.fr/ * Author : Thomas BERNARD - * copyright (c) 2005-2013 Thomas Bernard + * copyright (c) 2005-2014 Thomas Bernard * This software is subjet to the conditions detailed in the * provided LICENSE file. */ #define __EXTENSIONS__ 1 @@ -545,7 +545,8 @@ upnpDiscover(int delay, const char * multicastif, } } - /* Avant d'envoyer le paquet on bind pour recevoir la reponse */ + /* Before sending the packed, we first "bind" in order to be able + * to receive the response */ if (bind(sudp, (const struct sockaddr *)&sockudp_r, ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) != 0) { From 49780a99ea68f6a9399975fe7b78c87643631de9 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Mon, 3 Feb 2014 10:42:38 +0100 Subject: [PATCH 028/104] miniupnpd/minissdp.c: check return value of AddMulticastMembershipIPv6() --- miniupnpd/minissdp.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/miniupnpd/minissdp.c b/miniupnpd/minissdp.c index a67c94b..d593fe8 100644 --- a/miniupnpd/minissdp.c +++ b/miniupnpd/minissdp.c @@ -1,4 +1,4 @@ -/* $Id: minissdp.c,v 1.54 2013/06/15 12:50:10 nanard Exp $ */ +/* $Id: minissdp.c,v 1.56 2014/02/01 16:35:37 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2013 Thomas Bernard @@ -146,7 +146,11 @@ OpenAndConfSSDPReceiveSocket(int ipv6) #ifdef ENABLE_IPV6 if(ipv6) { - AddMulticastMembershipIPv6(s); + if(AddMulticastMembershipIPv6(s) < 0) + { + syslog(LOG_WARNING, + "Failed to add IPv6 multicast membership"); + } } else #endif From 18db1145eae079670350732f388313a8666ac347 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Mon, 3 Feb 2014 10:44:24 +0100 Subject: [PATCH 029/104] miniupnpd.c: comments in parselanaddr() --- miniupnpd/miniupnpd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/miniupnpd/miniupnpd.c b/miniupnpd/miniupnpd.c index 42313b4..3ca4dcc 100644 --- a/miniupnpd/miniupnpd.c +++ b/miniupnpd/miniupnpd.c @@ -586,6 +586,7 @@ parselanaddr(struct lan_addr_s * lan_addr, const char * str) p++; if(*p=='.') { + /* parse mask in /255.255.255.0 format */ while(*p && (*p=='.' || isdigit(*p))) p++; n = p - q; @@ -598,6 +599,7 @@ parselanaddr(struct lan_addr_s * lan_addr, const char * str) } else { + /* it is a /24 format */ int nbits = atoi(q); if(nbits > 32 || nbits < 0) goto parselan_error; From 3712118bc41926793ee86e3ae484c846fdbb225e Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Mon, 3 Feb 2014 10:45:59 +0100 Subject: [PATCH 030/104] miniupnpd: removed unused code ScanNATPMPforExpiration() CleanExpiredNATPMP() are not used anymore --- miniupnpd/miniupnpd.c | 29 ++------------------ miniupnpd/natpmp.c | 63 +------------------------------------------ miniupnpd/natpmp.h | 8 +----- 3 files changed, 4 insertions(+), 96 deletions(-) diff --git a/miniupnpd/miniupnpd.c b/miniupnpd/miniupnpd.c index 3ca4dcc..31bd643 100644 --- a/miniupnpd/miniupnpd.c +++ b/miniupnpd/miniupnpd.c @@ -1,7 +1,7 @@ -/* $Id: miniupnpd.c,v 1.178 2013/12/13 14:10:02 nanard Exp $ */ +/* $Id: miniupnpd.c,v 1.182 2014/02/03 08:37:32 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2013 Thomas Bernard + * (c) 2006-2014 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -1515,9 +1515,6 @@ main(int argc, char * * argv) syslog(LOG_NOTICE, "Listening for NAT-PMP traffic on port %u", NATPMP_PORT); } -#endif -#if 0 - ScanNATPMPforExpiration(); #endif } #endif @@ -1631,28 +1628,6 @@ main(int argc, char * * argv) syslog(LOG_DEBUG, "setting timeout to %u sec", (unsigned)timeout.tv_sec); } -#ifdef ENABLE_NATPMP -#if 0 - /* Remove expired NAT-PMP mappings */ - while(nextnatpmptoclean_timestamp - && (timeofday.tv_sec >= nextnatpmptoclean_timestamp + startup_time)) - { - /*syslog(LOG_DEBUG, "cleaning expired NAT-PMP mappings");*/ - if(CleanExpiredNATPMP() < 0) { - syslog(LOG_ERR, "CleanExpiredNATPMP() failed"); - break; - } - } - if(nextnatpmptoclean_timestamp - && timeout.tv_sec >= (nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec)) - { - /*syslog(LOG_DEBUG, "setting timeout to %d sec", - nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec);*/ - timeout.tv_sec = nextnatpmptoclean_timestamp + startup_time - timeofday.tv_sec; - timeout.tv_usec = 0; - } -#endif -#endif #ifdef ENABLE_6FC_SERVICE /* Clean up expired IPv6 PinHoles */ next_pinhole_ts = 0; diff --git a/miniupnpd/natpmp.c b/miniupnpd/natpmp.c index d1efd27..8a127a0 100644 --- a/miniupnpd/natpmp.c +++ b/miniupnpd/natpmp.c @@ -1,4 +1,4 @@ -/* $Id: natpmp.c,v 1.35 2013/12/13 14:07:08 nanard Exp $ */ +/* $Id: natpmp.c,v 1.36 2014/02/01 17:17:35 nanard Exp $ */ /* MiniUPnP project * (c) 2007-2013 Thomas Bernard * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ @@ -334,67 +334,6 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, } } -#if 0 -/* iterate through the redirection list to find those who came - * from NAT-PMP and select the first to expire */ -int ScanNATPMPforExpiration() -{ - char desc[64]; - unsigned short iport, eport; - int proto; - int r, i; - unsigned timestamp; - nextnatpmptoclean_eport = 0; - nextnatpmptoclean_timestamp = 0; - for(i = 0; ; i++) { - r = get_redirect_rule_by_index(i, 0, &eport, 0, 0, - &iport, &proto, desc, sizeof(desc), - ×tamp, 0, 0); - if(r<0) - break; - if(sscanf(desc, "NAT-PMP %u", ×tamp) == 1) { - if( !nextnatpmptoclean_eport - || timestamp < nextnatpmptoclean_timestamp) { - nextnatpmptoclean_eport = eport; - nextnatpmptoclean_proto = proto; - nextnatpmptoclean_timestamp = timestamp; - syslog(LOG_DEBUG, "set nextnatpmptoclean_timestamp to %u", timestamp); - } - } - } - return 0; -} - -/* remove the next redirection that is expired - */ -int CleanExpiredNATPMP() -{ - char desc[64]; - unsigned timestamp; - unsigned short iport; - if(get_redirect_rule(ext_if_name, nextnatpmptoclean_eport, - nextnatpmptoclean_proto, - 0, 0, - &iport, desc, sizeof(desc), ×tamp, 0, 0) < 0) - return ScanNATPMPforExpiration(); - /* check desc - this is important since we keep expiration time as part - * of the desc. - * If the rule is renewed, timestamp and nextnatpmptoclean_timestamp - * can be different. In that case, the rule must not be removed ! */ - if(sscanf(desc, "NAT-PMP %u", ×tamp) == 1) { - if(timestamp > nextnatpmptoclean_timestamp) - return ScanNATPMPforExpiration(); - } - /* remove redirection then search for next one:) */ - if(_upnp_delete_redir(nextnatpmptoclean_eport, nextnatpmptoclean_proto)<0) - return -1; - syslog(LOG_INFO, "Expired NAT-PMP mapping port %hu %s removed", - nextnatpmptoclean_eport, - nextnatpmptoclean_proto==IPPROTO_TCP?"TCP":"UDP"); - return ScanNATPMPforExpiration(); -} -#endif - /* SendNATPMPPublicAddressChangeNotification() * should be called when the public IP address changed */ void SendNATPMPPublicAddressChangeNotification(int * sockets, int n_sockets) diff --git a/miniupnpd/natpmp.h b/miniupnpd/natpmp.h index b8a73bf..5f63517 100644 --- a/miniupnpd/natpmp.h +++ b/miniupnpd/natpmp.h @@ -1,4 +1,4 @@ -/* $Id: natpmp.h,v 1.8 2011/05/27 21:36:22 nanard Exp $ */ +/* $Id: natpmp.h,v 1.11 2014/02/01 17:17:35 nanard Exp $ */ /* MiniUPnP project * author : Thomas Bernard * website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ @@ -26,12 +26,6 @@ int ReceiveNATPMPOrPCPPacket(int s, struct sockaddr_in* senderaddr, void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, struct sockaddr_in *senderaddr); -#if 0 -int ScanNATPMPforExpiration(void); - -int CleanExpiredNATPMP(void); -#endif - void SendNATPMPPublicAddressChangeNotification(int * sockets, int n_sockets); #endif From f6b5408e87bc541f1682f5d661254cfdd02eebca Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Mon, 3 Feb 2014 10:47:47 +0100 Subject: [PATCH 031/104] miniupnpd: define min/max_lifetime only when needed --- miniupnpd/miniupnpd.c | 4 +++- miniupnpd/upnpglobalvars.c | 7 +++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/miniupnpd/miniupnpd.c b/miniupnpd/miniupnpd.c index 31bd643..675f3c2 100644 --- a/miniupnpd/miniupnpd.c +++ b/miniupnpd/miniupnpd.c @@ -908,12 +908,14 @@ init(int argc, char * * argv, struct runtime_vars * v) optionsfile); } } - /* if lifetimes ae inverse*/ +#ifdef ENABLE_PCP + /* if lifetimes are inverse */ if (min_lifetime >= max_lifetime) { fprintf(stderr, "Minimum lifetime (%lu) is greater than or equal to maximum lifetime (%lu).\n", min_lifetime, max_lifetime); fprintf(stderr, "Check your configuration file.\n"); return 1; } +#endif } #endif /* DISABLE_CONFIG_FILE */ diff --git a/miniupnpd/upnpglobalvars.c b/miniupnpd/upnpglobalvars.c index 152a689..4ed29d8 100644 --- a/miniupnpd/upnpglobalvars.c +++ b/miniupnpd/upnpglobalvars.c @@ -1,7 +1,7 @@ -/* $Id: upnpglobalvars.c,v 1.32 2013/12/13 14:07:09 nanard Exp $ */ +/* $Id: upnpglobalvars.c,v 1.33 2014/02/03 08:37:32 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2012 Thomas Bernard + * (c) 2006-2014 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -33,8 +33,11 @@ unsigned long upstream_bitrate = 0; /* startup time */ time_t startup_time = 0; +#ifdef ENABLE_PCP +/* for PCP */ unsigned long int min_lifetime = 120; unsigned long int max_lifetime = 86400; +#endif int runtime_flags = 0; From 46905418caeb0e1f00d7eb933c066b19cc72a845 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Mon, 3 Feb 2014 10:49:59 +0100 Subject: [PATCH 032/104] miniupnpd: various PCP fixes --- miniupnpd/pcpserver.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/miniupnpd/pcpserver.c b/miniupnpd/pcpserver.c index bfae5e8..d79609b 100644 --- a/miniupnpd/pcpserver.c +++ b/miniupnpd/pcpserver.c @@ -1,4 +1,4 @@ -/* $Id: pcpserver.c,v 1.5 2014/01/27 10:06:08 nanard Exp $ */ +/* $Id: pcpserver.c,v 1.7 2014/02/03 09:38:26 nanard Exp $ */ /* MiniUPnP project * Website : http://miniupnp.free.fr/ * Author : Peter Tatrai @@ -558,7 +558,7 @@ static int CheckExternalAddress(pcp_info_t* pcp_msg_info) } } - if (IN6_IS_ADDR_UNSPECIFIED(pcp_msg_info->ext_ip)) { + if (pcp_msg_info->ext_ip == NULL || IN6_IS_ADDR_UNSPECIFIED(pcp_msg_info->ext_ip)) { pcp_msg_info->ext_ip = &external_addr; @@ -977,11 +977,16 @@ static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info) processedSize = 0; /* discard request that exceeds maximal length, - or that is shorter than 3 + or that is shorter than PCP_MIN_LEN (=24) or that is not the multiple of 4 */ - if (req_size < PCP_MIN_LEN) + if (req_size < 3) return 0; /* ignore msg */ + if (req_size < PCP_MIN_LEN) { + pcp_msg_info->result_code = PCP_ERR_MALFORMED_REQUEST; + return 1; /* send response */ + } + if ( (req_size > PCP_MAX_LEN) || ( (req_size & 3) != 0)) { syslog(LOG_ERR, "PCP: Size of PCP packet(%d) is larger than %d bytes or " "the size is not multiple of 4.\n", req_size, PCP_MAX_LEN); @@ -1000,7 +1005,7 @@ static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info) processedSize += sizeof(pcp_request_t); if (common_req->ver == 1) { - + /* legacy PCP version 1 support */ switch ( common_req->r_opcode & 0x7F ) { case PCP_OPCODE_MAP: @@ -1078,7 +1083,8 @@ static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info) } } else if (common_req->ver == 2) { - + /* RFC 6887 PCP support + * http://tools.ietf.org/html/rfc6887 */ switch ( common_req->r_opcode & 0x7F) { case PCP_OPCODE_MAP: @@ -1305,7 +1311,10 @@ int ProcessIncomingPCPPacket(int s, unsigned char *buff, int len, createPCPResponse(buff, &pcp_msg_info); - len = (len + 3) & ~3; /* round up resp. length to multiple of 4 */ + if(len < PCP_MIN_LEN) + len = PCP_MIN_LEN; + else + len = (len + 3) & ~3; /* round up resp. length to multiple of 4 */ len = sendto(s, buff, len, 0, (struct sockaddr *)senderaddr, sizeof(struct sockaddr_in)); if( len < 0 ) { From 538c002373eaf2fe44325ce4f791f04d8c1df072 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Mon, 3 Feb 2014 10:50:29 +0100 Subject: [PATCH 033/104] miniupnpd: PCP Add support for ANNOUNCE requests --- miniupnpd/Changelog.txt | 5 ++++- miniupnpd/pcpserver.c | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/miniupnpd/Changelog.txt b/miniupnpd/Changelog.txt index f2761ea..9683ace 100644 --- a/miniupnpd/Changelog.txt +++ b/miniupnpd/Changelog.txt @@ -1,4 +1,7 @@ -$Id: Changelog.txt,v 1.346 2013/12/13 13:41:52 nanard Exp $ +$Id: Changelog.txt,v 1.348 2014/02/03 09:32:09 nanard Exp $ + +2014/02/03: + PCP : Add support for ANNOUNCE requests 2013/12/16: Attempt to compile with OS X/pf diff --git a/miniupnpd/pcpserver.c b/miniupnpd/pcpserver.c index d79609b..9b11361 100644 --- a/miniupnpd/pcpserver.c +++ b/miniupnpd/pcpserver.c @@ -1086,6 +1086,10 @@ static int processPCPRequest(void * req, int req_size, pcp_info_t *pcp_msg_info) /* RFC 6887 PCP support * http://tools.ietf.org/html/rfc6887 */ switch ( common_req->r_opcode & 0x7F) { + case PCP_OPCODE_ANNOUNCE: + /* should check PCP Client's IP Address in request */ + /* see http://tools.ietf.org/html/rfc6887#section-14.1 */ + break; case PCP_OPCODE_MAP: remainingSize -= sizeof(pcp_map_v2_t); From b7a4f8d6961d37a1c84742ad02124af7cec4ffc1 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Mon, 3 Feb 2014 11:28:31 +0100 Subject: [PATCH 034/104] minixml.c: now handle XML comments --- miniupnpc/Changelog.txt | 3 +++ miniupnpc/minixml.c | 19 ++++++++++++++++--- miniupnpd/Changelog.txt | 1 + miniupnpd/minixml.c | 19 ++++++++++++++++--- 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/miniupnpc/Changelog.txt b/miniupnpc/Changelog.txt index 180015a..ccf3b91 100644 --- a/miniupnpc/Changelog.txt +++ b/miniupnpc/Changelog.txt @@ -1,6 +1,9 @@ $Id: Changelog.txt,v 1.191 2014/01/31 13:18:24 nanard Exp $ miniUPnP client Changelog. +2014/02/03: + minixml now handle XML comments + VERSION 1.9 : released 2014/01/31 2014/01/31: diff --git a/miniupnpc/minixml.c b/miniupnpc/minixml.c index d3f7d06..1f22273 100644 --- a/miniupnpc/minixml.c +++ b/miniupnpc/minixml.c @@ -1,10 +1,10 @@ -/* $Id: minixml.c,v 1.9 2011/02/07 13:44:57 nanard Exp $ */ +/* $Id: minixml.c,v 1.10 2012/03/05 19:42:47 nanard Exp $ */ /* minixml.c : the minimum size a xml parser can be ! */ /* Project : miniupnp * webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * Author : Thomas Bernard -Copyright (c) 2005-2011, Thomas BERNARD +Copyright (c) 2005-2014, Thomas BERNARD All rights reserved. Redistribution and use in source and binary forms, with or without @@ -113,7 +113,20 @@ static void parseelt(struct xmlparser * p) const char * elementname; while(p->xml < (p->xmlend - 1)) { - if((p->xml)[0]=='<' && (p->xml)[1]!='?') + if((p->xml + 4) <= p->xmlend && (0 == memcmp(p->xml, "", 3) != 0); + p->xml += 3; + } + else if((p->xml)[0]=='<' && (p->xml)[1]!='?') { i = 0; elementname = ++p->xml; while( !IS_WHITE_SPACE(*p->xml) diff --git a/miniupnpd/Changelog.txt b/miniupnpd/Changelog.txt index 9683ace..517b83e 100644 --- a/miniupnpd/Changelog.txt +++ b/miniupnpd/Changelog.txt @@ -2,6 +2,7 @@ $Id: Changelog.txt,v 1.348 2014/02/03 09:32:09 nanard Exp $ 2014/02/03: PCP : Add support for ANNOUNCE requests + minixml now handle XML comments 2013/12/16: Attempt to compile with OS X/pf diff --git a/miniupnpd/minixml.c b/miniupnpd/minixml.c index d3f7d06..1f22273 100644 --- a/miniupnpd/minixml.c +++ b/miniupnpd/minixml.c @@ -1,10 +1,10 @@ -/* $Id: minixml.c,v 1.9 2011/02/07 13:44:57 nanard Exp $ */ +/* $Id: minixml.c,v 1.10 2012/03/05 19:42:47 nanard Exp $ */ /* minixml.c : the minimum size a xml parser can be ! */ /* Project : miniupnp * webpage: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * Author : Thomas Bernard -Copyright (c) 2005-2011, Thomas BERNARD +Copyright (c) 2005-2014, Thomas BERNARD All rights reserved. Redistribution and use in source and binary forms, with or without @@ -113,7 +113,20 @@ static void parseelt(struct xmlparser * p) const char * elementname; while(p->xml < (p->xmlend - 1)) { - if((p->xml)[0]=='<' && (p->xml)[1]!='?') + if((p->xml + 4) <= p->xmlend && (0 == memcmp(p->xml, "", 3) != 0); + p->xml += 3; + } + else if((p->xml)[0]=='<' && (p->xml)[1]!='?') { i = 0; elementname = ++p->xml; while( !IS_WHITE_SPACE(*p->xml) From 2e4d11ba280e9f89e6a4bb86e0a2a9cfefce33cc Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Mon, 3 Feb 2014 16:48:51 +0100 Subject: [PATCH 035/104] minissdpd/listifaces: fix. now compatible with linux and BSD --- minissdpd/Makefile | 4 ++- minissdpd/listifaces.c | 66 +++++++++++++++++++++++++++++++----------- 2 files changed, 52 insertions(+), 18 deletions(-) diff --git a/minissdpd/Makefile b/minissdpd/Makefile index e924acb..99c2691 100644 --- a/minissdpd/Makefile +++ b/minissdpd/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.17 2012/05/02 10:26:50 nanard Exp $ +# $Id: Makefile,v 1.18 2014/02/03 14:32:14 nanard Exp $ # MiniUPnP project # author: Thomas Bernard # website: http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ @@ -59,6 +59,8 @@ testminissdpd: $(TESTMINISSDPDOBJS) testcodelength: testcodelength.o +listifaces: listifaces.o upnputils.o + depend: makedepend -f$(MAKEFILE_LIST) -Y \ $(ALLOBJS:.o=.c) 2>/dev/null diff --git a/minissdpd/listifaces.c b/minissdpd/listifaces.c index 14124ef..f893d6e 100644 --- a/minissdpd/listifaces.c +++ b/minissdpd/listifaces.c @@ -1,4 +1,7 @@ -/* $Id: listifaces.c,v 1.4 2007/09/23 16:59:02 nanard Exp $ */ +/* $Id: listifaces.c,v 1.6 2014/02/03 14:32:14 nanard Exp $ */ +/* (c) 2006-2014 Thomas BERNARD + * http://miniupnp.free.fr/ http://miniupnp.tuxfamily.org/ + */ #include #include #include @@ -8,7 +11,9 @@ #include #include #include +#include "upnputils.h" +/* hexdump */ void printhex(const unsigned char * p, int n) { int i; @@ -27,20 +32,28 @@ void printhex(const unsigned char * p, int n) } } -void listifaces() +/* List network interfaces */ +void listifaces(void) { struct ifconf ifc; - char * buf = 0; - int buflen = sizeof(struct ifreq)*20; - /*[sizeof(struct ifreq)*8];*/ + char * buf = NULL; + int buflen; int s, i; int j; char saddr[256/*INET_ADDRSTRLEN*/]; +#ifdef __linux__ + buflen = sizeof(struct ifreq)*10; +#else + buflen = 0; +#endif /*s = socket(PF_INET, SOCK_DGRAM, 0);*/ s = socket(AF_INET, SOCK_DGRAM, 0); do { +#ifdef __linux__ buflen += buflen; - buf = realloc(buf, buflen); +#endif + if(buflen > 0) + buf = realloc(buf, buflen); ifc.ifc_len = buflen; ifc.ifc_buf = (caddr_t)buf; if(ioctl(s, SIOCGIFCONF, &ifc) < 0) @@ -50,22 +63,39 @@ void listifaces() free(buf); return; } - printf("%d - %d - %d\n", buflen, ifc.ifc_len, (int)sizeof(struct ifreq)); - printf(" %d\n", IFNAMSIZ); - printf(" %d %d\n", (int)sizeof(struct sockaddr), (int)sizeof(struct sockaddr_in) ); - } while(buflen == ifc.ifc_len); + printf("buffer length=%d - buffer used=%d - sizeof(struct ifreq)=%d\n", + buflen, ifc.ifc_len, (int)sizeof(struct ifreq)); + printf("IFNAMSIZ=%d ", IFNAMSIZ); + printf("sizeof(struct sockaddr)=%d sizeof(struct sockaddr_in)=%d\n", + (int)sizeof(struct sockaddr), (int)sizeof(struct sockaddr_in) ); +#ifndef __linux__ + if(buflen == 0) + buflen = ifc.ifc_len; + else + break; + } while(1); +#else + } while(buflen <= ifc.ifc_len); +#endif printhex((const unsigned char *)ifc.ifc_buf, ifc.ifc_len); - j = 0; - for(i=0; iifr_name) + 16;//ifrp->ifr_addr.sa_len; /*inet_ntop(AF_INET, &(((struct sockaddr_in *)&(ifrp->ifr_addr))->sin_addr), saddr, sizeof(saddr));*/ saddr[0] = '\0'; - inet_ntop(ifrp->ifr_addr.sa_family, &(ifrp->ifr_addr.sa_data[2]), saddr, sizeof(saddr)); - printf("%2d %d %d %s %s\n", j, ifrp->ifr_addr.sa_family, -1/*ifrp->ifr_addr.sa_len*/, ifrp->ifr_name, saddr); - j++; + /* inet_ntop(ifrp->ifr_addr.sa_family, &(ifrp->ifr_addr.sa_data[2]), saddr, sizeof(saddr)); */ + sockaddr_to_string(&ifrp->ifr_addr, saddr, sizeof(saddr)); + printf("0x%03x %2d %2d %-16s %s\n", i, j, ifrp->ifr_addr.sa_family, ifrp->ifr_name, saddr); + /*ifrp->ifr_addr.sa_len is only available on BSD */ +#ifdef __linux__ + i += sizeof(struct ifreq); +#else + if(ifrp->ifr_addr.sa_len == 0) + break; + i += IFNAMSIZ + ifrp->ifr_addr.sa_len; +#endif } free(buf); close(s); @@ -73,6 +103,8 @@ void listifaces() int main(int argc, char * * argv) { + (void)argc; + (void)argv; listifaces(); return 0; } From 612d0e44fb91b4bb78a988a1505424540a53899b Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Mon, 3 Feb 2014 16:50:37 +0100 Subject: [PATCH 036/104] minissdpd.c: improve comments and logging --- minissdpd/minissdpd.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/minissdpd/minissdpd.c b/minissdpd/minissdpd.c index 520a6c5..25bacb3 100644 --- a/minissdpd/minissdpd.c +++ b/minissdpd/minissdpd.c @@ -1,6 +1,6 @@ -/* $Id: minissdpd.c,v 1.35 2012/05/21 17:13:11 nanard Exp $ */ +/* $Id: minissdpd.c,v 1.36 2014/02/03 15:45:07 nanard Exp $ */ /* MiniUPnP project - * (c) 2007-2012 Thomas Bernard + * (c) 2007-2014 Thomas Bernard * website : 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 */ @@ -282,8 +282,10 @@ processMSEARCH(int s, const char * st, int st_len, } } else { /* find matching services */ + /* remove version at the end of the ST string */ if(st[st_len-2]==':' && isdigit(st[st_len-1])) st_len -= 2; + /* answer for each matching service */ for(serv = servicelisthead.lh_first; serv; serv = serv->entries.le_next) { @@ -338,6 +340,7 @@ ParseSSDPPacket(int s, const char * p, ssize_t n, unsigned int lifetime = 180; /* 3 minutes by default */ const char * st = NULL; int st_len = 0; + memset(headers, 0, sizeof(headers)); for(methodlen = 0; methodlen < n && (isalpha(p[methodlen]) || p[methodlen]=='-'); @@ -566,9 +569,9 @@ void processRequest(struct reqelem * req) syslog(LOG_INFO, "(s=%d) request type=%d str='%.*s'", req->socket, type, l, p); switch(type) { - case 1: - case 2: - case 3: + case 1: /* request by type */ + case 2: /* request by USN (unique id) */ + case 3: /* everything */ while(d && (nrep < 255)) { if(d->t < t) { syslog(LOG_INFO, "outdated device"); @@ -633,12 +636,14 @@ void processRequest(struct reqelem * req) } } rbuf[0] = nrep; + syslog(LOG_DEBUG, "(s=%d) response : %d device%s", + req->socket, nrep, (nrep > 1) ? "s" : ""); if(write(req->socket, rbuf, rp - rbuf) < 0) { syslog(LOG_ERR, "(s=%d) write: %m", req->socket); goto error; } break; - case 4: + case 4: /* submit service */ newserv = malloc(sizeof(struct service)); if(!newserv) { syslog(LOG_ERR, "cannot allocate memory"); From 178f0b8c4d4b0106817fe291aafb513175928288 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Mon, 3 Feb 2014 16:51:25 +0100 Subject: [PATCH 037/104] minissdpd.c: silently ignore EAGAIN, EWOULDBLOCK, EINTR of recv calls --- minissdpd/Changelog.txt | 5 ++++- minissdpd/minissdpd.c | 11 +++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/minissdpd/Changelog.txt b/minissdpd/Changelog.txt index fa17abd..54cd416 100644 --- a/minissdpd/Changelog.txt +++ b/minissdpd/Changelog.txt @@ -1,4 +1,7 @@ -$Id: Changelog.txt,v 1.32 2013/08/19 16:40:55 nanard Exp $ +$Id: Changelog.txt,v 1.33 2014/02/03 15:45:07 nanard Exp $ + +2014/02/03: + silently ignore EAGAIN, EWOULDBLOCK, EINTR of recv calls 2013/08/19: Translate README in english diff --git a/minissdpd/minissdpd.c b/minissdpd/minissdpd.c index 25bacb3..9b6d63b 100644 --- a/minissdpd/minissdpd.c +++ b/minissdpd/minissdpd.c @@ -224,6 +224,7 @@ SendSSDPMSEARCHResponse(int s, const struct sockaddr * sockname, n = sendto(s, buf, l, 0, sockname, sockname_len ); if(n < 0) { + /* XXX handle EINTR, EAGAIN, EWOULDBLOCK */ syslog(LOG_ERR, "sendto(udp): %m"); } } @@ -1002,7 +1003,10 @@ int main(int argc, char * * argv) (struct sockaddr *)&sendername6, &sendername6_len); if(n<0) { - syslog(LOG_ERR, "recvfrom: %m"); + /* EAGAIN, EWOULDBLOCK, EINTR : silently ignore (try again next time) + * other errors : log to LOG_ERR */ + if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) + syslog(LOG_ERR, "recvfrom: %m"); } else { @@ -1033,7 +1037,10 @@ int main(int argc, char * * argv) (struct sockaddr *)&sendername, &sendername_len); if(n<0) { - syslog(LOG_ERR, "recvfrom: %m"); + /* EAGAIN, EWOULDBLOCK, EINTR : silently ignore (try again next time) + * other errors : log to LOG_ERR */ + if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) + syslog(LOG_ERR, "recvfrom: %m"); } else { From 04752985cc48a7e9c16b946a9642e33acdc3ace0 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Mon, 3 Feb 2014 16:52:38 +0100 Subject: [PATCH 038/104] minissdpd.c: Discover devices on the network at startup --- minissdpd/Changelog.txt | 1 + minissdpd/minissdpd.c | 67 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/minissdpd/Changelog.txt b/minissdpd/Changelog.txt index 54cd416..0cf152a 100644 --- a/minissdpd/Changelog.txt +++ b/minissdpd/Changelog.txt @@ -2,6 +2,7 @@ $Id: Changelog.txt,v 1.33 2014/02/03 15:45:07 nanard Exp $ 2014/02/03: silently ignore EAGAIN, EWOULDBLOCK, EINTR of recv calls + Discover devices on the network at startup 2013/08/19: Translate README in english diff --git a/minissdpd/minissdpd.c b/minissdpd/minissdpd.c index 9b6d63b..e1068ad 100644 --- a/minissdpd/minissdpd.c +++ b/minissdpd/minissdpd.c @@ -350,6 +350,12 @@ ParseSSDPPacket(int s, const char * p, ssize_t n, method = METHOD_MSEARCH; else if(methodlen==6 && 0==memcmp(p, "NOTIFY", 6)) method = METHOD_NOTIFY; + else if(methodlen==4 && 0==memcmp(p, "HTTP", 4)) { + /* answer to a M-SEARCH => process it as a NOTIFY + * with NTS: ssdp:alive */ + method = METHOD_NOTIFY; + nts = NTS_SSDP_ALIVE; + } linestart = p; while(linestart < p + n - 2) { /* start parsing the line : detect line end */ @@ -439,6 +445,8 @@ ParseSSDPPacket(int s, const char * p, ssize_t n, } else if(l==2 && 0==strncasecmp(linestart, "st", 2)) { st = valuestart; st_len = m; + if(method == METHOD_NOTIFY) + i = HEADER_NT; /* it was a M-SEARCH response */ } if(i>=0) { headers[i].p = valuestart; @@ -785,6 +793,60 @@ sigterm(int sig) /*errno = save_errno;*/ } +#define PORT 1900 +#define XSTR(s) STR(s) +#define STR(s) #s +#define UPNP_MCAST_ADDR "239.255.255.250" +/* for IPv6 */ +#define UPNP_MCAST_LL_ADDR "FF02::C" /* link-local */ +#define UPNP_MCAST_SL_ADDR "FF05::C" /* site-local */ + +/* send the M-SEARCH request for all devices */ +void ssdpDiscoverAll(int s, int ipv6) +{ + static const char MSearchMsgFmt[] = + "M-SEARCH * HTTP/1.1\r\n" + "HOST: %s:" XSTR(PORT) "\r\n" + "ST: ssdp:all\r\n" + "MAN: \"ssdp:discover\"\r\n" + "MX: %u\r\n" + "\r\n"; + char bufr[512]; + int n; + int mx = 3; + int linklocal = 1; + struct sockaddr_storage sockudp_w; + + { + n = snprintf(bufr, sizeof(bufr), + MSearchMsgFmt, + ipv6 ? + (linklocal ? "[" UPNP_MCAST_LL_ADDR "]" : "[" UPNP_MCAST_SL_ADDR "]") + : UPNP_MCAST_ADDR, mx); + memset(&sockudp_w, 0, sizeof(struct sockaddr_storage)); + if(ipv6) { + struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_w; + p->sin6_family = AF_INET6; + p->sin6_port = htons(PORT); + inet_pton(AF_INET6, + linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR, + &(p->sin6_addr)); + } else { + struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_w; + p->sin_family = AF_INET; + p->sin_port = htons(PORT); + p->sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR); + } + + n = sendto(s, bufr, n, 0, (const struct sockaddr *)&sockudp_w, + ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)); + if (n < 0) { + /* XXX : EINTR EWOULDBLOCK EAGAIN */ + syslog(LOG_ERR, "sendto: %m"); + } + } +} + /* main(): program entry point */ int main(int argc, char * * argv) { @@ -963,6 +1025,11 @@ int main(int argc, char * * argv) writepidfile(pidfilename, pid); + /* send M-SEARCH ssdp:all Requests */ + ssdpDiscoverAll(s_ssdp, 0); + if(s_ssdp6 >= 0) + ssdpDiscoverAll(s_ssdp6, 1); + /* Main loop */ while(!quitting) { From f354f73238c40a356d85670f03d15b75b1d11fe9 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Wed, 5 Feb 2014 18:31:28 +0100 Subject: [PATCH 039/104] miniupnpc/connecthostport.c: handle EINPROGRESS after connect() --- miniupnpc/Changelog.txt | 5 ++++- miniupnpc/connecthostport.c | 14 ++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/miniupnpc/Changelog.txt b/miniupnpc/Changelog.txt index ccf3b91..53e9a11 100644 --- a/miniupnpc/Changelog.txt +++ b/miniupnpc/Changelog.txt @@ -1,6 +1,9 @@ -$Id: Changelog.txt,v 1.191 2014/01/31 13:18:24 nanard Exp $ +$Id: Changelog.txt,v 1.193 2014/02/05 17:26:45 nanard Exp $ miniUPnP client Changelog. +2014/02/05: + handle EINPROGRESS after connect() + 2014/02/03: minixml now handle XML comments diff --git a/miniupnpc/connecthostport.c b/miniupnpc/connecthostport.c index aabc7a6..98f7253 100644 --- a/miniupnpc/connecthostport.c +++ b/miniupnpc/connecthostport.c @@ -1,7 +1,7 @@ -/* $Id: connecthostport.c,v 1.11 2013/08/01 21:21:25 nanard Exp $ */ +/* $Id: connecthostport.c,v 1.12 2014/02/05 17:26:46 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard - * Copyright (c) 2010-2013 Thomas Bernard + * Copyright (c) 2010-2014 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. */ @@ -109,7 +109,10 @@ int connecthostport(const char * host, unsigned short port, dest.sin_port = htons(port); n = connect(s, (struct sockaddr *)&dest, sizeof(struct sockaddr_in)); #ifdef MINIUPNPC_IGNORE_EINTR - while(n < 0 && errno == EINTR) + /* EINTR The system call was interrupted by a signal that was caught + * EINPROGRESS The socket is nonblocking and the connection cannot + * be completed immediately. */ + while(n < 0 && (errno == EINTR || errno = EINPROGRESS)) { socklen_t len; fd_set wset; @@ -203,7 +206,10 @@ int connecthostport(const char * host, unsigned short port, #endif /* #ifdef MINIUPNPC_SET_SOCKET_TIMEOUT */ n = connect(s, p->ai_addr, p->ai_addrlen); #ifdef MINIUPNPC_IGNORE_EINTR - while(n < 0 && errno == EINTR) + /* EINTR The system call was interrupted by a signal that was caught + * EINPROGRESS The socket is nonblocking and the connection cannot + * be completed immediately. */ + while(n < 0 && (errno == EINTR || errno == EINPROGRESS)) { socklen_t len; fd_set wset; From cd5cb6e48e0ea2e89da9c1dbf6e7b3c91cb48c19 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Wed, 5 Feb 2014 18:32:29 +0100 Subject: [PATCH 040/104] removed unused stuff --- miniupnpc/miniwget.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/miniupnpc/miniwget.c b/miniupnpc/miniwget.c index a75f55b..813db93 100644 --- a/miniupnpc/miniwget.c +++ b/miniupnpc/miniwget.c @@ -1,8 +1,8 @@ -/* $Id: miniwget.c,v 1.60 2013/10/07 10:03:16 nanard Exp $ */ +/* $Id: miniwget.c,v 1.61 2014/02/05 17:27:48 nanard Exp $ */ /* Project : miniupnp * Website : http://miniupnp.free.fr/ * Author : Thomas Bernard - * Copyright (c) 2005-2013 Thomas Bernard + * Copyright (c) 2005-2014 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. */ @@ -39,9 +39,6 @@ #include #include #define closesocket close -/* defining MINIUPNPC_IGNORE_EINTR enable the ignore of interruptions - * during the connect() call */ -#define MINIUPNPC_IGNORE_EINTR #endif /* #else _WIN32 */ #if defined(__sun) || defined(sun) #define MIN(x,y) (((x)<(y))?(x):(y)) From 8ffaa91b2df8db34b202af3a610c1940d42066d6 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Wed, 5 Feb 2014 18:32:47 +0100 Subject: [PATCH 041/104] upnpc.c: 2013 -> 2014 --- miniupnpc/upnpc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/miniupnpc/upnpc.c b/miniupnpc/upnpc.c index 9c9979a..70c9a54 100644 --- a/miniupnpc/upnpc.c +++ b/miniupnpc/upnpc.c @@ -1,7 +1,7 @@ -/* $Id: upnpc.c,v 1.101 2014/01/31 13:18:25 nanard Exp $ */ +/* $Id: upnpc.c,v 1.102 2014/02/05 17:27:14 nanard Exp $ */ /* Project : miniupnp * Author : Thomas Bernard - * Copyright (c) 2005-2013 Thomas Bernard + * Copyright (c) 2005-2014 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided in this distribution. */ @@ -500,7 +500,7 @@ int main(int argc, char ** argv) return -1; } #endif - printf("upnpc : miniupnpc library test client. (c) 2005-2013 Thomas Bernard\n"); + printf("upnpc : miniupnpc library test client. (c) 2005-2014 Thomas Bernard\n"); printf("Go to http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/\n" "for more information.\n"); /* command line processing */ From dce25a2e2797ebd5a8516f6ce4304e3a059e428e Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Thu, 6 Feb 2014 10:53:52 +0100 Subject: [PATCH 042/104] minissdpd/.gitignore: add listifaces --- minissdpd/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/minissdpd/.gitignore b/minissdpd/.gitignore index 9c8b266..6e1b69d 100644 --- a/minissdpd/.gitignore +++ b/minissdpd/.gitignore @@ -2,4 +2,5 @@ minissdpd testcodelength testminissdpd +listifaces Makefile.bak From 18f02dccb34dec088f5f249ed6ae85c0afcef21a Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Thu, 6 Feb 2014 10:55:28 +0100 Subject: [PATCH 043/104] miniupnpd: possibility to disable ipv6 at runtime fixes #049 --- miniupnpd/Changelog.txt | 5 +++- miniupnpd/minissdp.c | 24 +++++++++++++------ miniupnpd/miniupnpd.c | 48 +++++++++++++++++++++++++++----------- miniupnpd/upnpglobalvars.c | 3 ++- miniupnpd/upnpglobalvars.h | 5 ++-- miniupnpd/upnputils.c | 4 ++-- 6 files changed, 63 insertions(+), 26 deletions(-) diff --git a/miniupnpd/Changelog.txt b/miniupnpd/Changelog.txt index 517b83e..6d463e4 100644 --- a/miniupnpd/Changelog.txt +++ b/miniupnpd/Changelog.txt @@ -1,4 +1,7 @@ -$Id: Changelog.txt,v 1.348 2014/02/03 09:32:09 nanard Exp $ +$Id: Changelog.txt,v 1.350 2014/02/06 09:52:03 nanard Exp $ + +2014/02/06: + possibility to disable ipv6 at runtime 2014/02/03: PCP : Add support for ANNOUNCE requests diff --git a/miniupnpd/minissdp.c b/miniupnpd/minissdp.c index d593fe8..fb5a9b8 100644 --- a/miniupnpd/minissdp.c +++ b/miniupnpd/minissdp.c @@ -1,7 +1,7 @@ -/* $Id: minissdp.c,v 1.56 2014/02/01 16:35:37 nanard Exp $ */ +/* $Id: minissdp.c,v 1.57 2014/02/06 09:52:03 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2013 Thomas Bernard + * (c) 2006-2014 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -280,9 +280,16 @@ OpenAndConfSSDPNotifySockets(int * sockets) goto error; i++; #ifdef ENABLE_IPV6 - sockets[i] = OpenAndConfSSDPNotifySocketIPv6(lan_addr->index); - if(sockets[i] < 0) - goto error; + if(ipv6_enabled) + { + sockets[i] = OpenAndConfSSDPNotifySocketIPv6(lan_addr->index); + if(sockets[i] < 0) + goto error; + } + else + { + sockets[i] = -1; + } i++; #endif } @@ -568,8 +575,11 @@ SendSSDPNotifies2(int * sockets, lifetime, 0); i++; #ifdef ENABLE_IPV6 - SendSSDPNotifies(sockets[i], ipv6_addr_for_http_with_brackets, port, - lifetime, 1); + if(sockets[i] >= 0) + { + SendSSDPNotifies(sockets[i], ipv6_addr_for_http_with_brackets, port, + lifetime, 1); + } i++; #endif } diff --git a/miniupnpd/miniupnpd.c b/miniupnpd/miniupnpd.c index 675f3c2..805d788 100644 --- a/miniupnpd/miniupnpd.c +++ b/miniupnpd/miniupnpd.c @@ -1,4 +1,4 @@ -/* $Id: miniupnpd.c,v 1.182 2014/02/03 08:37:32 nanard Exp $ */ +/* $Id: miniupnpd.c,v 1.183 2014/02/06 09:52:01 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2014 Thomas Bernard @@ -116,7 +116,8 @@ OpenAndConfHTTPSocket(unsigned short port) int s; int i = 1; #ifdef ENABLE_IPV6 - struct sockaddr_in6 listenname; + struct sockaddr_in6 listenname6; + struct sockaddr_in listenname4; #else struct sockaddr_in listenname; #endif @@ -124,7 +125,7 @@ OpenAndConfHTTPSocket(unsigned short port) if( (s = socket( #ifdef ENABLE_IPV6 - PF_INET6, + ipv6_enabled ? PF_INET6 : PF_INET, #else PF_INET, #endif @@ -153,19 +154,35 @@ OpenAndConfHTTPSocket(unsigned short port) } #ifdef ENABLE_IPV6 - memset(&listenname, 0, sizeof(struct sockaddr_in6)); - listenname.sin6_family = AF_INET6; - listenname.sin6_port = htons(port); - listenname.sin6_addr = in6addr_any; - listenname_len = sizeof(struct sockaddr_in6); + if(ipv6_enabled) + { + memset(&listenname6, 0, sizeof(struct sockaddr_in6)); + listenname6.sin6_family = AF_INET6; + listenname6.sin6_port = htons(port); + listenname6.sin6_addr = in6addr_any; + listenname_len = sizeof(struct sockaddr_in6); + } else { + memset(&listenname4, 0, sizeof(struct sockaddr_in)); + listenname4.sin_family = AF_INET; + listenname4.sin_port = htons(port); + listenname4.sin_addr.s_addr = htonl(INADDR_ANY); + listenname_len = sizeof(struct sockaddr_in); + } #else + memset(&listenname, 0, sizeof(struct sockaddr_in)); listenname.sin_family = AF_INET; listenname.sin_port = htons(port); listenname.sin_addr.s_addr = htonl(INADDR_ANY); listenname_len = sizeof(struct sockaddr_in); #endif +#ifdef ENABLE_IPV6 + if(bind(s, + ipv6_enabled ? (struct sockaddr *)&listenname6 : (struct sockaddr *)&listenname4, + listenname_len) < 0) +#else if(bind(s, (struct sockaddr *)&listenname, listenname_len) < 0) +#endif { syslog(LOG_ERR, "bind(http): %m"); close(s); @@ -181,6 +198,7 @@ OpenAndConfHTTPSocket(unsigned short port) return s; } + #ifdef ENABLE_NFQUEUE int identify_ip_protocol(char *payload) { @@ -1347,7 +1365,7 @@ main(int argc, char * * argv) int sudpv6 = -1; /* IP v6 socket for receiving SSDP */ #endif #ifdef ENABLE_NATPMP - int * snatpmp = NULL; + int * snatpmp = NULL; /* also used for PCP */ #endif #ifdef ENABLE_NFQUEUE int nfqh = -1; @@ -1455,7 +1473,8 @@ main(int argc, char * * argv) ipv6_addr_for_http_with_brackets); } else { memcpy(ipv6_addr_for_http_with_brackets, "[::1]", 6); - syslog(LOG_WARNING, "no HTTP IPv6 address"); + syslog(LOG_WARNING, "no HTTP IPv6 address, disabling IPv6"); + ipv6_enabled = 0; } #endif @@ -1470,10 +1489,13 @@ main(int argc, char * * argv) } } #ifdef ENABLE_IPV6 - sudpv6 = OpenAndConfSSDPReceiveSocket(1); - if(sudpv6 < 0) + if(ipv6_enabled) { - syslog(LOG_WARNING, "Failed to open socket for receiving SSDP (IP v6)."); + sudpv6 = OpenAndConfSSDPReceiveSocket(1); + if(sudpv6 < 0) + { + syslog(LOG_WARNING, "Failed to open socket for receiving SSDP (IP v6)."); + } } #endif diff --git a/miniupnpd/upnpglobalvars.c b/miniupnpd/upnpglobalvars.c index 4ed29d8..ae4203c 100644 --- a/miniupnpd/upnpglobalvars.c +++ b/miniupnpd/upnpglobalvars.c @@ -1,4 +1,4 @@ -/* $Id: upnpglobalvars.c,v 1.33 2014/02/03 08:37:32 nanard Exp $ */ +/* $Id: upnpglobalvars.c,v 1.34 2014/02/06 09:52:03 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2014 Thomas Bernard @@ -121,6 +121,7 @@ struct lan_addr_list lan_addrs; #ifdef ENABLE_IPV6 /* ipv6 address used for HTTP */ char ipv6_addr_for_http_with_brackets[64]; +int ipv6_enabled = 1; #endif /* Path of the Unix socket used to communicate with MiniSSDPd */ diff --git a/miniupnpd/upnpglobalvars.h b/miniupnpd/upnpglobalvars.h index 80ea147..fb67428 100644 --- a/miniupnpd/upnpglobalvars.h +++ b/miniupnpd/upnpglobalvars.h @@ -1,7 +1,7 @@ -/* $Id: upnpglobalvars.h,v 1.35 2013/06/13 13:21:30 nanard Exp $ */ +/* $Id: upnpglobalvars.h,v 1.37 2014/02/06 09:52:03 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2012 Thomas Bernard + * (c) 2006-2014 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -139,6 +139,7 @@ extern struct lan_addr_list lan_addrs; #ifdef ENABLE_IPV6 /* ipv6 address used for HTTP */ extern char ipv6_addr_for_http_with_brackets[64]; +extern int ipv6_enabled; #endif extern const char * minissdpdsocketpath; diff --git a/miniupnpd/upnputils.c b/miniupnpd/upnputils.c index 23ad242..197df58 100644 --- a/miniupnpd/upnputils.c +++ b/miniupnpd/upnputils.c @@ -1,7 +1,7 @@ -/* $Id: upnputils.c,v 1.7 2013/04/20 09:03:18 nanard Exp $ */ +/* $Id: upnputils.c,v 1.8 2014/02/05 17:00:26 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2013 Thomas Bernard + * (c) 2006-2014 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ From bc67a7133b8cdeb6d7bc2d6da4f3756e0a8a33b0 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Thu, 6 Feb 2014 10:55:57 +0100 Subject: [PATCH 044/104] miniupnpd/upnputils.c: improve log in get_lan_for_peer() --- miniupnpd/upnputils.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/miniupnpd/upnputils.c b/miniupnpd/upnputils.c index 197df58..33ebc66 100644 --- a/miniupnpd/upnputils.c +++ b/miniupnpd/upnputils.c @@ -93,6 +93,7 @@ struct lan_addr_s * get_lan_for_peer(const struct sockaddr * peer) { struct lan_addr_s * lan_addr = NULL; + char dbg_str[64]; #ifdef ENABLE_IPV6 if(peer->sa_family == AF_INET6) @@ -153,11 +154,15 @@ get_lan_for_peer(const struct sockaddr * peer) } #endif - if(lan_addr) - syslog(LOG_DEBUG, "%s: found in LAN %s %s", - "get_lan_for_peer()", lan_addr->ifname, lan_addr->str); - else - syslog(LOG_DEBUG, "%s: not found !", "get_lan_for_peer()"); + sockaddr_to_string(peer, dbg_str, sizeof(dbg_str)); + if(lan_addr) { + syslog(LOG_DEBUG, "%s: %s found in LAN %s %s", + "get_lan_for_peer()", dbg_str, + lan_addr->ifname, lan_addr->str); + } else { + syslog(LOG_DEBUG, "%s: %s not found !", "get_lan_for_peer()", + dbg_str); + } return lan_addr; } From 32b6e8c0fa21f626017abe7b0cd0672a5df858df Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Tue, 11 Feb 2014 10:38:50 +0100 Subject: [PATCH 045/104] miniupnpd/commonrdr.h: improve comments --- miniupnpd/commonrdr.h | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/miniupnpd/commonrdr.h b/miniupnpd/commonrdr.h index dd5cf62..7c0bd7c 100644 --- a/miniupnpd/commonrdr.h +++ b/miniupnpd/commonrdr.h @@ -1,6 +1,6 @@ -/* $Id: commonrdr.h,v 1.7 2011/06/22 20:34:39 nanard Exp $ */ +/* $Id: commonrdr.h,v 1.9 2014/02/11 09:36:15 nanard Exp $ */ /* MiniUPnP project - * (c) 2006-2011 Thomas Bernard + * (c) 2006-2014 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 */ @@ -10,6 +10,9 @@ #include "config.h" /* init and shutdown functions */ +/* init_redirect() return values : + * 0 : OK + * -1 : error */ int init_redirect(void); @@ -17,7 +20,10 @@ void shutdown_redirect(void); /* get_redirect_rule() gets internal IP and port from - * interface, external port and protocl + * interface, external port and protocol + * return value : + * 0 success (rule found) + * -1 error or rule not found */ int get_redirect_rule(const char * ifname, unsigned short eport, int proto, @@ -27,6 +33,10 @@ get_redirect_rule(const char * ifname, unsigned short eport, int proto, unsigned int * timestamp, u_int64_t * packets, u_int64_t * bytes); +/* get_redirect_rule_by_index() + * return values : + * 0 success (rule found) + * -1 error or rule not found */ int get_redirect_rule_by_index(int index, char * ifname, unsigned short * eport, From 50f8f6c76fde708540812740ba727e9f0e8bdf12 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Tue, 11 Feb 2014 10:40:46 +0100 Subject: [PATCH 046/104] miniupnpd/pcpserver.c: add info message for Mapping renewal --- miniupnpd/pcpserver.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/miniupnpd/pcpserver.c b/miniupnpd/pcpserver.c index 9b11361..c12eb96 100644 --- a/miniupnpd/pcpserver.c +++ b/miniupnpd/pcpserver.c @@ -827,6 +827,10 @@ static void CreatePCPMap(pcp_info_t *pcp_msg_info) return; } } else { + syslog(LOG_INFO, "port %hu %s already redirected to %s:%hu, replacing", + pcp_msg_info->ext_port, (pcp_msg_info->protocol==IPPROTO_TCP)?"tcp":"udp", + iaddr_old, iport_old); + /* remove and then add again */ if (_upnp_delete_redir(pcp_msg_info->ext_port, pcp_msg_info->protocol)==0) { break; From 16ea0db41162f80bdbee37bcc92bc8ce1f45e695 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Tue, 11 Feb 2014 10:41:26 +0100 Subject: [PATCH 047/104] miniupnpd: Fix PCP Map renewal --- miniupnpd/Changelog.txt | 5 ++++- miniupnpd/pcpserver.c | 6 ++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/miniupnpd/Changelog.txt b/miniupnpd/Changelog.txt index 6d463e4..2835f5b 100644 --- a/miniupnpd/Changelog.txt +++ b/miniupnpd/Changelog.txt @@ -1,4 +1,7 @@ -$Id: Changelog.txt,v 1.350 2014/02/06 09:52:03 nanard Exp $ +$Id: Changelog.txt,v 1.351 2014/02/11 09:35:52 nanard Exp $ + +2014/02/11: + Fix PCP Map renewal 2014/02/06: possibility to disable ipv6 at runtime diff --git a/miniupnpd/pcpserver.c b/miniupnpd/pcpserver.c index c12eb96..7354fb3 100644 --- a/miniupnpd/pcpserver.c +++ b/miniupnpd/pcpserver.c @@ -1,4 +1,4 @@ -/* $Id: pcpserver.c,v 1.7 2014/02/03 09:38:26 nanard Exp $ */ +/* $Id: pcpserver.c,v 1.9 2014/02/11 09:35:53 nanard Exp $ */ /* MiniUPnP project * Website : http://miniupnp.free.fr/ * Author : Peter Tatrai @@ -803,7 +803,7 @@ static void CreatePCPMap(pcp_info_t *pcp_msg_info) char desc[64]; char iaddr_old[INET_ADDRSTRLEN]; uint16_t iport_old; - unsigned int timestamp = time(NULL) + pcp_msg_info->lifetime; + unsigned int timestamp; int r=0; if (pcp_msg_info->ext_port == 0) { @@ -840,6 +840,8 @@ static void CreatePCPMap(pcp_info_t *pcp_msg_info) } } while (r==0); + timestamp = time(NULL) + pcp_msg_info->lifetime; + if ((pcp_msg_info->ext_port == 0) || (IN6_IS_ADDR_V4MAPPED(pcp_msg_info->int_ip) && (!check_upnp_rule_against_permissions(upnppermlist, From 86d3e7c0530ff28ef11b6cfb4cc98211df4aac45 Mon Sep 17 00:00:00 2001 From: Christopher Meng Date: Fri, 14 Feb 2014 16:56:10 +0800 Subject: [PATCH 048/104] Corrent the binary permission from 555 to 755 --- miniupnpd/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miniupnpd/Makefile b/miniupnpd/Makefile index 4f085fd..09f776b 100644 --- a/miniupnpd/Makefile +++ b/miniupnpd/Makefile @@ -148,7 +148,7 @@ clean: install: miniupnpd genuuid $(STRIP) miniupnpd $(INSTALL) -d $(DESTDIR)$(INSTALLBINDIR) - $(INSTALL) -m 555 miniupnpd $(DESTDIR)$(INSTALLBINDIR) + $(INSTALL) -m 755 miniupnpd $(DESTDIR)$(INSTALLBINDIR) $(INSTALL) -d $(DESTDIR)$(INSTALLETCDIR) $(INSTALL) -b miniupnpd.conf $(DESTDIR)$(INSTALLETCDIR) # TODO : install man page correctly From 7fb5fe5dcb8b64bdbd2bf285f2fd03e53cfc0a6e Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Mon, 17 Feb 2014 16:52:53 +0100 Subject: [PATCH 049/104] miniupnpc/upnpcommands.h: explain UPNP error codes --- miniupnpc/upnpcommands.h | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/miniupnpc/upnpcommands.h b/miniupnpc/upnpcommands.h index dc3f23f..93d9f3d 100644 --- a/miniupnpc/upnpcommands.h +++ b/miniupnpc/upnpcommands.h @@ -1,7 +1,7 @@ -/* $Id: upnpcommands.h,v 1.26 2014/01/31 13:18:26 nanard Exp $ */ +/* $Id: upnpcommands.h,v 1.27 2014/02/17 15:38:26 nanard Exp $ */ /* Miniupnp project : http://miniupnp.free.fr/ * Author : Thomas Bernard - * Copyright (c) 2005-2011 Thomas Bernard + * Copyright (c) 2005-2014 Thomas Bernard * This software is subject to the conditions detailed in the * LICENCE file provided within this distribution */ #ifndef UPNPCOMMANDS_H_INCLUDED @@ -100,6 +100,8 @@ UPNP_GetLinkLayerMaxBitRates(const char* controlURL, * errorCode errorDescription (short) - Description (long) * 402 Invalid Args - See UPnP Device Architecture section on Control. * 501 Action Failed - See UPnP Device Architecture section on Control. + * 606 Action not authorized - The action requested REQUIRES authorization and + * the sender was not authorized. * 715 WildCardNotPermittedInSrcIP - The source IP address cannot be * wild-carded * 716 WildCardNotPermittedInExtPort - The external port cannot be wild-carded @@ -112,7 +114,13 @@ UPNP_GetLinkLayerMaxBitRates(const char* controlURL, * 726 RemoteHostOnlySupportsWildcard - RemoteHost must be a wildcard * and cannot be a specific IP address or DNS name * 727 ExternalPortOnlySupportsWildcard - ExternalPort must be a wildcard and - * cannot be a specific port value */ + * cannot be a specific port value + * 728 NoPortMapsAvailable - There are not enough free ports available to + * complete port mapping. + * 729 ConflictWithOtherMechanisms - Attempted port mapping is not allowed + * due to conflict with other mechanisms. + * 732 WildCardNotPermittedInIntPort - The internal port cannot be wild-carded + */ LIBSPEC int UPNP_AddPortMapping(const char * controlURL, const char * servicetype, const char * extPort, @@ -132,6 +140,8 @@ UPNP_AddPortMapping(const char * controlURL, const char * servicetype, * * List of possible UPnP errors for DeletePortMapping : * 402 Invalid Args - See UPnP Device Architecture section on Control. + * 606 Action not authorized - The action requested REQUIRES authorization + * and the sender was not authorized. * 714 NoSuchEntryInArray - The specified value does not exist in the array */ LIBSPEC int UPNP_DeletePortMapping(const char * controlURL, const char * servicetype, @@ -159,7 +169,15 @@ UPNP_GetPortMappingNumberOfEntries(const char* controlURL, * * return value : * UPNPCOMMAND_SUCCESS, UPNPCOMMAND_INVALID_ARGS, UPNPCOMMAND_UNKNOWN_ERROR - * or a UPnP Error Code. */ + * or a UPnP Error Code. + * + * List of possible UPnP errors for _GetSpecificPortMappingEntry : + * 402 Invalid Args - See UPnP Device Architecture section on Control. + * 501 Action Failed - See UPnP Device Architecture section on Control. + * 606 Action not authorized - The action requested REQUIRES authorization + * and the sender was not authorized. + * 714 NoSuchEntryInArray - The specified value does not exist in the array. + */ LIBSPEC int UPNP_GetSpecificPortMappingEntry(const char * controlURL, const char * servicetype, @@ -190,6 +208,8 @@ UPNP_GetSpecificPortMappingEntry(const char * controlURL, * * Possible UPNP Error codes : * 402 Invalid Args - See UPnP Device Architecture section on Control. + * 606 Action not authorized - The action requested REQUIRES authorization + * and the sender was not authorized. * 713 SpecifiedArrayIndexInvalid - The specified array index is out of bounds */ LIBSPEC int From b2143eff9436d4a76f4716022474a0058f013a9b Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Tue, 18 Feb 2014 09:34:42 +0100 Subject: [PATCH 050/104] implementation of queuing of messages to send. --- miniupnpd/.gitignore | 1 + miniupnpd/Makefile | 8 +- miniupnpd/Makefile.linux | 8 +- miniupnpd/asyncsendto.c | 153 ++++++++++++++++++++++++++++++++++++ miniupnpd/asyncsendto.h | 26 ++++++ miniupnpd/testasyncsendto.c | 117 +++++++++++++++++++++++++++ 6 files changed, 308 insertions(+), 5 deletions(-) create mode 100644 miniupnpd/asyncsendto.c create mode 100644 miniupnpd/asyncsendto.h create mode 100644 miniupnpd/testasyncsendto.c diff --git a/miniupnpd/.gitignore b/miniupnpd/.gitignore index f97b1ce..d6c6eb9 100644 --- a/miniupnpd/.gitignore +++ b/miniupnpd/.gitignore @@ -9,6 +9,7 @@ testgetifstats testupnpdescgen testupnppermissions testgetroute +testasyncsendto netfilter/testiptcrdr netfilter/testiptcrdr_dscp netfilter/testiptcrdr_peer diff --git a/miniupnpd/Makefile b/miniupnpd/Makefile index 09f776b..8fa4e4d 100644 --- a/miniupnpd/Makefile +++ b/miniupnpd/Makefile @@ -116,10 +116,11 @@ TESTUPNPDESCGENOBJS = testupnpdescgen.o upnpdescgen.o TESTUPNPPERMISSIONSOBJS = testupnppermissions.o upnppermissions.o TESTGETIFADDROBJS = testgetifaddr.o getifaddr.o MINIUPNPDCTLOBJS = miniupnpdctl.o +TESTASYNCSENDTOOBJS = testasyncsendto.o asyncsendto.o upnputils.o EXECUTABLES = miniupnpd testupnpdescgen testgetifstats \ testupnppermissions miniupnpdctl \ - testgetifaddr testgetroute + testgetifaddr testgetroute testasyncsendto .if $(OSNAME) == "Darwin" LIBS = .else @@ -142,7 +143,7 @@ clean: $(RM) $(STDOBJS) $(BSDOBJS) $(SUNOSOBJS) $(MACOBJS) $(EXECUTABLES) \ testupnpdescgen.o \ $(MISCOBJS) config.h testgetifstats.o testupnppermissions.o \ - miniupnpdctl.o testgetifaddr.o testgetroute.o \ + miniupnpdctl.o testgetifaddr.o testgetroute.o testasyncsendto.o \ $(PFOBJS) $(IPFOBJS) $(IPFWOBJS) install: miniupnpd genuuid @@ -199,6 +200,9 @@ testupnppermissions: config.h $(TESTUPNPPERMISSIONSOBJS) testgetroute: config.h $(TESTGETROUTEOBJS) $(CC) $(CFLAGS) -o $@ $(TESTGETROUTEOBJS) +testasyncsendto: config.h $(TESTASYNCSENDTOOBJS) + $(CC) $(CFLAGS) -o $@ $(TESTASYNCSENDTOOBJS) + # gmake : # $(CC) $(CFLAGS) -o $@ $^ # BSDmake : diff --git a/miniupnpd/Makefile.linux b/miniupnpd/Makefile.linux index a9bab57..6c3b9ad 100644 --- a/miniupnpd/Makefile.linux +++ b/miniupnpd/Makefile.linux @@ -150,7 +150,7 @@ TESTUPNPDESCGENOBJS = testupnpdescgen.o upnpdescgen.o EXECUTABLES = miniupnpd testupnpdescgen testgetifstats \ testupnppermissions miniupnpdctl testgetifaddr \ - testgetroute + testgetroute testasyncsendto .PHONY: all clean install depend genuuid @@ -161,7 +161,7 @@ clean: $(RM) $(EXECUTABLES) $(RM) testupnpdescgen.o testgetifstats.o $(RM) testupnppermissions.o testgetifaddr.o - $(RM) testgetroute.o + $(RM) testgetroute.o testasyncsendto.o $(RM) miniupnpdctl.o install: miniupnpd miniupnpd.8 miniupnpd.conf genuuid \ @@ -205,6 +205,8 @@ testgetifaddr: testgetifaddr.o getifaddr.o testgetroute: testgetroute.o linux/getroute.o upnputils.o -lnfnetlink +testasyncsendto: testasyncsendto.o asyncsendto.o upnputils.o + miniupnpdctl: miniupnpdctl.o config.h: genconfig.sh VERSION @@ -214,7 +216,7 @@ depend: config.h makedepend -f$(MAKEFILE_LIST) -Y \ $(ALLOBJS:.o=.c) $(TESTUPNPDESCGENOBJS:.o=.c) \ testgetifstats.c testupnppermissions.c testgetifaddr.c \ - testgetroute.c miniupnpdctl.c 2>/dev/null + testgetroute.c testasyncsendto.c miniupnpdctl.c 2>/dev/null # DO NOT DELETE diff --git a/miniupnpd/asyncsendto.c b/miniupnpd/asyncsendto.c new file mode 100644 index 0000000..1107f6d --- /dev/null +++ b/miniupnpd/asyncsendto.c @@ -0,0 +1,153 @@ +/* $Id: $ */ +/* MiniUPnP project + * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * (c) 2006-2014 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 + +#include "asyncsendto.h" + +struct scheduled_send { + LIST_ENTRY(scheduled_send) entries; + struct timeval ts; + int sockfd; + const void * buf; + size_t len; + int flags; + const struct sockaddr *dest_addr; + socklen_t addrlen; + char data[]; +}; + +static LIST_HEAD(listhead, scheduled_send) send_list = { NULL }; + +/* + * ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, + * const struct sockaddr *dest_addr, socklen_t addrlen); + */ + +/* delay = milli seconds */ +ssize_t +sendto_schedule(int sockfd, const void *buf, size_t len, int flags, + const struct sockaddr *dest_addr, socklen_t addrlen, + unsigned int delay) +{ + ssize_t n; + struct timeval tv; + struct scheduled_send * elt; + + if(delay == 0) { + /* first try to send at once */ + n = sendto(sockfd, buf, len, flags, dest_addr, addrlen); + if((n >= 0) || (errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK)) + return n; + } + /* schedule */ + if(gettimeofday(&tv, 0) < 0) { + return -1; + } + /* allocate enough space for structure + buffers */ + elt = malloc(sizeof(struct scheduled_send) + len + addrlen); + if(elt == NULL) { + syslog(LOG_ERR, "malloc failed to allocate %u bytes", + (unsigned)(sizeof(struct scheduled_send) + len + addrlen)); + return -1; + } + /* time the packet should be sent */ + elt->ts.tv_sec = tv.tv_sec + (delay / 1000); + elt->ts.tv_usec = tv.tv_usec + (delay % 1000) * 1000; + if(elt->ts.tv_usec > 1000000) { + elt->ts.tv_sec++; + elt->ts.tv_usec -= 1000000; + } + elt->sockfd = sockfd; + elt->flags = flags; + memcpy(elt->data, dest_addr, addrlen); + elt->dest_addr = (struct sockaddr *)elt->data; + elt->addrlen = addrlen; + memcpy(elt->data + addrlen, buf, len); + elt->buf = (void *)(elt->data + addrlen); + elt->len = len; + /* insert */ + LIST_INSERT_HEAD( &send_list, elt, entries); + return 0; +} + + +ssize_t +sendto_or_schedule(int sockfd, const void *buf, size_t len, int flags, + const struct sockaddr *dest_addr, socklen_t addrlen) +{ + return sendto_schedule(sockfd, buf, len, flags, dest_addr, addrlen, 0); +} + +/* get_next_scheduled_send() return number of scheduled send in list */ +int get_next_scheduled_send(struct timeval * next_send) +{ + int n = 0; + struct scheduled_send * elt; + if(next_send == NULL) + return -1; + for(elt = send_list.lh_first; elt != NULL; elt = elt->entries.le_next) { + if(n == 0 || (elt->ts.tv_sec < next_send->tv_sec) || + (elt->ts.tv_sec == next_send->tv_sec && elt->ts.tv_usec < next_send->tv_usec)) { + next_send->tv_sec = elt->ts.tv_sec; + next_send->tv_usec = elt->ts.tv_usec; + } + n++; + } + return n; +} + +int get_sendto_fds(fd_set * writefds, int * max_fd, const struct timeval * now) +{ + int n = 0; + struct scheduled_send * elt; + for(elt = send_list.lh_first; elt != NULL; elt = elt->entries.le_next) { + if((elt->ts.tv_sec < now->tv_sec) || + (elt->ts.tv_sec == now->tv_sec && elt->ts.tv_usec <= now->tv_usec)) { + FD_SET(elt->sockfd, writefds); + if(elt->sockfd > *max_fd) + *max_fd = elt->sockfd; + n++; + } + } +syslog(LOG_DEBUG, "%x", (int)writefds->fds_bits[0]); + return n; +} + +int try_sendto(fd_set * writefds) +{ + ssize_t n; + struct scheduled_send * elt; + struct scheduled_send * next; + for(elt = send_list.lh_first; elt != NULL; elt = next) { + next = elt->entries.le_next; +syslog(LOG_DEBUG, "s=%d fds=%x", elt->sockfd, (int)writefds->fds_bits[0]); + if(FD_ISSET(elt->sockfd, writefds)) { + syslog(LOG_DEBUG, "sending %d bytes", (int)elt->len); + n = sendto(elt->sockfd, elt->buf, elt->len, elt->flags, + elt->dest_addr, elt->addrlen); + if(n < 0) { + syslog(LOG_DEBUG, "sendto: %m"); + if(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) + continue; + return n; + } else { + LIST_REMOVE(elt, entries); + free(elt); + } + } + } + return 0; +} + diff --git a/miniupnpd/asyncsendto.h b/miniupnpd/asyncsendto.h new file mode 100644 index 0000000..d46de69 --- /dev/null +++ b/miniupnpd/asyncsendto.h @@ -0,0 +1,26 @@ +/* $Id: $ */ +/* MiniUPnP project + * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * (c) 2006-2014 Thomas Bernard + * This software is subject to the conditions detailed + * in the LICENCE file provided within the distribution */ + +#ifndef ASYNCSENDTO_H_INCLUDED +#define ASYNCSENDTO_H_INCLUDED + +ssize_t +sendto_schedule(int sockfd, const void *buf, size_t len, int flags, + const struct sockaddr *dest_addr, socklen_t addrlen, + unsigned int delay); + +ssize_t +sendto_or_schedule(int sockfd, const void *buf, size_t len, int flags, + const struct sockaddr *dest_addr, socklen_t addrlen); + +int get_next_scheduled_send(struct timeval * next_send); + +int try_sendto(fd_set * writefds); + +int get_sendto_fds(fd_set * writefds, int * max_fd, const struct timeval * now); + +#endif diff --git a/miniupnpd/testasyncsendto.c b/miniupnpd/testasyncsendto.c new file mode 100644 index 0000000..e2bc5d4 --- /dev/null +++ b/miniupnpd/testasyncsendto.c @@ -0,0 +1,117 @@ +/* $Id: $ */ +/* MiniUPnP project + * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ + * (c) 2006-2014 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 +#include + +#include "miniupnpdtypes.h" +#include "upnputils.h" +#include "asyncsendto.h" + +struct lan_addr_list lan_addrs; + +#define DEST_IP "239.255.255.250" +#define DEST_PORT 1900 +/* +ssize_t +sendto_schedule(int sockfd, const void *buf, size_t len, int flags, + const struct sockaddr *dest_addr, socklen_t addrlen, + unsigned int delay) +*/ + +int test(void) +{ + int s; + ssize_t n; + int i; + struct sockaddr_in addr; + struct sockaddr_in dest_addr; + struct timeval next_send; + if( (s = socket(PF_INET, SOCK_DGRAM, 0)) < 0) { + syslog(LOG_ERR, "socket(): %m"); + return 1; + } + set_non_blocking(s); + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + if(bind(s, &addr, sizeof(addr)) < 0) { + syslog(LOG_ERR, "bind(): %m"); + close(s); + return 1; + } + memset(&dest_addr, 0, sizeof(struct sockaddr_in)); + dest_addr.sin_family = AF_INET; + dest_addr.sin_addr.s_addr = inet_addr(DEST_IP); + dest_addr.sin_port = htons(DEST_PORT); + n = sendto_or_schedule(s, "1234", 4, 0, + (struct sockaddr *)&dest_addr, sizeof(dest_addr)); + syslog(LOG_DEBUG, "sendto_or_schedule : %d", (int)n); + n = sendto_schedule(s, "1234", 4, 0, + (struct sockaddr *)&dest_addr, sizeof(dest_addr), + 3000); + syslog(LOG_DEBUG, "sendto_schedule : %d", (int)n); + while ((i = get_next_scheduled_send(&next_send)) > 0) { + fd_set writefds; + int max_fd; + struct timeval timeout; + struct timeval now; + syslog(LOG_DEBUG, "get_next_scheduled_send : %d next_send=%ld.%06ld", + i, next_send.tv_sec, next_send.tv_usec); + FD_ZERO(&writefds); + max_fd = 0; + gettimeofday(&now, NULL); + if(now.tv_sec > next_send.tv_sec || + (now.tv_sec == next_send.tv_sec && now.tv_usec >= next_send.tv_usec)) { + /* wait 10sec :) */ + timeout.tv_sec = 10; + timeout.tv_usec = 0; + } else { + /* ... */ + timeout.tv_sec = (next_send.tv_sec - now.tv_sec); + timeout.tv_usec = (next_send.tv_usec - now.tv_usec); + if(timeout.tv_usec < 0) { + timeout.tv_usec += 1000000; + timeout.tv_sec--; + } + } + i = get_sendto_fds(&writefds, &max_fd, &now); + syslog(LOG_DEBUG, "get_sendto_fds() returned %d", i); + syslog(LOG_DEBUG, "select(%d, NULL, xx, NULL, %ld.%06ld)", + max_fd, timeout.tv_sec, timeout.tv_usec); + i = select(max_fd, NULL, &writefds, NULL, &timeout); + if(i < 0) { + syslog(LOG_ERR, "select: %m"); + if(errno != EINTR) + break; + } else if(try_sendto(&writefds) < 0) { + syslog(LOG_ERR, "try_sendto: %m"); + break; + } + } + close(s); + return 0; +} + +int main(int argc, char * * argv) +{ + int r; + (void)argc; + (void)argv; + openlog("testasyncsendto", LOG_CONS|LOG_PERROR, LOG_USER); + r = test(); + closelog(); + return r; +} + From 06d9d36e990dfab57a46db68112f0cb347b8f24a Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Thu, 20 Feb 2014 16:08:20 +0100 Subject: [PATCH 051/104] miniupnpd/asyncsendto: make sendto_schedule work --- miniupnpd/asyncsendto.c | 59 +++++++++++++++++++++++++++++++------ miniupnpd/testasyncsendto.c | 15 ++++++++-- 2 files changed, 62 insertions(+), 12 deletions(-) diff --git a/miniupnpd/asyncsendto.c b/miniupnpd/asyncsendto.c index 1107f6d..4a79bc0 100644 --- a/miniupnpd/asyncsendto.c +++ b/miniupnpd/asyncsendto.c @@ -16,9 +16,19 @@ #include "asyncsendto.h" +/* state diagram for a packet : + * + * | + * V + * -> ESCHEDULED -> ESENDNOW -> sent + * ^ | + * | V + * EWAITREADY -> sent + */ struct scheduled_send { LIST_ENTRY(scheduled_send) entries; struct timeval ts; + enum {ESCHEDULED=1, EWAITREADY=2, ESENDNOW=3} state; int sockfd; const void * buf; size_t len; @@ -41,6 +51,7 @@ sendto_schedule(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen, unsigned int delay) { + enum {ESCHEDULED, EWAITREADY, ESENDNOW} state; ssize_t n; struct timeval tv; struct scheduled_send * elt; @@ -48,9 +59,21 @@ sendto_schedule(int sockfd, const void *buf, size_t len, int flags, if(delay == 0) { /* first try to send at once */ n = sendto(sockfd, buf, len, flags, dest_addr, addrlen); - if((n >= 0) || (errno != EINTR && errno != EAGAIN && errno != EWOULDBLOCK)) + if(n >= 0) return n; + else if(errno == EAGAIN || errno == EWOULDBLOCK) { + /* use select() on this socket */ + state = EWAITREADY; + } else if(errno == EINTR) { + state = ESENDNOW; + } else { + /* uncatched error */ + return n; + } + } else { + state = ESCHEDULED; } + /* schedule */ if(gettimeofday(&tv, 0) < 0) { return -1; @@ -62,6 +85,7 @@ sendto_schedule(int sockfd, const void *buf, size_t len, int flags, (unsigned)(sizeof(struct scheduled_send) + len + addrlen)); return -1; } + elt->state = state; /* time the packet should be sent */ elt->ts.tv_sec = tv.tv_sec + (delay / 1000); elt->ts.tv_usec = tv.tv_usec + (delay % 1000) * 1000; @@ -83,6 +107,7 @@ sendto_schedule(int sockfd, const void *buf, size_t len, int flags, } +/* try to send at once, and queue the packet if needed */ ssize_t sendto_or_schedule(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) @@ -108,23 +133,30 @@ int get_next_scheduled_send(struct timeval * next_send) return n; } +/* update writefds for select() call + * return the number of packets to try to send at once */ int get_sendto_fds(fd_set * writefds, int * max_fd, const struct timeval * now) { int n = 0; struct scheduled_send * elt; for(elt = send_list.lh_first; elt != NULL; elt = elt->entries.le_next) { - if((elt->ts.tv_sec < now->tv_sec) || - (elt->ts.tv_sec == now->tv_sec && elt->ts.tv_usec <= now->tv_usec)) { + if(elt->state == EWAITREADY) { + /* last sendto() call returned EAGAIN/EWOULDBLOCK */ FD_SET(elt->sockfd, writefds); if(elt->sockfd > *max_fd) *max_fd = elt->sockfd; n++; + } else if((elt->ts.tv_sec < now->tv_sec) || + (elt->ts.tv_sec == now->tv_sec && elt->ts.tv_usec <= now->tv_usec)) { + /* we waited long enough, now send ! */ + elt->state = ESENDNOW; + n++; } } -syslog(LOG_DEBUG, "%x", (int)writefds->fds_bits[0]); return n; } +/* executed sendto() when needed */ int try_sendto(fd_set * writefds) { ssize_t n; @@ -132,17 +164,26 @@ int try_sendto(fd_set * writefds) struct scheduled_send * next; for(elt = send_list.lh_first; elt != NULL; elt = next) { next = elt->entries.le_next; -syslog(LOG_DEBUG, "s=%d fds=%x", elt->sockfd, (int)writefds->fds_bits[0]); - if(FD_ISSET(elt->sockfd, writefds)) { - syslog(LOG_DEBUG, "sending %d bytes", (int)elt->len); + if((elt->state == ESENDNOW) || + (elt->state == EWAITREADY && FD_ISSET(elt->sockfd, writefds))) { + syslog(LOG_DEBUG, "try_sendto(): %d bytes on socket %d", + (int)elt->len, elt->sockfd); n = sendto(elt->sockfd, elt->buf, elt->len, elt->flags, elt->dest_addr, elt->addrlen); if(n < 0) { - syslog(LOG_DEBUG, "sendto: %m"); - if(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) + if(errno == EINTR) { + /* retry at once */ + elt->state = ESENDNOW; continue; + } else if(errno == EAGAIN || errno == EWOULDBLOCK) { + /* retry once the socket is ready for writing */ + elt->state = EWAITREADY; + continue; + } + /* uncatched error */ return n; } else { + /* remove from the list */ LIST_REMOVE(elt, entries); free(elt); } diff --git a/miniupnpd/testasyncsendto.c b/miniupnpd/testasyncsendto.c index e2bc5d4..7a4eb6e 100644 --- a/miniupnpd/testasyncsendto.c +++ b/miniupnpd/testasyncsendto.c @@ -58,6 +58,10 @@ int test(void) n = sendto_or_schedule(s, "1234", 4, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr)); syslog(LOG_DEBUG, "sendto_or_schedule : %d", (int)n); + n = sendto_schedule(s, "1234", 4, 0, + (struct sockaddr *)&dest_addr, sizeof(dest_addr), + 4400); + syslog(LOG_DEBUG, "sendto_schedule : %d", (int)n); n = sendto_schedule(s, "1234", 4, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr), 3000); @@ -72,10 +76,16 @@ int test(void) FD_ZERO(&writefds); max_fd = 0; gettimeofday(&now, NULL); + i = get_sendto_fds(&writefds, &max_fd, &now); if(now.tv_sec > next_send.tv_sec || (now.tv_sec == next_send.tv_sec && now.tv_usec >= next_send.tv_usec)) { - /* wait 10sec :) */ - timeout.tv_sec = 10; + if(i > 0) { + /* dont wait */ + timeout.tv_sec = 0; + } else { + /* wait 10sec :) */ + timeout.tv_sec = 10; + } timeout.tv_usec = 0; } else { /* ... */ @@ -86,7 +96,6 @@ int test(void) timeout.tv_sec--; } } - i = get_sendto_fds(&writefds, &max_fd, &now); syslog(LOG_DEBUG, "get_sendto_fds() returned %d", i); syslog(LOG_DEBUG, "select(%d, NULL, xx, NULL, %ld.%06ld)", max_fd, timeout.tv_sec, timeout.tv_usec); From 8691c9c0e0246773397e22608d9c11ec76aca4d2 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Tue, 25 Feb 2014 10:23:59 +0100 Subject: [PATCH 052/104] miniupnpd.c: improve comment for init() --- miniupnpd/miniupnpd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/miniupnpd/miniupnpd.c b/miniupnpd/miniupnpd.c index 805d788..3840833 100644 --- a/miniupnpd/miniupnpd.c +++ b/miniupnpd/miniupnpd.c @@ -705,7 +705,9 @@ void complete_uuidvalues(void) * 5) check and write pid file * 6) set startup time stamp * 7) compute presentation URL - * 8) set signal handlers */ + * 8) set signal handlers + * 10) init redirection engine + * 11) reload mapping from leasefile */ static int init(int argc, char * * argv, struct runtime_vars * v) { @@ -1263,6 +1265,7 @@ init(int argc, char * * argv, struct runtime_vars * v) syslog(LOG_NOTICE, "Failed to set %s handler", "SIGUSR1"); } + /* initialize redirection engine (and pinholes) */ if(init_redirect() < 0) { syslog(LOG_ERR, "Failed to init redirection engine. EXITING"); From e00c1bc6e9e08b7d4deae27272b2409c3f03c707 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Tue, 25 Feb 2014 10:24:22 +0100 Subject: [PATCH 053/104] miniupnpd.c: init random number generator in init() --- miniupnpd/miniupnpd.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/miniupnpd/miniupnpd.c b/miniupnpd/miniupnpd.c index 3840833..8bd4a0f 100644 --- a/miniupnpd/miniupnpd.c +++ b/miniupnpd/miniupnpd.c @@ -706,6 +706,7 @@ void complete_uuidvalues(void) * 6) set startup time stamp * 7) compute presentation URL * 8) set signal handlers + * 9) init random generator (srandom()) * 10) init redirection engine * 11) reload mapping from leasefile */ static int @@ -1265,6 +1266,9 @@ init(int argc, char * * argv, struct runtime_vars * v) syslog(LOG_NOTICE, "Failed to set %s handler", "SIGUSR1"); } + /* initialize random number generator */ + srandom((unsigned int)time(NULL)); + /* initialize redirection engine (and pinholes) */ if(init_redirect() < 0) { From d20d959920ed660b3fa1aa86b1cc06a39ee2cbe2 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Tue, 25 Feb 2014 11:07:47 +0100 Subject: [PATCH 054/104] miniupnpd/asyncsendto.h: improve comments/doc --- miniupnpd/asyncsendto.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/miniupnpd/asyncsendto.h b/miniupnpd/asyncsendto.h index d46de69..6afb322 100644 --- a/miniupnpd/asyncsendto.h +++ b/miniupnpd/asyncsendto.h @@ -8,19 +8,28 @@ #ifndef ASYNCSENDTO_H_INCLUDED #define ASYNCSENDTO_H_INCLUDED +/* sendto_schedule() : see sendto(2) + * schedule sendto() call after delay (milliseconds) */ ssize_t sendto_schedule(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen, unsigned int delay); +/* sendto_schedule() : see sendto(2) + * try sendto() at once and schedule if EINTR/EAGAIN/EWOULDBLOCK */ ssize_t sendto_or_schedule(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); +/* get_next_scheduled_send() + * return number of scheduled sendto + * set next_send to timestamp to send next packet */ int get_next_scheduled_send(struct timeval * next_send); +/* execute sendto() for needed packets */ int try_sendto(fd_set * writefds); +/* set writefds before select() */ int get_sendto_fds(fd_set * writefds, int * max_fd, const struct timeval * now); #endif From 1985cbf3ef4e0d0790eafa277e9f06617a761445 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Tue, 25 Feb 2014 11:08:27 +0100 Subject: [PATCH 055/104] asyncsendto: remove failed sendto() from queue --- miniupnpd/asyncsendto.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/miniupnpd/asyncsendto.c b/miniupnpd/asyncsendto.c index 4a79bc0..faae87e 100644 --- a/miniupnpd/asyncsendto.c +++ b/miniupnpd/asyncsendto.c @@ -181,6 +181,9 @@ int try_sendto(fd_set * writefds) continue; } /* uncatched error */ + /* remove from the list */ + LIST_REMOVE(elt, entries); + free(elt); return n; } else { /* remove from the list */ From cbc1a3c96a5b49a35481e30be7e46a2c7b2ad705 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Tue, 25 Feb 2014 11:10:05 +0100 Subject: [PATCH 056/104] miniupnpd: add sendto() queuing --- miniupnpd/Makefile | 2 +- miniupnpd/Makefile.linux | 2 +- miniupnpd/Makefile.macosx | 3 ++- miniupnpd/miniupnpd.c | 36 ++++++++++++++++++++++++++++++++++++ 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/miniupnpd/Makefile b/miniupnpd/Makefile index 8fa4e4d..e404609 100644 --- a/miniupnpd/Makefile +++ b/miniupnpd/Makefile @@ -80,7 +80,7 @@ STDOBJS = miniupnpd.o upnphttp.o upnpdescgen.o upnpsoap.o \ upnpredirect.o getifaddr.o daemonize.o upnpglobalvars.o \ options.o upnppermissions.o minissdp.o natpmp.o pcpserver.o \ upnpevents.o upnputils.o getconnstatus.o \ - upnppinhole.o + upnppinhole.o asyncsendto.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 diff --git a/miniupnpd/Makefile.linux b/miniupnpd/Makefile.linux index 6c3b9ad..270c72d 100644 --- a/miniupnpd/Makefile.linux +++ b/miniupnpd/Makefile.linux @@ -47,7 +47,7 @@ BASEOBJS = miniupnpd.o upnphttp.o upnpdescgen.o upnpsoap.o \ upnpredirect.o getifaddr.o daemonize.o upnpglobalvars.o \ options.o upnppermissions.o minissdp.o natpmp.o pcpserver.o \ upnpevents.o upnputils.o getconnstatus.o \ - upnppinhole.o pcplearndscp.o + upnppinhole.o pcplearndscp.o asyncsendto.o LNXOBJS = linux/getifstats.o linux/ifacewatcher.o linux/getroute.o NETFILTEROBJS = netfilter/iptcrdr.o netfilter/iptpinhole.o netfilter/nfct_get.o diff --git a/miniupnpd/Makefile.macosx b/miniupnpd/Makefile.macosx index 7520124..27280c6 100644 --- a/miniupnpd/Makefile.macosx +++ b/miniupnpd/Makefile.macosx @@ -32,7 +32,8 @@ FWNAME = $(shell [ `uname -r | cut -d. -f1` -ge 11 ] && echo "pf" || echo "ipfw STD_OBJS = miniupnpd.o upnphttp.o upnpdescgen.o upnpsoap.o \ upnpredirect.o getifaddr.o daemonize.o upnpglobalvars.o \ options.o upnppermissions.o minissdp.o natpmp.o \ - upnpevents.o getconnstatus.o upnputils.o + upnpevents.o getconnstatus.o upnputils.o \ + asyncsendto.o MAC_OBJS = mac/getifstats.o bsd/ifacewatcher.o IPFW_OBJS = ipfw/ipfwrdr.o ipfw/ipfwaux.o PF_OBJS = pf/obsdrdr.o pf/pfpinhole.o diff --git a/miniupnpd/miniupnpd.c b/miniupnpd/miniupnpd.c index 8bd4a0f..9219e47 100644 --- a/miniupnpd/miniupnpd.c +++ b/miniupnpd/miniupnpd.c @@ -63,6 +63,7 @@ #include "miniupnpdtypes.h" #include "daemonize.h" #include "upnpevents.h" +#include "asyncsendto.h" #ifdef ENABLE_NATPMP #include "natpmp.h" #ifdef ENABLE_PCP @@ -1756,6 +1757,38 @@ main(int argc, char * * argv) upnpevents_selectfds(&readset, &writeset, &max_fd); #endif + /* queued "sendto" */ + { + struct timeval next_send; + i = get_next_scheduled_send(&next_send); + if(i > 0) { +#ifdef DEBUG + syslog(LOG_DEBUG, "%d queued sendto", i); +#endif + i = get_sendto_fds(&writeset, &max_fd, &timeofday); + if(timeofday.tv_sec > next_send.tv_sec || + (timeofday.tv_sec == next_send.tv_sec && timeofday.tv_usec >= next_send.tv_usec)) { + if(i > 0) { + timeout.tv_sec = 0; + timeout.tv_usec = 0; + } + } else { + struct timeval tmp_timeout; + tmp_timeout.tv_sec = (next_send.tv_sec - timeofday.tv_sec); + tmp_timeout.tv_usec = (next_send.tv_usec - timeofday.tv_usec); + if(tmp_timeout.tv_usec < 0) { + tmp_timeout.tv_usec += 1000000; + tmp_timeout.tv_sec--; + } + if(timeout.tv_sec > tmp_timeout.tv_sec + || (timeout.tv_sec == tmp_timeout.tv_sec && timeout.tv_usec > tmp_timeout.tv_usec)) { + timeout.tv_sec = tmp_timeout.tv_sec; + timeout.tv_usec = tmp_timeout.tv_usec; + } + } + } + } + if(select(max_fd+1, &readset, &writeset, 0, &timeout) < 0) { if(quitting) goto shutdown; @@ -1764,6 +1797,9 @@ main(int argc, char * * argv) syslog(LOG_ERR, "Failed to select open sockets. EXITING"); return 1; /* very serious cause of error */ } + if(try_sendto(&writeset) < 0) { + syslog(LOG_ERR, "try_sendto: %m"); + } #ifdef USE_MINIUPNPDCTL for(ectl = ctllisthead.lh_first; ectl;) { From c1e624ecd4e9d035240ec2a927beb29f60035df3 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Tue, 25 Feb 2014 11:15:30 +0100 Subject: [PATCH 057/104] miniupnpd: use asyncsendto --- miniupnpd/minissdp.c | 46 +++++++++++++++++++++++++++++-------------- miniupnpd/natpmp.c | 9 +++++---- miniupnpd/pcpserver.c | 3 ++- 3 files changed, 38 insertions(+), 20 deletions(-) diff --git a/miniupnpd/minissdp.c b/miniupnpd/minissdp.c index fb5a9b8..c6b70f2 100644 --- a/miniupnpd/minissdp.c +++ b/miniupnpd/minissdp.c @@ -24,6 +24,7 @@ #include "minissdp.h" #include "upnputils.h" #include "getroute.h" +#include "asyncsendto.h" #include "codelength.h" /* SSDP ip/port */ @@ -330,11 +331,13 @@ EXT: * st, st_len : ST: header * suffix : suffix for USN: header * host, port : our HTTP host, port + * delay : in milli-seconds */ static void SendSSDPResponse(int s, const struct sockaddr * addr, const char * st, int st_len, const char * suffix, - const char * host, unsigned short port, const char * uuidvalue) + const char * host, unsigned short port, const char * uuidvalue, + unsigned int delay) { int l, n; char buf[512]; @@ -399,15 +402,14 @@ SendSSDPResponse(int s, const struct sockaddr * addr, } addrlen = (addr->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in); - n = sendto(s, buf, l, 0, - addr, addrlen); + n = sendto_schedule(s, buf, l, 0, + addr, addrlen, delay); sockaddr_to_string(addr, addr_str, sizeof(addr_str)); syslog(LOG_INFO, "SSDP Announce %d bytes to %s ST: %.*s",n, addr_str, l, buf); if(n < 0) { - /* XXX handle EINTR, EAGAIN, EWOULDBLOCK */ syslog(LOG_ERR, "sendto(udp): %m"); } } @@ -488,7 +490,7 @@ SendSSDPNotify(int s, const struct sockaddr * dest, syslog(LOG_WARNING, "SendSSDPNotify(): truncated output"); l = sizeof(bufr) - 1; } - n = sendto(s, bufr, l, 0, dest, + n = sendto_or_schedule(s, bufr, l, 0, dest, #ifdef ENABLE_IPV6 ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in) #else @@ -497,7 +499,6 @@ SendSSDPNotify(int s, const struct sockaddr * dest, ); if(n < 0) { - /* XXX handle EINTR, EAGAIN, EWOULDBLOCK */ syslog(LOG_ERR, "sendto(udp_notify=%d, %s): %m", s, host ? host : "NULL"); } @@ -636,6 +637,16 @@ ProcessSSDPData(int s, const char *bufr, int n, #endif int mx_value = -1; #endif + unsigned int delay = 0; + /* UPnP Device Architecture v1.1. 1.3.3 Search response : + * Devices responding to a multicast M-SEARCH SHOULD wait a random period + * of time between 0 seconds and the number of seconds specified in the + * MX field value of the search request before responding, in order to + * avoid flooding the requesting control point with search responses + * from multiple devices. If the search request results in the need for + * a multiple part response from the device, those multiple part + * responses SHOULD be spread at random intervals through the time period + * from 0 to the number of seconds specified in the MX header field. */ /* get the string representation of the sender address */ sockaddr_to_string(sender, sender_str, sizeof(sender_str)); @@ -771,7 +782,8 @@ ProcessSSDPData(int s, const char *bufr, int n, SendSSDPResponse(s, sender, st, st_len, "", announced_host, port, - known_service_types[i].uuid); + known_service_types[i].uuid, + delay); break; } } @@ -790,15 +802,16 @@ ProcessSSDPData(int s, const char *bufr, int n, SendSSDPResponse(s, sender, known_service_types[i].s, l, ver_str, announced_host, port, - known_service_types[i].uuid); + known_service_types[i].uuid, + delay); } /* also answer for uuid */ SendSSDPResponse(s, sender, uuidvalue_igd, strlen(uuidvalue_igd), "", - announced_host, port, uuidvalue_igd); + announced_host, port, uuidvalue_igd, delay); SendSSDPResponse(s, sender, uuidvalue_wan, strlen(uuidvalue_wan), "", - announced_host, port, uuidvalue_wan); + announced_host, port, uuidvalue_wan, delay); SendSSDPResponse(s, sender, uuidvalue_wcd, strlen(uuidvalue_wcd), "", - announced_host, port, uuidvalue_wcd); + announced_host, port, uuidvalue_wcd, delay); } /* responds to request by UUID value */ l = (int)strlen(uuidvalue_igd); @@ -808,19 +821,22 @@ ProcessSSDPData(int s, const char *bufr, int n, { syslog(LOG_INFO, "ssdp:uuid (IGD) found"); SendSSDPResponse(s, sender, st, st_len, "", - announced_host, port, uuidvalue_igd); + announced_host, port, uuidvalue_igd, + delay); } else if(0 == memcmp(st, uuidvalue_wan, l)) { syslog(LOG_INFO, "ssdp:uuid (WAN) found"); SendSSDPResponse(s, sender, st, st_len, "", - announced_host, port, uuidvalue_wan); + announced_host, port, uuidvalue_wan, + delay); } else if(0 == memcmp(st, uuidvalue_wcd, l)) { syslog(LOG_INFO, "ssdp:uuid (WCD) found"); SendSSDPResponse(s, sender, st, st_len, "", - announced_host, port, uuidvalue_wcd); + announced_host, port, uuidvalue_wcd, + delay); } } } @@ -870,7 +886,7 @@ SendSSDPbyebye(int s, const struct sockaddr * dest, syslog(LOG_WARNING, "SendSSDPbyebye(): truncated output"); l = sizeof(bufr) - 1; } - n = sendto(s, bufr, l, 0, dest, + n = sendto_or_schedule(s, bufr, l, 0, dest, #ifdef ENABLE_IPV6 ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in) #else diff --git a/miniupnpd/natpmp.c b/miniupnpd/natpmp.c index 8a127a0..860c41b 100644 --- a/miniupnpd/natpmp.c +++ b/miniupnpd/natpmp.c @@ -1,6 +1,6 @@ /* $Id: natpmp.c,v 1.36 2014/02/01 17:17:35 nanard Exp $ */ /* MiniUPnP project - * (c) 2007-2013 Thomas Bernard + * (c) 2007-2014 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 */ @@ -23,6 +23,7 @@ #include "upnpredirect.h" #include "commonrdr.h" #include "upnputils.h" +#include "asyncsendto.h" #ifdef ENABLE_NATPMP @@ -324,7 +325,7 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, default: resp[3] = 5; /* Unsupported OPCODE */ } - n = sendto(s, resp, resplen, 0, + n = sendto_or_schedule(s, resp, resplen, 0, (struct sockaddr *)senderaddr, sizeof(*senderaddr)); if(n<0) { syslog(LOG_ERR, "sendto(natpmp): %m"); @@ -378,7 +379,7 @@ void SendNATPMPPublicAddressChangeNotification(int * sockets, int n_sockets) #endif /* Port to use in 2006 version of the NAT-PMP specification */ sockname.sin_port = htons(NATPMP_PORT); - n = sendto(sockets[j], notif, 12, 0, + n = sendto_or_schedule(sockets[j], notif, 12, 0, (struct sockaddr *)&sockname, sizeof(struct sockaddr_in)); if(n < 0) { @@ -388,7 +389,7 @@ void SendNATPMPPublicAddressChangeNotification(int * sockets, int n_sockets) } /* Port to use in 2008 version of the NAT-PMP specification */ sockname.sin_port = htons(NATPMP_NOTIF_PORT); - n = sendto(sockets[j], notif, 12, 0, + n = sendto_or_schedule(sockets[j], notif, 12, 0, (struct sockaddr *)&sockname, sizeof(struct sockaddr_in)); if(n < 0) { diff --git a/miniupnpd/pcpserver.c b/miniupnpd/pcpserver.c index 7354fb3..61a6208 100644 --- a/miniupnpd/pcpserver.c +++ b/miniupnpd/pcpserver.c @@ -58,6 +58,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "upnpredirect.h" #include "commonrdr.h" #include "getifaddr.h" +#include "asyncsendto.h" #include "pcp_msg_struct.h" #ifdef PCP_PEER @@ -1325,7 +1326,7 @@ int ProcessIncomingPCPPacket(int s, unsigned char *buff, int len, len = PCP_MIN_LEN; else len = (len + 3) & ~3; /* round up resp. length to multiple of 4 */ - len = sendto(s, buff, len, 0, + len = sendto_or_schedule(s, buff, len, 0, (struct sockaddr *)senderaddr, sizeof(struct sockaddr_in)); if( len < 0 ) { syslog(LOG_ERR, "sendto(pcpserver): %m"); From 02165b70dc64b2acbae7b85283c296fdfc5d0865 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Tue, 25 Feb 2014 11:16:34 +0100 Subject: [PATCH 058/104] minissdp.c: wait for a delay before answering M-SEARCH --- miniupnpd/genconfig.sh | 12 +++++++++-- miniupnpd/minissdp.c | 46 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/miniupnpd/genconfig.sh b/miniupnpd/genconfig.sh index 2bf59db..fdb81c5 100755 --- a/miniupnpd/genconfig.sh +++ b/miniupnpd/genconfig.sh @@ -2,7 +2,7 @@ # $Id: genconfig.sh,v 1.65 2013/12/13 14:07:08 nanard Exp $ # miniupnp daemon # http://miniupnp.free.fr or http://miniupnp.tuxfamily.org/ -# (c) 2006-2013 Thomas Bernard +# (c) 2006-2014 Thomas Bernard # This software is subject to the conditions detailed in the # LICENCE file provided within the distribution @@ -83,7 +83,7 @@ ${RM} ${CONFIGFILE} echo "/* MiniUPnP Project" >> ${CONFIGFILE} echo " * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/" >> ${CONFIGFILE} -echo " * (c) 2006-2013 Thomas Bernard" >> ${CONFIGFILE} +echo " * (c) 2006-2014 Thomas Bernard" >> ${CONFIGFILE} echo " * generated by $0 on `date`" >> ${CONFIGFILE} echo " * using command line options $* */" >> ${CONFIGFILE} echo "#ifndef $CONFIGMACRO" >> ${CONFIGFILE} @@ -465,6 +465,14 @@ else fi echo "" >> ${CONFIGFILE} +echo "/* Wait a little before answering M-SEARCH request */" >> ${CONFIGFILE} +if [ -n "$STRICT" ] ; then + echo "#define DELAY_MSEARCH_RESPONSE" >> ${CONFIGFILE} +else + echo "/*#define DELAY_MSEARCH_RESPONSE*/" >> ${CONFIGFILE} +fi +echo "" >> ${CONFIGFILE} + echo "/* disable reading and parsing of config file (miniupnpd.conf) */" >> ${CONFIGFILE} echo "/*#define DISABLE_CONFIG_FILE*/" >> ${CONFIGFILE} echo "" >> ${CONFIGFILE} diff --git a/miniupnpd/minissdp.c b/miniupnpd/minissdp.c index c6b70f2..dc050e0 100644 --- a/miniupnpd/minissdp.c +++ b/miniupnpd/minissdp.c @@ -635,6 +635,8 @@ ProcessSSDPData(int s, const char *bufr, int n, #ifdef ENABLE_IPV6 char announced_host_buf[64]; #endif +#endif +#if defined(UPNP_STRICT) || defined(DELAY_MSEARCH_RESPONSE) int mx_value = -1; #endif unsigned int delay = 0; @@ -689,7 +691,7 @@ ProcessSSDPData(int s, const char *bufr, int n, /*while(bufr[i+j]!='\r') j++;*/ /*syslog(LOG_INFO, "%.*s", j, bufr+i);*/ } -#ifdef UPNP_STRICT +#if defined(UPNP_STRICT) || defined(DELAY_MSEARCH_RESPONSE) else if((i < n - 3) && (strncasecmp(bufr+i, "mx:", 3) == 0)) { const char * mx; @@ -707,16 +709,32 @@ ProcessSSDPData(int s, const char *bufr, int n, #endif } #ifdef UPNP_STRICT + /* For multicast M-SEARCH requests, if the search request does + * not contain an MX header field, the device MUST silently + * discard and ignore the search request. */ if(mx_value < 0) { syslog(LOG_INFO, "ignoring SSDP packet missing MX: header"); return; + } else if(mx_value > 5) { + /* If the MX header field specifies a field value greater + * than 5, the device SHOULD assume that it contained the + * value 5 or less. */ + mx_value = 5; + } +#elif defined(DELAY_MSEARCH_RESPONSE) + if(mx_value < 0) { + mx_value = 1; + } else if(mx_value > 5) { + /* If the MX header field specifies a field value greater + * than 5, the device SHOULD assume that it contained the + * value 5 or less. */ + mx_value = 5; } #endif /*syslog(LOG_INFO, "SSDP M-SEARCH packet received from %s", sender_str );*/ if(st && (st_len > 0)) { - /* TODO : doesnt answer at once but wait for a random time */ syslog(LOG_INFO, "SSDP M-SEARCH from %s ST: %.*s", sender_str, st_len, st); /* find in which sub network the client is */ @@ -779,6 +797,12 @@ ProcessSSDPData(int s, const char *bufr, int n, ) { syslog(LOG_INFO, "Single search found"); +#ifdef DELAY_MSEARCH_RESPONSE + delay = random() / (1 + RAND_MAX / (1000 * mx_value)); +#ifdef DEBUG + syslog(LOG_DEBUG, "mx=%dsec delay=%ums", mx_value, delay); +#endif +#endif SendSSDPResponse(s, sender, st, st_len, "", announced_host, port, @@ -791,9 +815,15 @@ ProcessSSDPData(int s, const char *bufr, int n, /* strlen("ssdp:all") == 8 */ if(st_len==8 && (0 == memcmp(st, "ssdp:all", 8))) { +#ifdef DELAY_MSEARCH_RESPONSE + unsigned int delay_increment = (mx_value * 1000) / 15; +#endif syslog(LOG_INFO, "ssdp:all found"); for(i=0; known_service_types[i].s; i++) { +#ifdef DELAY_MSEARCH_RESPONSE + delay += delay_increment; +#endif if(i==0) ver_str[0] = '\0'; else @@ -806,10 +836,19 @@ ProcessSSDPData(int s, const char *bufr, int n, delay); } /* also answer for uuid */ +#ifdef DELAY_MSEARCH_RESPONSE + delay += delay_increment; +#endif SendSSDPResponse(s, sender, uuidvalue_igd, strlen(uuidvalue_igd), "", announced_host, port, uuidvalue_igd, delay); +#ifdef DELAY_MSEARCH_RESPONSE + delay += delay_increment; +#endif SendSSDPResponse(s, sender, uuidvalue_wan, strlen(uuidvalue_wan), "", announced_host, port, uuidvalue_wan, delay); +#ifdef DELAY_MSEARCH_RESPONSE + delay += delay_increment; +#endif SendSSDPResponse(s, sender, uuidvalue_wcd, strlen(uuidvalue_wcd), "", announced_host, port, uuidvalue_wcd, delay); } @@ -817,6 +856,9 @@ ProcessSSDPData(int s, const char *bufr, int n, l = (int)strlen(uuidvalue_igd); if(l==st_len) { +#ifdef DELAY_MSEARCH_RESPONSE + delay = random() / (1 + RAND_MAX / (1000 * mx_value)); +#endif if(0 == memcmp(st, uuidvalue_igd, l)) { syslog(LOG_INFO, "ssdp:uuid (IGD) found"); From a06c695fe3dd822d3e1af17326b6c15d6af9c6aa Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Tue, 25 Feb 2014 11:36:58 +0100 Subject: [PATCH 059/104] miniupnpd/asyncsendto: finalize_sendto() --- miniupnpd/asyncsendto.c | 22 ++++++++++++++++++++++ miniupnpd/asyncsendto.h | 3 +++ miniupnpd/miniupnpd.c | 24 ++++++++++++++++-------- 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/miniupnpd/asyncsendto.c b/miniupnpd/asyncsendto.c index faae87e..5cd2a3d 100644 --- a/miniupnpd/asyncsendto.c +++ b/miniupnpd/asyncsendto.c @@ -195,3 +195,25 @@ int try_sendto(fd_set * writefds) return 0; } +/* empty the list */ +void finalize_sendto(void) +{ + ssize_t n; + struct scheduled_send * elt; + struct scheduled_send * next; + /* TODO : improve with a select() and a short timeout */ + for(elt = send_list.lh_first; elt != NULL; elt = next) { + next = elt->entries.le_next; + syslog(LOG_DEBUG, "finalize_sendto(): %d bytes on socket %d", + (int)elt->len, elt->sockfd); + n = sendto(elt->sockfd, elt->buf, elt->len, elt->flags, + elt->dest_addr, elt->addrlen); + if(n < 0) { + syslog(LOG_WARNING, "sendto(): %m"); + } + /* remove from the list */ + LIST_REMOVE(elt, entries); + free(elt); + } +} + diff --git a/miniupnpd/asyncsendto.h b/miniupnpd/asyncsendto.h index 6afb322..60c04de 100644 --- a/miniupnpd/asyncsendto.h +++ b/miniupnpd/asyncsendto.h @@ -32,4 +32,7 @@ int try_sendto(fd_set * writefds); /* set writefds before select() */ int get_sendto_fds(fd_set * writefds, int * max_fd, const struct timeval * now); +/* empty the list */ +void finalize_sendto(void); + #endif diff --git a/miniupnpd/miniupnpd.c b/miniupnpd/miniupnpd.c index 9219e47..10667a7 100644 --- a/miniupnpd/miniupnpd.c +++ b/miniupnpd/miniupnpd.c @@ -2026,6 +2026,21 @@ main(int argc, char * * argv) } /* end of main loop */ shutdown: + /* send good-bye */ + if (GETFLAG(ENABLEUPNPMASK)) + { +#ifndef ENABLE_IPV6 + if(SendSSDPGoodbye(snotify, addr_count) < 0) +#else + if(SendSSDPGoodbye(snotify, addr_count * 2) < 0) +#endif + { + syslog(LOG_ERR, "Failed to broadcast good-bye notifications"); + } + } + /* try to send pending packets */ + finalize_sendto(); + /* close out open sockets */ while(upnphttphead.lh_first != NULL) { @@ -2065,14 +2080,6 @@ shutdown: if (GETFLAG(ENABLEUPNPMASK)) { -#ifndef ENABLE_IPV6 - if(SendSSDPGoodbye(snotify, addr_count) < 0) -#else - if(SendSSDPGoodbye(snotify, addr_count * 2) < 0) -#endif - { - syslog(LOG_ERR, "Failed to broadcast good-bye notifications"); - } #ifndef ENABLE_IPV6 for(i = 0; i < addr_count; i++) #else @@ -2081,6 +2088,7 @@ shutdown: close(snotify[i]); } + /* remove pidfile */ if(pidfilename && (unlink(pidfilename) < 0)) { syslog(LOG_ERR, "Failed to remove pidfile %s: %m", pidfilename); From 9832adc45613d0b079ac8a09e49755ec01991736 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Tue, 25 Feb 2014 11:37:36 +0100 Subject: [PATCH 060/104] miniupnpd/minissdp.c: send ssdp:alive packets more than once fixes #35 --- miniupnpd/minissdp.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/miniupnpd/minissdp.c b/miniupnpd/minissdp.c index dc050e0..967c092 100644 --- a/miniupnpd/minissdp.c +++ b/miniupnpd/minissdp.c @@ -506,6 +506,22 @@ SendSSDPNotify(int s, const struct sockaddr * dest, { syslog(LOG_NOTICE, "sendto() sent %d out of %d bytes", n, l); } + /* Due to the unreliable nature of UDP, devices SHOULD send the entire + * set of discovery messages more than once with some delay between + * sets e.g. a few hundred milliseconds. To avoid network congestion + * discovery messages SHOULD NOT be sent more than three times. */ + n = sendto_schedule(s, bufr, l, 0, dest, +#ifdef ENABLE_IPV6 + ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in), +#else + sizeof(struct sockaddr_in), +#endif + 250); + if(n < 0) + { + syslog(LOG_ERR, "sendto(udp_notify=%d, %s): %m", s, + host ? host : "NULL"); + } } static void From ec1686f29f1a8facb00f06f60feb8e7b9a458162 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Tue, 25 Feb 2014 11:45:51 +0100 Subject: [PATCH 061/104] miniupnpd/minissdp: Introduce SSDP_RESPOND_SAME_VERSION changes something when compiled as IGDv2. --- miniupnpd/Changelog.txt | 5 ++++- miniupnpd/genconfig.sh | 8 +++++++- miniupnpd/minissdp.c | 27 ++++++++++++++++++++++++++- 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/miniupnpd/Changelog.txt b/miniupnpd/Changelog.txt index 2835f5b..36594c2 100644 --- a/miniupnpd/Changelog.txt +++ b/miniupnpd/Changelog.txt @@ -1,4 +1,7 @@ -$Id: Changelog.txt,v 1.351 2014/02/11 09:35:52 nanard Exp $ +$Id: Changelog.txt,v 1.352 2014/02/24 18:41:23 nanard Exp $ + +2014/02/24: + Defaulting to SSDP_RESPOND_SAME_VERSION 2014/02/11: Fix PCP Map renewal diff --git a/miniupnpd/genconfig.sh b/miniupnpd/genconfig.sh index 2bf59db..1a4e785 100755 --- a/miniupnpd/genconfig.sh +++ b/miniupnpd/genconfig.sh @@ -1,5 +1,5 @@ #! /bin/sh -# $Id: genconfig.sh,v 1.65 2013/12/13 14:07:08 nanard Exp $ +# $Id: genconfig.sh,v 1.69 2014/02/24 18:41:25 nanard Exp $ # miniupnp daemon # http://miniupnp.free.fr or http://miniupnp.tuxfamily.org/ # (c) 2006-2013 Thomas Bernard @@ -457,6 +457,12 @@ else fi echo "" >> ${CONFIGFILE} +echo "/* If SSDP_RESPOND_SAME_VERSION is defined, the M-SEARCH response" >> ${CONFIGFILE} +echo " * include the same device version as was contained in the search" >> ${CONFIGFILE} +echo " * request. It conforms to UPnP DA v1.1 */" >> ${CONFIGFILE} +echo "#define SSDP_RESPOND_SAME_VERSION" >> ${CONFIGFILE} +echo "" >> ${CONFIGFILE} + echo "/* Add the optional Date: header in all HTTP responses */" >> ${CONFIGFILE} if [ -n "$STRICT" ] ; then echo "#define ENABLE_HTTP_DATE" >> ${CONFIGFILE} diff --git a/miniupnpd/minissdp.c b/miniupnpd/minissdp.c index fb5a9b8..31110dc 100644 --- a/miniupnpd/minissdp.c +++ b/miniupnpd/minissdp.c @@ -1,4 +1,4 @@ -/* $Id: minissdp.c,v 1.57 2014/02/06 09:52:03 nanard Exp $ */ +/* $Id: minissdp.c,v 1.58 2014/02/24 18:41:24 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2014 Thomas Bernard @@ -767,9 +767,34 @@ ProcessSSDPData(int s, const char *bufr, int n, #endif ) { + /* SSDP_RESPOND_SAME_VERSION : + * response is urn:schemas-upnp-org:service:WANIPConnection:1 when + * M-SEARCH included urn:schemas-upnp-org:service:WANIPConnection:1 + * else the implemented versions is included in the response + * + * From UPnP Device Architecture v1.1 : + * 1.3.2 [...] Updated versions of device and service types + * are REQUIRED to be fully backward compatible with + * previous versions. Devices MUST respond to M-SEARCH + * requests for any supported version. For example, if a + * device implements “urn:schemas-upnporg:service:xyz:2”, + * it MUST respond to search requests for both that type + * and “urn:schemas-upnp-org:service:xyz:1”. The response + * MUST specify the same version as was contained in the + * search request. [...] */ +#ifndef SSDP_RESPOND_SAME_VERSION + if(i==0) + ver_str[0] = '\0'; + else + snprintf(ver_str, sizeof(ver_str), "%d", known_service_types[i].version); +#endif syslog(LOG_INFO, "Single search found"); SendSSDPResponse(s, sender, +#ifdef SSDP_RESPOND_SAME_VERSION st, st_len, "", +#else + known_service_types[i].s, l, ver_str, +#endif announced_host, port, known_service_types[i].uuid); break; From c492b6f56f846b511276a80d62f08c8192fdf56e Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Wed, 26 Feb 2014 02:02:34 +0100 Subject: [PATCH 062/104] minissdp.c: try again write after EINTR in SubmitServicesToMiniSSDPD() --- miniupnpd/minissdp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/miniupnpd/minissdp.c b/miniupnpd/minissdp.c index dcee00c..9f5fc72 100644 --- a/miniupnpd/minissdp.c +++ b/miniupnpd/minissdp.c @@ -1126,6 +1126,8 @@ SubmitServicesToMiniSSDPD(const char * host, unsigned short port) { while(n > 0) { l = write(s, p, n); if (l < 0) { + if(errno == EINTR) + continue; syslog(LOG_ERR, "write(): %m"); close(s); return -1; From 1efb4cc03c167abc40a3a1bd77e06561ab61f555 Mon Sep 17 00:00:00 2001 From: hashiz Date: Fri, 28 Feb 2014 11:28:07 +0900 Subject: [PATCH 063/104] * fix incorrect filter port in pf redirect. --- miniupnpd/pf/obsdrdr.c | 10 +++++----- miniupnpd/upnpredirect.c | 16 +++++++++++++++- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/miniupnpd/pf/obsdrdr.c b/miniupnpd/pf/obsdrdr.c index 04c2ddb..663cea3 100644 --- a/miniupnpd/pf/obsdrdr.c +++ b/miniupnpd/pf/obsdrdr.c @@ -374,7 +374,7 @@ add_filter_rule2(const char * ifname, #endif pcr.rule.dst.port_op = PF_OP_EQ; - pcr.rule.dst.port[0] = htons(eport); + pcr.rule.dst.port[0] = htons(iport); pcr.rule.direction = PF_IN; pcr.rule.action = PF_PASS; pcr.rule.af = AF_INET; @@ -408,7 +408,7 @@ add_filter_rule2(const char * ifname, pcr.rule.src.addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE); } #ifndef PF_NEWSTYLE - pcr.rule.rpool.proxy_port[0] = eport; + pcr.rule.rpool.proxy_port[0] = iport; a = calloc(1, sizeof(struct pf_pooladdr)); inet_pton(AF_INET, iaddr, &a->addr.v.a.addr.v4.s_addr); a->addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE); @@ -636,10 +636,10 @@ error: } int -delete_filter_rule(const char * ifname, unsigned short eport, int proto) +delete_filter_rule(const char * ifname, unsigned short iport, int proto) { #ifndef PF_ENABLE_FILTER_RULES - UNUSED(ifname); UNUSED(eport); UNUSED(proto); + UNUSED(ifname); UNUSED(iport); UNUSED(proto); return 0; #else int i, n; @@ -665,7 +665,7 @@ delete_filter_rule(const char * ifname, unsigned short eport, int proto) syslog(LOG_ERR, "ioctl(dev, DIOCGETRULE): %m"); goto error; } - if( (eport == ntohs(pr.rule.dst.port[0])) + if( (iport == ntohs(pr.rule.dst.port[0])) && (pr.rule.proto == proto) ) { pr.action = PF_CHANGE_GET_TICKET; diff --git a/miniupnpd/upnpredirect.c b/miniupnpd/upnpredirect.c index 7b398ec..1e03b93 100644 --- a/miniupnpd/upnpredirect.c +++ b/miniupnpd/upnpredirect.c @@ -420,8 +420,22 @@ _upnp_delete_redir(unsigned short eport, int proto) #if defined(__linux__) r = delete_redirect_and_filter_rules(eport, proto); #else + char iaddr[INET6_ADDRSTRLEN]; + unsigned short iport; + char desc[64]; + char rhost[64]; + unsigned int timestamp; + u_int64_t packets; + u_int64_t bytes; + int r2 = get_redirect_rule(ext_if_name, eport, proto, + &iaddr, sizeof(iaddr), &iport, + &desc, sizeof(desc), + &rhost, sizeof(rhost), + ×tamp, + &packets, &bytes); r = delete_redirect_rule(ext_if_name, eport, proto); - delete_filter_rule(ext_if_name, eport, proto); + if (r2==0) + delete_filter_rule(ext_if_name, iport, proto); #endif #ifdef ENABLE_LEASEFILE lease_file_remove( eport, proto); From c6a8879c8717aec43774913cc355054f383b4c97 Mon Sep 17 00:00:00 2001 From: Daniel Becker Date: Fri, 28 Feb 2014 00:00:26 -0800 Subject: [PATCH 064/104] miniupnpd/natpmp.c: avoid hang when all external ports in use The NAT-PMP code attempts to find a different eport if the requested one is already in use. If all eports are in use, that would previously cause the code to iterate through the range of eports forever. To avoid this case, we keep track of the first eport we attempted to use and abort the loop once we've cycled through all possible values exactly once (which takes us back to the initial eport). --- miniupnpd/natpmp.c | 94 +++++++++++++++++++++++++--------------------- 1 file changed, 52 insertions(+), 42 deletions(-) diff --git a/miniupnpd/natpmp.c b/miniupnpd/natpmp.c index 860c41b..6764732 100644 --- a/miniupnpd/natpmp.c +++ b/miniupnpd/natpmp.c @@ -205,6 +205,7 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, int proto; char iaddr_old[16]; unsigned short iport_old; + unsigned short eport_first; unsigned int timestamp; iport = ntohs(*((uint16_t *)(req+4))); @@ -266,56 +267,65 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, } else if(iport==0 || !check_upnp_rule_against_permissions(upnppermlist, num_upnpperm, eport, senderaddr->sin_addr, iport)) { resp[3] = 2; /* Not Authorized/Refused */ - } else do { - r = get_redirect_rule(ext_if_name, eport, proto, - iaddr_old, sizeof(iaddr_old), - &iport_old, 0, 0, 0, 0, - ×tamp, 0, 0); - if(r==0) { - if(strcmp(senderaddrstr, iaddr_old)==0 - && iport==iport_old) { - /* redirection allready existing */ - syslog(LOG_INFO, "port %hu %s already redirected to %s:%hu, replacing", - eport, (proto==IPPROTO_TCP)?"tcp":"udp", iaddr_old, iport_old); - /* remove and then add again */ - if(_upnp_delete_redir(eport, proto) < 0) { - syslog(LOG_ERR, "failed to remove port mapping"); - break; + } else { + eport_first = eport; + do { + r = get_redirect_rule(ext_if_name, eport, proto, + iaddr_old, sizeof(iaddr_old), + &iport_old, 0, 0, 0, 0, + ×tamp, 0, 0); + if(r==0) { + if(strcmp(senderaddrstr, iaddr_old)==0 + && iport==iport_old) { + /* redirection allready existing */ + syslog(LOG_INFO, "port %hu %s already redirected to %s:%hu, replacing", + eport, (proto==IPPROTO_TCP)?"tcp":"udp", iaddr_old, iport_old); + /* remove and then add again */ + if(_upnp_delete_redir(eport, proto) < 0) { + syslog(LOG_ERR, "failed to remove port mapping"); + break; + } + } else { + eport++; + if(eport == eport_first) { /* no external port available */ + syslog(LOG_ERR, "Failed to find available eport for NAT-PMP %hu %s->%s:%hu", + eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport); + resp[3] = 3; /* Failure */ + break; + } + continue; } - } else { - eport++; - continue; } - } - { /* do the redirection */ - char desc[64]; + { /* do the redirection */ + char desc[64]; #if 0 - timestamp = (unsigned)(time(NULL) - startup_time) - + lifetime; - snprintf(desc, sizeof(desc), "NAT-PMP %u", timestamp); + timestamp = (unsigned)(time(NULL) - startup_time) + + lifetime; + snprintf(desc, sizeof(desc), "NAT-PMP %u", timestamp); #else - timestamp = time(NULL) + lifetime; - snprintf(desc, sizeof(desc), "NAT-PMP %hu %s", - eport, (proto==IPPROTO_TCP)?"tcp":"udp"); + timestamp = time(NULL) + lifetime; + snprintf(desc, sizeof(desc), "NAT-PMP %hu %s", + eport, (proto==IPPROTO_TCP)?"tcp":"udp"); #endif - /* TODO : check return code */ - if(upnp_redirect_internal(NULL, eport, senderaddrstr, - iport, proto, desc, - timestamp) < 0) { - syslog(LOG_ERR, "Failed to add NAT-PMP %hu %s->%s:%hu '%s'", - eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport, desc); - resp[3] = 3; /* Failure */ + /* TODO : check return code */ + if(upnp_redirect_internal(NULL, eport, senderaddrstr, + iport, proto, desc, + timestamp) < 0) { + syslog(LOG_ERR, "Failed to add NAT-PMP %hu %s->%s:%hu '%s'", + eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport, desc); + resp[3] = 3; /* Failure */ #if 0 - } else if( !nextnatpmptoclean_eport - || timestamp < nextnatpmptoclean_timestamp) { - nextnatpmptoclean_timestamp = timestamp; - nextnatpmptoclean_eport = eport; - nextnatpmptoclean_proto = proto; + } else if( !nextnatpmptoclean_eport + || timestamp < nextnatpmptoclean_timestamp) { + nextnatpmptoclean_timestamp = timestamp; + nextnatpmptoclean_eport = eport; + nextnatpmptoclean_proto = proto; #endif + } + break; } - break; - } - } while(r==0); + } while(r==0); + } *((uint16_t *)(resp+8)) = htons(iport); /* private port */ *((uint16_t *)(resp+10)) = htons(eport); /* public port */ *((uint32_t *)(resp+12)) = htonl(lifetime); /* Port Mapping lifetime */ From 6dff4263bd9f1ca023da29fd4d3320c55b30fc70 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Fri, 28 Feb 2014 13:16:06 +0100 Subject: [PATCH 065/104] miniupnpd/Changelog.txt catch up... --- miniupnpd/Changelog.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/miniupnpd/Changelog.txt b/miniupnpd/Changelog.txt index 36594c2..7aeb0a9 100644 --- a/miniupnpd/Changelog.txt +++ b/miniupnpd/Changelog.txt @@ -1,4 +1,8 @@ -$Id: Changelog.txt,v 1.352 2014/02/24 18:41:23 nanard Exp $ +$Id: Changelog.txt,v 1.354 2014/02/28 12:14:29 nanard Exp $ + +2014/02/25: + add implementation of scheduled sendto (asyncsendto) in order + to retry failed sendto() calls or schedule sending of packets 2014/02/24: Defaulting to SSDP_RESPOND_SAME_VERSION From 8fc7f0b5e13aa71e5a213dc0785b9a975e5859aa Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Fri, 28 Feb 2014 13:16:22 +0100 Subject: [PATCH 066/104] miniupnpd: log message when shutting down --- miniupnpd/Changelog.txt | 3 +++ miniupnpd/miniupnpd.c | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/miniupnpd/Changelog.txt b/miniupnpd/Changelog.txt index 7aeb0a9..e47f2fb 100644 --- a/miniupnpd/Changelog.txt +++ b/miniupnpd/Changelog.txt @@ -1,5 +1,8 @@ $Id: Changelog.txt,v 1.354 2014/02/28 12:14:29 nanard Exp $ +2014/02/28: + log message when shutting down + 2014/02/25: add implementation of scheduled sendto (asyncsendto) in order to retry failed sendto() calls or schedule sending of packets diff --git a/miniupnpd/miniupnpd.c b/miniupnpd/miniupnpd.c index 10667a7..b215b6c 100644 --- a/miniupnpd/miniupnpd.c +++ b/miniupnpd/miniupnpd.c @@ -1,4 +1,4 @@ -/* $Id: miniupnpd.c,v 1.183 2014/02/06 09:52:01 nanard Exp $ */ +/* $Id: miniupnpd.c,v 1.185 2014/02/28 12:14:26 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2014 Thomas Bernard @@ -2026,6 +2026,7 @@ main(int argc, char * * argv) } /* end of main loop */ shutdown: + syslog(LOG_NOTICE, "shutting down MiniUPnPd"); /* send good-bye */ if (GETFLAG(ENABLEUPNPMASK)) { From 3c90f6a30d83e1803f34497136003bc3c0b3787e Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Fri, 28 Feb 2014 13:34:46 +0100 Subject: [PATCH 067/104] miniupnpd/natpmp.c: avoid hang when all external ports in use reorganize a bit --- miniupnpd/Changelog.txt | 3 +++ miniupnpd/natpmp.c | 55 ++++++++++++++++++++--------------------- 2 files changed, 30 insertions(+), 28 deletions(-) diff --git a/miniupnpd/Changelog.txt b/miniupnpd/Changelog.txt index 36594c2..c6b04ea 100644 --- a/miniupnpd/Changelog.txt +++ b/miniupnpd/Changelog.txt @@ -1,5 +1,8 @@ $Id: Changelog.txt,v 1.352 2014/02/24 18:41:23 nanard Exp $ +2014/02/28: + natpmp : avoid hang when all external ports in use + 2014/02/24: Defaulting to SSDP_RESPOND_SAME_VERSION diff --git a/miniupnpd/natpmp.c b/miniupnpd/natpmp.c index 6764732..c3d26ce 100644 --- a/miniupnpd/natpmp.c +++ b/miniupnpd/natpmp.c @@ -205,7 +205,6 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, int proto; char iaddr_old[16]; unsigned short iport_old; - unsigned short eport_first; unsigned int timestamp; iport = ntohs(*((uint16_t *)(req+4))); @@ -268,12 +267,14 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, || !check_upnp_rule_against_permissions(upnppermlist, num_upnpperm, eport, senderaddr->sin_addr, iport)) { resp[3] = 2; /* Not Authorized/Refused */ } else { + unsigned short eport_first; + char desc[64]; eport_first = eport; do { r = get_redirect_rule(ext_if_name, eport, proto, - iaddr_old, sizeof(iaddr_old), - &iport_old, 0, 0, 0, 0, - ×tamp, 0, 0); + iaddr_old, sizeof(iaddr_old), + &iport_old, 0, 0, 0, 0, + ×tamp, 0, 0); if(r==0) { if(strcmp(senderaddrstr, iaddr_old)==0 && iport==iport_old) { @@ -288,42 +289,40 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, } else { eport++; if(eport == eport_first) { /* no external port available */ - syslog(LOG_ERR, "Failed to find available eport for NAT-PMP %hu %s->%s:%hu", - eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport); + syslog(LOG_ERR, "Failed to find available eport for NAT-PMP %hu %s->%s:%hu", + eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport); resp[3] = 3; /* Failure */ break; } continue; } } - { /* do the redirection */ - char desc[64]; + /* do the redirection */ #if 0 - timestamp = (unsigned)(time(NULL) - startup_time) - + lifetime; - snprintf(desc, sizeof(desc), "NAT-PMP %u", timestamp); + timestamp = (unsigned)(time(NULL) - startup_time) + + lifetime; + snprintf(desc, sizeof(desc), "NAT-PMP %u", timestamp); #else - timestamp = time(NULL) + lifetime; - snprintf(desc, sizeof(desc), "NAT-PMP %hu %s", - eport, (proto==IPPROTO_TCP)?"tcp":"udp"); + timestamp = time(NULL) + lifetime; + snprintf(desc, sizeof(desc), "NAT-PMP %hu %s", + eport, (proto==IPPROTO_TCP)?"tcp":"udp"); #endif - /* TODO : check return code */ - if(upnp_redirect_internal(NULL, eport, senderaddrstr, - iport, proto, desc, - timestamp) < 0) { - syslog(LOG_ERR, "Failed to add NAT-PMP %hu %s->%s:%hu '%s'", - eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport, desc); - resp[3] = 3; /* Failure */ + /* TODO : check return code */ + if(upnp_redirect_internal(NULL, eport, senderaddrstr, + iport, proto, desc, + timestamp) < 0) { + syslog(LOG_ERR, "Failed to add NAT-PMP %hu %s->%s:%hu '%s'", + eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport, desc); + resp[3] = 3; /* Failure */ #if 0 - } else if( !nextnatpmptoclean_eport - || timestamp < nextnatpmptoclean_timestamp) { - nextnatpmptoclean_timestamp = timestamp; - nextnatpmptoclean_eport = eport; - nextnatpmptoclean_proto = proto; + } else if( !nextnatpmptoclean_eport + || timestamp < nextnatpmptoclean_timestamp) { + nextnatpmptoclean_timestamp = timestamp; + nextnatpmptoclean_eport = eport; + nextnatpmptoclean_proto = proto; #endif - } - break; } + break; } while(r==0); } *((uint16_t *)(resp+8)) = htons(iport); /* private port */ From dbdad6a79b1cb3105fd3dc3f3735e39e3fee9f49 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Fri, 28 Feb 2014 16:39:59 +0100 Subject: [PATCH 068/104] miniupnpd: improve finalize_sendto() --- miniupnpd/asyncsendto.c | 78 ++++++++++++++++++++++++++++++++++------- 1 file changed, 66 insertions(+), 12 deletions(-) diff --git a/miniupnpd/asyncsendto.c b/miniupnpd/asyncsendto.c index 5cd2a3d..8c83e25 100644 --- a/miniupnpd/asyncsendto.c +++ b/miniupnpd/asyncsendto.c @@ -195,25 +195,79 @@ int try_sendto(fd_set * writefds) return 0; } +/* maximum execution time for finalize_sendto() in milliseconds */ +#define FINALIZE_SENDTO_DELAY (500) + /* empty the list */ void finalize_sendto(void) { ssize_t n; struct scheduled_send * elt; struct scheduled_send * next; - /* TODO : improve with a select() and a short timeout */ - for(elt = send_list.lh_first; elt != NULL; elt = next) { - next = elt->entries.le_next; - syslog(LOG_DEBUG, "finalize_sendto(): %d bytes on socket %d", - (int)elt->len, elt->sockfd); - n = sendto(elt->sockfd, elt->buf, elt->len, elt->flags, - elt->dest_addr, elt->addrlen); - if(n < 0) { - syslog(LOG_WARNING, "sendto(): %m"); + fd_set writefds; + struct timeval deadline; + struct timeval now; + struct timeval timeout; + int max_fd; + + if(gettimeofday(&deadline, NULL) < 0) { + syslog(LOG_ERR, "gettimeofday: %m"); + return; + } + deadline.tv_usec += FINALIZE_SENDTO_DELAY*1000; + if(deadline.tv_usec > 1000000) { + deadline.tv_sec++; + deadline.tv_usec -= 1000000; + } + while(send_list.lh_first) { + FD_ZERO(&writefds); + max_fd = -1; + for(elt = send_list.lh_first; elt != NULL; elt = next) { + next = elt->entries.le_next; + syslog(LOG_DEBUG, "finalize_sendto(): %d bytes on socket %d", + (int)elt->len, elt->sockfd); + n = sendto(elt->sockfd, elt->buf, elt->len, elt->flags, + elt->dest_addr, elt->addrlen); + if(n < 0) { + if(errno==EAGAIN || errno==EWOULDBLOCK) { + FD_SET(elt->sockfd, &writefds); + if(elt->sockfd > max_fd) + max_fd = elt->sockfd; + continue; + } + syslog(LOG_WARNING, "finalize_sendto(): socket=%d sendto: %m", elt->sockfd); + } + /* remove from the list */ + LIST_REMOVE(elt, entries); + free(elt); + } + /* check deadline */ + if(gettimeofday(&now, NULL) < 0) { + syslog(LOG_ERR, "gettimeofday: %m"); + return; + } + if(now.tv_sec > deadline.tv_sec || + (now.tv_sec == deadline.tv_sec && now.tv_usec > deadline.tv_usec)) { + /* deadline ! */ + while((elt = send_list.lh_first) != NULL) { + LIST_REMOVE(elt, entries); + free(elt); + } + return; + } + /* compute timeout value */ + timeout.tv_sec = deadline.tv_sec - now.tv_sec; + timeout.tv_usec = deadline.tv_usec - now.tv_usec; + if(timeout.tv_usec < 0) { + timeout.tv_sec--; + timeout.tv_usec += 1000000; + } + if(max_fd >= 0) { + if(select(max_fd + 1, NULL, &writefds, NULL, &timeout) < 0) { + syslog(LOG_ERR, "select: %m"); + return; + } } - /* remove from the list */ - LIST_REMOVE(elt, entries); - free(elt); } } From 802ad22f4d45512c1db6d024d674ed5aa1bad75c Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Fri, 28 Feb 2014 16:40:20 +0100 Subject: [PATCH 069/104] miniupnpd: minor stuff (remove warning, add debug log) --- miniupnpd/testasyncsendto.c | 4 ++-- miniupnpd/upnpsoap.c | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/miniupnpd/testasyncsendto.c b/miniupnpd/testasyncsendto.c index 7a4eb6e..e413bd7 100644 --- a/miniupnpd/testasyncsendto.c +++ b/miniupnpd/testasyncsendto.c @@ -1,4 +1,4 @@ -/* $Id: $ */ +/* $Id: testasyncsendto.c,v 1.2 2014/02/25 11:00:14 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2014 Thomas Bernard @@ -46,7 +46,7 @@ int test(void) memset(&addr, 0, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; - if(bind(s, &addr, sizeof(addr)) < 0) { + if(bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { syslog(LOG_ERR, "bind(): %m"); close(s); return 1; diff --git a/miniupnpd/upnpsoap.c b/miniupnpd/upnpsoap.c index a8023c0..fc08ecb 100644 --- a/miniupnpd/upnpsoap.c +++ b/miniupnpd/upnpsoap.c @@ -1,4 +1,4 @@ -/* $Id: upnpsoap.c,v 1.119 2013/08/19 16:16:00 nanard Exp $ */ +/* $Id: upnpsoap.c,v 1.121 2014/02/28 15:01:31 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2013 Thomas Bernard @@ -1910,6 +1910,10 @@ ExecuteSoapAction(struct upnphttp * h, const char * action, int n) len = strlen(soapMethods[i].methodName); if(strncmp(p, soapMethods[i].methodName, len) == 0) { +#ifdef DEBUG + syslog(LOG_DEBUG, "Remote Call of SoapMethod '%s'\n", + soapMethods[i].methodName); +#endif soapMethods[i].methodImpl(h, soapMethods[i].methodName); return; } From 56aca98164690743b475bfe0ff1e3dce3b74ffde Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Fri, 28 Feb 2014 20:20:51 +0100 Subject: [PATCH 070/104] miniupnpd/pf: catch up test programs --- miniupnpd/pf/testobsdrdr.c | 13 +++++++------ miniupnpd/pf/testpfpinhole.c | 16 +++++++++------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/miniupnpd/pf/testobsdrdr.c b/miniupnpd/pf/testobsdrdr.c index 7d288c6..3ce3c85 100644 --- a/miniupnpd/pf/testobsdrdr.c +++ b/miniupnpd/pf/testobsdrdr.c @@ -1,7 +1,7 @@ -/* $Id: testobsdrdr.c,v 1.24 2012/04/18 19:42:03 nanard Exp $ */ +/* $Id: testobsdrdr.c,v 1.26 2014/02/28 18:03:31 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2012 Thomas Bernard + * (c) 2006-2014 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -17,6 +17,7 @@ int runtime_flags = 0; const char * tag = 0; const char * anchor_name = "miniupnpd"; +const char * queue = NULL; void list_rules(void); @@ -90,10 +91,10 @@ main(int arc, char * * argv) #endif add_redirect_rule2("ep0", "8.8.8.8", 12123, "192.168.1.125", 1234, IPPROTO_UDP, "test description", 0); -#if 0 - add_redirect_rule2("em0", 12123, "127.1.2.3", 1234, - IPPROTO_TCP, "test description tcp"); -#endif + add_redirect_rule2("em0", NULL, 12123, "127.1.2.3", 1234, + IPPROTO_TCP, "test description tcp", 0); + add_filter_rule2("em0", NULL, "127.1.2.3", 12123, 1234, IPPROTO_TCP, + "test description tcp"); list_rules(); list_eports_tcp(); diff --git a/miniupnpd/pf/testpfpinhole.c b/miniupnpd/pf/testpfpinhole.c index e09199c..ec754e2 100644 --- a/miniupnpd/pf/testpfpinhole.c +++ b/miniupnpd/pf/testpfpinhole.c @@ -1,7 +1,7 @@ -/* $Id: testpfpinhole.c,v 1.10 2012/04/22 23:12:51 nanard Exp $ */ +/* $Id: testpfpinhole.c,v 1.11 2014/02/28 16:49:15 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2012 Thomas Bernard + * (c) 2012-2014 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -21,6 +21,7 @@ const char * tag = NULL; const char * anchor_name = "miniupnpd"; const char * queue = NULL; +#ifdef ENABLE_IPV6 static int print_pinhole(int uid) { int r; @@ -32,11 +33,11 @@ static int print_pinhole(int uid) unsigned int timestamp; u_int64_t packets, bytes; - r = get_pinhole((unsigned short)uid, - rem_host, sizeof(rem_host), &rem_port, - int_client, sizeof(int_client), &int_port, - &proto, ×tamp, - &packets, &bytes); + r = get_pinhole_info((unsigned short)uid, + rem_host, sizeof(rem_host), &rem_port, + int_client, sizeof(int_client), &int_port, + &proto, ×tamp, + &packets, &bytes); if(r < 0) { fprintf(stderr, "get_pinhole(%d) returned %d\n", uid, r); } else { @@ -47,6 +48,7 @@ static int print_pinhole(int uid) } return r; } +#endif int main(int argc, char * *argv) { From bd83aa90c53f9a91cf4dfb5a425b6f16accdd081 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Fri, 28 Feb 2014 20:23:51 +0100 Subject: [PATCH 071/104] minissdpd: accept request of type 3 with 0 lenght argument --- minissdpd/minissdpd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/minissdpd/minissdpd.c b/minissdpd/minissdpd.c index e1068ad..2421a42 100644 --- a/minissdpd/minissdpd.c +++ b/minissdpd/minissdpd.c @@ -1,4 +1,4 @@ -/* $Id: minissdpd.c,v 1.36 2014/02/03 15:45:07 nanard Exp $ */ +/* $Id: minissdpd.c,v 1.37 2014/02/28 18:39:11 nanard Exp $ */ /* MiniUPnP project * (c) 2007-2014 Thomas Bernard * website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ @@ -571,7 +571,7 @@ void processRequest(struct reqelem * req) syslog(LOG_WARNING, "bad request (length encoding)"); goto error; } - if(l == 0) { + if(l == 0 && type != 3) { syslog(LOG_WARNING, "bad request (length=0)"); goto error; } From 7f3fbccbebdda4588189eb4a9a0ef17feae6e256 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Fri, 28 Feb 2014 20:24:19 +0100 Subject: [PATCH 072/104] testminissdpd: various improvements more tests. --- minissdpd/testminissdpd.c | 67 ++++++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 12 deletions(-) diff --git a/minissdpd/testminissdpd.c b/minissdpd/testminissdpd.c index c06cf50..30ee92d 100644 --- a/minissdpd/testminissdpd.c +++ b/minissdpd/testminissdpd.c @@ -1,12 +1,13 @@ -/* $Id: testminissdpd.c,v 1.7 2012/05/02 10:28:25 nanard Exp $ */ +/* $Id: testminissdpd.c,v 1.8 2014/02/28 18:38:21 nanard Exp $ */ /* Project : miniupnp * website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * Author : Thomas BERNARD - * copyright (c) 2005-2007 Thomas Bernard + * copyright (c) 2005-2014 Thomas Bernard * This software is subjet to the conditions detailed in the * provided LICENCE file. */ #include #include +#include #include #include #include @@ -21,6 +22,8 @@ void printresponse(const unsigned char * resp, int n) int i, l; unsigned int nresp; const unsigned char * p; + if(n == 0) + return; for(i=0; i Date: Fri, 28 Feb 2014 20:26:02 +0100 Subject: [PATCH 073/104] miniupnpd/pcpserver.c: fix defines with OpenBSD, must be included before --- miniupnpd/pcpserver.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/miniupnpd/pcpserver.c b/miniupnpd/pcpserver.c index 61a6208..8a88c6a 100644 --- a/miniupnpd/pcpserver.c +++ b/miniupnpd/pcpserver.c @@ -1,4 +1,4 @@ -/* $Id: pcpserver.c,v 1.9 2014/02/11 09:35:53 nanard Exp $ */ +/* $Id: pcpserver.c,v 1.12 2014/02/28 17:50:22 nanard Exp $ */ /* MiniUPnP project * Website : http://miniupnp.free.fr/ * Author : Peter Tatrai @@ -43,6 +43,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include #include #include From 37208eecae0a9b9c8a4ad3e7a5f748a827651023 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Fri, 28 Feb 2014 21:22:52 +0100 Subject: [PATCH 074/104] miniupnpd/pf/obsdrdr.c: improve documentation --- miniupnpd/pf/obsdrdr.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/miniupnpd/pf/obsdrdr.c b/miniupnpd/pf/obsdrdr.c index 663cea3..ac3616d 100644 --- a/miniupnpd/pf/obsdrdr.c +++ b/miniupnpd/pf/obsdrdr.c @@ -1,7 +1,7 @@ -/* $Id: obsdrdr.c,v 1.74 2012/05/01 09:20:43 nanard Exp $ */ +/* $Id: obsdrdr.c,v 1.78 2014/02/28 20:18:41 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2012 Thomas Bernard + * (c) 2006-2014 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -9,15 +9,19 @@ * pf rules created (with ext_if = xl1) * - OpenBSD up to version 4.6 : * rdr pass on xl1 inet proto udp from any to any port = 54321 \ - * label "test label" -> 192.168.0.141 port 12345 - * or a rdr rule + a pass rule + * keep state label "test label" -> 192.168.0.42 port 12345 + * or a rdr rule + a pass rule : + * rdr quick on xl1 inet proto udp from any to any port = 54321 \ + * keep state label "test label" -> 192.168.0.42 port 12345 + * pass in quick on xl1 inet proto udp from any to any port = 12345 \ + * flags S/SA keep state label "test label" * * - OpenBSD starting from version 4.7 * match in on xl1 inet proto udp from any to any port 54321 \ - * label "test label" rdr-to 192.168.0.141 port 12345 + * label "test label" rdr-to 192.168.0.42 port 12345 * or * pass in quick on xl1 inet proto udp from any to any port 54321 \ - * label "test label" rdr-to 192.168.0.141 port 12345 + * label "test label" rdr-to 192.168.0.42 port 12345 * * * From 9d23b88cefd3736b5a72826c876c3b7e593e550e Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Fri, 28 Feb 2014 21:26:52 +0100 Subject: [PATCH 075/104] miniupnpd/pf: replace delete_filter_rule() now use delete_redirect_and_filter_rules() --- miniupnpd/pf/obsdrdr.c | 35 ++++++++++++++++++++++++++++++++--- miniupnpd/pf/obsdrdr.h | 9 +++++---- miniupnpd/upnpredirect.c | 22 +++++----------------- 3 files changed, 42 insertions(+), 24 deletions(-) diff --git a/miniupnpd/pf/obsdrdr.c b/miniupnpd/pf/obsdrdr.c index ac3616d..e4887bf 100644 --- a/miniupnpd/pf/obsdrdr.c +++ b/miniupnpd/pf/obsdrdr.c @@ -579,8 +579,9 @@ error: return -1; } -int -delete_redirect_rule(const char * ifname, unsigned short eport, int proto) +static int +priv_delete_redirect_rule(const char * ifname, unsigned short eport, + int proto, unsigned short * iport) { int i, n; struct pfioc_rule pr; @@ -618,6 +619,12 @@ delete_redirect_rule(const char * ifname, unsigned short eport, int proto) #endif && (pr.rule.proto == proto) ) { + /* retrieve iport in order to remove filter rule */ +#ifndef PF_NEWSTYLE + if(iport) *iport = pr.rule.rpool.proxy_port[0]; +#else + if(iport) *iport = pr.rule.rdr.proxy_port[0]; +#endif pr.action = PF_CHANGE_GET_TICKET; if(ioctl(dev, DIOCCHANGERULE, &pr) < 0) { @@ -640,7 +647,15 @@ error: } int -delete_filter_rule(const char * ifname, unsigned short iport, int proto) +delete_redirect_rule(const char * ifname, unsigned short eport, + int proto) +{ + return priv_delete_redirect_rule(ifname, eport, proto, NULL); +} + +static int +priv_delete_filter_rule(const char * ifname, unsigned short iport, + int proto) { #ifndef PF_ENABLE_FILTER_RULES UNUSED(ifname); UNUSED(iport); UNUSED(proto); @@ -693,6 +708,20 @@ error: #endif } +int +delete_redirect_and_filter_rules(const char * ifname, unsigned short eport, + int proto) +{ + int r; + unsigned short iport; + r = priv_delete_redirect_rule(ifname, eport, proto, &iport); + if(r == 0) + { + priv_delete_filter_rule(ifname, iport, proto); + } + return r; +} + int get_redirect_rule_by_index(int index, char * ifname, unsigned short * eport, diff --git a/miniupnpd/pf/obsdrdr.h b/miniupnpd/pf/obsdrdr.h index 59225fd..7bd7e0c 100644 --- a/miniupnpd/pf/obsdrdr.h +++ b/miniupnpd/pf/obsdrdr.h @@ -1,7 +1,7 @@ -/* $Id: obsdrdr.h,v 1.20 2012/03/05 20:36:20 nanard Exp $ */ +/* $Id: obsdrdr.h,v 1.22 2014/02/28 20:18:41 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006 Thomas Bernard + * (c) 2006-2014 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -52,10 +52,11 @@ get_redirect_rule_by_index(int index, int delete_redirect_rule(const char * ifname, unsigned short eport, int proto); -/* delete_filter_rule() +/* delete_redirect_and_filter_rules() */ int -delete_filter_rule(const char * ifname, unsigned short eport, int proto); +delete_redirect_and_filter_rules(const char * ifname, unsigned short eport, + int proto); int clear_redirect_rules(void); diff --git a/miniupnpd/upnpredirect.c b/miniupnpd/upnpredirect.c index 1e03b93..0b7e8a3 100644 --- a/miniupnpd/upnpredirect.c +++ b/miniupnpd/upnpredirect.c @@ -1,7 +1,7 @@ -/* $Id: upnpredirect.c,v 1.80 2012/05/01 20:08:22 nanard Exp $ */ +/* $Id: upnpredirect.c,v 1.82 2014/02/28 20:18:35 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2012 Thomas Bernard + * (c) 2006-2014 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -419,23 +419,11 @@ _upnp_delete_redir(unsigned short eport, int proto) int r; #if defined(__linux__) r = delete_redirect_and_filter_rules(eport, proto); +#elif defined(USE_PF) + r = delete_redirect_and_filter_rules(ext_if_name, eport, proto); #else - char iaddr[INET6_ADDRSTRLEN]; - unsigned short iport; - char desc[64]; - char rhost[64]; - unsigned int timestamp; - u_int64_t packets; - u_int64_t bytes; - int r2 = get_redirect_rule(ext_if_name, eport, proto, - &iaddr, sizeof(iaddr), &iport, - &desc, sizeof(desc), - &rhost, sizeof(rhost), - ×tamp, - &packets, &bytes); r = delete_redirect_rule(ext_if_name, eport, proto); - if (r2==0) - delete_filter_rule(ext_if_name, iport, proto); + delete_filter_rule(ext_if_name, eport, proto); #endif #ifdef ENABLE_LEASEFILE lease_file_remove( eport, proto); From 5512d022acb84cd23d73cd91a7e7d35d02f6b887 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Fri, 28 Feb 2014 21:28:12 +0100 Subject: [PATCH 076/104] miniupnpd/pf/obsdrdr.c: add UNUSED() when necessary --- miniupnpd/pf/obsdrdr.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/miniupnpd/pf/obsdrdr.c b/miniupnpd/pf/obsdrdr.c index e4887bf..5c87fec 100644 --- a/miniupnpd/pf/obsdrdr.c +++ b/miniupnpd/pf/obsdrdr.c @@ -353,6 +353,10 @@ add_filter_rule2(const char * ifname, struct pfioc_pooladdr pp; struct pf_pooladdr *a; #endif +#ifndef USE_IFNAME_IN_RULES + UNUSED(ifname); +#endif + UNUSED(eport); if(dev<0) { syslog(LOG_ERR, "pf device is not open"); return -1; @@ -663,6 +667,7 @@ priv_delete_filter_rule(const char * ifname, unsigned short iport, #else int i, n; struct pfioc_rule pr; + UNUSED(ifname); if(dev<0) { syslog(LOG_ERR, "pf device is not open"); return -1; From edd501f59c957547c5098ad480c48dfdfa5adf7e Mon Sep 17 00:00:00 2001 From: Daniel Becker Date: Fri, 28 Feb 2014 14:47:53 -0800 Subject: [PATCH 077/104] miniupnpd/natpmp.c: return correct error code when all external ports in use Instead of returning code 3 ("Network Failure"), we should the more appropriate code 4 ("Out of resources") when no external port is available for a mapping. --- miniupnpd/natpmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miniupnpd/natpmp.c b/miniupnpd/natpmp.c index c3d26ce..8238a11 100644 --- a/miniupnpd/natpmp.c +++ b/miniupnpd/natpmp.c @@ -291,7 +291,7 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, if(eport == eport_first) { /* no external port available */ syslog(LOG_ERR, "Failed to find available eport for NAT-PMP %hu %s->%s:%hu", eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport); - resp[3] = 3; /* Failure */ + resp[3] = 4; /* Out of resources */ break; } continue; From e5146cdf24c777d01b99c45e989b5659e0bb7080 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Mon, 3 Mar 2014 12:35:12 +0100 Subject: [PATCH 078/104] miniupnpd/Makefile.linux: fixes for testasyncsendto also update dependencies --- miniupnpd/Makefile.linux | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/miniupnpd/Makefile.linux b/miniupnpd/Makefile.linux index 270c72d..636ba94 100644 --- a/miniupnpd/Makefile.linux +++ b/miniupnpd/Makefile.linux @@ -205,7 +205,8 @@ testgetifaddr: testgetifaddr.o getifaddr.o testgetroute: testgetroute.o linux/getroute.o upnputils.o -lnfnetlink -testasyncsendto: testasyncsendto.o asyncsendto.o upnputils.o +testasyncsendto: testasyncsendto.o asyncsendto.o upnputils.o \ + linux/getroute.o -lnfnetlink miniupnpdctl: miniupnpdctl.o @@ -223,8 +224,8 @@ depend: config.h miniupnpd.o: config.h macros.h upnpglobalvars.h upnppermissions.h miniupnpd.o: miniupnpdtypes.h upnphttp.h upnpdescgen.h miniupnpdpath.h miniupnpd.o: getifaddr.h upnpsoap.h options.h minissdp.h upnpredirect.h -miniupnpd.o: upnppinhole.h daemonize.h upnpevents.h natpmp.h pcpserver.h -miniupnpd.o: commonrdr.h upnputils.h ifacewatcher.h +miniupnpd.o: upnppinhole.h daemonize.h upnpevents.h asyncsendto.h natpmp.h +miniupnpd.o: pcpserver.h commonrdr.h upnputils.h ifacewatcher.h upnphttp.o: config.h upnphttp.h upnpdescgen.h miniupnpdpath.h upnpsoap.h upnphttp.o: upnpevents.h upnputils.h upnpdescgen.o: config.h getifaddr.h upnpredirect.h upnpdescgen.h @@ -248,12 +249,13 @@ options.o: miniupnpdtypes.h upnppermissions.o: config.h upnppermissions.h minissdp.o: config.h upnpdescstrings.h miniupnpdpath.h upnphttp.h minissdp.o: upnpglobalvars.h upnppermissions.h miniupnpdtypes.h minissdp.h -minissdp.o: upnputils.h getroute.h codelength.h +minissdp.o: upnputils.h getroute.h asyncsendto.h codelength.h natpmp.o: macros.h config.h natpmp.h upnpglobalvars.h upnppermissions.h natpmp.o: miniupnpdtypes.h getifaddr.h upnpredirect.h commonrdr.h upnputils.h +natpmp.o: asyncsendto.h pcpserver.o: config.h pcpserver.h macros.h upnpglobalvars.h upnppermissions.h pcpserver.o: miniupnpdtypes.h pcplearndscp.h upnpredirect.h commonrdr.h -pcpserver.o: getifaddr.h pcp_msg_struct.h +pcpserver.o: getifaddr.h asyncsendto.h pcp_msg_struct.h upnpevents.o: config.h upnpevents.h miniupnpdpath.h upnpglobalvars.h upnpevents.o: upnppermissions.h miniupnpdtypes.h upnpdescgen.h upnputils.h upnputils.o: config.h upnputils.h upnpglobalvars.h upnppermissions.h @@ -264,6 +266,7 @@ upnppinhole.o: upnppermissions.h miniupnpdtypes.h upnpevents.h upnppinhole.o: netfilter/iptpinhole.h pcplearndscp.o: config.h upnpglobalvars.h upnppermissions.h miniupnpdtypes.h pcplearndscp.o: pcplearndscp.h +asyncsendto.o: asyncsendto.h linux/getifstats.o: config.h getifstats.h linux/ifacewatcher.o: config.h ifacewatcher.h config.h minissdp.h linux/ifacewatcher.o: miniupnpdtypes.h getifaddr.h upnpglobalvars.h @@ -284,4 +287,5 @@ testupnppermissions.o: upnppermissions.h config.h testgetifaddr.o: getifaddr.h testgetroute.o: getroute.h upnputils.h upnpglobalvars.h upnppermissions.h testgetroute.o: config.h miniupnpdtypes.h +testasyncsendto.o: miniupnpdtypes.h config.h upnputils.h asyncsendto.h miniupnpdctl.o: macros.h From f49a70aab02e9359d93e4bd19924ee5a1d1e85b3 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Mon, 3 Mar 2014 12:37:01 +0100 Subject: [PATCH 079/104] miniupnpd/testgetifaddr.c: also test find_ipv6_addr() --- miniupnpd/Makefile.linux | 2 +- miniupnpd/testgetifaddr.c | 18 +++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/miniupnpd/Makefile.linux b/miniupnpd/Makefile.linux index 636ba94..86d7d7c 100644 --- a/miniupnpd/Makefile.linux +++ b/miniupnpd/Makefile.linux @@ -284,7 +284,7 @@ upnpdescgen.o: miniupnpdpath.h upnpglobalvars.h upnppermissions.h upnpdescgen.o: miniupnpdtypes.h upnpdescstrings.h upnpurns.h getconnstatus.h testgetifstats.o: getifstats.h testupnppermissions.o: upnppermissions.h config.h -testgetifaddr.o: getifaddr.h +testgetifaddr.o: config.h getifaddr.h testgetroute.o: getroute.h upnputils.h upnpglobalvars.h upnppermissions.h testgetroute.o: config.h miniupnpdtypes.h testasyncsendto.o: miniupnpdtypes.h config.h upnputils.h asyncsendto.h diff --git a/miniupnpd/testgetifaddr.c b/miniupnpd/testgetifaddr.c index 4c31907..8045b89 100644 --- a/miniupnpd/testgetifaddr.c +++ b/miniupnpd/testgetifaddr.c @@ -1,7 +1,7 @@ /* $Id: testgetifaddr.c,v 1.7 2013/04/27 15:38:57 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2013 Thomas Bernard + * (c) 2006-2014 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ #include @@ -10,6 +10,7 @@ #include #include #include +#include "config.h" #include "getifaddr.h" #if defined(__sun) @@ -21,6 +22,10 @@ int main(int argc, char * * argv) { char str_addr[64]; struct in_addr addr; struct in_addr mask; +#ifdef ENABLE_IPV6 + int r; + char str_addr6[64]; +#endif if(argc < 2) { fprintf(stderr, "Usage:\t%s interface_name\n", argv[0]); return 1; @@ -34,5 +39,16 @@ int main(int argc, char * * argv) { printf("Interface %s has IP address %s.\n", argv[1], str_addr); printf("addr=%s ", inet_ntoa(addr)); printf("mask=%s\n", inet_ntoa(mask)); +#ifdef ENABLE_IPV6 + r = find_ipv6_addr(argv[1], str_addr6, sizeof(str_addr6)); + if(r < 0) { + fprintf(stderr, "find_ipv6_addr() failed\n"); + return 1; + } else if(r == 0) { + printf("Interface %s has no IPv6 address.\n", argv[1]); + } else { + printf("Interface %s has IPv6 address %s.\n", argv[1], str_addr6); + } +#endif return 0; } From 65b776f1edf1fa12f542a14d191db6f4dfa06e82 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Thu, 6 Mar 2014 14:21:39 +0100 Subject: [PATCH 080/104] miniupnpd/pf: add clear_filter_rules() for testing also add a --clear / -c argument to testobsdrdr programm --- miniupnpd/pf/obsdrdr.c | 39 ++++++++++++++++++++++++++++++++++++++ miniupnpd/pf/obsdrdr.h | 6 +++++- miniupnpd/pf/testobsdrdr.c | 23 +++++++++++++++------- 3 files changed, 60 insertions(+), 8 deletions(-) diff --git a/miniupnpd/pf/obsdrdr.c b/miniupnpd/pf/obsdrdr.c index 5c87fec..d09a1be 100644 --- a/miniupnpd/pf/obsdrdr.c +++ b/miniupnpd/pf/obsdrdr.c @@ -180,6 +180,45 @@ clear_redirect_rules(void) error: return -1; } + +int +clear_filter_rules(void) +{ +#ifndef PF_ENABLE_FILTER_RULES + return 0; +#else + struct pfioc_trans io; + struct pfioc_trans_e ioe; + if(dev<0) { + syslog(LOG_ERR, "pf device is not open"); + return -1; + } + memset(&ioe, 0, sizeof(ioe)); + io.size = 1; + io.esize = sizeof(ioe); + io.array = &ioe; +#ifndef PF_NEWSTYLE + ioe.rs_num = PF_RULESET_FILTER; +#else + /* ? */ + ioe.type = PF_TRANS_RULESET; +#endif + strlcpy(ioe.anchor, anchor_name, MAXPATHLEN); + if(ioctl(dev, DIOCXBEGIN, &io) < 0) + { + syslog(LOG_ERR, "ioctl(dev, DIOCXBEGIN, ...): %m"); + goto error; + } + if(ioctl(dev, DIOCXCOMMIT, &io) < 0) + { + syslog(LOG_ERR, "ioctl(dev, DIOCXCOMMIT, ...): %m"); + goto error; + } + return 0; +error: + return -1; +#endif +} #endif /* add_redirect_rule2() : diff --git a/miniupnpd/pf/obsdrdr.h b/miniupnpd/pf/obsdrdr.h index 7bd7e0c..3defa8e 100644 --- a/miniupnpd/pf/obsdrdr.h +++ b/miniupnpd/pf/obsdrdr.h @@ -1,4 +1,4 @@ -/* $Id: obsdrdr.h,v 1.22 2014/02/28 20:18:41 nanard Exp $ */ +/* $Id: obsdrdr.h,v 1.23 2014/03/06 12:24:33 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2014 Thomas Bernard @@ -58,8 +58,12 @@ int delete_redirect_and_filter_rules(const char * ifname, unsigned short eport, int proto); +#ifdef TEST int clear_redirect_rules(void); +int +clear_filter_rules(void); +#endif #endif diff --git a/miniupnpd/pf/testobsdrdr.c b/miniupnpd/pf/testobsdrdr.c index 7d288c6..5cf8307 100644 --- a/miniupnpd/pf/testobsdrdr.c +++ b/miniupnpd/pf/testobsdrdr.c @@ -1,10 +1,11 @@ -/* $Id: testobsdrdr.c,v 1.24 2012/04/18 19:42:03 nanard Exp $ */ +/* $Id: testobsdrdr.c,v 1.28 2014/03/06 13:02:47 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2012 Thomas Bernard + * (c) 2006-2014 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ +#include #include #include #include @@ -17,6 +18,7 @@ int runtime_flags = 0; const char * tag = 0; const char * anchor_name = "miniupnpd"; +const char * queue = NULL; void list_rules(void); @@ -67,7 +69,7 @@ test_index(void) } int -main(int arc, char * * argv) +main(int argc, char * * argv) { char buf[32]; char desc[64]; @@ -77,6 +79,12 @@ main(int arc, char * * argv) unsigned int timestamp; u_int64_t packets = 0; u_int64_t bytes = 0; + int clear = 0; + + if(argc > 1) { + if(0 == strcmp(argv[1], "--clear") || 0 == strcmp(argv[1], "-c")) + clear = 1; + } openlog("testobsdrdr", LOG_PERROR, LOG_USER); if(init_redirect() < 0) @@ -121,12 +129,13 @@ main(int arc, char * * argv) else printf("delete_redirect_rule() succeded\n"); -#if 0 test_index(); - clear_redirect_rules(); - list_rules(); -#endif + if(clear) { + clear_redirect_rules(); + clear_filter_rules(); + } + /*list_rules();*/ return 0; } From acc149ee995d5d0e6679dc3406a83accf9f7d173 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Thu, 6 Mar 2014 14:23:13 +0100 Subject: [PATCH 081/104] miniupnpd/pf: fix add_filter_rule2() by adding internal address --- miniupnpd/pf/obsdrdr.c | 36 +++++++----------------------------- 1 file changed, 7 insertions(+), 29 deletions(-) diff --git a/miniupnpd/pf/obsdrdr.c b/miniupnpd/pf/obsdrdr.c index d09a1be..63bd0aa 100644 --- a/miniupnpd/pf/obsdrdr.c +++ b/miniupnpd/pf/obsdrdr.c @@ -1,4 +1,4 @@ -/* $Id: obsdrdr.c,v 1.78 2014/02/28 20:18:41 nanard Exp $ */ +/* $Id: obsdrdr.c,v 1.80 2014/03/06 13:02:46 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2014 Thomas Bernard @@ -13,7 +13,7 @@ * or a rdr rule + a pass rule : * rdr quick on xl1 inet proto udp from any to any port = 54321 \ * keep state label "test label" -> 192.168.0.42 port 12345 - * pass in quick on xl1 inet proto udp from any to any port = 12345 \ + * pass in quick on xl1 inet proto udp from any to 192.168.0.42 port = 12345 \ * flags S/SA keep state label "test label" * * - OpenBSD starting from version 4.7 @@ -390,7 +390,6 @@ add_filter_rule2(const char * ifname, struct pfioc_rule pcr; #ifndef PF_NEWSTYLE struct pfioc_pooladdr pp; - struct pf_pooladdr *a; #endif #ifndef USE_IFNAME_IN_RULES UNUSED(ifname); @@ -419,7 +418,6 @@ add_filter_rule2(const char * ifname, if(1) { #endif - pcr.rule.dst.port_op = PF_OP_EQ; pcr.rule.dst.port[0] = htons(iport); pcr.rule.direction = PF_IN; @@ -454,33 +452,16 @@ add_filter_rule2(const char * ifname, inet_pton(AF_INET, rhost, &pcr.rule.src.addr.v.a.addr.v4.s_addr); pcr.rule.src.addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE); } + /* we want any - iaddr port = # keep state label */ + inet_pton(AF_INET, iaddr, &pcr.rule.dst.addr.v.a.addr.v4.s_addr); + pcr.rule.dst.addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE); #ifndef PF_NEWSTYLE pcr.rule.rpool.proxy_port[0] = iport; - a = calloc(1, sizeof(struct pf_pooladdr)); - inet_pton(AF_INET, iaddr, &a->addr.v.a.addr.v4.s_addr); - a->addr.v.a.mask.v4.s_addr = htonl(INADDR_NONE); - memcpy(&pp.addr, a, sizeof(struct pf_pooladdr)); + pcr.rule.rpool.proxy_port[1] = iport; TAILQ_INIT(&pcr.rule.rpool.list); - inet_pton(AF_INET, iaddr, &a->addr.v.a.addr.v4.s_addr); - TAILQ_INSERT_TAIL(&pcr.rule.rpool.list, a, entries); - - /* we have any - any port = # keep state label */ - /* we want any - iaddr port = # keep state label */ - /* memcpy(&pcr.rule.dst, a, sizeof(struct pf_pooladdr)); */ - - memcpy(&pp.addr, a, sizeof(struct pf_pooladdr)); - strlcpy(pcr.rule.label, desc, PF_RULE_LABEL_SIZE); - if(ioctl(dev, DIOCADDADDR, &pp) < 0) - { - syslog(LOG_ERR, "ioctl(dev, DIOCADDADDR, ...): %m"); - r = -1; - } - else - { -#else +#endif if(1) { -#endif pcr.action = PF_CHANGE_GET_TICKET; if(ioctl(dev, DIOCCHANGERULE, &pcr) < 0) { @@ -497,9 +478,6 @@ add_filter_rule2(const char * ifname, } } } -#ifndef PF_NEWSTYLE - free(a); -#endif } return r; #endif From 60e129d131494ec16bc9f14b2aaf85ca016f30d5 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Thu, 6 Mar 2014 14:24:10 +0100 Subject: [PATCH 082/104] miniupnpd/pf: delete_redirect_and_filter_rules() now take internal address into account --- miniupnpd/pf/obsdrdr.c | 54 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/miniupnpd/pf/obsdrdr.c b/miniupnpd/pf/obsdrdr.c index 63bd0aa..349f68e 100644 --- a/miniupnpd/pf/obsdrdr.c +++ b/miniupnpd/pf/obsdrdr.c @@ -602,7 +602,8 @@ error: static int priv_delete_redirect_rule(const char * ifname, unsigned short eport, - int proto, unsigned short * iport) + int proto, unsigned short * iport, + in_addr_t * iaddr) { int i, n; struct pfioc_rule pr; @@ -643,8 +644,40 @@ priv_delete_redirect_rule(const char * ifname, unsigned short eport, /* retrieve iport in order to remove filter rule */ #ifndef PF_NEWSTYLE if(iport) *iport = pr.rule.rpool.proxy_port[0]; + if(iaddr) + { + /* retrieve internal address */ + struct pfioc_pooladdr pp; + memset(&pp, 0, sizeof(pp)); + strlcpy(pp.anchor, anchor_name, MAXPATHLEN); + pp.r_action = PF_RDR; + pp.r_num = i; + pp.ticket = pr.ticket; + if(ioctl(dev, DIOCGETADDRS, &pp) < 0) + { + syslog(LOG_ERR, "ioctl(dev, DIOCGETADDRS, ...): %m"); + goto error; + } + if(pp.nr != 1) + { + syslog(LOG_NOTICE, "No address associated with pf rule"); + goto error; + } + pp.nr = 0; /* first */ + if(ioctl(dev, DIOCGETADDR, &pp) < 0) + { + syslog(LOG_ERR, "ioctl(dev, DIOCGETADDR, ...): %m"); + goto error; + } + *iaddr = pp.addr.addr.v.a.addr.v4.s_addr; + } #else if(iport) *iport = pr.rule.rdr.proxy_port[0]; + if(iaddr) + { + /* retrieve internal address */ + *iaddr = pr.rule.rdr.addr.v.a.addr.v4.s_addr; + } #endif pr.action = PF_CHANGE_GET_TICKET; if(ioctl(dev, DIOCCHANGERULE, &pr) < 0) @@ -671,12 +704,12 @@ int delete_redirect_rule(const char * ifname, unsigned short eport, int proto) { - return priv_delete_redirect_rule(ifname, eport, proto, NULL); + return priv_delete_redirect_rule(ifname, eport, proto, NULL, NULL); } static int priv_delete_filter_rule(const char * ifname, unsigned short iport, - int proto) + int proto, in_addr_t iaddr) { #ifndef PF_ENABLE_FILTER_RULES UNUSED(ifname); UNUSED(iport); UNUSED(proto); @@ -706,8 +739,16 @@ priv_delete_filter_rule(const char * ifname, unsigned short iport, syslog(LOG_ERR, "ioctl(dev, DIOCGETRULE): %m"); goto error; } +#ifdef TEST +syslog(LOG_DEBUG, "%2d port=%hu proto=%d addr=%8x", + i, ntohs(pr.rule.dst.port[0]), pr.rule.proto, + pr.rule.dst.addr.v.a.addr.v4.s_addr); +/*pr.rule.dst.addr.v.a.mask.v4.s_addr*/ +#endif if( (iport == ntohs(pr.rule.dst.port[0])) - && (pr.rule.proto == proto) ) + && (pr.rule.proto == proto) && + (iaddr == pr.rule.dst.addr.v.a.addr.v4.s_addr) + ) { pr.action = PF_CHANGE_GET_TICKET; if(ioctl(dev, DIOCCHANGERULE, &pr) < 0) @@ -736,10 +777,11 @@ delete_redirect_and_filter_rules(const char * ifname, unsigned short eport, { int r; unsigned short iport; - r = priv_delete_redirect_rule(ifname, eport, proto, &iport); + in_addr_t iaddr; + r = priv_delete_redirect_rule(ifname, eport, proto, &iport, &iaddr); if(r == 0) { - priv_delete_filter_rule(ifname, iport, proto); + r = priv_delete_filter_rule(ifname, iport, proto, iaddr); } return r; } From b7ee4699809705238643b1ef4aaf847d6a8dee3b Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Thu, 6 Mar 2014 14:24:58 +0100 Subject: [PATCH 083/104] miniupnpd/pf: update testobsdrdr.c --- miniupnpd/pf/testobsdrdr.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/miniupnpd/pf/testobsdrdr.c b/miniupnpd/pf/testobsdrdr.c index 5cf8307..13d9ee5 100644 --- a/miniupnpd/pf/testobsdrdr.c +++ b/miniupnpd/pf/testobsdrdr.c @@ -96,12 +96,15 @@ main(int argc, char * * argv) add_redirect_rule("ep0", 12123, "192.168.1.23", 1234); add_redirect_rule2("ep0", 12155, "192.168.1.155", 1255, IPPROTO_TCP); #endif - add_redirect_rule2("ep0", "8.8.8.8", 12123, "192.168.1.125", 1234, - IPPROTO_UDP, "test description", 0); -#if 0 - add_redirect_rule2("em0", 12123, "127.1.2.3", 1234, - IPPROTO_TCP, "test description tcp"); -#endif + if(add_redirect_rule2("ep0", "8.8.8.8", 12123, "192.168.1.125", 1234, + IPPROTO_UDP, "test description", 0) < 0) + printf("add_redirect_rule2() #3 failed\n"); + if(add_redirect_rule2("em0", NULL, 12123, "127.1.2.3", 1234, + IPPROTO_TCP, "test description tcp", 0) < 0) + printf("add_redirect_rule2() #4 failed\n"); + if(add_filter_rule2("em0", NULL, "127.1.2.3", 12123, 1234, IPPROTO_TCP, + "test description tcp") < 0) + printf("add_filter_rule2() #1 failed\n"); list_rules(); list_eports_tcp(); @@ -121,13 +124,12 @@ main(int argc, char * * argv) if(delete_redirect_rule("ep0", 12123, IPPROTO_UDP) < 0) printf("delete_redirect_rule() failed\n"); - else - printf("delete_redirect_rule() succeded\n"); if(delete_redirect_rule("ep0", 12123, IPPROTO_UDP) < 0) printf("delete_redirect_rule() failed\n"); - else - printf("delete_redirect_rule() succeded\n"); + + if(delete_redirect_and_filter_rules("em0", 12123, IPPROTO_TCP) < 0) + printf("delete_redirect_and_filter_rules() failed\n"); test_index(); From e385db03b9262ff8e459e175f0ad1d444a06ade3 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Fri, 7 Mar 2014 11:48:17 +0100 Subject: [PATCH 084/104] miniupnpd: improved permission checking for NAT-PMP NAT-PMP now searches an allowed eport if the one from request is not, instead of returning an error --- miniupnpd/Changelog.txt | 6 +++++- miniupnpd/natpmp.c | 37 ++++++++++++++++++++++++------------- miniupnpd/upnppermissions.c | 37 +++++++++++++++++++++++++++++++++++-- miniupnpd/upnppermissions.h | 13 +++++++++++-- 4 files changed, 75 insertions(+), 18 deletions(-) diff --git a/miniupnpd/Changelog.txt b/miniupnpd/Changelog.txt index 830fcc4..e2856ad 100644 --- a/miniupnpd/Changelog.txt +++ b/miniupnpd/Changelog.txt @@ -1,4 +1,8 @@ -$Id: Changelog.txt,v 1.354 2014/02/28 12:14:29 nanard Exp $ +$Id: Changelog.txt,v 1.357 2014/03/07 10:43:29 nanard Exp $ + +2014/04/07: + NAT-PMP search an allowed eport instead of returning an error + if the original eport is not allowed. 2014/02/28: log message when shutting down diff --git a/miniupnpd/natpmp.c b/miniupnpd/natpmp.c index 8238a11..533fdfe 100644 --- a/miniupnpd/natpmp.c +++ b/miniupnpd/natpmp.c @@ -1,4 +1,4 @@ -/* $Id: natpmp.c,v 1.36 2014/02/01 17:17:35 nanard Exp $ */ +/* $Id: natpmp.c,v 1.39 2014/03/07 10:43:30 nanard Exp $ */ /* MiniUPnP project * (c) 2007-2014 Thomas Bernard * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ @@ -263,14 +263,32 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, } } eport = 0; /* to indicate correct removing of port mapping */ - } else if(iport==0 - || !check_upnp_rule_against_permissions(upnppermlist, num_upnpperm, eport, senderaddr->sin_addr, iport)) { + } else if(iport==0) { resp[3] = 2; /* Not Authorized/Refused */ - } else { + } else { /* iport > 0 && lifetime > 0 */ unsigned short eport_first; char desc[64]; + if(!check_upnp_rule_against_permissions(upnppermlist, num_upnpperm, eport, senderaddr->sin_addr, iport)) { + /* if the mapping is forbidden because of eport only + * (ie iaddr/iport are ok with another eport) + * change eport value ! */ + if(!find_allowed_eport(upnppermlist, num_upnpperm, senderaddr->sin_addr, iport, &eport)) { + /* no rule allow a mapping with this iaddr/iport */ + resp[3] = 2; /* Not Authorized/Refused */ + } + } eport_first = eport; - do { + while(resp[3] == 0) { + if(!check_upnp_rule_against_permissions(upnppermlist, num_upnpperm, eport, senderaddr->sin_addr, iport)) { + eport++; + if(eport == eport_first) { /* no external port available */ + syslog(LOG_ERR, "Failed to find available eport for NAT-PMP %hu %s->%s:%hu", + eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport); + resp[3] = 4; /* Out of resources */ + break; + } + continue; + } r = get_redirect_rule(ext_if_name, eport, proto, iaddr_old, sizeof(iaddr_old), &iport_old, 0, 0, 0, 0, @@ -314,16 +332,9 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, syslog(LOG_ERR, "Failed to add NAT-PMP %hu %s->%s:%hu '%s'", eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport, desc); resp[3] = 3; /* Failure */ -#if 0 - } else if( !nextnatpmptoclean_eport - || timestamp < nextnatpmptoclean_timestamp) { - nextnatpmptoclean_timestamp = timestamp; - nextnatpmptoclean_eport = eport; - nextnatpmptoclean_proto = proto; -#endif } break; - } while(r==0); + } } *((uint16_t *)(resp+8)) = htons(iport); /* private port */ *((uint16_t *)(resp+10)) = htons(eport); /* public port */ diff --git a/miniupnpd/upnppermissions.c b/miniupnpd/upnppermissions.c index 0fd43f7..c016451 100644 --- a/miniupnpd/upnppermissions.c +++ b/miniupnpd/upnppermissions.c @@ -1,7 +1,7 @@ -/* $Id: upnppermissions.c,v 1.17 2012/02/15 22:43:34 nanard Exp $ */ +/* $Id: upnppermissions.c,v 1.18 2014/03/07 10:43:29 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2012 Thomas Bernard + * (c) 2006-2014 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -223,6 +223,21 @@ match_permission(const struct upnpperm * perm, return 1; } +/* match_permission_internal() + * returns: 1 if address, iport matches the permission rule + * 0 if no match */ +static int +match_permission_internal(const struct upnpperm * perm, + struct in_addr address, u_short iport) +{ + if( (iport < perm->iport_min) || (perm->iport_max < iport)) + return 0; + if( (address.s_addr & perm->mask.s_addr) + != (perm->address.s_addr & perm->mask.s_addr) ) + return 0; + return 1; +} + int check_upnp_rule_against_permissions(const struct upnpperm * permary, int n_perms, @@ -245,3 +260,21 @@ check_upnp_rule_against_permissions(const struct upnpperm * permary, return 1; /* Default : accept */ } +int +find_allowed_eport(const struct upnpperm * permary, + int n_perms, + struct in_addr address, u_short iport, + u_short *allowed_eport) +{ + int i; + for(i=0; i Date: Fri, 7 Mar 2014 07:42:40 -0800 Subject: [PATCH 085/104] miniupnpd/natpmp.c: remove redundant break statements These two break statements are redundant: The subsequent continue statement will cause the loop condition to be re-evaluated, at which point the loop will terminate if resp[3] != 0. --- miniupnpd/natpmp.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/miniupnpd/natpmp.c b/miniupnpd/natpmp.c index 533fdfe..5de5f73 100644 --- a/miniupnpd/natpmp.c +++ b/miniupnpd/natpmp.c @@ -285,7 +285,6 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, syslog(LOG_ERR, "Failed to find available eport for NAT-PMP %hu %s->%s:%hu", eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport); resp[3] = 4; /* Out of resources */ - break; } continue; } @@ -310,7 +309,6 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, syslog(LOG_ERR, "Failed to find available eport for NAT-PMP %hu %s->%s:%hu", eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport); resp[3] = 4; /* Out of resources */ - break; } continue; } From 1db670d6ff2b143cb6e1c3f07132bf88a1b90429 Mon Sep 17 00:00:00 2001 From: Daniel Becker Date: Fri, 7 Mar 2014 11:02:04 -0800 Subject: [PATCH 086/104] miniupnpd/natpmp.c: skip port zero when finding free eport When skipping ports that are in use or not allowed, the existing NAT-PMP code will consider port zero as a candidate eport after wraparound occurs. Since this is not a legal port, we skip over it. port zero as an eport value. --- miniupnpd/natpmp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/miniupnpd/natpmp.c b/miniupnpd/natpmp.c index 533fdfe..7e456de 100644 --- a/miniupnpd/natpmp.c +++ b/miniupnpd/natpmp.c @@ -281,6 +281,7 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, while(resp[3] == 0) { if(!check_upnp_rule_against_permissions(upnppermlist, num_upnpperm, eport, senderaddr->sin_addr, iport)) { eport++; + if(eport == 0) eport++; /* skip port zero */ if(eport == eport_first) { /* no external port available */ syslog(LOG_ERR, "Failed to find available eport for NAT-PMP %hu %s->%s:%hu", eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport); @@ -306,6 +307,7 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, } } else { eport++; + if(eport == 0) eport++; /* skip port zero */ if(eport == eport_first) { /* no external port available */ syslog(LOG_ERR, "Failed to find available eport for NAT-PMP %hu %s->%s:%hu", eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport); From ecf414e1608af330f503b397bd6c01c32097c679 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Mon, 10 Mar 2014 00:12:20 +0100 Subject: [PATCH 087/104] miniupnpd/Changelog.txt: Catch up changes... --- miniupnpd/Changelog.txt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/miniupnpd/Changelog.txt b/miniupnpd/Changelog.txt index e2856ad..3078657 100644 --- a/miniupnpd/Changelog.txt +++ b/miniupnpd/Changelog.txt @@ -1,9 +1,15 @@ -$Id: Changelog.txt,v 1.357 2014/03/07 10:43:29 nanard Exp $ +$Id: Changelog.txt,v 1.358 2014/03/09 23:11:43 nanard Exp $ -2014/04/07: +2014/03/09: + IPv6 support in testgetifaddr + +2014/03/07: NAT-PMP search an allowed eport instead of returning an error if the original eport is not allowed. +2014/03/06: + Fix add_filter_rule2() for pf. + 2014/02/28: log message when shutting down natpmp : avoid hang when all external ports in use From f4f4573f5387fa909ad833d40ed47ac691717fdd Mon Sep 17 00:00:00 2001 From: Daniel Becker Date: Mon, 10 Mar 2014 00:32:23 -0700 Subject: [PATCH 088/104] miniupnpd: fix eport selection and error handling The find_available_eport function that was intended to check if at least one eport is allowed for a given iaddr/iport does not work as intended; for example, it does not properly handle rule precedence (i.e., it considers allow rules even if they are effectively masked by earlier deny rules), and it also does not handle the case where no rules are specified at all (which should default to accept in order to be consistent with check_upnp_rule_against_permissions). The present change removes this function and instead integrates the check into the existing while loop that iterates over all eports. --- miniupnpd/natpmp.c | 39 +++++++++++++++++-------------------- miniupnpd/upnppermissions.c | 18 ----------------- miniupnpd/upnppermissions.h | 9 --------- 3 files changed, 18 insertions(+), 48 deletions(-) diff --git a/miniupnpd/natpmp.c b/miniupnpd/natpmp.c index 5f434fe..74a035e 100644 --- a/miniupnpd/natpmp.c +++ b/miniupnpd/natpmp.c @@ -266,29 +266,31 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, } else if(iport==0) { resp[3] = 2; /* Not Authorized/Refused */ } else { /* iport > 0 && lifetime > 0 */ - unsigned short eport_first; + unsigned short eport_first = 0; + int any_eport_allowed = 0; char desc[64]; - if(!check_upnp_rule_against_permissions(upnppermlist, num_upnpperm, eport, senderaddr->sin_addr, iport)) { - /* if the mapping is forbidden because of eport only - * (ie iaddr/iport are ok with another eport) - * change eport value ! */ - if(!find_allowed_eport(upnppermlist, num_upnpperm, senderaddr->sin_addr, iport, &eport)) { - /* no rule allow a mapping with this iaddr/iport */ - resp[3] = 2; /* Not Authorized/Refused */ - } - } eport_first = eport; while(resp[3] == 0) { - if(!check_upnp_rule_against_permissions(upnppermlist, num_upnpperm, eport, senderaddr->sin_addr, iport)) { - eport++; - if(eport == 0) eport++; /* skip port zero */ - if(eport == eport_first) { /* no external port available */ + if(eport_first == 0) { /* first time in loop */ + eport_first = eport; + } else if(eport == eport_first) { /* no eport available */ + if(any_eport_allowed == 0) { /* all eports rejected by permissions */ + syslog(LOG_ERR, "No allowed eport for NAT-PMP %hu %s->%s:%hu", + eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport); + resp[3] = 2; /* Not Authorized/Refused */ + } else { /* at least one eport allowed (but none available) */ syslog(LOG_ERR, "Failed to find available eport for NAT-PMP %hu %s->%s:%hu", eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport); - resp[3] = 4; /* Out of resources */ + resp[3] = 4; /* Out of resources */ } + break; + } + if(!check_upnp_rule_against_permissions(upnppermlist, num_upnpperm, eport, senderaddr->sin_addr, iport)) { + eport++; + if(eport == 0) eport++; /* skip port zero */ continue; } + any_eport_allowed = 1; r = get_redirect_rule(ext_if_name, eport, proto, iaddr_old, sizeof(iaddr_old), &iport_old, 0, 0, 0, 0, @@ -306,12 +308,7 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, } } else { eport++; - if(eport == 0) eport++; /* skip port zero */ - if(eport == eport_first) { /* no external port available */ - syslog(LOG_ERR, "Failed to find available eport for NAT-PMP %hu %s->%s:%hu", - eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport); - resp[3] = 4; /* Out of resources */ - } + if(eport == 0) eport++; /* skip port zero */ continue; } } diff --git a/miniupnpd/upnppermissions.c b/miniupnpd/upnppermissions.c index c016451..edc9ad9 100644 --- a/miniupnpd/upnppermissions.c +++ b/miniupnpd/upnppermissions.c @@ -260,21 +260,3 @@ check_upnp_rule_against_permissions(const struct upnpperm * permary, return 1; /* Default : accept */ } -int -find_allowed_eport(const struct upnpperm * permary, - int n_perms, - struct in_addr address, u_short iport, - u_short *allowed_eport) -{ - int i; - for(i=0; i Date: Mon, 10 Mar 2014 11:14:49 -0700 Subject: [PATCH 089/104] miniupnpd/natpmp.c: remove obsolete assignment The eport_first variable now gets initialized in the first iteration of the while loop; the assignment right before the loop should have been removed in the previous commit. --- miniupnpd/natpmp.c | 1 - 1 file changed, 1 deletion(-) diff --git a/miniupnpd/natpmp.c b/miniupnpd/natpmp.c index 74a035e..802aba2 100644 --- a/miniupnpd/natpmp.c +++ b/miniupnpd/natpmp.c @@ -269,7 +269,6 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, unsigned short eport_first = 0; int any_eport_allowed = 0; char desc[64]; - eport_first = eport; while(resp[3] == 0) { if(eport_first == 0) { /* first time in loop */ eport_first = eport; From 210876f2a7a96e01e4d8496184c278ff66f363cf Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Tue, 11 Mar 2014 09:47:09 +0100 Subject: [PATCH 090/104] miniupnpd/natpmp.c: make indentation consistant and add a comment --- miniupnpd/natpmp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/miniupnpd/natpmp.c b/miniupnpd/natpmp.c index 802aba2..3c55ee5 100644 --- a/miniupnpd/natpmp.c +++ b/miniupnpd/natpmp.c @@ -267,7 +267,7 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, resp[3] = 2; /* Not Authorized/Refused */ } else { /* iport > 0 && lifetime > 0 */ unsigned short eport_first = 0; - int any_eport_allowed = 0; + int any_eport_allowed = 0; char desc[64]; while(resp[3] == 0) { if(eport_first == 0) { /* first time in loop */ @@ -280,7 +280,7 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, } else { /* at least one eport allowed (but none available) */ syslog(LOG_ERR, "Failed to find available eport for NAT-PMP %hu %s->%s:%hu", eport, (proto==IPPROTO_TCP)?"tcp":"udp", senderaddrstr, iport); - resp[3] = 4; /* Out of resources */ + resp[3] = 4; /* Out of resources */ } break; } @@ -289,7 +289,7 @@ void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, if(eport == 0) eport++; /* skip port zero */ continue; } - any_eport_allowed = 1; + any_eport_allowed = 1; /* at lease one eport is allowed */ r = get_redirect_rule(ext_if_name, eport, proto, iaddr_old, sizeof(iaddr_old), &iport_old, 0, 0, 0, 0, From efbb95aa10765326a2358b11e5d6b9657caf255f Mon Sep 17 00:00:00 2001 From: Daniel Becker Date: Tue, 11 Mar 2014 01:54:10 -0700 Subject: [PATCH 091/104] miniupnpd/pcpserver.c: port NAT-PMP updates to PCP This change ports the recent updates to the permissions checking and eport selection code for NAT-PMP to the PCP MAP handler. --- miniupnpd/pcpserver.c | 44 +++++++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/miniupnpd/pcpserver.c b/miniupnpd/pcpserver.c index 8a88c6a..5ba4a25 100644 --- a/miniupnpd/pcpserver.c +++ b/miniupnpd/pcpserver.c @@ -805,6 +805,8 @@ static void CreatePCPMap(pcp_info_t *pcp_msg_info) char desc[64]; char iaddr_old[INET_ADDRSTRLEN]; uint16_t iport_old; + uint16_t eport_first = 0; + int any_eport_allowed = 0; unsigned int timestamp; int r=0; @@ -812,6 +814,32 @@ static void CreatePCPMap(pcp_info_t *pcp_msg_info) pcp_msg_info->ext_port = pcp_msg_info->int_port; } do { + if (eport_first == 0) { /* first time in loop */ + eport_first = pcp_msg_info->ext_port; + } else if (pcp_msg_info->ext_port == eport_first) { /* no eport available */ + if (any_eport_allowed == 0) { /* all eports rejected by permissions */ + pcp_msg_info->result_code = PCP_ERR_NOT_AUTHORIZED; + } else { /* at least one eport allowed (but none available) */ + pcp_msg_info->result_code = PCP_ERR_NO_RESOURCES; + } + return; + } + if ((IN6_IS_ADDR_V4MAPPED(pcp_msg_info->int_ip) && + (!check_upnp_rule_against_permissions(upnppermlist, + num_upnpperm, pcp_msg_info->ext_port, + ((struct in_addr*)pcp_msg_info->int_ip->s6_addr)[3], + pcp_msg_info->int_port)))) { + if (pcp_msg_info->pfailure_present) { + pcp_msg_info->result_code = PCP_ERR_CANNOT_PROVIDE_EXTERNAL; + return; + } + pcp_msg_info->ext_port++; + if (pcp_msg_info->ext_port == 0) { /* skip port zero */ + pcp_msg_info->ext_port++; + } + continue; + } + any_eport_allowed = 1; r = get_redirect_rule(ext_if_name, pcp_msg_info->ext_port, pcp_msg_info->protocol, @@ -836,24 +864,20 @@ static void CreatePCPMap(pcp_info_t *pcp_msg_info) if (_upnp_delete_redir(pcp_msg_info->ext_port, pcp_msg_info->protocol)==0) { break; + } else if (pcp_msg_info->pfailure_present) { + pcp_msg_info->result_code = PCP_ERR_CANNOT_PROVIDE_EXTERNAL; + return; } } pcp_msg_info->ext_port++; + if (pcp_msg_info->ext_port == 0) { /* skip port zero */ + pcp_msg_info->ext_port++; + } } } while (r==0); timestamp = time(NULL) + pcp_msg_info->lifetime; - if ((pcp_msg_info->ext_port == 0) || - (IN6_IS_ADDR_V4MAPPED(pcp_msg_info->int_ip) && - (!check_upnp_rule_against_permissions(upnppermlist, - num_upnpperm, pcp_msg_info->ext_port, - ((struct in_addr*)pcp_msg_info->int_ip->s6_addr)[3], - pcp_msg_info->int_port)))) { - pcp_msg_info->result_code = PCP_ERR_CANNOT_PROVIDE_EXTERNAL; - return; - } - snprintf(desc, sizeof(desc), "PCP %hu %s", pcp_msg_info->ext_port, (pcp_msg_info->protocol==IPPROTO_TCP)?"tcp":"udp"); From 408a0b55f60d475157d1c9234b217cda9232c6dc Mon Sep 17 00:00:00 2001 From: Daniel Becker Date: Tue, 11 Mar 2014 02:06:38 -0700 Subject: [PATCH 092/104] miniupnpd/pcpserver.c: return error code if PCP mapping fails This change causes CreatePCPMap to return a PCP_ERR_NO_RESOURCES response when upnp_redirect_internal does not succeed; previously, no error code was returned in this case. --- miniupnpd/pcpserver.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/miniupnpd/pcpserver.c b/miniupnpd/pcpserver.c index 5ba4a25..98a6feb 100644 --- a/miniupnpd/pcpserver.c +++ b/miniupnpd/pcpserver.c @@ -897,6 +897,8 @@ static void CreatePCPMap(pcp_info_t *pcp_msg_info) pcp_msg_info->int_port, desc); + pcp_msg_info->result_code = PCP_ERR_NO_RESOURCES; + } else { syslog(LOG_INFO, "PCP MAP: added mapping %s %hu->%s:%hu '%s'", (pcp_msg_info->protocol==IPPROTO_TCP)?"TCP":"UDP", From b01152666c7b497cd031037b5fb5ca7bc1149824 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Wed, 12 Mar 2014 09:04:47 +0100 Subject: [PATCH 093/104] Adding Daniel Becker to thanks list --- README | 1 + 1 file changed, 1 insertion(+) diff --git a/README b/README index 96b37df..95cac83 100644 --- a/README +++ b/README @@ -44,3 +44,4 @@ Thanks to : * Leah X. Schmidt * Peter Tatrai * Leo Moll + * Daniel Becker From 081c46338c74918bf25709f9ad167010d974f23f Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Thu, 13 Mar 2014 09:53:44 +0100 Subject: [PATCH 094/104] miniupnpd/upnppermissions.c: disable match_permission_internal() --- miniupnpd/upnppermissions.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/miniupnpd/upnppermissions.c b/miniupnpd/upnppermissions.c index edc9ad9..ad02d8c 100644 --- a/miniupnpd/upnppermissions.c +++ b/miniupnpd/upnppermissions.c @@ -223,6 +223,7 @@ match_permission(const struct upnpperm * perm, return 1; } +#if 0 /* match_permission_internal() * returns: 1 if address, iport matches the permission rule * 0 if no match */ @@ -237,6 +238,7 @@ match_permission_internal(const struct upnpperm * perm, return 0; return 1; } +#endif int check_upnp_rule_against_permissions(const struct upnpperm * permary, From d397d736282affae9862fd114f243518e7680f14 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Thu, 13 Mar 2014 09:56:34 +0100 Subject: [PATCH 095/104] miniupnpd/getifaddr.c: fix getifaddr_in6() -1 is returned if no address is found --- miniupnpd/getifaddr.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/miniupnpd/getifaddr.c b/miniupnpd/getifaddr.c index 1430336..2b71909 100644 --- a/miniupnpd/getifaddr.c +++ b/miniupnpd/getifaddr.c @@ -122,6 +122,7 @@ getifaddr(const char * ifname, char * buf, int len, int getifaddr_in6(const char * ifname, struct in6_addr * addr){ struct ifaddrs * ifap; struct ifaddrs * ife; + int found = 0; if(!ifname || ifname[0]=='\0') return -1; @@ -130,9 +131,8 @@ int getifaddr_in6(const char * ifname, struct in6_addr * addr){ syslog(LOG_ERR, "getifaddrs: %m"); return -1; } - for(ife = ifap; ife; ife = ife->ifa_next) + for(ife = ifap; ife && !found; ife = ife->ifa_next) { - int found = 0; /* skip other interfaces if one was specified */ if(ifname && (0 != strcmp(ifname, ife->ifa_name))) continue; @@ -165,12 +165,9 @@ int getifaddr_in6(const char * ifname, struct in6_addr * addr){ } break; } - if (found) { - break; - } } freeifaddrs(ifap); - return 0; + return (found ? 0 : -1); } #endif From 81fa1bcd57e6f00b3b1d0aa6d240abb3e35a30a7 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Thu, 13 Mar 2014 10:00:42 +0100 Subject: [PATCH 096/104] miniupnpd/getifaddr.c: getifaddr_in6() only return IPv4 address when IPV6 disabled see if it can help for issue #62 pcp/CheckAddress() is likely to need more changes. --- miniupnpd/getifaddr.c | 6 +++++- miniupnpd/pcpserver.c | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/miniupnpd/getifaddr.c b/miniupnpd/getifaddr.c index 2b71909..3bdc281 100644 --- a/miniupnpd/getifaddr.c +++ b/miniupnpd/getifaddr.c @@ -119,6 +119,8 @@ getifaddr(const char * ifname, char * buf, int len, } #ifdef ENABLE_PCP +/* XXX I don't know if this function should return + * IPv4 or IPv6 if both are enabled... */ int getifaddr_in6(const char * ifname, struct in6_addr * addr){ struct ifaddrs * ifap; struct ifaddrs * ife; @@ -157,6 +159,7 @@ int getifaddr_in6(const char * ifname, struct in6_addr * addr){ found = 1; break; +#ifdef ENABLE_IPV6 case AF_INET6: if(!IN6_IS_ADDR_LOOPBACK(addr) && !IN6_IS_ADDR_LINKLOCAL(addr)) { @@ -164,12 +167,13 @@ int getifaddr_in6(const char * ifname, struct in6_addr * addr){ found = 1; } break; +#endif /* ENABLE_IPV6 */ } } freeifaddrs(ifap); return (found ? 0 : -1); } -#endif +#endif /* ENABLE_PCP */ #ifdef ENABLE_IPV6 int diff --git a/miniupnpd/pcpserver.c b/miniupnpd/pcpserver.c index 98a6feb..ed6416e 100644 --- a/miniupnpd/pcpserver.c +++ b/miniupnpd/pcpserver.c @@ -536,6 +536,7 @@ static int parsePCPOptions(void* pcp_buf, int* remainingSize, static int CheckExternalAddress(pcp_info_t* pcp_msg_info) { + /* can contain a IPv4-mapped IPv6 address */ static struct in6_addr external_addr; if(use_ext_ip_addr) { @@ -554,6 +555,7 @@ static int CheckExternalAddress(pcp_info_t* pcp_msg_info) pcp_msg_info->result_code = PCP_ERR_NETWORK_FAILURE; return -1; } + /* how do we know which address we need ? IPv6 or IPv4 ? */ if(getifaddr_in6(ext_if_name, &external_addr) < 0) { pcp_msg_info->result_code = PCP_ERR_NETWORK_FAILURE; return -1; From 3ed34783981881856b14dcd3e98246495dc6e419 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Thu, 13 Mar 2014 10:42:07 +0100 Subject: [PATCH 097/104] miniupnpd/getifaddr.c: clean up and fix getifaddr_in6() --- miniupnpd/getifaddr.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/miniupnpd/getifaddr.c b/miniupnpd/getifaddr.c index 3bdc281..f3459a5 100644 --- a/miniupnpd/getifaddr.c +++ b/miniupnpd/getifaddr.c @@ -121,9 +121,13 @@ getifaddr(const char * ifname, char * buf, int len, #ifdef ENABLE_PCP /* XXX I don't know if this function should return * IPv4 or IPv6 if both are enabled... */ -int getifaddr_in6(const char * ifname, struct in6_addr * addr){ +int getifaddr_in6(const char * ifname, struct in6_addr * addr) +{ struct ifaddrs * ifap; struct ifaddrs * ife; +#ifdef ENABLE_IPV6 + const struct sockaddr_in6 * tmpaddr; +#endif /* ENABLE_IPV6 */ int found = 0; if(!ifname || ifname[0]=='\0') @@ -143,27 +147,25 @@ int getifaddr_in6(const char * ifname, struct in6_addr * addr){ switch(ife->ifa_addr->sa_family) { case AF_INET: -#if 0 - addr->s6_addr32[0]=0; - addr->s6_addr32[1]=0; - addr->s6_addr32[2]=htonl(0xffff); - addr->s6_addr32[3]=((struct sockaddr_in *)ife->ifa_addr)->sin_addr.s_addr; -#endif + /* IPv4-mapped IPv6 address ::ffff:1.2.3.4 */ memset(addr->s6_addr, 0, 10); addr->s6_addr[10] = 0xff; addr->s6_addr[11] = 0xff; - memcpy(addr->s6_addr + 12, &(((struct sockaddr_in *)ife->ifa_addr)->sin_addr.s_addr), 4); - /*inet_ntop(ife->ifa_addr->sa_family, - &((struct sockaddr_in *)ife->ifa_addr)->sin_addr, - buf, len);*/ + memcpy(addr->s6_addr + 12, + &(((struct sockaddr_in *)ife->ifa_addr)->sin_addr.s_addr), + 4); found = 1; break; #ifdef ENABLE_IPV6 case AF_INET6: - if(!IN6_IS_ADDR_LOOPBACK(addr) - && !IN6_IS_ADDR_LINKLOCAL(addr)) { - memcpy(addr->s6_addr, &((struct sockaddr_in6 *)ife->ifa_addr)->sin6_addr, 16); + tmpaddr = (const struct sockaddr_in6 *)ife->ifa_addr; + if(!IN6_IS_ADDR_LOOPBACK(&tmpaddr->sin6_addr) + && !IN6_IS_ADDR_LINKLOCAL(&tmpaddr->sin6_addr)) + { + memcpy(addr->s6_addr, + &tmpaddr->sin6_addr, + 16); found = 1; } break; From 2a48074f4504a5330745d582bccc1384860b7345 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Thu, 13 Mar 2014 11:24:04 +0100 Subject: [PATCH 098/104] miniupnpd: Enable PCP by default. --- miniupnpd/Changelog.txt | 5 ++++- miniupnpd/genconfig.sh | 15 ++------------- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/miniupnpd/Changelog.txt b/miniupnpd/Changelog.txt index 3078657..73065ad 100644 --- a/miniupnpd/Changelog.txt +++ b/miniupnpd/Changelog.txt @@ -1,4 +1,7 @@ -$Id: Changelog.txt,v 1.358 2014/03/09 23:11:43 nanard Exp $ +$Id: Changelog.txt,v 1.362 2014/03/13 10:20:57 nanard Exp $ + +2014/03/10: + Enable PCP by default. 2014/03/09: IPv6 support in testgetifaddr diff --git a/miniupnpd/genconfig.sh b/miniupnpd/genconfig.sh index 8b13389..755a5be 100755 --- a/miniupnpd/genconfig.sh +++ b/miniupnpd/genconfig.sh @@ -1,5 +1,5 @@ #! /bin/sh -# $Id: genconfig.sh,v 1.69 2014/02/24 18:41:25 nanard Exp $ +# $Id: genconfig.sh,v 1.72 2014/03/10 10:17:17 nanard Exp $ # miniupnp daemon # http://miniupnp.free.fr or http://miniupnp.tuxfamily.org/ # (c) 2006-2014 Thomas Bernard @@ -13,11 +13,7 @@ case "$argv" in --strict) STRICT=1 ;; --leasefile) LEASEFILE=1 ;; --vendorcfg) VENDORCFG=1 ;; - --pcp) PCP=1 ;; - --pcp-peer) - PCP=1 - PCP_PEER=1 - ;; + --pcp-peer) PCP_PEER=1 ;; --help|-h) echo "Usage : $0 [options]" echo " --ipv6 enable IPv6" @@ -25,7 +21,6 @@ case "$argv" in echo " --strict be more strict regarding compliance with UPnP specifications" echo " --leasefile enable lease file" echo " --vendorcfg enable configuration of manufacturer info" - echo " --pcp enable PCP" echo " --pcp-peer enable PCP PEER operation" exit 1 ;; @@ -341,15 +336,9 @@ echo "/* Comment the following line to disable NAT-PMP operations */" >> ${CONFI echo "#define ENABLE_NATPMP" >> ${CONFIGFILE} echo "" >> ${CONFIGFILE} -if [ -n "$PCP" ]; then echo "/* Comment the following line to disable PCP operations */" >> ${CONFIGFILE} echo "#define ENABLE_PCP" >> ${CONFIGFILE} echo "" >> ${CONFIGFILE} -else -echo "/* Uncomment the following line to enable PCP operations */" >> ${CONFIGFILE} -echo "/*#define ENABLE_PCP*/" >> ${CONFIGFILE} -echo "" >> ${CONFIGFILE} -fi echo "#ifdef ENABLE_PCP" >> ${CONFIGFILE} if [ -n "$PCP_PEER" ]; then From 15682180a5f658b10797b99107e2dbe3e6263c50 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Thu, 13 Mar 2014 11:30:24 +0100 Subject: [PATCH 099/104] miniupnpd: Work in IPv6 on system where PF_INET6 are restricted to IPv6 only --- miniupnpd/Changelog.txt | 1 + miniupnpd/genconfig.sh | 17 ++++ miniupnpd/miniupnpd.c | 198 +++++++++++++++++++++++++--------------- 3 files changed, 143 insertions(+), 73 deletions(-) diff --git a/miniupnpd/Changelog.txt b/miniupnpd/Changelog.txt index 73065ad..513aa01 100644 --- a/miniupnpd/Changelog.txt +++ b/miniupnpd/Changelog.txt @@ -2,6 +2,7 @@ $Id: Changelog.txt,v 1.362 2014/03/13 10:20:57 nanard Exp $ 2014/03/10: Enable PCP by default. + Work in IPv6 on system where PF_INET6 are restricted to IPv6 only 2014/03/09: IPv6 support in testgetifaddr diff --git a/miniupnpd/genconfig.sh b/miniupnpd/genconfig.sh index 755a5be..13a54e6 100755 --- a/miniupnpd/genconfig.sh +++ b/miniupnpd/genconfig.sh @@ -115,6 +115,7 @@ case $OS_NAME in FW=pf echo "#define USE_IFACEWATCHER 1" >> ${CONFIGFILE} OS_URL=http://www.openbsd.org/ + V6SOCKETS_ARE_V6ONLY=`sysctl -n net.inet6.ip6.v6only` ;; FreeBSD) VER=`grep '#define __FreeBSD_version' /usr/include/sys/param.h | awk '{print $3}'` @@ -145,12 +146,14 @@ case $OS_NAME in fi echo "#define USE_IFACEWATCHER 1" >> ${CONFIGFILE} OS_URL=http://www.freebsd.org/ + V6SOCKETS_ARE_V6ONLY=`sysctl -n net.inet6.ip6.v6only` ;; pfSense) # we need to detect if PFRULE_INOUT_COUNTS macro is needed FW=pf echo "#define USE_IFACEWATCHER 1" >> ${CONFIGFILE} OS_URL=http://www.pfsense.com/ + V6SOCKETS_ARE_V6ONLY=`sysctl -n net.inet6.ip6.v6only` ;; NetBSD) if [ -f /etc/rc.subr ] && [ -f /etc/rc.conf ] ; then @@ -308,6 +311,11 @@ case $FW in ;; esac +# set V6SOCKETS_ARE_V6ONLY to 0 if it was not set above +if [ -z "$V6SOCKETS_ARE_V6ONLY" ] ; then + V6SOCKETS_ARE_V6ONLY=0 +fi + echo "Configuring compilation for [$OS_NAME] [$OS_VERSION] with [$FW] firewall software." echo "Please edit config.h for more compilation options." @@ -403,6 +411,15 @@ else fi echo "" >> ${CONFIGFILE} +echo "/* Define V6SOCKETS_ARE_V6ONLY if AF_INET6 sockets are restricted" >> ${CONFIGFILE} +echo " * to IPv6 communications only. */" >> ${CONFIGFILE} +if [ $V6SOCKETS_ARE_V6ONLY -eq 1 ] ; then + echo "#define V6SOCKETS_ARE_V6ONLY" >> ${CONFIGFILE} +else + echo "/*#define V6SOCKETS_ARE_V6ONLY*/" >> ${CONFIGFILE} +fi +echo "" >> ${CONFIGFILE} + echo "/* Enable the support of IGD v2 specification." >> ${CONFIGFILE} echo " * This is not fully tested yet and can cause incompatibilities with some" >> ${CONFIGFILE} echo " * control points, so enable with care. */" >> ${CONFIGFILE} diff --git a/miniupnpd/miniupnpd.c b/miniupnpd/miniupnpd.c index b215b6c..6616c63 100644 --- a/miniupnpd/miniupnpd.c +++ b/miniupnpd/miniupnpd.c @@ -112,7 +112,11 @@ volatile sig_atomic_t should_send_public_address_change_notif = 0; /* OpenAndConfHTTPSocket() : * setup the socket used to handle incoming HTTP connections. */ static int +#ifdef ENABLE_IPV6 +OpenAndConfHTTPSocket(unsigned short port, int ipv6) +#else OpenAndConfHTTPSocket(unsigned short port) +#endif { int s; int i = 1; @@ -126,7 +130,7 @@ OpenAndConfHTTPSocket(unsigned short port) if( (s = socket( #ifdef ENABLE_IPV6 - ipv6_enabled ? PF_INET6 : PF_INET, + ipv6 ? PF_INET6 : PF_INET, #else PF_INET, #endif @@ -155,7 +159,7 @@ OpenAndConfHTTPSocket(unsigned short port) } #ifdef ENABLE_IPV6 - if(ipv6_enabled) + if(ipv6) { memset(&listenname6, 0, sizeof(struct sockaddr_in6)); listenname6.sin6_family = AF_INET6; @@ -179,7 +183,7 @@ OpenAndConfHTTPSocket(unsigned short port) #ifdef ENABLE_IPV6 if(bind(s, - ipv6_enabled ? (struct sockaddr *)&listenname6 : (struct sockaddr *)&listenname4, + ipv6 ? (struct sockaddr *)&listenname6 : (struct sockaddr *)&listenname4, listenname_len) < 0) #else if(bind(s, (struct sockaddr *)&listenname, listenname_len) < 0) @@ -200,6 +204,84 @@ OpenAndConfHTTPSocket(unsigned short port) return s; } +static struct upnphttp * +ProcessIncomingHTTP(int shttpl) +{ + int shttp; + socklen_t clientnamelen; +#ifdef ENABLE_IPV6 + struct sockaddr_storage clientname; + clientnamelen = sizeof(struct sockaddr_storage); +#else + struct sockaddr_in clientname; + clientnamelen = sizeof(struct sockaddr_in); +#endif + shttp = accept(shttpl, (struct sockaddr *)&clientname, &clientnamelen); + if(shttp<0) + { + /* ignore EAGAIN, EWOULDBLOCK, EINTR, we just try again later */ + if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) + syslog(LOG_ERR, "accept(http): %m"); + } + else + { + struct upnphttp * tmp = 0; + char addr_str[64]; + + sockaddr_to_string((struct sockaddr *)&clientname, addr_str, sizeof(addr_str)); + syslog(LOG_INFO, "HTTP connection from %s", addr_str); + if(get_lan_for_peer((struct sockaddr *)&clientname) == NULL) + { + /* The peer is not a LAN ! */ + syslog(LOG_WARNING, + "HTTP peer %s is not from a LAN, closing the connection", + addr_str); + close(shttp); + } + else + { + /* Create a new upnphttp object and add it to + * the active upnphttp object list */ + tmp = New_upnphttp(shttp); + if(tmp) + { +#ifdef ENABLE_IPV6 + if(clientname.ss_family == AF_INET) + { + tmp->clientaddr = ((struct sockaddr_in *)&clientname)->sin_addr; + } + else if(clientname.ss_family == AF_INET6) + { + struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&clientname; + if(IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr)) + { + memcpy(&tmp->clientaddr, + &addr->sin6_addr.s6_addr[12], + 4); + } + else + { + tmp->ipv6 = 1; + memcpy(&tmp->clientaddr_v6, + &addr->sin6_addr, + sizeof(struct in6_addr)); + } + } +#else + tmp->clientaddr = clientname.sin_addr; +#endif + return tmp; + } + else + { + syslog(LOG_ERR, "New_upnphttp() failed"); + close(shttp); + } + } + } + return NULL; +} + #ifdef ENABLE_NFQUEUE int identify_ip_protocol(char *payload) { @@ -1368,6 +1450,9 @@ main(int argc, char * * argv) { int i; int shttpl = -1; /* socket for HTTP */ +#if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6) + int shttpl_v4 = -1; /* socket for HTTP (ipv4 only) */ +#endif int sudp = -1; /* IP v4 socket for receiving SSDP */ #ifdef ENABLE_IPV6 int sudpv6 = -1; /* IP v6 socket for receiving SSDP */ @@ -1459,7 +1544,11 @@ main(int argc, char * * argv) { /* open socket for HTTP connections. Listen on the 1st LAN address */ +#ifdef ENABLE_IPV6 + shttpl = OpenAndConfHTTPSocket((v.port > 0) ? v.port : 0, 1); +#else /* ENABLE_IPV6 */ shttpl = OpenAndConfHTTPSocket((v.port > 0) ? v.port : 0); +#endif /* ENABLE_IPV6 */ if(shttpl < 0) { syslog(LOG_ERR, "Failed to open socket for HTTP. EXITING"); @@ -1475,6 +1564,14 @@ main(int argc, char * * argv) v.port = ntohs(sockinfo.sin_port); } syslog(LOG_NOTICE, "HTTP listening on port %d", v.port); +#if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6) + shttpl_v4 = OpenAndConfHTTPSocket(v.port, 0); + if(shttpl_v4 < 0) + { + syslog(LOG_ERR, "Failed to open socket for HTTP on port %hu (IPv4). EXITING", v.port); + return 1; + } +#endif /* V6SOCKETS_ARE_V6ONLY */ #ifdef ENABLE_IPV6 if(find_ipv6_addr(NULL, ipv6_addr_for_http_with_brackets, sizeof(ipv6_addr_for_http_with_brackets)) > 0) { syslog(LOG_NOTICE, "HTTP IPv6 address given to control points : %s", @@ -1692,6 +1789,13 @@ main(int argc, char * * argv) FD_SET(shttpl, &readset); max_fd = MAX( max_fd, shttpl); } +#if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6) + if (shttpl_v4 >= 0) + { + FD_SET(shttpl_v4, &readset); + max_fd = MAX( max_fd, shttpl_v4); + } +#endif #ifdef ENABLE_IPV6 if (sudpv6 >= 0) { @@ -1930,79 +2034,24 @@ main(int argc, char * * argv) /* process incoming HTTP connections */ if(shttpl >= 0 && FD_ISSET(shttpl, &readset)) { - int shttp; - socklen_t clientnamelen; -#ifdef ENABLE_IPV6 - struct sockaddr_storage clientname; - clientnamelen = sizeof(struct sockaddr_storage); -#else - struct sockaddr_in clientname; - clientnamelen = sizeof(struct sockaddr_in); -#endif - shttp = accept(shttpl, (struct sockaddr *)&clientname, &clientnamelen); - if(shttp<0) + struct upnphttp * tmp; + tmp = ProcessIncomingHTTP(shttpl); + if(tmp) { - /* ignore EAGAIN, EWOULDBLOCK, EINTR, we just try again later */ - if(errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) - syslog(LOG_ERR, "accept(http): %m"); - } - else - { - struct upnphttp * tmp = 0; - char addr_str[64]; - - sockaddr_to_string((struct sockaddr *)&clientname, addr_str, sizeof(addr_str)); - syslog(LOG_INFO, "HTTP connection from %s", addr_str); - if(get_lan_for_peer((struct sockaddr *)&clientname) == NULL) - { - /* The peer is not a LAN ! */ - syslog(LOG_WARNING, - "HTTP peer %s is not from a LAN, closing the connection", - addr_str); - close(shttp); - } - else - { - /* Create a new upnphttp object and add it to - * the active upnphttp object list */ - tmp = New_upnphttp(shttp); - if(tmp) - { -#ifdef ENABLE_IPV6 - if(clientname.ss_family == AF_INET) - { - tmp->clientaddr = ((struct sockaddr_in *)&clientname)->sin_addr; - } - else if(clientname.ss_family == AF_INET6) - { - struct sockaddr_in6 * addr = (struct sockaddr_in6 *)&clientname; - if(IN6_IS_ADDR_V4MAPPED(&addr->sin6_addr)) - { - memcpy(&tmp->clientaddr, - &addr->sin6_addr.s6_addr[12], - 4); - } - else - { - tmp->ipv6 = 1; - memcpy(&tmp->clientaddr_v6, - &addr->sin6_addr, - sizeof(struct in6_addr)); - } - } -#else - tmp->clientaddr = clientname.sin_addr; -#endif - LIST_INSERT_HEAD(&upnphttphead, tmp, entries); - } - else - { - syslog(LOG_ERR, "New_upnphttp() failed"); - close(shttp); - } - } + LIST_INSERT_HEAD(&upnphttphead, tmp, entries); } } +#if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6) + if(shttpl_v4 >= 0 && FD_ISSET(shttpl_v4, &readset)) + { + struct upnphttp * tmp; + tmp = ProcessIncomingHTTP(shttpl_v4); + if(tmp) + { + LIST_INSERT_HEAD(&upnphttphead, tmp, entries); + } + } +#endif #ifdef ENABLE_NFQUEUE /* process NFQ packets */ if(nfqh >= 0 && FD_ISSET(nfqh, &readset)) @@ -2052,6 +2101,9 @@ shutdown: if (sudp >= 0) close(sudp); if (shttpl >= 0) close(shttpl); +#if defined(V6SOCKETS_ARE_V6ONLY) && defined(ENABLE_IPV6) + if (shttpl_v4 >= 0) close(shttpl_v4); +#endif #ifdef ENABLE_IPV6 if (sudpv6 >= 0) close(sudpv6); #endif From 7b13adafbd4dce38a2b58c571d16856ab27ee2f8 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Thu, 13 Mar 2014 11:26:53 +0100 Subject: [PATCH 100/104] miniupnpd: reduce number of global variables by using more runtime_flags change ipv6_enabled/ipv6fc_inbound_pinhole_allowed/ipv6fc_firewall_enabled global vars to flags in runtime_flags --- miniupnpd/Changelog.txt | 2 ++ miniupnpd/minissdp.c | 12 ++++++------ miniupnpd/miniupnpd.c | 6 +++--- miniupnpd/testupnpdescgen.c | 9 +++------ miniupnpd/upnpdescgen.c | 8 ++++---- miniupnpd/upnpglobalvars.c | 19 +------------------ miniupnpd/upnpglobalvars.h | 23 ++++++++--------------- miniupnpd/upnpsoap.c | 14 ++++++++------ 8 files changed, 35 insertions(+), 58 deletions(-) diff --git a/miniupnpd/Changelog.txt b/miniupnpd/Changelog.txt index 513aa01..7856b4e 100644 --- a/miniupnpd/Changelog.txt +++ b/miniupnpd/Changelog.txt @@ -3,6 +3,8 @@ $Id: Changelog.txt,v 1.362 2014/03/13 10:20:57 nanard Exp $ 2014/03/10: Enable PCP by default. Work in IPv6 on system where PF_INET6 are restricted to IPv6 only + change ipv6_enabled/ipv6fc_inbound_pinhole_allowed/ipv6fc_firewall_enabled + global vars to flags in runtime_flags 2014/03/09: IPv6 support in testgetifaddr diff --git a/miniupnpd/minissdp.c b/miniupnpd/minissdp.c index 9f5fc72..cdd6f08 100644 --- a/miniupnpd/minissdp.c +++ b/miniupnpd/minissdp.c @@ -1,4 +1,4 @@ -/* $Id: minissdp.c,v 1.58 2014/02/24 18:41:24 nanard Exp $ */ +/* $Id: minissdp.c,v 1.61 2014/03/10 11:04:51 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2014 Thomas Bernard @@ -281,16 +281,16 @@ OpenAndConfSSDPNotifySockets(int * sockets) goto error; i++; #ifdef ENABLE_IPV6 - if(ipv6_enabled) + if(GETFLAG(IPV6DISABLEDMASK)) + { + sockets[i] = -1; + } + else { sockets[i] = OpenAndConfSSDPNotifySocketIPv6(lan_addr->index); if(sockets[i] < 0) goto error; } - else - { - sockets[i] = -1; - } i++; #endif } diff --git a/miniupnpd/miniupnpd.c b/miniupnpd/miniupnpd.c index 6616c63..ccbbd8f 100644 --- a/miniupnpd/miniupnpd.c +++ b/miniupnpd/miniupnpd.c @@ -1,4 +1,4 @@ -/* $Id: miniupnpd.c,v 1.185 2014/02/28 12:14:26 nanard Exp $ */ +/* $Id: miniupnpd.c,v 1.189 2014/03/10 11:04:52 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2014 Thomas Bernard @@ -1579,7 +1579,7 @@ main(int argc, char * * argv) } else { memcpy(ipv6_addr_for_http_with_brackets, "[::1]", 6); syslog(LOG_WARNING, "no HTTP IPv6 address, disabling IPv6"); - ipv6_enabled = 0; + SETFLAG(IPV6DISABLEDMASK); } #endif @@ -1594,7 +1594,7 @@ main(int argc, char * * argv) } } #ifdef ENABLE_IPV6 - if(ipv6_enabled) + if(!GETFLAG(IPV6DISABLEDMASK)) { sudpv6 = OpenAndConfSSDPReceiveSocket(1); if(sudpv6 < 0) diff --git a/miniupnpd/testupnpdescgen.c b/miniupnpd/testupnpdescgen.c index c2cd028..ee30a8b 100644 --- a/miniupnpd/testupnpdescgen.c +++ b/miniupnpd/testupnpdescgen.c @@ -1,7 +1,7 @@ -/* $Id: testupnpdescgen.c,v 1.30 2013/06/13 13:21:30 nanard Exp $ */ +/* $Id: testupnpdescgen.c,v 1.32 2014/03/10 11:04:52 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2013 Thomas Bernard + * (c) 2006-2014 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -38,10 +38,7 @@ char model_url[] = ROOTDEV_MODELURL; char * use_ext_ip_addr = NULL; const char * ext_if_name = "eth0"; -#ifdef ENABLE_6FC_SERVICE -int ipv6fc_firewall_enabled = 1; -int ipv6fc_inbound_pinhole_allowed = 1; -#endif +int runtime_flags = 0; int getifaddr(const char * ifname, char * buf, int len, struct in_addr * addr, struct in_addr * mask) { diff --git a/miniupnpd/upnpdescgen.c b/miniupnpd/upnpdescgen.c index f88ea0b..5e5ebfb 100644 --- a/miniupnpd/upnpdescgen.c +++ b/miniupnpd/upnpdescgen.c @@ -1,7 +1,7 @@ -/* $Id: upnpdescgen.c,v 1.74 2013/06/13 13:21:30 nanard Exp $ */ +/* $Id: upnpdescgen.c,v 1.77 2014/03/10 11:04:53 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2013 Thomas Bernard + * (c) 2006-2014 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -1176,13 +1176,13 @@ genEventVars(int * len, const struct serviceDesc * s) case FIREWALLENABLED_MAGICALVALUE: /* see 2.4.2 of UPnP-gw-WANIPv6FirewallControl-v1-Service.pdf */ snprintf(tmp, sizeof(tmp), "%d", - ipv6fc_firewall_enabled); + GETFLAG(IPV6FCFWDISABLEDMASK) ? 0 : 1); str = strcat_str(str, len, &tmplen, tmp); break; case INBOUNDPINHOLEALLOWED_MAGICALVALUE: /* see 2.4.3 of UPnP-gw-WANIPv6FirewallControl-v1-Service.pdf */ snprintf(tmp, sizeof(tmp), "%d", - ipv6fc_inbound_pinhole_allowed); + GETFLAG(IPV6FCINBOUNDDISALLOWEDMASK) ? 0 : 1); str = strcat_str(str, len, &tmplen, tmp); break; #endif diff --git a/miniupnpd/upnpglobalvars.c b/miniupnpd/upnpglobalvars.c index ae4203c..9750f04 100644 --- a/miniupnpd/upnpglobalvars.c +++ b/miniupnpd/upnpglobalvars.c @@ -1,4 +1,4 @@ -/* $Id: upnpglobalvars.c,v 1.34 2014/02/06 09:52:03 nanard Exp $ */ +/* $Id: upnpglobalvars.c,v 1.35 2014/03/10 11:04:53 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2014 Thomas Bernard @@ -24,9 +24,6 @@ const char* lease_file = 0; * when NULL, getifaddr() is used */ const char * use_ext_ip_addr = 0; -/* LAN address */ -/*const char * listen_addr = 0;*/ - unsigned long downstream_bitrate = 0; unsigned long upstream_bitrate = 0; @@ -78,18 +75,10 @@ char model_url[MODEL_URL_MAX_LEN] = ROOTDEV_MODELURL; struct upnpperm * upnppermlist = 0; unsigned int num_upnpperm = 0; -#ifdef ENABLE_NATPMP -/* NAT-PMP */ -#if 0 -unsigned int nextnatpmptoclean_timestamp = 0; -unsigned short nextnatpmptoclean_eport = 0; -unsigned short nextnatpmptoclean_proto = 0; -#endif #ifdef PCP_SADSCP struct dscp_values* dscp_values_list = 0; unsigned int num_dscp_values = 0; #endif /*PCP_SADSCP*/ -#endif /* For automatic removal of expired rules (with LeaseDuration) */ unsigned int nextruletoclean_timestamp = 0; @@ -121,7 +110,6 @@ struct lan_addr_list lan_addrs; #ifdef ENABLE_IPV6 /* ipv6 address used for HTTP */ char ipv6_addr_for_http_with_brackets[64]; -int ipv6_enabled = 1; #endif /* Path of the Unix socket used to communicate with MiniSSDPd */ @@ -131,8 +119,3 @@ const char * minissdpdsocketpath = "/var/run/minissdpd.sock"; unsigned int upnp_bootid = 1; unsigned int upnp_configid = 1337; -#ifdef ENABLE_6FC_SERVICE -int ipv6fc_firewall_enabled = 1; -int ipv6fc_inbound_pinhole_allowed = 1; -#endif - diff --git a/miniupnpd/upnpglobalvars.h b/miniupnpd/upnpglobalvars.h index fb67428..bbfccef 100644 --- a/miniupnpd/upnpglobalvars.h +++ b/miniupnpd/upnpglobalvars.h @@ -1,4 +1,4 @@ -/* $Id: upnpglobalvars.h,v 1.37 2014/02/06 09:52:03 nanard Exp $ */ +/* $Id: upnpglobalvars.h,v 1.38 2014/03/10 11:04:53 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2014 Thomas Bernard @@ -51,6 +51,13 @@ extern int runtime_flags; #ifdef PF_ENABLE_FILTER_RULES #define PFNOQUICKRULESMASK 0x0040 #endif +#ifdef ENABLE_IPV6 +#define IPV6DISABLEDMASK 0x0080 +#endif +#ifdef ENABLE_6FC_SERVICE +#define IPV6FCFWDISABLEDMASK 0x0100 +#define IPV6FCINBOUNDDISALLOWEDMASK 0x0200 +#endif #define SETFLAG(mask) runtime_flags |= mask #define GETFLAG(mask) (runtime_flags & mask) @@ -95,18 +102,10 @@ extern char model_url[]; extern struct upnpperm * upnppermlist; extern unsigned int num_upnpperm; -#ifdef ENABLE_NATPMP -/* NAT-PMP */ -#if 0 -extern unsigned int nextnatpmptoclean_timestamp; -extern unsigned short nextnatpmptoclean_eport; -extern unsigned short nextnatpmptoclean_proto; -#endif #ifdef PCP_SADSCP extern struct dscp_values* dscp_values_list; extern unsigned int num_dscp_values; #endif -#endif /* For automatic removal of expired rules (with LeaseDuration) */ extern unsigned int nextruletoclean_timestamp; @@ -139,7 +138,6 @@ extern struct lan_addr_list lan_addrs; #ifdef ENABLE_IPV6 /* ipv6 address used for HTTP */ extern char ipv6_addr_for_http_with_brackets[64]; -extern int ipv6_enabled; #endif extern const char * minissdpdsocketpath; @@ -148,10 +146,5 @@ extern const char * minissdpdsocketpath; extern unsigned int upnp_bootid; extern unsigned int upnp_configid; -#ifdef ENABLE_6FC_SERVICE -extern int ipv6fc_firewall_enabled; -extern int ipv6fc_inbound_pinhole_allowed; -#endif - #endif diff --git a/miniupnpd/upnpsoap.c b/miniupnpd/upnpsoap.c index fc08ecb..21fc33b 100644 --- a/miniupnpd/upnpsoap.c +++ b/miniupnpd/upnpsoap.c @@ -1,7 +1,7 @@ -/* $Id: upnpsoap.c,v 1.121 2014/02/28 15:01:31 nanard Exp $ */ +/* $Id: upnpsoap.c,v 1.122 2014/03/10 11:04:53 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ - * (c) 2006-2013 Thomas Bernard + * (c) 2006-2014 Thomas Bernard * This software is subject to the conditions detailed * in the LICENCE file provided within the distribution */ @@ -1220,19 +1220,21 @@ GetFirewallStatus(struct upnphttp * h, const char * action) bodylen = snprintf(body, sizeof(body), resp, action, "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1", - ipv6fc_firewall_enabled, ipv6fc_inbound_pinhole_allowed, action); + GETFLAG(IPV6FCFWDISABLEDMASK) ? 0 : 1, + GETFLAG(IPV6FCINBOUNDDISALLOWEDMASK) ? 0 : 1, + action); BuildSendAndCloseSoapResp(h, body, bodylen); } static int CheckStatus(struct upnphttp * h) { - if (!ipv6fc_firewall_enabled) + if (GETFLAG(IPV6FCFWDISABLEDMASK)) { SoapError(h, 702, "FirewallDisabled"); return 0; } - else if(!ipv6fc_inbound_pinhole_allowed) + else if(GETFLAG(IPV6FCINBOUNDDISALLOWEDMASK)) { SoapError(h, 703, "InboundPinholeNotAllowed"); return 0; @@ -1604,7 +1606,7 @@ GetOutboundPinholeTimeout(struct upnphttp * h, const char * action) int opt=0, proto=0; unsigned short iport, rport; - if (!ipv6fc_firewall_enabled) + if (GETFLAG(IPV6FCFWDISABLEDMASK)) { SoapError(h, 702, "FirewallDisabled"); return; From 62d6c860ce83171c6c22d86d4e26c00f7a5a59a2 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Thu, 13 Mar 2014 11:30:53 +0100 Subject: [PATCH 101/104] catch up Changelog.txt see commit 3ed34783981881856b14dcd3e98246495dc6e419 --- miniupnpd/Changelog.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/miniupnpd/Changelog.txt b/miniupnpd/Changelog.txt index 7856b4e..18cac00 100644 --- a/miniupnpd/Changelog.txt +++ b/miniupnpd/Changelog.txt @@ -1,5 +1,9 @@ $Id: Changelog.txt,v 1.362 2014/03/13 10:20:57 nanard Exp $ +2014/03/13: + fix getifaddr_in6() (used for PCP) + implement permissions with PCP Map + 2014/03/10: Enable PCP by default. Work in IPv6 on system where PF_INET6 are restricted to IPv6 only From 9f665b572fe43e2186b9d954ced9ba22979ae39c Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Thu, 13 Mar 2014 11:31:34 +0100 Subject: [PATCH 102/104] miniupnpd: fix BSD Makefile --- miniupnpd/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/miniupnpd/Makefile b/miniupnpd/Makefile index e404609..0025377 100644 --- a/miniupnpd/Makefile +++ b/miniupnpd/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.74 2013/12/13 15:28:34 nanard Exp $ +# $Id: Makefile,v 1.76 2014/03/10 10:26:15 nanard Exp $ # MiniUPnP project # http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ # Author: Thomas Bernard @@ -116,7 +116,7 @@ TESTUPNPDESCGENOBJS = testupnpdescgen.o upnpdescgen.o TESTUPNPPERMISSIONSOBJS = testupnppermissions.o upnppermissions.o TESTGETIFADDROBJS = testgetifaddr.o getifaddr.o MINIUPNPDCTLOBJS = miniupnpdctl.o -TESTASYNCSENDTOOBJS = testasyncsendto.o asyncsendto.o upnputils.o +TESTASYNCSENDTOOBJS = testasyncsendto.o asyncsendto.o upnputils.o bsd/getroute.o EXECUTABLES = miniupnpd testupnpdescgen testgetifstats \ testupnppermissions miniupnpdctl \ From 8d93ddb07672c73ef880ec76e63d3b380b503c32 Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Thu, 13 Mar 2014 11:31:51 +0100 Subject: [PATCH 103/104] miniupnpd: change IP change msg from LOG_DEBUG to LOG_INFO --- miniupnpd/miniupnpd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miniupnpd/miniupnpd.c b/miniupnpd/miniupnpd.c index ccbbd8f..3a8be99 100644 --- a/miniupnpd/miniupnpd.c +++ b/miniupnpd/miniupnpd.c @@ -1676,7 +1676,7 @@ main(int argc, char * * argv) /* send public address change notifications if needed */ if(should_send_public_address_change_notif) { - syslog(LOG_DEBUG, "should send external iface address change notification(s)"); + syslog(LOG_INFO, "should send external iface address change notification(s)"); #ifdef ENABLE_NATPMP if(GETFLAG(ENABLENATPMPMASK)) SendNATPMPPublicAddressChangeNotification(snatpmp, addr_count); From a7d9071c5a03b6009cf3a0e4e62a15a6112e72fd Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Thu, 13 Mar 2014 11:56:28 +0100 Subject: [PATCH 104/104] miniupnpd/upnpevents.c: fix upnp_event_notify_connect() when ENABLE_IPV6 is set --- miniupnpd/Changelog.txt | 3 ++- miniupnpd/upnpevents.c | 13 ++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/miniupnpd/Changelog.txt b/miniupnpd/Changelog.txt index 18cac00..6fe9f06 100644 --- a/miniupnpd/Changelog.txt +++ b/miniupnpd/Changelog.txt @@ -1,8 +1,9 @@ -$Id: Changelog.txt,v 1.362 2014/03/13 10:20:57 nanard Exp $ +$Id: Changelog.txt,v 1.363 2014/03/13 10:53:40 nanard Exp $ 2014/03/13: fix getifaddr_in6() (used for PCP) implement permissions with PCP Map + fix upnp_event_notify_connect() when ENABLE_IPV6 is set 2014/03/10: Enable PCP by default. diff --git a/miniupnpd/upnpevents.c b/miniupnpd/upnpevents.c index 660ccc0..617da21 100644 --- a/miniupnpd/upnpevents.c +++ b/miniupnpd/upnpevents.c @@ -1,4 +1,4 @@ -/* $Id: upnpevents.c,v 1.27 2013/06/13 13:21:30 nanard Exp $ */ +/* $Id: upnpevents.c,v 1.28 2014/03/13 10:53:40 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2008-2013 Thomas Bernard @@ -233,8 +233,10 @@ upnp_event_notify_connect(struct upnp_event_notify * obj) unsigned short port; #ifdef ENABLE_IPV6 struct sockaddr_storage addr; + socklen_t addrlen; #else struct sockaddr_in addr; + socklen_t addrlen; #endif if(!obj) return; @@ -283,23 +285,28 @@ upnp_event_notify_connect(struct upnp_event_notify * obj) sa->sin6_family = AF_INET6; inet_pton(AF_INET6, obj->addrstr, &(sa->sin6_addr)); sa->sin6_port = htons(port); + addrlen = sizeof(struct sockaddr_in6); } else { struct sockaddr_in * sa = (struct sockaddr_in *)&addr; sa->sin_family = AF_INET; inet_pton(AF_INET, obj->addrstr, &(sa->sin_addr)); sa->sin_port = htons(port); + addrlen = sizeof(struct sockaddr_in); } #else addr.sin_family = AF_INET; inet_aton(obj->addrstr, &addr.sin_addr); addr.sin_port = htons(port); + addrlen = sizeof(struct sockaddr_in); #endif syslog(LOG_DEBUG, "%s: '%s' %hu '%s'", "upnp_event_notify_connect", obj->addrstr, port, obj->path); obj->state = EConnecting; - if(connect(obj->s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + if(connect(obj->s, (struct sockaddr *)&addr, addrlen) < 0) { if(errno != EINPROGRESS && errno != EWOULDBLOCK) { - syslog(LOG_ERR, "%s: connect(): %m", "upnp_event_notify_connect"); + syslog(LOG_ERR, "%s: connect(%d, %s, %u): %m", + "upnp_event_notify_connect", obj->s, + obj->addrstr, addrlen); obj->state = EError; } }