From ad88cc0819321eb2841958f846138ac3a225152f Mon Sep 17 00:00:00 2001 From: Thomas Bernard Date: Mon, 24 Mar 2014 12:07:31 +0100 Subject: [PATCH] miniupnpd: start work to enable IPv6 PCP operations --- miniupnpd/Changelog.txt | 5 ++- miniupnpd/Makefile.linux | 9 +++--- miniupnpd/miniupnpd.c | 53 +++++++++++++++++++++++++++--- miniupnpd/natpmp.c | 40 ++++++++++++----------- miniupnpd/natpmp.h | 11 ++++--- miniupnpd/pcpserver.c | 70 ++++++++++++++++++++++++++++++++++------ miniupnpd/pcpserver.h | 11 +++++-- 7 files changed, 154 insertions(+), 45 deletions(-) diff --git a/miniupnpd/Changelog.txt b/miniupnpd/Changelog.txt index 104e129..eefa138 100644 --- a/miniupnpd/Changelog.txt +++ b/miniupnpd/Changelog.txt @@ -1,4 +1,7 @@ -$Id: Changelog.txt,v 1.365 2014/03/14 21:26:34 nanard Exp $ +$Id: Changelog.txt,v 1.366 2014/03/24 11:03:50 nanard Exp $ + +2014/03/24: + start work to enable IPv6 PCP operations 2014/03/14: reject renewal of subscribtion that already timeouted diff --git a/miniupnpd/Makefile.linux b/miniupnpd/Makefile.linux index 86d7d7c..a162db3 100644 --- a/miniupnpd/Makefile.linux +++ b/miniupnpd/Makefile.linux @@ -1,4 +1,4 @@ -# $Id: Makefile.linux,v 1.81 2014/01/27 10:06:58 nanard Exp $ +# $Id: Makefile.linux,v 1.84 2014/03/24 10:43:25 nanard Exp $ # MiniUPnP project # (c) 2006-2014 Thomas Bernard # http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ @@ -253,9 +253,10 @@ 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 asyncsendto.h pcp_msg_struct.h +pcpserver.o: config.h pcpserver.h natpmp.h macros.h upnpglobalvars.h +pcpserver.o: upnppermissions.h miniupnpdtypes.h pcplearndscp.h upnpredirect.h +pcpserver.o: commonrdr.h getifaddr.h asyncsendto.h upnputils.h +pcpserver.o: pcp_msg_struct.h netfilter/iptcrdr.h commonrdr.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 diff --git a/miniupnpd/miniupnpd.c b/miniupnpd/miniupnpd.c index 3a8be99..42829fb 100644 --- a/miniupnpd/miniupnpd.c +++ b/miniupnpd/miniupnpd.c @@ -1,4 +1,4 @@ -/* $Id: miniupnpd.c,v 1.189 2014/03/10 11:04:52 nanard Exp $ */ +/* $Id: miniupnpd.c,v 1.190 2014/03/24 10:49:44 nanard Exp $ */ /* MiniUPnP project * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ * (c) 2006-2014 Thomas Bernard @@ -1460,6 +1460,9 @@ main(int argc, char * * argv) #ifdef ENABLE_NATPMP int * snatpmp = NULL; /* also used for PCP */ #endif +#if defined(ENABLE_IPV6) && defined(ENABLE_PCP) + int spcp_v6 = -1; +#endif #ifdef ENABLE_NFQUEUE int nfqh = -1; #endif @@ -1648,6 +1651,10 @@ main(int argc, char * * argv) } #endif +#if defined(ENABLE_IPV6) && defined(ENABLE_PCP) + spcp_v6 = OpenAndConfPCPv6Socket(); +#endif + /* for miniupnpdctl */ #ifdef USE_MINIUPNPDCTL sctl = OpenAndConfCtlUnixSocket("/var/run/miniupnpd.ctl"); @@ -1842,6 +1849,12 @@ main(int argc, char * * argv) } } #endif +#if defined(ENABLE_IPV6) && defined(ENABLE_PCP) + if(spcp_v6 >= 0) { + FD_SET(spcp_v6, &readset); + max_fd = MAX(max_fd, spcp_v6); + } +#endif #ifdef USE_MINIUPNPDCTL if(sctl >= 0) { FD_SET(sctl, &readset); @@ -1978,19 +1991,23 @@ main(int argc, char * * argv) { unsigned char msg_buff[PCP_MAX_LEN]; struct sockaddr_in senderaddr; + socklen_t senderaddrlen; int len; memset(msg_buff, 0, PCP_MAX_LEN); - len = ReceiveNATPMPOrPCPPacket(snatpmp[i], &senderaddr, - msg_buff, sizeof(msg_buff)); + senderaddrlen = sizeof(senderaddr); + len = ReceiveNATPMPOrPCPPacket(snatpmp[i], + (struct sockaddr *)&senderaddr, + &senderaddrlen, + msg_buff, sizeof(msg_buff)); if (len < 1) continue; #ifdef ENABLE_PCP if (msg_buff[0]==0) { /* version equals to 0 -> means NAT-PMP */ ProcessIncomingNATPMPPacket(snatpmp[i], msg_buff, len, - &senderaddr); + &senderaddr); } else { /* everything else can be PCP */ ProcessIncomingPCPPacket(snatpmp[i], msg_buff, len, - &senderaddr); + (struct sockaddr *)&senderaddr); } #else @@ -1998,6 +2015,25 @@ main(int argc, char * * argv) #endif } } +#endif +#if defined(ENABLE_IPV6) && defined(ENABLE_PCP) + /* in IPv6, only PCP is supported, not NAT-PMP */ + if(spcp_v6 >= 0 && FD_ISSET(spcp_v6, &readset)) + { + unsigned char msg_buff[PCP_MAX_LEN]; + struct sockaddr_in6 senderaddr; + socklen_t senderaddrlen; + int len; + memset(msg_buff, 0, PCP_MAX_LEN); + senderaddrlen = sizeof(senderaddr); + len = ReceiveNATPMPOrPCPPacket(spcp_v6, + (struct sockaddr *)&senderaddr, + &senderaddrlen, + msg_buff, sizeof(msg_buff)); + if(len >= 1) + ProcessIncomingPCPPacket(spcp_v6, msg_buff, len, + (struct sockaddr *)&senderaddr); + } #endif /* process SSDP packets */ if(sudp >= 0 && FD_ISSET(sudp, &readset)) @@ -2119,6 +2155,13 @@ shutdown: } } #endif +#if defined(ENABLE_IPV6) && defined(ENABLE_PCP) + if(spcp_v6 >= 0) + { + close(spcp_v6); + spcp_v6 = -1; + } +#endif #ifdef USE_MINIUPNPDCTL if(sctl>=0) { diff --git a/miniupnpd/natpmp.c b/miniupnpd/natpmp.c index 3c55ee5..694e26c 100644 --- a/miniupnpd/natpmp.c +++ b/miniupnpd/natpmp.c @@ -1,4 +1,4 @@ -/* $Id: natpmp.c,v 1.39 2014/03/07 10:43:30 nanard Exp $ */ +/* $Id: natpmp.c,v 1.43 2014/03/24 10:49:45 nanard Exp $ */ /* MiniUPnP project * (c) 2007-2014 Thomas Bernard * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ @@ -34,13 +34,13 @@ int OpenAndConfNATPMPSocket(in_addr_t addr) snatpmp = socket(PF_INET, SOCK_DGRAM, 0/*IPPROTO_UDP*/); if(snatpmp<0) { - syslog(LOG_ERR, "%s: socket(natpmp): %m", + syslog(LOG_ERR, "%s: socket(): %m", "OpenAndConfNATPMPSocket"); return -1; } if(setsockopt(snatpmp, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0) { - syslog(LOG_WARNING, "%s: setsockopt(natpmp, SO_REUSEADDR): %m", + syslog(LOG_WARNING, "%s: setsockopt(SO_REUSEADDR): %m", "OpenAndConfNATPMPSocket"); } if(!set_non_blocking(snatpmp)) @@ -57,7 +57,8 @@ int OpenAndConfNATPMPSocket(in_addr_t addr) natpmp_addr.sin_addr.s_addr = addr; if(bind(snatpmp, (struct sockaddr *)&natpmp_addr, sizeof(natpmp_addr)) < 0) { - syslog(LOG_ERR, "bind(natpmp): %m"); + syslog(LOG_ERR, "%s: bind(): %m", + "OpenAndConfNATPMPSocket"); close(snatpmp); return -1; } @@ -67,22 +68,25 @@ int OpenAndConfNATPMPSocket(in_addr_t addr) int OpenAndConfNATPMPSockets(int * sockets) { - int i, j; + int i; struct lan_addr_s * lan_addr; - for(i = 0, lan_addr = lan_addrs.lh_first; lan_addr != NULL; lan_addr = lan_addr->list.le_next, i++) + for(i = 0, lan_addr = lan_addrs.lh_first; + lan_addr != NULL; + lan_addr = lan_addr->list.le_next) { sockets[i] = OpenAndConfNATPMPSocket(lan_addr->addr.s_addr); if(sockets[i] < 0) - { - for(j=0; j= 0) + { + close(sockets[i]); + sockets[i] = -1; + } + return -1; } static void FillPublicAddressResponse(unsigned char * resp, in_addr_t senderaddr) @@ -124,15 +128,15 @@ static void FillPublicAddressResponse(unsigned char * resp, in_addr_t senderaddr * The sender information is stored in senderaddr. * Returns number of bytes recevied, even if number is negative. */ -int ReceiveNATPMPOrPCPPacket(int s, struct sockaddr_in* senderaddr, - unsigned char *msg_buff, size_t msg_buff_size) +int ReceiveNATPMPOrPCPPacket(int s, struct sockaddr * senderaddr, + socklen_t * senderaddrlen, + unsigned char * msg_buff, size_t msg_buff_size) { - socklen_t senderaddrlen = sizeof(*senderaddr); int n; n = recvfrom(s, msg_buff, msg_buff_size, 0, - (struct sockaddr *)senderaddr, &senderaddrlen); + senderaddr, senderaddrlen); if(n<0) { /* EAGAIN, EWOULDBLOCK and EINTR : silently ignore (retry next time) diff --git a/miniupnpd/natpmp.h b/miniupnpd/natpmp.h index 5f63517..2f6091b 100644 --- a/miniupnpd/natpmp.h +++ b/miniupnpd/natpmp.h @@ -1,4 +1,4 @@ -/* $Id: natpmp.h,v 1.11 2014/02/01 17:17:35 nanard Exp $ */ +/* $Id: natpmp.h,v 1.12 2014/03/24 10:49:46 nanard Exp $ */ /* MiniUPnP project * author : Thomas Bernard * website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/ @@ -20,11 +20,12 @@ int OpenAndConfNATPMPSockets(int * sockets); -int ReceiveNATPMPOrPCPPacket(int s, struct sockaddr_in* senderaddr, - unsigned char *msg_buff, size_t msg_buff_size); +int ReceiveNATPMPOrPCPPacket(int s, struct sockaddr * senderaddr, + socklen_t * senderaddrlen, + unsigned char * msg_buff, size_t msg_buff_size); -void ProcessIncomingNATPMPPacket(int s, unsigned char *msg_buff, int len, - struct sockaddr_in *senderaddr); +void ProcessIncomingNATPMPPacket(int s, unsigned char * msg_buff, int len, + struct sockaddr_in * senderaddr); void SendNATPMPPublicAddressChangeNotification(int * sockets, int n_sockets); diff --git a/miniupnpd/pcpserver.c b/miniupnpd/pcpserver.c index e6a62bd..b5074dc 100644 --- a/miniupnpd/pcpserver.c +++ b/miniupnpd/pcpserver.c @@ -1,4 +1,4 @@ -/* $Id: pcpserver.c,v 1.20 2014/03/22 12:06:15 nanard Exp $ */ +/* $Id: pcpserver.c,v 1.24 2014/03/24 11:03:52 nanard Exp $ */ /* MiniUPnP project * Website : http://miniupnp.free.fr/ * Author : Peter Tatrai @@ -53,6 +53,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include "pcpserver.h" +#include "natpmp.h" #include "macros.h" #include "upnpglobalvars.h" #include "pcplearndscp.h" @@ -60,6 +61,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "commonrdr.h" #include "getifaddr.h" #include "asyncsendto.h" +#include "upnputils.h" #include "pcp_msg_struct.h" #ifdef PCP_PEER @@ -117,7 +119,7 @@ typedef struct pcp_info { uint8_t is_peer_op; int thirdp_present; /* indicate presence of the options */ int pfailure_present; - char senderaddrstr[INET_ADDRSTRLEN]; + char senderaddrstr[INET_ADDRSTRLEN]; /* only if IPv4 sender */ } pcp_info_t; @@ -1385,19 +1387,29 @@ static void createPCPResponse(unsigned char *response, pcp_info_t *pcp_msg_info) } int ProcessIncomingPCPPacket(int s, unsigned char *buff, int len, - struct sockaddr_in *senderaddr) + const struct sockaddr * senderaddr) { pcp_info_t pcp_msg_info; +#ifdef DEBUG + char addr_str[64]; +#endif memset(&pcp_msg_info, 0, sizeof(pcp_info_t)); - if(!inet_ntop(AF_INET, &senderaddr->sin_addr, - pcp_msg_info.senderaddrstr, - sizeof(pcp_msg_info.senderaddrstr))) { - syslog(LOG_ERR, "inet_ntop(pcpserver): %m"); + if(senderaddr->sa_family == AF_INET) { + const struct sockaddr_in * senderaddr_v4; + senderaddr_v4 = (const struct sockaddr_in *)senderaddr; + if(!inet_ntop(AF_INET, &senderaddr_v4->sin_addr, + pcp_msg_info.senderaddrstr, + sizeof(pcp_msg_info.senderaddrstr))) { + syslog(LOG_ERR, "inet_ntop(pcpserver): %m"); + } } - syslog(LOG_DEBUG, "PCP request received from %s:%hu %dbytes", - pcp_msg_info.senderaddrstr, ntohs(senderaddr->sin_port), len); +#ifdef DEBUG + if(sockaddr_to_string(senderaddr, addr_str, sizeof(addr_str))) + syslog(LOG_DEBUG, "PCP request received from %s %dbytes", + addr_str, len); +#endif if(buff[1] & 128) { /* discarding PCP responses silently */ @@ -1421,4 +1433,44 @@ int ProcessIncomingPCPPacket(int s, unsigned char *buff, int len, return 0; } + +#ifdef ENABLE_IPV6 +int OpenAndConfPCPv6Socket(void) +{ + int s; + int i = 1; + struct sockaddr_in6 addr; + s = socket(PF_INET6, SOCK_DGRAM, 0/*IPPROTO_UDP*/); + if(s < 0) { + syslog(LOG_ERR, "%s: socket(): %m", "OpenAndConfPCPv6Socket"); + return -1; + } + if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i)) < 0) { + syslog(LOG_WARNING, "%s: setsockopt(SO_REUSEADDR): %m", + "OpenAndConfPCPv6Socket"); + } +#ifdef IPV6_V6ONLY + /* force IPV6 only for IPV6 socket. + * see http://www.ietf.org/rfc/rfc3493.txt section 5.3 */ + if(setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &i, sizeof(i)) < 0) { + syslog(LOG_WARNING, "%s: setsockopt(IPV6_V6ONLY): %m", + "OpenAndConfPCPv6Socket"); + } +#endif + if(!set_non_blocking(s)) { + syslog(LOG_WARNING, "%s: set_non_blocking(): %m", + "OpenAndConfPCPv6Socket"); + } + memset(&addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + addr.sin6_port = htons(NATPMP_PORT); + addr.sin6_addr = in6addr_any; + if(bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + syslog(LOG_ERR, "%s: bind(): %m", "OpenAndConfPCPv6Socket"); + close(s); + return -1; + } + return s; +} +#endif /*ENABLE_IPV6*/ #endif /*ENABLE_PCP*/ diff --git a/miniupnpd/pcpserver.h b/miniupnpd/pcpserver.h index cc295f3..bd03b91 100644 --- a/miniupnpd/pcpserver.h +++ b/miniupnpd/pcpserver.h @@ -1,4 +1,4 @@ -/* $Id: pcpserver.h,v 1.2 2013/12/13 15:48:39 nanard Exp $ */ +/* $Id: pcpserver.h,v 1.3 2014/03/24 10:49:46 nanard Exp $ */ /* MiniUPnP project * Website : http://miniupnp.free.fr/ * Author : Peter Tatrai @@ -36,12 +36,17 @@ POSSIBILITY OF SUCH DAMAGE. #define PCP_MIN_LEN 24 #define PCP_MAX_LEN 1100 -struct sockaddr_in; +struct sockaddr; /* * returns 0 upon success 1 otherwise */ int ProcessIncomingPCPPacket(int s, unsigned char *msg_buff, int len, - struct sockaddr_in *senderaddr); + const struct sockaddr *senderaddr); + +/* + * returns the socket + */ +int OpenAndConfPCPv6Socket(void); #endif /* PCPSERVER_H_INCLUDED */