Add support for conditionally enabling ipv6

(cherry picked from commit 6b0d84fc952350e4e99a5f2e2ba9bd1231a670a2)
This commit is contained in:
Chandra Penke 2010-09-09 17:36:25 -07:00 committed by Marcelo Roberto Jimenez
parent 7137f6e261
commit ae516b6bd3
9 changed files with 110 additions and 17 deletions

View File

@ -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])

View File

@ -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.
*

View File

@ -90,6 +90,9 @@
* (i.e. configure --enable-tools) : <upnp/upnptools.h> 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 */

View File

@ -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)

View File

@ -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 */

View File

@ -6,6 +6,9 @@
#ifdef WIN32
#ifdef IPV6_
#define INET_IPV6
#endif
#include "unixutil.h"

View File

@ -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 *);

View File

@ -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;

View File

@ -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, "<Invalid address family>", 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 */