Forward port of svn rev. 564:

* New internal buffer added to store global/ula IPV6 address.
* Macros to test whether an IPV6 address is global or ula.
* UpnpGetServerUlaGuaIp6Address(): added interface.
* IN6_IS_ADDR_GLOBAL, IN6_IS_ADDR_ULA: new macros.
* gIF_IPV6_ULA_GUA: new buffer.
* UpnpRegisterRootDevice3(): Change to the test of already registered
devices for IPV6.
* UpnpGetIfInfo(): gua/ula issues.

Patch submitted by Ronan Menard.



git-svn-id: https://pupnp.svn.sourceforge.net/svnroot/pupnp/trunk@565 119443c7-1b9e-41f8-b6fc-b9c35fce742c
This commit is contained in:
Marcelo Roberto Jimenez 2010-08-21 20:51:29 +00:00
parent bc551a1ab3
commit b895fce678
4 changed files with 99 additions and 38 deletions

View File

@ -211,6 +211,18 @@ Version 1.8.0
Version 1.6.7 Version 1.6.7
******************************************************************************* *******************************************************************************
2010-08-21 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
* New internal buffer added to store global/ula IPV6 address.
* Macros to test whether an IPV6 address is global or ula.
* UpnpGetServerUlaGuaIp6Address(): added interface.
* IN6_IS_ADDR_GLOBAL, IN6_IS_ADDR_ULA: new macros.
* gIF_IPV6_ULA_GUA: new buffer.
* UpnpRegisterRootDevice3(): Change to the test of already registered
devices for IPV6.
* UpnpGetIfInfo(): gua/ula issues.
Patch submitted by Ronan Menard.
2010-08-19 Marcelo Jimenez <mroberto(at)users.sourceforge.net> 2010-08-19 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
* libUPnP does support IPV6 now. * libUPnP does support IPV6 now.

View File

