* upnp/src/ssdp/ssdp_device.c: Fix for IPV6 ULA/GUA issues.

* upnp/src/ssdp/ssdp_ctrlpt.c: Fix for IPV6 ULA/GUA issues.
* upnp/src/ssdp/ssdp_server.c: Fix for IPV6 ULA/GUA issues.

Patch submitted by Ronan Menard.



git-svn-id: https://pupnp.svn.sourceforge.net/svnroot/pupnp/branches/branch-1.6.x@578 119443c7-1b9e-41f8-b6fc-b9c35fce742c
This commit is contained in:
Marcelo Roberto Jimenez
2010-08-22 01:34:35 +00:00
parent a362d06dff
commit 5a2cc884c1
4 changed files with 577 additions and 275 deletions

View File

@@ -387,6 +387,35 @@ CreateClientRequestPacket( IN char *RqstBuf,
strcat( RqstBuf, "\r\n" );
}
static void CreateClientRequestPacketUlaGua(
IN char *RqstBuf,
IN int Mx,
IN char *SearchTarget,
IN int AddressFamily)
{
char TempBuf[COMMAND_LEN];
strcpy(RqstBuf, "M-SEARCH * HTTP/1.1\r\n");
if (AddressFamily == AF_INET) {
sprintf(TempBuf, "HOST: %s:%d\r\n", SSDP_IP, SSDP_PORT);
} else if (AddressFamily == AF_INET6) {
sprintf(TempBuf, "HOST: [%s]:%d\r\n", SSDP_IPV6_SITELOCAL, SSDP_PORT);
}
strcat(RqstBuf, TempBuf);
strcat(RqstBuf, "MAN: \"ssdp:discover\"\r\n");
if (Mx > 0) {
sprintf(TempBuf, "MX: %d\r\n", Mx);
strcat(RqstBuf, TempBuf);
}
if (SearchTarget) {
sprintf(TempBuf, "ST: %s\r\n", SearchTarget);
strcat(RqstBuf, TempBuf);
}
strcat(RqstBuf, "\r\n");
}
/************************************************************************
* Function : searchExpired
*
@@ -475,136 +504,152 @@ searchExpired( void *arg )
* Returns: int
* 1 if successful else appropriate error
***************************************************************************/
int
SearchByTarget( IN int Mx,
IN char *St,
IN void *Cookie )
int SearchByTarget(
IN int Mx,
IN char *St,
IN void *Cookie)
{
char errorBuffer[ERROR_BUFFER_LEN];
int socklen = sizeof( struct sockaddr_storage );
int *id = NULL;
int ret = 0;
char ReqBufv4[BUFSIZE];
char ReqBufv6[BUFSIZE];
struct sockaddr_storage __ss_v4;
struct sockaddr_storage __ss_v6;
struct sockaddr_in* destAddr4 = (struct sockaddr_in*)&__ss_v4;
struct sockaddr_in6* destAddr6 = (struct sockaddr_in6*)&__ss_v6;
fd_set wrSet;
SsdpSearchArg *newArg = NULL;
int timeTillRead = 0;
int handle;
struct Handle_Info *ctrlpt_info = NULL;
enum SsdpSearchType requestType;
unsigned long addrv4 = inet_addr( gIF_IPV4 );
int max_fd = 0;
char errorBuffer[ERROR_BUFFER_LEN];
int socklen = sizeof( struct sockaddr_storage );
int *id = NULL;
int ret = 0;
char ReqBufv4[BUFSIZE];
char ReqBufv6[BUFSIZE];
char ReqBufv6UlaGua[BUFSIZE];
struct sockaddr_storage __ss_v4;
struct sockaddr_storage __ss_v6;
struct sockaddr_in* destAddr4 = (struct sockaddr_in*)&__ss_v4;
struct sockaddr_in6* destAddr6 = (struct sockaddr_in6*)&__ss_v6;
fd_set wrSet;
SsdpSearchArg *newArg = NULL;
int timeTillRead = 0;
int handle;
struct Handle_Info *ctrlpt_info = NULL;
enum SsdpSearchType requestType;
unsigned long addrv4 = inet_addr(gIF_IPV4);
int max_fd = 0;
//ThreadData *ThData;
ThreadPoolJob job;
//ThreadData *ThData;
ThreadPoolJob job;
requestType = ssdp_request_type1( St );
if( requestType == SSDP_SERROR ) {
return UPNP_E_INVALID_PARAM;
}
requestType = ssdp_request_type1(St);
if (requestType == SSDP_SERROR) {
return UPNP_E_INVALID_PARAM;
}
UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, "Inside SearchByTarget\n");
UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__, "Inside SearchByTarget\n");
timeTillRead = Mx;
timeTillRead = Mx;
if (timeTillRead < MIN_SEARCH_TIME) {
timeTillRead = MIN_SEARCH_TIME;
} else if (timeTillRead > MAX_SEARCH_TIME) {
timeTillRead = MAX_SEARCH_TIME;
}
if( timeTillRead < MIN_SEARCH_TIME ) {
timeTillRead = MIN_SEARCH_TIME;
} else if( timeTillRead > MAX_SEARCH_TIME ) {
timeTillRead = MAX_SEARCH_TIME;
}
CreateClientRequestPacket(ReqBufv4, timeTillRead, St, AF_INET);
CreateClientRequestPacket(ReqBufv6, timeTillRead, St, AF_INET6);
CreateClientRequestPacketUlaGua(ReqBufv6UlaGua, timeTillRead, St, AF_INET6);
CreateClientRequestPacket( ReqBufv4, timeTillRead, St, AF_INET );
CreateClientRequestPacket( ReqBufv6, timeTillRead, St, AF_INET6 );
memset(&__ss_v4, 0, sizeof(__ss_v4));
destAddr4->sin_family = AF_INET;
inet_pton(AF_INET, SSDP_IP, &destAddr4->sin_addr);
destAddr4->sin_port = htons(SSDP_PORT);
memset( &__ss_v4, 0, sizeof( __ss_v4 ) );
destAddr4->sin_family = AF_INET;
inet_pton( AF_INET, SSDP_IP, &destAddr4->sin_addr );
destAddr4->sin_port = htons( SSDP_PORT );
memset(&__ss_v6, 0, sizeof(__ss_v6));
destAddr6->sin6_family = AF_INET6;
inet_pton(AF_INET6, SSDP_IPV6_SITELOCAL, &destAddr6->sin6_addr);
destAddr6->sin6_port = htons(SSDP_PORT);
destAddr6->sin6_scope_id = gIF_INDEX;
memset( &__ss_v6, 0, sizeof( __ss_v6 ) );
destAddr6->sin6_family = AF_INET6;
inet_pton( AF_INET6, SSDP_IPV6_LINKLOCAL, &destAddr6->sin6_addr );
destAddr6->sin6_port = htons( SSDP_PORT );
destAddr6->sin6_scope_id = gIF_INDEX;
/* add search criteria to list */
HandleLock();
if (GetClientHandleInfo(&handle, &ctrlpt_info) != HND_CLIENT) {
HandleUnlock();
// add search criteria to list
HandleLock();
if( GetClientHandleInfo( &handle, &ctrlpt_info ) != HND_CLIENT ) {
HandleUnlock();
return UPNP_E_INTERNAL_ERROR;
}
return UPNP_E_INTERNAL_ERROR;
}
newArg = ( SsdpSearchArg * ) malloc( sizeof( SsdpSearchArg ) );
newArg->searchTarget = strdup( St );
newArg->cookie = Cookie;
newArg->requestType = requestType;
newArg = (SsdpSearchArg *)malloc(sizeof(SsdpSearchArg));
newArg->searchTarget = strdup(St);
newArg->cookie = Cookie;
newArg->requestType = requestType;
id = ( int * )malloc( sizeof( int ) );
TPJobInit( &job, ( start_routine ) searchExpired, id );
TPJobSetPriority( &job, MED_PRIORITY );
TPJobSetFreeFunction( &job, ( free_routine ) free );
id = (int *)malloc(sizeof(int));
TPJobInit(&job, (start_routine)searchExpired, id);
TPJobSetPriority(&job, MED_PRIORITY);
TPJobSetFreeFunction(&job, (free_routine)free);
// Schedule a timeout event to remove search Arg
TimerThreadSchedule( &gTimerThread, timeTillRead,
REL_SEC, &job, SHORT_TERM, id );
newArg->timeoutEventId = ( *id );
/* Schedule a timeout event to remove search Arg */
TimerThreadSchedule(&gTimerThread, timeTillRead,
REL_SEC, &job, SHORT_TERM, id);
newArg->timeoutEventId = *id;
ListAddTail( &ctrlpt_info->SsdpSearchList, newArg );
HandleUnlock();
ListAddTail(&ctrlpt_info->SsdpSearchList, newArg);
HandleUnlock();
/* End of lock */
FD_ZERO( &wrSet );
if( gSsdpReqSocket4 != INVALID_SOCKET ) {
setsockopt( gSsdpReqSocket4, IPPROTO_IP, IP_MULTICAST_IF,
(char *)&addrv4, sizeof (addrv4) );
FD_SET( gSsdpReqSocket4, &wrSet );
max_fd = max(max_fd, gSsdpReqSocket4);
}
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);
}
FD_ZERO(&wrSet);
if (gSsdpReqSocket4 != INVALID_SOCKET) {
setsockopt(gSsdpReqSocket4, IPPROTO_IP, IP_MULTICAST_IF,
(char *)&addrv4, sizeof (addrv4));
FD_SET(gSsdpReqSocket4, &wrSet);
max_fd = max(max_fd, gSsdpReqSocket4);
}
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);
}
ret = select( max_fd + 1, NULL, &wrSet, NULL, NULL );
if( ret == -1 ) {
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
"SSDP_LIB: Error in select(): %s\n",
errorBuffer );
shutdown( gSsdpReqSocket4, SD_BOTH );
UpnpCloseSocket( gSsdpReqSocket4 );
shutdown( gSsdpReqSocket6, SD_BOTH );
UpnpCloseSocket( gSsdpReqSocket6 );
ret = select(max_fd + 1, NULL, &wrSet, NULL, NULL);
if (ret == -1) {
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
"SSDP_LIB: Error in select(): %s\n",
errorBuffer);
shutdown(gSsdpReqSocket4, SD_BOTH);
UpnpCloseSocket(gSsdpReqSocket4);
shutdown(gSsdpReqSocket6, SD_BOTH);
UpnpCloseSocket(gSsdpReqSocket6);
return UPNP_E_INTERNAL_ERROR;
}
if( gSsdpReqSocket6 != INVALID_SOCKET &&
FD_ISSET( gSsdpReqSocket6, &wrSet ) ) {
int NumCopy = 0;
while( NumCopy < NUM_SSDP_COPY ) {
sendto( gSsdpReqSocket6, ReqBufv6, strlen( ReqBufv6 ), 0,
(struct sockaddr *)&__ss_v6, socklen );
NumCopy++;
imillisleep( SSDP_PAUSE );
}
}
if( gSsdpReqSocket4 != INVALID_SOCKET &&
FD_ISSET( gSsdpReqSocket4, &wrSet ) ) {
int NumCopy = 0;
while( NumCopy < NUM_SSDP_COPY ) {
sendto( gSsdpReqSocket4, ReqBufv4, strlen( ReqBufv4 ), 0,
(struct sockaddr *)&__ss_v4, socklen );
NumCopy++;
imillisleep( SSDP_PAUSE );
}
}
return UPNP_E_INTERNAL_ERROR;
}
if (gSsdpReqSocket6 != INVALID_SOCKET &&
FD_ISSET(gSsdpReqSocket6, &wrSet)) {
int NumCopy = 0;
return 1;
while (NumCopy < NUM_SSDP_COPY) {
sendto(gSsdpReqSocket6,
ReqBufv6UlaGua, strlen(ReqBufv6UlaGua), 0,
(struct sockaddr *)&__ss_v6, socklen);
NumCopy++;
imillisleep(SSDP_PAUSE);
}
NumCopy = 0;
inet_pton(AF_INET6, SSDP_IPV6_LINKLOCAL, &destAddr6->sin6_addr);
while (NumCopy < NUM_SSDP_COPY) {
sendto(gSsdpReqSocket6,
ReqBufv6, strlen(ReqBufv6), 0,
(struct sockaddr *)&__ss_v6, socklen);
NumCopy++;
imillisleep(SSDP_PAUSE);
}
}
if (gSsdpReqSocket4 != INVALID_SOCKET &&
FD_ISSET(gSsdpReqSocket4, &wrSet)) {
int NumCopy = 0;
while (NumCopy < NUM_SSDP_COPY) {
sendto(gSsdpReqSocket4,
ReqBufv4, strlen(ReqBufv4), 0,
(struct sockaddr *)&__ss_v4, socklen);
NumCopy++;
imillisleep(SSDP_PAUSE);
}
}
return 1;
}
#endif // EXCLUDE_SSDP