diff --git a/configure.ac b/configure.ac index a29c5c1..cb971c4 100644 --- a/configure.ac +++ b/configure.ac @@ -256,6 +256,11 @@ if test "x$enable_tools" = xyes ; then AC_DEFINE(UPNP_HAVE_TOOLS, 1, [see upnpconfig.h]) fi +RT_BOOL_ARG_ENABLE([ipv6], [no], [ipv6 support]) +if test "x$enable_ipv6" = xyes ; then + AC_DEFINE(UPNP_ENABLE_IPV6, 1, [see upnpconfig.h]) +fi + RT_BOOL_ARG_ENABLE([samples], [yes], [compilation of upnp/sample/ code]) diff --git a/upnp/inc/upnp.h b/upnp/inc/upnp.h index 324853b..15e67f2 100644 --- a/upnp/inc/upnp.h +++ b/upnp/inc/upnp.h @@ -987,6 +987,7 @@ EXPORT_SPEC int UpnpInit( * \li \c UPNP_E_INVALID_INTERFACE: IfName is invalid or does not * have a valid IPv4 or IPv6 addresss configured. */ +#ifdef ENABLE_IPV6 EXPORT_SPEC int UpnpInit2( /*! The interface name to use by the UPnP SDK operations. * Examples: "eth0", "xl0", "Local Area Connection", \c NULL to @@ -995,6 +996,7 @@ EXPORT_SPEC int UpnpInit2( /*! Local Port to listen for incoming connections. * \c NULL will pick an arbitrary free port. */ unsigned short DestPort); +#endif /*! @@ -1044,8 +1046,9 @@ EXPORT_SPEC unsigned short UpnpGetServerPort(void); * related requests. * \li On error: 0 is returned if \b UpnpInit has not succeeded. */ +#ifdef ENABLE_IPV6 EXPORT_SPEC unsigned short UpnpGetServerPort6(void); - +#endif /*! * \brief Returns the local IPv4 listening ip address. * @@ -1071,10 +1074,11 @@ EXPORT_SPEC char *UpnpGetServerIpAddress(void); * listening for UPnP related requests. * \li On error: \c NULL is returned if \b UpnpInit has not succeeded. */ +#ifdef ENABLE_IPV6 EXPORT_SPEC char *UpnpGetServerIp6Address(void); EXPORT_SPEC char *UpnpGetServerUlaGuaIp6Address(void); - +#endif /*! * \brief Registers a device application with the UPnP Library. * diff --git a/upnp/inc/upnpconfig.h.in b/upnp/inc/upnpconfig.h.in index b729f43..78d7b0d 100644 --- a/upnp/inc/upnpconfig.h.in +++ b/upnp/inc/upnpconfig.h.in @@ -90,6 +90,9 @@ * (i.e. configure --enable-tools) : file is available */ #undef UPNP_HAVE_TOOLS +/** Defined to 1 if the library has been compiled with ipv6 support + * (i.e. configure --enable-ipv6) */ +#undef UPNP_ENABLE_IPV6 #endif /* UPNP_CONFIG_H */ diff --git a/upnp/src/api/upnpapi.c b/upnp/src/api/upnpapi.c index 01be2fb..b340120 100644 --- a/upnp/src/api/upnpapi.c +++ b/upnp/src/api/upnpapi.c @@ -488,7 +488,7 @@ exit_function: return retVal; } - +#ifndef UPNP_ENABLE_IPV6 int UpnpInit2(const char *IfName, unsigned short DestPort) { int retVal; @@ -535,6 +535,7 @@ exit_function: return UPNP_E_SUCCESS; } +#endif int UpnpFinish(void) @@ -620,7 +621,7 @@ unsigned short UpnpGetServerPort(void) return LOCAL_PORT_V4; } - +#ifdef UPNP_ENABLE_IPV6 unsigned short UpnpGetServerPort6(void) { if (UpnpSdkInit != 1) { @@ -629,6 +630,7 @@ unsigned short UpnpGetServerPort6(void) return LOCAL_PORT_V6; } +#endif char *UpnpGetServerIpAddress(void) diff --git a/upnp/src/genlib/miniserver/miniserver.c b/upnp/src/genlib/miniserver/miniserver.c index 842339c..80ad18b 100644 --- a/upnp/src/genlib/miniserver/miniserver.c +++ b/upnp/src/genlib/miniserver/miniserver.c @@ -581,39 +581,58 @@ static int get_miniserver_sockets( struct sockaddr_storage __ss_v4; struct sockaddr_storage __ss_v6; struct sockaddr_in* serverAddr4 = (struct sockaddr_in*)&__ss_v4; +#ifdef UPNP_ENABLE_IPV6 struct sockaddr_in6* serverAddr6 = (struct sockaddr_in6*)&__ss_v6; - SOCKET listenfd4, listenfd6; +#endif + SOCKET listenfd4 = INVALID_SOCKET; +#ifdef UPNP_ENABLE_IPV6 + SOCKET listenfd6 = INVALID_SOCKET; +#endif int ret_code; unsigned short actual_port4, actual_port6; int reuseaddr_on = 0; int sockError = UPNP_E_SUCCESS; int errCode = 0; + // + // Initialize all the sockets to be invalid + // + out->miniServerSock4 = INVALID_SOCKET; + out->miniServerSock6 = INVALID_SOCKET; + // Create listen socket for IPv4/IPv6. An error here may indicate // that we don't have an IPv4/IPv6 stack. listenfd4 = socket(AF_INET, SOCK_STREAM, 0); - listenfd6 = socket(AF_INET6, SOCK_STREAM, 0); - if (listenfd4 == INVALID_SOCKET && listenfd6 == INVALID_SOCKET) { + if (listenfd4 == INVALID_SOCKET) { return UPNP_E_OUTOF_SOCKET; } +#ifdef UPNP_ENABLE_IPV6 + listenfd6 = socket(AF_INET6, SOCK_STREAM, 0); + if (listenfd6 == INVALID_SOCKET) { + return UPNP_E_OUTOF_SOCKET; + } +#endif + // As per the IANA specifications for the use of ports by applications // override the listen port passed in with the first available if (listen_port4 < APPLICATION_LISTENING_PORT) { listen_port4 = APPLICATION_LISTENING_PORT; } +#ifdef UPNP_ENABLE_IPV6 if (listen_port6 < APPLICATION_LISTENING_PORT) { listen_port6 = APPLICATION_LISTENING_PORT; } - +#endif memset(&__ss_v4, 0, sizeof (__ss_v4)); serverAddr4->sin_family = AF_INET; serverAddr4->sin_addr.s_addr = htonl(INADDR_ANY); +#ifdef UPNP_ENABLE_IPV6 memset(&__ss_v6, 0, sizeof (__ss_v6)); serverAddr6->sin6_family = AF_INET6; serverAddr6->sin6_addr = in6addr_any; - +#endif // Getting away with implementation of re-using address:port and instead // choosing to increment port numbers. // Keeping the re-use address code as an optional behaviour that can be @@ -633,8 +652,10 @@ static int get_miniserver_sockets( if (sockError == -1) { shutdown(listenfd4, SD_BOTH); UpnpCloseSocket(listenfd4); +#ifdef UPNP_ENABLE_IPV6 shutdown(listenfd6, SD_BOTH); UpnpCloseSocket(listenfd6); +#endif return UPNP_E_SOCKET_BIND; } @@ -647,14 +668,18 @@ static int get_miniserver_sockets( errorBuffer); shutdown(listenfd4, SD_BOTH); UpnpCloseSocket(listenfd4); +#ifdef UPNP_ENABLE_IPV6 shutdown(listenfd6, SD_BOTH); UpnpCloseSocket(listenfd6); +#endif /* Bind failed */ return UPNP_E_SOCKET_BIND; } } - if(listenfd6 != INVALID_SOCKET) { +#ifdef UPNP_ENABLE_IPV6 + if(listenfd6 != INVALID_SOCKET) + { sockError = setsockopt(listenfd6, SOL_SOCKET, SO_REUSEADDR, (const char *)&reuseaddr_on, sizeof (int)); if (sockError == -1) { @@ -680,7 +705,9 @@ static int get_miniserver_sockets( return UPNP_E_SOCKET_BIND; } } - } else { +#endif //IPv6 + } else + { if (listenfd4 != INVALID_SOCKET) { unsigned short orig_listen_port4 = listen_port4; do { @@ -707,12 +734,15 @@ static int get_miniserver_sockets( errorBuffer); shutdown(listenfd4, SD_BOTH); UpnpCloseSocket(listenfd4); +#ifdef UPNP_ENABLE_IPV6 shutdown(listenfd6, SD_BOTH); UpnpCloseSocket(listenfd6); +#endif return UPNP_E_SOCKET_BIND; // bind failed } } +#ifdef UPNP_ENABLE_IPV6 if (listenfd6 != INVALID_SOCKET) { unsigned short orig_listen_port6 = listen_port6; do { @@ -745,6 +775,7 @@ static int get_miniserver_sockets( return UPNP_E_SOCKET_BIND; } } +#endif } UpnpPrintf( UPNP_INFO, MSERV, __FILE__, __LINE__, @@ -759,8 +790,10 @@ static int get_miniserver_sockets( errorBuffer); shutdown(listenfd4, SD_BOTH); UpnpCloseSocket(listenfd4); +#ifdef UPNP_ENABLE_IPV6 shutdown(listenfd6, SD_BOTH); UpnpCloseSocket(listenfd6); +#endif return UPNP_E_LISTEN; } @@ -768,14 +801,17 @@ static int get_miniserver_sockets( if (actual_port4 <= 0) { shutdown(listenfd4, SD_BOTH); UpnpCloseSocket(listenfd4); +#ifdef UPNP_ENABLE_IPV6 shutdown(listenfd6, SD_BOTH); UpnpCloseSocket(listenfd6); +#endif return UPNP_E_INTERNAL_ERROR; } out->miniServerPort4 = actual_port4; } +#ifdef UPNP_ENABLE_IPV6 if (listenfd6 != INVALID_SOCKET) { ret_code = listen(listenfd6, SOMAXCONN); if (ret_code == -1) { @@ -801,10 +837,11 @@ static int get_miniserver_sockets( out->miniServerPort6 = actual_port6; } - +#endif out->miniServerSock4 = listenfd4; +#ifdef UPNP_ENABLE_IPV6 out->miniServerSock6 = listenfd6; - +#endif return UPNP_E_SUCCESS; } #endif /* INTERNAL_WEB_SERVER */ diff --git a/upnp/src/inc/inet_pton.h b/upnp/src/inc/inet_pton.h index f828e8e..38f884e 100644 --- a/upnp/src/inc/inet_pton.h +++ b/upnp/src/inc/inet_pton.h @@ -6,6 +6,9 @@ #ifdef WIN32 +#ifdef IPV6_ +#define INET_IPV6 +#endif #include "unixutil.h" diff --git a/upnp/src/inc/ssdplib.h b/upnp/src/inc/ssdplib.h index b2d5f6a..948b2a2 100644 --- a/upnp/src/inc/ssdplib.h +++ b/upnp/src/inc/ssdplib.h @@ -186,8 +186,9 @@ typedef struct /* globals */ CLIENTONLY(extern SOCKET gSsdpReqSocket4;); +#ifdef UPNP_ENABLE_IPV6 CLIENTONLY(extern SOCKET gSsdpReqSocket6;); - +#endif typedef int (*ParserFun)(char *, Event *); diff --git a/upnp/src/ssdp/ssdp_ctrlpt.c b/upnp/src/ssdp/ssdp_ctrlpt.c index 48941b0..456ff0b 100644 --- a/upnp/src/ssdp/ssdp_ctrlpt.c +++ b/upnp/src/ssdp/ssdp_ctrlpt.c @@ -594,12 +594,14 @@ int SearchByTarget( FD_SET(gSsdpReqSocket4, &wrSet); max_fd = max(max_fd, gSsdpReqSocket4); } +#ifdef UPNP_ENABLE_IPV6 if (gSsdpReqSocket6 != INVALID_SOCKET) { setsockopt(gSsdpReqSocket6, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *)&gIF_INDEX, sizeof (gIF_INDEX)); FD_SET(gSsdpReqSocket6, &wrSet); max_fd = max(max_fd, gSsdpReqSocket6); } +#endif ret = select(max_fd + 1, NULL, &wrSet, NULL, NULL); if (ret == -1) { @@ -609,11 +611,13 @@ int SearchByTarget( errorBuffer); shutdown(gSsdpReqSocket4, SD_BOTH); UpnpCloseSocket(gSsdpReqSocket4); +#ifdef UPNP_ENABLE_IPV6 shutdown(gSsdpReqSocket6, SD_BOTH); UpnpCloseSocket(gSsdpReqSocket6); - +#endif return UPNP_E_INTERNAL_ERROR; } +#ifdef UPNP_ENABLE_IPV6 if (gSsdpReqSocket6 != INVALID_SOCKET && FD_ISSET(gSsdpReqSocket6, &wrSet)) { int NumCopy = 0; @@ -640,6 +644,8 @@ int SearchByTarget( imillisleep(SSDP_PAUSE); } } +#endif //IPv6 + if (gSsdpReqSocket4 != INVALID_SOCKET && FD_ISSET(gSsdpReqSocket4, &wrSet)) { int NumCopy = 0; diff --git a/upnp/src/ssdp/ssdp_server.c b/upnp/src/ssdp/ssdp_server.c index f230b75..c1ac8df 100644 --- a/upnp/src/ssdp/ssdp_server.c +++ b/upnp/src/ssdp/ssdp_server.c @@ -51,16 +51,22 @@ #define MAX_TIME_TOREAD 45 CLIENTONLY( SOCKET gSsdpReqSocket4 = INVALID_SOCKET; ) +#ifdef UPNP_ENABLE_IPV6 CLIENTONLY( SOCKET gSsdpReqSocket6 = INVALID_SOCKET; ) +#endif void RequestHandler(); int create_ssdp_sock_v4( SOCKET* ssdpSock ); +#ifdef UPNP_ENABLE_IPV6 int create_ssdp_sock_v6( SOCKET* ssdpSock ); int create_ssdp_sock_v6_ula_gua( SOCKET* ssdpSock ); +#endif #if INCLUDE_CLIENT_APIS int create_ssdp_sock_reqv4( SOCKET* ssdpReqSock ); +#ifdef UPNP_ENABLE_IPV6 int create_ssdp_sock_reqv6( SOCKET* ssdpReqSock ); #endif +#endif Event ErrotEvt; enum Listener { Idle, Stopping, Running }; @@ -791,11 +797,20 @@ readFromSSDPSocket( SOCKET socket ) //initialize parser #ifdef INCLUDE_CLIENT_APIS +#ifdef UPNP_ENABLE_IPV6 if( socket == gSsdpReqSocket4 || socket == gSsdpReqSocket6 ) { parser_response_init( &data->parser, HTTPMETHOD_MSEARCH ); } else { parser_request_init( &data->parser ); } +#else + if( socket == gSsdpReqSocket4 ) { + parser_response_init( &data->parser, HTTPMETHOD_MSEARCH ); + } else { + parser_request_init( &data->parser ); + } + +#endif #else parser_request_init( &data->parser ); #endif @@ -820,8 +835,10 @@ readFromSSDPSocket( SOCKET socket ) if( __ss.ss_family == AF_INET ) inet_ntop( AF_INET, &((struct sockaddr_in*)&__ss)->sin_addr, ntop_buf, sizeof(ntop_buf) ); +#ifdef UPNP_ENABLE_IPV6 else if( __ss.ss_family == AF_INET6 ) inet_ntop( AF_INET6, &((struct sockaddr_in6*)&__ss)->sin6_addr, ntop_buf, sizeof(ntop_buf) ); +#endif else strncpy( ntop_buf, "", sizeof(ntop_buf) ); @@ -876,6 +893,9 @@ int get_ssdp_sockets(MiniServerSockArray *out) { int retVal; + out->ssdpReqSock4 = INVALID_SOCKET; + out->ssdpReqSock6 = INVALID_SOCKET; + #if INCLUDE_CLIENT_APIS /* Create the IPv4 socket for SSDP REQUESTS */ if(strlen(gIF_IPV4) > 0) { @@ -890,6 +910,7 @@ int get_ssdp_sockets(MiniServerSockArray *out) } /* Create the IPv6 socket for SSDP REQUESTS */ +#ifdef UPNP_ENABLE_IPV6 if (strlen(gIF_IPV6) > 0) { retVal = create_ssdp_sock_reqv6(&out->ssdpReqSock6); if (retVal != UPNP_E_SUCCESS) { @@ -902,6 +923,9 @@ int get_ssdp_sockets(MiniServerSockArray *out) } else { out->ssdpReqSock6 = INVALID_SOCKET; } +#endif //IPv6 + + #endif /* INCLUDE_CLIENT_APIS */ /* Create the IPv4 socket for SSDP */ @@ -921,6 +945,7 @@ int get_ssdp_sockets(MiniServerSockArray *out) } /* Create the IPv6 socket for SSDP */ +#ifdef UPNP_ENABLE_IPV6 if (strlen(gIF_IPV6) > 0) { retVal = create_ssdp_sock_v6(&out->ssdpSock6); if (retVal != UPNP_E_SUCCESS) { @@ -956,6 +981,8 @@ int get_ssdp_sockets(MiniServerSockArray *out) } else { out->ssdpSock6UlaGua = INVALID_SOCKET; } +#endif //IPv6 + return UPNP_E_SUCCESS; } @@ -1011,6 +1038,7 @@ int create_ssdp_sock_reqv4( SOCKET* ssdpReqSock ) * Returns: void * ***************************************************************************/ +#ifdef UPNP_ENABLE_IPV6 int create_ssdp_sock_reqv6( SOCKET* ssdpReqSock ) { char errorBuffer[ERROR_BUFFER_LEN]; @@ -1035,6 +1063,8 @@ int create_ssdp_sock_reqv6( SOCKET* ssdpReqSock ) return UPNP_E_SUCCESS; } +#endif // IPv6 + #endif /* INCLUDE_CLIENT_APIS */ @@ -1178,6 +1208,7 @@ int create_ssdp_sock_v4( SOCKET* ssdpSock ) * Returns: void * ***************************************************************************/ +#ifdef UPNP_ENABLE_IPV6 int create_ssdp_sock_v6( SOCKET* ssdpSock ) { char errorBuffer[ERROR_BUFFER_LEN]; @@ -1274,7 +1305,7 @@ int create_ssdp_sock_v6( SOCKET* ssdpSock ) return UPNP_E_SUCCESS; } - +#endif // IPv6 /************************************************************************ * Function : create_ssdp_sock_v6_ula_gua @@ -1288,6 +1319,7 @@ int create_ssdp_sock_v6( SOCKET* ssdpSock ) * Returns: void * ***************************************************************************/ +#ifdef UPNP_ENABLE_IPV6 int create_ssdp_sock_v6_ula_gua(SOCKET *ssdpSock) { char errorBuffer[ERROR_BUFFER_LEN]; @@ -1385,7 +1417,7 @@ int create_ssdp_sock_v6_ula_gua(SOCKET *ssdpSock) return UPNP_E_SUCCESS; } - +#endif //IPv6 #endif /* EXCLUDE_SSDP */