@ -844,6 +844,7 @@ EXPORT_SPEC char *UpnpGetServerIpAddress(void);
*/ */
EXPORT_SPEC char *UpnpGetServerIp6Address(void); EXPORT_SPEC char *UpnpGetServerIp6Address(void);
EXPORT_SPEC char *UpnpGetServerUlaGuaIp6Address(void);
/*! /*!
* \brief Registers a device application with the UPnP Library. * \brief Registers a device application with the UPnP Library.

View File

@ -96,6 +96,18 @@
#endif /* INTERNAL_WEB_SERVER */ #endif /* INTERNAL_WEB_SERVER */
#ifndef IN6_IS_ADDR_GLOBAL
#define IN6_IS_ADDR_GLOBAL(a) \
(((((__const uint8_t *) (a))[0] & htonl(0xff000000)) <= htonl(0x3f000000) \
&& (((__const uint8_t *) (a))[0] & htonl(0xff000000)) >= htonl(0x20000000)))
#endif /* IS ADDR GLOBAL */
#ifndef IN6_IS_ADDR_ULA
#define IN6_IS_ADDR_ULA(a) \
((((__const uint32_t *) (a))[0] & htonl(0xfe000000)) \
== htonl (0xfc000000))
#endif /* IS ADDR ULA */
/*! This structure is for virtual directory callbacks */ /*! This structure is for virtual directory callbacks */
struct VirtualDirCallbacks virtualDirCallback; struct VirtualDirCallbacks virtualDirCallback;
@ -140,6 +152,9 @@ char gIF_IPV4[22]/* INET_ADDRSTRLEN*/ = { '\0' };
/*! Static buffer to contain interface IPv6 address. (extern'ed in upnp.h) */ /*! Static buffer to contain interface IPv6 address. (extern'ed in upnp.h) */
char gIF_IPV6[65]/* INET6_ADDRSTRLEN*/ = { '\0' }; char gIF_IPV6[65]/* INET6_ADDRSTRLEN*/ = { '\0' };
/*! Static buffer to contain interface ULA or GUA IPv6 address. (extern'ed in upnp.h) */
char gIF_IPV6_ULA_GUA[INET6_ADDRSTRLEN] = { '\0' };
/*! Contains interface index. (extern'ed in upnp.h) */ /*! Contains interface index. (extern'ed in upnp.h) */
int gIF_INDEX = -1; int gIF_INDEX = -1;
@ -634,6 +649,14 @@ char *UpnpGetServerIp6Address(void)
return gIF_IPV6; return gIF_IPV6;
} }
char *UpnpGetServerUlaGuaIp6Address(void)
{
if( UpnpSdkInit != 1 ) {
return NULL;
}
return gIF_IPV6_ULA_GUA;
}
#ifdef INCLUDE_DEVICE_APIS #ifdef INCLUDE_DEVICE_APIS
int UpnpRegisterRootDevice( int UpnpRegisterRootDevice(
@ -947,12 +970,24 @@ int UpnpRegisterRootDevice3(
goto exit_function; goto exit_function;
} }
if ((AddressFamily == AF_INET && UpnpSdkDeviceRegisteredV4 == 1) || /* Test for already regsitered IPV4. */
(AddressFamily == AF_INET6 && UpnpSdkDeviceregisteredV6 == 1)) { if (AddressFamily == AF_INET && UpnpSdkDeviceRegisteredV4 == 1) {
retVal = UPNP_E_ALREADY_REGISTERED; retVal = UPNP_E_ALREADY_REGISTERED;
goto exit_function; goto exit_function;
} }
/* Test for already registered IPV6. IPV6 devices might register on multiple
* IPv6 addresses (link local and GUA or ULA), so we must to check the
* description URL in the HandleTable. */
int handler_index = 0;
while (handler_index < NUM_HANDLE && HandleTable[handler_index] != NULL) {
if (strcmp(((struct Handle_Info *)HandleTable[handler_index])->DescURL, DescUrl)) {
retVal = UPNP_E_ALREADY_REGISTERED;
goto exit_function;
}
handler_index++;
}
*Hnd = GetFreeHandle(); *Hnd = GetFreeHandle();
if (*Hnd == UPNP_E_OUTOF_HANDLE) { if (*Hnd == UPNP_E_OUTOF_HANDLE) {
retVal = UPNP_E_OUTOF_MEMORY; retVal = UPNP_E_OUTOF_MEMORY;
@ -3152,44 +3187,53 @@ int UpnpGetIfInfo(const char *IfName)
} }
close( LocalSock ); close( LocalSock );
// Failed to find a valid interface, or valid address. // Failed to find a valid interface, or valid address.
if( ifname_found == 0 || valid_addr_found == 0 ) { if (ifname_found == 0 || valid_addr_found == 0) {
UpnpPrintf( UPNP_CRITICAL, API, __FILE__, __LINE__, UpnpPrintf(UPNP_CRITICAL, API, __FILE__, __LINE__,
"Failed to find an adapter with valid IP addresses for use.\n" ); "Failed to find an adapter with valid IP addresses for use.\n");
return UPNP_E_INVALID_INTERFACE;
} return UPNP_E_INVALID_INTERFACE;
}
// Try to get the IPv6 address for the same interface
// from "/proc/net/if_inet6", if possible. // Try to get the IPv6 address for the same interface
inet6_procfd = fopen( "/proc/net/if_inet6", "r" ); // from "/proc/net/if_inet6", if possible.
if( inet6_procfd != NULL ) { inet6_procfd = fopen("/proc/net/if_inet6", "r");
while( fscanf(inet6_procfd, if (inet6_procfd) {
"%4s%4s%4s%4s%4s%4s%4s%4s %02x %*02x %*02x %*02x %*20s\n", while (fscanf(inet6_procfd,
addr6[0],addr6[1],addr6[2],addr6[3], "%4s%4s%4s%4s%4s%4s%4s%4s %02x %*02x %*02x %*02x %*20s\n",
addr6[4],addr6[5],addr6[6],addr6[7], &if_idx) != EOF) { addr6[0],addr6[1],addr6[2],addr6[3],
// Get same interface as IPv4 address retrieved. addr6[4],addr6[5],addr6[6],addr6[7], &if_idx) != EOF) {
if( gIF_INDEX == if_idx ) { // Get same interface as IPv4 address retrieved.
snprintf(buf, sizeof(buf), "%s:%s:%s:%s:%s:%s:%s:%s", if( gIF_INDEX == if_idx ) {
addr6[0],addr6[1],addr6[2],addr6[3], snprintf(buf, sizeof(buf), "%s:%s:%s:%s:%s:%s:%s:%s",
addr6[4],addr6[5],addr6[6],addr6[7]); addr6[0],addr6[1],addr6[2],addr6[3],
// Validate formed address and check for link-local. addr6[4],addr6[5],addr6[6],addr6[7]);
if( inet_pton(AF_INET6, buf, &v6_addr) > 0 && // Validate formed address and check for link-local.
IN6_IS_ADDR_LINKLOCAL(&v6_addr) ) { if (inet_pton(AF_INET6, buf, &v6_addr) > 0) {
// Got valid IPv6 link-local adddress. if (IN6_IS_ADDR_ULA(&v6_addr)) {
strncpy( gIF_IPV6, buf, sizeof(gIF_IPV6) ); // Got valid IPv6 ula.
break; strncpy(gIF_IPV6_ULA_GUA, buf, sizeof(gIF_IPV6_ULA_GUA));
} } else if (IN6_IS_ADDR_GLOBAL(&v6_addr) &&
} strlen(gIF_IPV6_ULA_GUA) == 0) {
} // got a GUA, should store it while no ULA is found
fclose( inet6_procfd ); strncpy(gIF_IPV6_ULA_GUA, buf, sizeof(gIF_IPV6_ULA_GUA));
} } else if (IN6_IS_ADDR_LINKLOCAL(&v6_addr) &&
strlen(gIF_IPV6) == 0) {
// got a Link local IPv6 address.
strncpy(gIF_IPV6, buf, sizeof(gIF_IPV6));
}
}
}
}
fclose(inet6_procfd);
}
#endif #endif
UpnpPrintf( UPNP_INFO, API, __FILE__, __LINE__, UpnpPrintf( UPNP_INFO, API, __FILE__, __LINE__,
"Interface name=%s, index=%d, v4=%s, v6=%s\n", "Interface name=%s, index=%d, v4=%s, v6=%s, ULA or GUA v6=%s\n",
gIF_NAME, gIF_INDEX, gIF_IPV4, gIF_IPV6 ); gIF_NAME, gIF_INDEX, gIF_IPV4, gIF_IPV6, gIF_IPV6_ULA_GUA );
return UPNP_E_SUCCESS; return UPNP_E_SUCCESS;
} }
@ -3204,7 +3248,7 @@ void UpnpThreadDistribution(struct UpnpNonblockParam *Param)
UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__, UpnpPrintf(UPNP_ALL, API, __FILE__, __LINE__,
"Inside UpnpThreadDistribution \n"); "Inside UpnpThreadDistribution \n");
switch ( Param->FunName ) { switch (Param->FunName) {
#if EXCLUDE_GENA == 0 #if EXCLUDE_GENA == 0
case SUBSCRIBE: { case SUBSCRIBE: {
UpnpEventSubscribe *evt = UpnpEventSubscribe_new(); UpnpEventSubscribe *evt = UpnpEventSubscribe_new();

View File

@ -180,6 +180,9 @@ extern char gIF_NAME[LINE_SIZE];
extern char gIF_IPV4[22]; extern char gIF_IPV4[22];
/*! INET6_ADDRSTRLEN. */ /*! INET6_ADDRSTRLEN. */
extern char gIF_IPV6[65]; extern char gIF_IPV6[65];
extern char gIF_IPV6_ULA_GUA[INET6_ADDRSTRLEN];
extern int gIF_INDEX; extern int gIF_INDEX;
@ -259,6 +262,7 @@ typedef enum {
* \li gIF_NAME -> Interface name (by input or found). * \li gIF_NAME -> Interface name (by input or found).
* \li gIF_IPV4 -> IPv4 address (if any). * \li gIF_IPV4 -> IPv4 address (if any).
* \li gIF_IPV6 -> IPv6 address (if any). * \li gIF_IPV6 -> IPv6 address (if any).
* \li gIF_IPV6_ULA_GUA -> ULA or GUA IPv6 address (if any)
* \li gIF_INDEX -> Interface index number. * \li gIF_INDEX -> Interface index number.
* *
* \return UPNP_E_SUCCESS on success. * \return UPNP_E_SUCCESS on success.