* 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:
parent
a362d06dff
commit
5a2cc884c1
@ -2,6 +2,13 @@
|
|||||||
Version 1.6.7
|
Version 1.6.7
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
|
|
||||||
|
2010-08-21 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
|
||||||
|
* 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.
|
||||||
|
|
||||||
2010-08-21 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
|
2010-08-21 Marcelo Jimenez <mroberto(at)users.sourceforge.net>
|
||||||
* upnp/src/genlib/miniserver/miniserver.c: Fix for IPV6 ULA/GUA issues.
|
* upnp/src/genlib/miniserver/miniserver.c: Fix for IPV6 ULA/GUA issues.
|
||||||
|
|
||||||
|
@ -387,6 +387,35 @@ CreateClientRequestPacket( IN char *RqstBuf,
|
|||||||
strcat( RqstBuf, "\r\n" );
|
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
|
* Function : searchExpired
|
||||||
*
|
*
|
||||||
@ -475,136 +504,152 @@ searchExpired( void *arg )
|
|||||||
* Returns: int
|
* Returns: int
|
||||||
* 1 if successful else appropriate error
|
* 1 if successful else appropriate error
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
int
|
int SearchByTarget(
|
||||||
SearchByTarget( IN int Mx,
|
IN int Mx,
|
||||||
IN char *St,
|
IN char *St,
|
||||||
IN void *Cookie )
|
IN void *Cookie)
|
||||||
{
|
{
|
||||||
char errorBuffer[ERROR_BUFFER_LEN];
|
char errorBuffer[ERROR_BUFFER_LEN];
|
||||||
int socklen = sizeof( struct sockaddr_storage );
|
int socklen = sizeof( struct sockaddr_storage );
|
||||||
int *id = NULL;
|
int *id = NULL;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
char ReqBufv4[BUFSIZE];
|
char ReqBufv4[BUFSIZE];
|
||||||
char ReqBufv6[BUFSIZE];
|
char ReqBufv6[BUFSIZE];
|
||||||
struct sockaddr_storage __ss_v4;
|
char ReqBufv6UlaGua[BUFSIZE];
|
||||||
struct sockaddr_storage __ss_v6;
|
struct sockaddr_storage __ss_v4;
|
||||||
struct sockaddr_in* destAddr4 = (struct sockaddr_in*)&__ss_v4;
|
struct sockaddr_storage __ss_v6;
|
||||||
struct sockaddr_in6* destAddr6 = (struct sockaddr_in6*)&__ss_v6;
|
struct sockaddr_in* destAddr4 = (struct sockaddr_in*)&__ss_v4;
|
||||||
fd_set wrSet;
|
struct sockaddr_in6* destAddr6 = (struct sockaddr_in6*)&__ss_v6;
|
||||||
SsdpSearchArg *newArg = NULL;
|
fd_set wrSet;
|
||||||
int timeTillRead = 0;
|
SsdpSearchArg *newArg = NULL;
|
||||||
int handle;
|
int timeTillRead = 0;
|
||||||
struct Handle_Info *ctrlpt_info = NULL;
|
int handle;
|
||||||
enum SsdpSearchType requestType;
|
struct Handle_Info *ctrlpt_info = NULL;
|
||||||
unsigned long addrv4 = inet_addr( gIF_IPV4 );
|
enum SsdpSearchType requestType;
|
||||||
int max_fd = 0;
|
unsigned long addrv4 = inet_addr(gIF_IPV4);
|
||||||
|
int max_fd = 0;
|
||||||
|
|
||||||
//ThreadData *ThData;
|
//ThreadData *ThData;
|
||||||
ThreadPoolJob job;
|
ThreadPoolJob job;
|
||||||
|
|
||||||
requestType = ssdp_request_type1( St );
|
requestType = ssdp_request_type1(St);
|
||||||
if( requestType == SSDP_SERROR ) {
|
if (requestType == SSDP_SERROR) {
|
||||||
return UPNP_E_INVALID_PARAM;
|
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 ) {
|
CreateClientRequestPacket(ReqBufv4, timeTillRead, St, AF_INET);
|
||||||
timeTillRead = MIN_SEARCH_TIME;
|
CreateClientRequestPacket(ReqBufv6, timeTillRead, St, AF_INET6);
|
||||||
} else if( timeTillRead > MAX_SEARCH_TIME ) {
|
CreateClientRequestPacketUlaGua(ReqBufv6UlaGua, timeTillRead, St, AF_INET6);
|
||||||
timeTillRead = MAX_SEARCH_TIME;
|
|
||||||
}
|
|
||||||
|
|
||||||
CreateClientRequestPacket( ReqBufv4, timeTillRead, St, AF_INET );
|
memset(&__ss_v4, 0, sizeof(__ss_v4));
|
||||||
CreateClientRequestPacket( ReqBufv6, timeTillRead, St, AF_INET6 );
|
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 ) );
|
memset(&__ss_v6, 0, sizeof(__ss_v6));
|
||||||
destAddr4->sin_family = AF_INET;
|
destAddr6->sin6_family = AF_INET6;
|
||||||
inet_pton( AF_INET, SSDP_IP, &destAddr4->sin_addr );
|
inet_pton(AF_INET6, SSDP_IPV6_SITELOCAL, &destAddr6->sin6_addr);
|
||||||
destAddr4->sin_port = htons( SSDP_PORT );
|
destAddr6->sin6_port = htons(SSDP_PORT);
|
||||||
|
destAddr6->sin6_scope_id = gIF_INDEX;
|
||||||
|
|
||||||
memset( &__ss_v6, 0, sizeof( __ss_v6 ) );
|
/* add search criteria to list */
|
||||||
destAddr6->sin6_family = AF_INET6;
|
HandleLock();
|
||||||
inet_pton( AF_INET6, SSDP_IPV6_LINKLOCAL, &destAddr6->sin6_addr );
|
if (GetClientHandleInfo(&handle, &ctrlpt_info) != HND_CLIENT) {
|
||||||
destAddr6->sin6_port = htons( SSDP_PORT );
|
HandleUnlock();
|
||||||
destAddr6->sin6_scope_id = gIF_INDEX;
|
|
||||||
|
|
||||||
// add search criteria to list
|
return UPNP_E_INTERNAL_ERROR;
|
||||||
HandleLock();
|
}
|
||||||
if( GetClientHandleInfo( &handle, &ctrlpt_info ) != HND_CLIENT ) {
|
|
||||||
HandleUnlock();
|
|
||||||
return UPNP_E_INTERNAL_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
newArg = ( SsdpSearchArg * ) malloc( sizeof( SsdpSearchArg ) );
|
newArg = (SsdpSearchArg *)malloc(sizeof(SsdpSearchArg));
|
||||||
newArg->searchTarget = strdup( St );
|
newArg->searchTarget = strdup(St);
|
||||||
newArg->cookie = Cookie;
|
newArg->cookie = Cookie;
|
||||||
newArg->requestType = requestType;
|
newArg->requestType = requestType;
|
||||||
|
|
||||||
id = ( int * )malloc( sizeof( int ) );
|
id = (int *)malloc(sizeof(int));
|
||||||
TPJobInit( &job, ( start_routine ) searchExpired, id );
|
TPJobInit(&job, (start_routine)searchExpired, id);
|
||||||
TPJobSetPriority( &job, MED_PRIORITY );
|
TPJobSetPriority(&job, MED_PRIORITY);
|
||||||
TPJobSetFreeFunction( &job, ( free_routine ) free );
|
TPJobSetFreeFunction(&job, (free_routine)free);
|
||||||
|
|
||||||
// Schedule a timeout event to remove search Arg
|
/* Schedule a timeout event to remove search Arg */
|
||||||
TimerThreadSchedule( &gTimerThread, timeTillRead,
|
TimerThreadSchedule(&gTimerThread, timeTillRead,
|
||||||
REL_SEC, &job, SHORT_TERM, id );
|
REL_SEC, &job, SHORT_TERM, id);
|
||||||
newArg->timeoutEventId = ( *id );
|
newArg->timeoutEventId = *id;
|
||||||
|
|
||||||
ListAddTail( &ctrlpt_info->SsdpSearchList, newArg );
|
ListAddTail(&ctrlpt_info->SsdpSearchList, newArg);
|
||||||
HandleUnlock();
|
HandleUnlock();
|
||||||
|
/* End of lock */
|
||||||
|
|
||||||
FD_ZERO( &wrSet );
|
FD_ZERO(&wrSet);
|
||||||
if( gSsdpReqSocket4 != INVALID_SOCKET ) {
|
if (gSsdpReqSocket4 != INVALID_SOCKET) {
|
||||||
setsockopt( gSsdpReqSocket4, IPPROTO_IP, IP_MULTICAST_IF,
|
setsockopt(gSsdpReqSocket4, IPPROTO_IP, IP_MULTICAST_IF,
|
||||||
(char *)&addrv4, sizeof (addrv4) );
|
(char *)&addrv4, sizeof (addrv4));
|
||||||
FD_SET( gSsdpReqSocket4, &wrSet );
|
FD_SET(gSsdpReqSocket4, &wrSet);
|
||||||
max_fd = max(max_fd, gSsdpReqSocket4);
|
max_fd = max(max_fd, gSsdpReqSocket4);
|
||||||
}
|
}
|
||||||
if( gSsdpReqSocket6 != INVALID_SOCKET ) {
|
if (gSsdpReqSocket6 != INVALID_SOCKET) {
|
||||||
setsockopt( gSsdpReqSocket6, IPPROTO_IPV6, IPV6_MULTICAST_IF,
|
setsockopt(gSsdpReqSocket6, IPPROTO_IPV6, IPV6_MULTICAST_IF,
|
||||||
(char *)&gIF_INDEX, sizeof(gIF_INDEX) );
|
(char *)&gIF_INDEX, sizeof (gIF_INDEX));
|
||||||
FD_SET( gSsdpReqSocket6, &wrSet );
|
FD_SET(gSsdpReqSocket6, &wrSet);
|
||||||
max_fd = max(max_fd, gSsdpReqSocket6);
|
max_fd = max(max_fd, gSsdpReqSocket6);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = select( max_fd + 1, NULL, &wrSet, NULL, NULL );
|
ret = select(max_fd + 1, NULL, &wrSet, NULL, NULL);
|
||||||
if( ret == -1 ) {
|
if (ret == -1) {
|
||||||
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||||
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
|
||||||
"SSDP_LIB: Error in select(): %s\n",
|
"SSDP_LIB: Error in select(): %s\n",
|
||||||
errorBuffer );
|
errorBuffer);
|
||||||
shutdown( gSsdpReqSocket4, SD_BOTH );
|
shutdown(gSsdpReqSocket4, SD_BOTH);
|
||||||
UpnpCloseSocket( gSsdpReqSocket4 );
|
UpnpCloseSocket(gSsdpReqSocket4);
|
||||||
shutdown( gSsdpReqSocket6, SD_BOTH );
|
shutdown(gSsdpReqSocket6, SD_BOTH);
|
||||||
UpnpCloseSocket( gSsdpReqSocket6 );
|
UpnpCloseSocket(gSsdpReqSocket6);
|
||||||
|
|
||||||
return UPNP_E_INTERNAL_ERROR;
|
return UPNP_E_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
if( gSsdpReqSocket6 != INVALID_SOCKET &&
|
if (gSsdpReqSocket6 != INVALID_SOCKET &&
|
||||||
FD_ISSET( gSsdpReqSocket6, &wrSet ) ) {
|
FD_ISSET(gSsdpReqSocket6, &wrSet)) {
|
||||||
int NumCopy = 0;
|
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 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
|
#endif // EXCLUDE_SSDP
|
||||||
|
@ -291,6 +291,61 @@ NewRequestHandler( IN struct sockaddr *DestAddr,
|
|||||||
return UPNP_E_SUCCESS;
|
return UPNP_E_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return 1 if an inet6 @ has been found
|
||||||
|
*/
|
||||||
|
int extractIPv6address(char *url, char *address)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
int j = 0;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
while (url[i] != '[' && url[i] != '\0') {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if( url[i] == '\0') {
|
||||||
|
goto exit_function;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* bracket has been found, we deal with an IPv6 address */
|
||||||
|
i++;
|
||||||
|
while (url[i] != '\0' && url[i] != ']' ) {
|
||||||
|
address[j] = url[i];
|
||||||
|
i++;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
if (url[i] == '\0') {
|
||||||
|
goto exit_function;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url[i] == ']') {
|
||||||
|
address[j] = '\0';
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
exit_function:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return 1 if the Url contains an ULA or GUA IPv6 address
|
||||||
|
* 0 otherwise
|
||||||
|
*/
|
||||||
|
int isUrlV6UlaGua(char *descdocUrl)
|
||||||
|
{
|
||||||
|
char address[INET6_ADDRSTRLEN];
|
||||||
|
struct in6_addr v6_addr;
|
||||||
|
|
||||||
|
if (extractIPv6address(descdocUrl, address)) {
|
||||||
|
inet_pton(AF_INET6, address, &v6_addr);
|
||||||
|
return !IN6_IS_ADDR_LINKLOCAL(&v6_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* Function : CreateServiceRequestPacket
|
* Function : CreateServiceRequestPacket
|
||||||
*
|
*
|
||||||
@ -312,85 +367,92 @@ NewRequestHandler( IN struct sockaddr *DestAddr,
|
|||||||
* Returns: void
|
* Returns: void
|
||||||
*
|
*
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
void
|
void CreateServicePacket(
|
||||||
CreateServicePacket( IN int msg_type,
|
IN int msg_type,
|
||||||
IN char *nt,
|
IN char *nt,
|
||||||
IN char *usn,
|
IN char *usn,
|
||||||
IN char *location,
|
IN char *location,
|
||||||
IN int duration,
|
IN int duration,
|
||||||
OUT char **packet,
|
OUT char **packet,
|
||||||
IN int AddressFamily)
|
IN int AddressFamily)
|
||||||
{
|
{
|
||||||
int ret_code;
|
int ret_code;
|
||||||
char *nts;
|
char *nts;
|
||||||
membuffer buf;
|
membuffer buf;
|
||||||
|
|
||||||
//Notf=0 means service shutdown,
|
/* Notf == 0 means service shutdown,
|
||||||
//Notf=1 means service advertisement, Notf =2 means reply
|
* Notf == 1 means service advertisement,
|
||||||
|
* Notf == 2 means reply */
|
||||||
|
membuffer_init(&buf);
|
||||||
|
buf.size_inc = 30;
|
||||||
|
*packet = NULL;
|
||||||
|
|
||||||
membuffer_init( &buf );
|
if (msg_type == MSGTYPE_REPLY) {
|
||||||
buf.size_inc = 30;
|
ret_code = http_MakeMessage(
|
||||||
|
&buf, 1, 1,
|
||||||
|
"R" "sdc" "D" "sc" "ssc" "ssc" "ssc" "S" "Xc" "ssc" "sscc",
|
||||||
|
HTTP_OK,
|
||||||
|
"CACHE-CONTROL: max-age=", duration,
|
||||||
|
"EXT:",
|
||||||
|
"LOCATION: ", location,
|
||||||
|
"OPT: ", "\"http://schemas.upnp.org/upnp/1/0/\"; ns=01",
|
||||||
|
"01-NLS: ", gUpnpSdkNLSuuid,
|
||||||
|
X_USER_AGENT,
|
||||||
|
"ST: ", nt,
|
||||||
|
"USN: ", usn);
|
||||||
|
if (ret_code != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (msg_type == MSGTYPE_ADVERTISEMENT ||
|
||||||
|
msg_type == MSGTYPE_SHUTDOWN) {
|
||||||
|
if (msg_type == MSGTYPE_ADVERTISEMENT) {
|
||||||
|
nts = "ssdp:alive";
|
||||||
|
} else {
|
||||||
|
/* shutdown */
|
||||||
|
nts = "ssdp:byebye";
|
||||||
|
}
|
||||||
|
/* NOTE: The CACHE-CONTROL and LOCATION headers are not present in
|
||||||
|
* a shutdown msg, but are present here for MS WinMe interop. */
|
||||||
|
char *host = NULL;
|
||||||
|
if (AddressFamily == AF_INET) {
|
||||||
|
host = SSDP_IP;
|
||||||
|
} else {
|
||||||
|
if (isUrlV6UlaGua(location)) {
|
||||||
|
host = "[" SSDP_IPV6_SITELOCAL "]";
|
||||||
|
} else {
|
||||||
|
host = "[" SSDP_IPV6_LINKLOCAL "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret_code = http_MakeMessage(
|
||||||
|
&buf, 1, 1,
|
||||||
|
"Q" "sssdc" "sdc" "ssc" "ssc" "ssc" "ssc" "ssc" "S" "Xc" "sscc",
|
||||||
|
HTTPMETHOD_NOTIFY, "*", (size_t)1,
|
||||||
|
"HOST: ", host,
|
||||||
|
":", SSDP_PORT,
|
||||||
|
"CACHE-CONTROL: max-age=", duration,
|
||||||
|
"LOCATION: ", location,
|
||||||
|
"OPT: ", "\"http://schemas.upnp.org/upnp/1/0/\"; ns=01",
|
||||||
|
"01-NLS: ", gUpnpSdkNLSuuid,
|
||||||
|
"NT: ", nt,
|
||||||
|
"NTS: ", nts,
|
||||||
|
X_USER_AGENT,
|
||||||
|
"USN: ", usn );
|
||||||
|
if (ret_code != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* unknown msg */
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
*packet = NULL;
|
/* return msg */
|
||||||
|
*packet = membuffer_detach(&buf);
|
||||||
|
membuffer_destroy(&buf);
|
||||||
|
|
||||||
if( msg_type == MSGTYPE_REPLY ) {
|
return;
|
||||||
ret_code = http_MakeMessage(
|
|
||||||
&buf, 1, 1,
|
|
||||||
"R" "sdc" "D" "sc" "ssc" "ssc" "ssc" "S" "Xc" "ssc" "sscc",
|
|
||||||
HTTP_OK,
|
|
||||||
"CACHE-CONTROL: max-age=", duration,
|
|
||||||
"EXT:",
|
|
||||||
"LOCATION: ", location,
|
|
||||||
"OPT: ", "\"http://schemas.upnp.org/upnp/1/0/\"; ns=01",
|
|
||||||
"01-NLS: ", gUpnpSdkNLSuuid,
|
|
||||||
X_USER_AGENT,
|
|
||||||
"ST: ", nt,
|
|
||||||
"USN: ", usn);
|
|
||||||
if( ret_code != 0 ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if( msg_type == MSGTYPE_ADVERTISEMENT ||
|
|
||||||
msg_type == MSGTYPE_SHUTDOWN ) {
|
|
||||||
if( msg_type == MSGTYPE_ADVERTISEMENT ) {
|
|
||||||
nts = "ssdp:alive";
|
|
||||||
} else // shutdown
|
|
||||||
{
|
|
||||||
nts = "ssdp:byebye";
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: The CACHE-CONTROL and LOCATION headers are not present in
|
|
||||||
// a shutdown msg, but are present here for MS WinMe interop.
|
|
||||||
|
|
||||||
ret_code = http_MakeMessage(
|
|
||||||
&buf, 1, 1,
|
|
||||||
"Q" "sssdc" "sdc" "ssc" "ssc" "ssc" "ssc" "ssc" "S" "Xc" "sscc",
|
|
||||||
HTTPMETHOD_NOTIFY, "*", (size_t)1,
|
|
||||||
"HOST: ",
|
|
||||||
(AddressFamily==AF_INET) ? SSDP_IP : "[" SSDP_IPV6_LINKLOCAL "]",
|
|
||||||
":", SSDP_PORT,
|
|
||||||
"CACHE-CONTROL: max-age=", duration,
|
|
||||||
"LOCATION: ", location,
|
|
||||||
"OPT: ", "\"http://schemas.upnp.org/upnp/1/0/\"; ns=01",
|
|
||||||
"01-NLS: ", gUpnpSdkNLSuuid,
|
|
||||||
"NT: ", nt,
|
|
||||||
"NTS: ", nts,
|
|
||||||
X_USER_AGENT,
|
|
||||||
"USN: ", usn );
|
|
||||||
if( ret_code != 0 ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
assert( 0 ); // unknown msg
|
|
||||||
}
|
|
||||||
|
|
||||||
*packet = membuffer_detach( &buf ); // return msg
|
|
||||||
|
|
||||||
membuffer_destroy( &buf );
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* Function : DeviceAdvertisement
|
* Function : DeviceAdvertisement
|
||||||
*
|
*
|
||||||
@ -436,7 +498,9 @@ DeviceAdvertisement( IN char *DevType,
|
|||||||
DestAddr4->sin_port = htons( SSDP_PORT );
|
DestAddr4->sin_port = htons( SSDP_PORT );
|
||||||
} else if( AddressFamily == AF_INET6 ) {
|
} else if( AddressFamily == AF_INET6 ) {
|
||||||
DestAddr6->sin6_family = AF_INET6;
|
DestAddr6->sin6_family = AF_INET6;
|
||||||
inet_pton( AF_INET6, SSDP_IPV6_LINKLOCAL, &DestAddr6->sin6_addr );
|
inet_pton(AF_INET6,
|
||||||
|
(isUrlV6UlaGua(Location)) ? SSDP_IPV6_SITELOCAL : SSDP_IPV6_LINKLOCAL,
|
||||||
|
&DestAddr6->sin6_addr );
|
||||||
DestAddr6->sin6_port = htons( SSDP_PORT );
|
DestAddr6->sin6_port = htons( SSDP_PORT );
|
||||||
DestAddr6->sin6_scope_id = gIF_INDEX;
|
DestAddr6->sin6_scope_id = gIF_INDEX;
|
||||||
} else {
|
} else {
|
||||||
@ -683,7 +747,9 @@ ServiceAdvertisement( IN char *Udn,
|
|||||||
DestAddr4->sin_port = htons( SSDP_PORT );
|
DestAddr4->sin_port = htons( SSDP_PORT );
|
||||||
} else if( AddressFamily == AF_INET6 ) {
|
} else if( AddressFamily == AF_INET6 ) {
|
||||||
DestAddr6->sin6_family = AF_INET6;
|
DestAddr6->sin6_family = AF_INET6;
|
||||||
inet_pton( AF_INET6, SSDP_IPV6_LINKLOCAL, &DestAddr6->sin6_addr );
|
inet_pton(AF_INET6,
|
||||||
|
(isUrlV6UlaGua(Location)) ? SSDP_IPV6_SITELOCAL : SSDP_IPV6_LINKLOCAL,
|
||||||
|
&DestAddr6->sin6_addr );
|
||||||
DestAddr6->sin6_port = htons( SSDP_PORT );
|
DestAddr6->sin6_port = htons( SSDP_PORT );
|
||||||
DestAddr6->sin6_scope_id = gIF_INDEX;
|
DestAddr6->sin6_scope_id = gIF_INDEX;
|
||||||
} else {
|
} else {
|
||||||
@ -787,7 +853,9 @@ ServiceShutdown( IN char *Udn,
|
|||||||
DestAddr4->sin_port = htons( SSDP_PORT );
|
DestAddr4->sin_port = htons( SSDP_PORT );
|
||||||
} else if( AddressFamily == AF_INET6 ) {
|
} else if( AddressFamily == AF_INET6 ) {
|
||||||
DestAddr6->sin6_family = AF_INET6;
|
DestAddr6->sin6_family = AF_INET6;
|
||||||
inet_pton( AF_INET6, SSDP_IPV6_LINKLOCAL, &DestAddr6->sin6_addr );
|
inet_pton(AF_INET6,
|
||||||
|
(isUrlV6UlaGua(Location)) ? SSDP_IPV6_SITELOCAL : SSDP_IPV6_LINKLOCAL,
|
||||||
|
&DestAddr6->sin6_addr );
|
||||||
DestAddr6->sin6_port = htons( SSDP_PORT );
|
DestAddr6->sin6_port = htons( SSDP_PORT );
|
||||||
DestAddr6->sin6_scope_id = gIF_INDEX;
|
DestAddr6->sin6_scope_id = gIF_INDEX;
|
||||||
} else {
|
} else {
|
||||||
@ -855,7 +923,9 @@ DeviceShutdown( IN char *DevType,
|
|||||||
DestAddr4->sin_port = htons( SSDP_PORT );
|
DestAddr4->sin_port = htons( SSDP_PORT );
|
||||||
} else if( AddressFamily == AF_INET6 ) {
|
} else if( AddressFamily == AF_INET6 ) {
|
||||||
DestAddr6->sin6_family = AF_INET6;
|
DestAddr6->sin6_family = AF_INET6;
|
||||||
inet_pton( AF_INET6, SSDP_IPV6_LINKLOCAL, &DestAddr6->sin6_addr );
|
inet_pton(AF_INET6,
|
||||||
|
(isUrlV6UlaGua(Location)) ? SSDP_IPV6_SITELOCAL : SSDP_IPV6_LINKLOCAL,
|
||||||
|
&DestAddr6->sin6_addr );
|
||||||
DestAddr6->sin6_port = htons( SSDP_PORT );
|
DestAddr6->sin6_port = htons( SSDP_PORT );
|
||||||
DestAddr6->sin6_scope_id = gIF_INDEX;
|
DestAddr6->sin6_scope_id = gIF_INDEX;
|
||||||
} else {
|
} else {
|
||||||
|
@ -56,6 +56,7 @@ CLIENTONLY( SOCKET gSsdpReqSocket6 = INVALID_SOCKET; )
|
|||||||
void RequestHandler();
|
void RequestHandler();
|
||||||
int create_ssdp_sock_v4( SOCKET* ssdpSock );
|
int create_ssdp_sock_v4( SOCKET* ssdpSock );
|
||||||
int create_ssdp_sock_v6( SOCKET* ssdpSock );
|
int create_ssdp_sock_v6( SOCKET* ssdpSock );
|
||||||
|
int create_ssdp_sock_v6_ula_gua( SOCKET* ssdpSock );
|
||||||
#if INCLUDE_CLIENT_APIS
|
#if INCLUDE_CLIENT_APIS
|
||||||
int create_ssdp_sock_reqv4( SOCKET* ssdpReqSock );
|
int create_ssdp_sock_reqv4( SOCKET* ssdpReqSock );
|
||||||
int create_ssdp_sock_reqv6( SOCKET* ssdpReqSock );
|
int create_ssdp_sock_reqv6( SOCKET* ssdpReqSock );
|
||||||
@ -260,15 +261,31 @@ int AdvertiseAndReply(
|
|||||||
}
|
}
|
||||||
case SSDP_DEVICETYPE: {
|
case SSDP_DEVICETYPE: {
|
||||||
if (!strncasecmp(DeviceType, devType, strlen(DeviceType))) {
|
if (!strncasecmp(DeviceType, devType, strlen(DeviceType))) {
|
||||||
|
/* (char *) support for atoi */
|
||||||
|
/* TODO: Patch pending. */
|
||||||
|
#if 0
|
||||||
|
if (atoi(&DeviceType[strlen(DeviceType)-1]) <= atoi(&devType[strlen(devType)-1])) {
|
||||||
|
/* the requested version is lower than the device version
|
||||||
|
* must reply with the lower version number */
|
||||||
|
UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
|
||||||
|
"DeviceType=%s and search devType=%s MATCH\n",
|
||||||
|
devType, DeviceType);
|
||||||
|
SendReply(DestAddr, DeviceType, 0, UDNstr, SInfo->DescURL, defaultExp, 1);
|
||||||
|
} else {
|
||||||
|
UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
|
||||||
|
"DeviceType=%s and search devType=%s"
|
||||||
|
" DID NOT MATCH\n",
|
||||||
|
devType, DeviceType);
|
||||||
|
}
|
||||||
|
#else
|
||||||
UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
|
||||||
"DeviceType=%s and search devType=%s MATCH\n",
|
"DeviceType=%s and search devType=%s MATCH\n",
|
||||||
devType, DeviceType);
|
devType, DeviceType);
|
||||||
SendReply(DestAddr, devType, 0, UDNstr,
|
SendReply(DestAddr, devType, 0, UDNstr, SInfo->DescURL, defaultExp, 1);
|
||||||
SInfo->DescURL, defaultExp, 1);
|
#endif
|
||||||
} else {
|
} else {
|
||||||
UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
|
UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
|
||||||
"DeviceType=%s and search devType=%s"
|
"DeviceType=%s and search devType=%s DID NOT MATCH\n",
|
||||||
" DID NOT MATCH\n",
|
|
||||||
devType, DeviceType);
|
devType, DeviceType);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -346,9 +363,33 @@ int AdvertiseAndReply(
|
|||||||
break;
|
break;
|
||||||
case SSDP_SERVICE:
|
case SSDP_SERVICE:
|
||||||
if (ServiceType) {
|
if (ServiceType) {
|
||||||
|
/* TODO: Patch pending. */
|
||||||
|
#if 0
|
||||||
|
if (!strncasecmp(ServiceType, servType, strlen(ServiceType) - 2)) {
|
||||||
|
/*ServiceReply(DestAddr, servType, UDNstr, SInfo->DescURL, defaultExp);*/
|
||||||
|
if (atoi(&ServiceType[strlen(ServiceType)-1]) <= atoi(&servType[strlen(servType)-1])) {
|
||||||
|
/* the requested version is lower than the service version
|
||||||
|
* must reply with the lower version number */
|
||||||
|
UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
|
||||||
|
"ServiceType=%s and search servType=%s MATCH\n",
|
||||||
|
ServiceType, servType);
|
||||||
|
SendReply(DestAddr, ServiceType, 0, UDNstr, SInfo->DescURL, defaultExp, 1);
|
||||||
|
} else {
|
||||||
|
UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
|
||||||
|
"ServiceType=%s and search servType=%s DID NOT MATCH\n",
|
||||||
|
ServiceType, servType);
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (!strncasecmp(ServiceType, servType, strlen(ServiceType))) {
|
if (!strncasecmp(ServiceType, servType, strlen(ServiceType))) {
|
||||||
ServiceReply(DestAddr, servType,
|
UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
|
||||||
UDNstr, SInfo->DescURL, defaultExp);
|
"ServiceType=%s and search servType=%s MATCH\n",
|
||||||
|
ServiceType, servType);
|
||||||
|
ServiceReply(DestAddr, servType, UDNstr, SInfo->DescURL, defaultExp);
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
|
||||||
|
"ServiceType=%s and search servType=%s DID NOT MATCH\n",
|
||||||
|
ServiceType, servType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -614,35 +655,38 @@ free_ssdp_event_handler_data( void *the_data )
|
|||||||
* Returns: xboolean
|
* Returns: xboolean
|
||||||
* returns TRUE if msg is valid else FALSE
|
* returns TRUE if msg is valid else FALSE
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
static UPNP_INLINE xboolean
|
static UPNP_INLINE xboolean valid_ssdp_msg(IN http_message_t *hmsg)
|
||||||
valid_ssdp_msg( IN http_message_t * hmsg )
|
|
||||||
{
|
{
|
||||||
memptr hdr_value;
|
memptr hdr_value;
|
||||||
|
|
||||||
// check for valid methods - NOTIFY or M-SEARCH
|
/* check for valid methods - NOTIFY or M-SEARCH */
|
||||||
if( hmsg->method != HTTPMETHOD_NOTIFY &&
|
if (hmsg->method != HTTPMETHOD_NOTIFY &&
|
||||||
hmsg->method != HTTPMETHOD_MSEARCH
|
hmsg->method != HTTPMETHOD_MSEARCH &&
|
||||||
&& hmsg->request_method != HTTPMETHOD_MSEARCH ) {
|
hmsg->request_method != HTTPMETHOD_MSEARCH) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if( hmsg->request_method != HTTPMETHOD_MSEARCH ) {
|
if (hmsg->request_method != HTTPMETHOD_MSEARCH) {
|
||||||
// check PATH == *
|
/* check PATH == "*" */
|
||||||
if( hmsg->uri.type != RELATIVE ||
|
if (hmsg->uri.type != RELATIVE ||
|
||||||
strncmp( "*", hmsg->uri.pathquery.buff,
|
strncmp("*", hmsg->uri.pathquery.buff, hmsg->uri.pathquery.size) != 0) {
|
||||||
hmsg->uri.pathquery.size ) != 0 ) {
|
return FALSE;
|
||||||
return FALSE;
|
}
|
||||||
}
|
/* check HOST header */
|
||||||
// check HOST header
|
if (httpmsg_find_hdr(hmsg, HDR_HOST, &hdr_value) == NULL ||
|
||||||
if( ( httpmsg_find_hdr( hmsg, HDR_HOST, &hdr_value ) == NULL ) ||
|
(memptr_cmp(&hdr_value, "239.255.255.250:1900") != 0 &&
|
||||||
( ( memptr_cmp( &hdr_value, "239.255.255.250:1900" ) != 0 ) &&
|
memptr_cmp(&hdr_value, "[FF02::C]:1900") != 0 &&
|
||||||
( memptr_cmp( &hdr_value, "[FF02::C]:1900" ) != 0 ) )
|
memptr_cmp(&hdr_value, "[ff02::c]:1900") != 0 &&
|
||||||
) {
|
memptr_cmp(&hdr_value, "[FF05::C]:1900") != 0 &&
|
||||||
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
|
memptr_cmp(&hdr_value, "[ff05::c]:1900") != 0)) {
|
||||||
"Invalid HOST header from SSDP message\n" );
|
UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
|
||||||
return FALSE;
|
"Invalid HOST header from SSDP message\n");
|
||||||
}
|
|
||||||
}
|
return FALSE;
|
||||||
return TRUE; // passed quick check
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* passed quick check */
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
@ -850,69 +894,92 @@ readFromSSDPSocket( SOCKET socket )
|
|||||||
* Returns: int
|
* Returns: int
|
||||||
* return UPNP_E_SUCCESS if successful else returns appropriate error
|
* return UPNP_E_SUCCESS if successful else returns appropriate error
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
int get_ssdp_sockets( MiniServerSockArray * out )
|
int get_ssdp_sockets(MiniServerSockArray *out)
|
||||||
{
|
{
|
||||||
int retVal;
|
int retVal;
|
||||||
|
|
||||||
#if INCLUDE_CLIENT_APIS
|
#if INCLUDE_CLIENT_APIS
|
||||||
// Create the IPv4 socket for SSDP REQUESTS
|
/* Create the IPv4 socket for SSDP REQUESTS */
|
||||||
if( strlen( gIF_IPV4 ) > 0 ) {
|
if(strlen(gIF_IPV4) > 0) {
|
||||||
retVal = create_ssdp_sock_reqv4( &out->ssdpReqSock4 );
|
retVal = create_ssdp_sock_reqv4(&out->ssdpReqSock4);
|
||||||
if( retVal != UPNP_E_SUCCESS ) {
|
if(retVal != UPNP_E_SUCCESS) {
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
// For use by ssdp control point.
|
/* For use by ssdp control point. */
|
||||||
gSsdpReqSocket4 = out->ssdpReqSock4;
|
gSsdpReqSocket4 = out->ssdpReqSock4;
|
||||||
} else {
|
} else {
|
||||||
out->ssdpReqSock4 = INVALID_SOCKET;
|
out->ssdpReqSock4 = INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the IPv6 socket for SSDP REQUESTS
|
/* Create the IPv6 socket for SSDP REQUESTS */
|
||||||
if( strlen( gIF_IPV6 ) > 0 ) {
|
if (strlen(gIF_IPV6) > 0) {
|
||||||
retVal = create_ssdp_sock_reqv6( &out->ssdpReqSock6 );
|
retVal = create_ssdp_sock_reqv6(&out->ssdpReqSock6);
|
||||||
if( retVal != UPNP_E_SUCCESS ) {
|
if (retVal != UPNP_E_SUCCESS) {
|
||||||
CLIENTONLY( shutdown( out->ssdpReqSock4, SD_BOTH ); )
|
shutdown(out->ssdpReqSock4, SD_BOTH);
|
||||||
CLIENTONLY( UpnpCloseSocket( out->ssdpReqSock4 ); )
|
UpnpCloseSocket(out->ssdpReqSock4);
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
// For use by ssdp control point.
|
/* For use by ssdp control point. */
|
||||||
gSsdpReqSocket6 = out->ssdpReqSock6;
|
gSsdpReqSocket6 = out->ssdpReqSock6;
|
||||||
} else {
|
} else {
|
||||||
out->ssdpReqSock6 = INVALID_SOCKET;
|
out->ssdpReqSock6 = INVALID_SOCKET;
|
||||||
}
|
}
|
||||||
#endif /* INCLUDE_CLIENT_APIS */
|
#endif /* INCLUDE_CLIENT_APIS */
|
||||||
|
|
||||||
// Create the IPv4 socket for SSDP
|
/* Create the IPv4 socket for SSDP */
|
||||||
if( strlen( gIF_IPV4 ) > 0 ) {
|
if (strlen(gIF_IPV4) > 0) {
|
||||||
retVal = create_ssdp_sock_v4( &out->ssdpSock4 );
|
retVal = create_ssdp_sock_v4(&out->ssdpSock4);
|
||||||
if( retVal != UPNP_E_SUCCESS ) {
|
if (retVal != UPNP_E_SUCCESS) {
|
||||||
CLIENTONLY( shutdown( out->ssdpReqSock4, SD_BOTH ); )
|
#ifdef INCLUDE_CLIENT_APIS
|
||||||
CLIENTONLY( UpnpCloseSocket( out->ssdpReqSock4 ); )
|
shutdown(out->ssdpReqSock4, SD_BOTH);
|
||||||
CLIENTONLY( shutdown( out->ssdpReqSock6, SD_BOTH ); )
|
UpnpCloseSocket(out->ssdpReqSock4);
|
||||||
CLIENTONLY( UpnpCloseSocket( out->ssdpReqSock6 ); )
|
shutdown(out->ssdpReqSock6, SD_BOTH);
|
||||||
return retVal;
|
UpnpCloseSocket(out->ssdpReqSock6);
|
||||||
}
|
#endif
|
||||||
} else {
|
return retVal;
|
||||||
out->ssdpSock4 = INVALID_SOCKET;
|
}
|
||||||
}
|
} else {
|
||||||
|
out->ssdpSock4 = INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
// Create the IPv6 socket for SSDP
|
/* Create the IPv6 socket for SSDP */
|
||||||
if( strlen( gIF_IPV6 ) > 0 ) {
|
if (strlen(gIF_IPV6) > 0) {
|
||||||
retVal = create_ssdp_sock_v6( &out->ssdpSock6 );
|
retVal = create_ssdp_sock_v6(&out->ssdpSock6);
|
||||||
if( retVal != UPNP_E_SUCCESS ) {
|
if (retVal != UPNP_E_SUCCESS) {
|
||||||
shutdown( out->ssdpSock4, SD_BOTH );
|
shutdown(out->ssdpSock4, SD_BOTH);
|
||||||
UpnpCloseSocket( out->ssdpSock4 );
|
UpnpCloseSocket(out->ssdpSock4);
|
||||||
CLIENTONLY( shutdown( out->ssdpReqSock4, SD_BOTH ); )
|
#ifdef INCLUDE_CLIENT_APIS
|
||||||
CLIENTONLY( UpnpCloseSocket( out->ssdpReqSock4 ); )
|
shutdown(out->ssdpReqSock4, SD_BOTH);
|
||||||
CLIENTONLY( shutdown( out->ssdpReqSock6, SD_BOTH ); )
|
UpnpCloseSocket(out->ssdpReqSock4);
|
||||||
CLIENTONLY( UpnpCloseSocket( out->ssdpReqSock6 ); )
|
shutdown(out->ssdpReqSock6, SD_BOTH);
|
||||||
return retVal;
|
UpnpCloseSocket(out->ssdpReqSock6);
|
||||||
}
|
#endif
|
||||||
} else {
|
return retVal;
|
||||||
out->ssdpSock6 = INVALID_SOCKET;
|
}
|
||||||
}
|
} else {
|
||||||
|
out->ssdpSock6 = INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
return UPNP_E_SUCCESS;
|
if (strlen(gIF_IPV6_ULA_GUA) > 0) {
|
||||||
|
retVal = create_ssdp_sock_v6_ula_gua(&out->ssdpSock6UlaGua);
|
||||||
|
if (retVal != UPNP_E_SUCCESS) {
|
||||||
|
shutdown(out->ssdpSock4, SD_BOTH);
|
||||||
|
UpnpCloseSocket(out->ssdpSock4);
|
||||||
|
shutdown(out->ssdpSock6, SD_BOTH);
|
||||||
|
UpnpCloseSocket(out->ssdpSock6);
|
||||||
|
#ifdef INCLUDE_CLIENT_APIS
|
||||||
|
shutdown(out->ssdpReqSock4, SD_BOTH);
|
||||||
|
UpnpCloseSocket(out->ssdpReqSock4);
|
||||||
|
shutdown(out->ssdpReqSock6, SD_BOTH);
|
||||||
|
UpnpCloseSocket(out->ssdpReqSock6);
|
||||||
|
#endif
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out->ssdpSock6UlaGua = INVALID_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
return UPNP_E_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1229,5 +1296,118 @@ int create_ssdp_sock_v6( SOCKET* ssdpSock )
|
|||||||
return UPNP_E_SUCCESS;
|
return UPNP_E_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************
|
||||||
|
* Function : create_ssdp_sock_v6_ula_gua
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* IN SOCKET* ssdpSock: SSDP IPv6 socket to be created
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* This function ...
|
||||||
|
*
|
||||||
|
* Returns: void
|
||||||
|
*
|
||||||
|
***************************************************************************/
|
||||||
|
int create_ssdp_sock_v6_ula_gua(SOCKET *ssdpSock)
|
||||||
|
{
|
||||||
|
char errorBuffer[ERROR_BUFFER_LEN];
|
||||||
|
struct ipv6_mreq ssdpMcastAddr;
|
||||||
|
struct sockaddr_storage __ss;
|
||||||
|
struct sockaddr_in6 *ssdpAddr6 = (struct sockaddr_in6 *)&__ss;
|
||||||
|
int onOff;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
*ssdpSock = socket(AF_INET6, SOCK_DGRAM, 0);
|
||||||
|
if (*ssdpSock == -1) {
|
||||||
|
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||||
|
UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||||
|
"Error in socket(): %s\n", errorBuffer);
|
||||||
|
|
||||||
|
return UPNP_E_OUTOF_SOCKET;
|
||||||
|
}
|
||||||
|
|
||||||
|
onOff = 1;
|
||||||
|
ret = setsockopt(*ssdpSock, SOL_SOCKET, SO_REUSEADDR,
|
||||||
|
(char*)&onOff, sizeof(onOff) );
|
||||||
|
if (ret == -1) {
|
||||||
|
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||||
|
UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||||
|
"Error in setsockopt() SO_REUSEADDR: %s\n", errorBuffer);
|
||||||
|
shutdown(*ssdpSock, SD_BOTH);
|
||||||
|
UpnpCloseSocket(*ssdpSock);
|
||||||
|
|
||||||
|
return UPNP_E_SOCKET_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(BSD) || defined(__OSX__) || defined(__APPLE__)
|
||||||
|
onOff = 1;
|
||||||
|
ret = setsockopt( *ssdpSock, SOL_SOCKET, SO_REUSEPORT,
|
||||||
|
(char*)&onOff, sizeof (onOff) );
|
||||||
|
if ( ret == -1 ) {
|
||||||
|
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||||
|
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||||
|
"Error in setsockopt() SO_REUSEPORT: %s\n", errorBuffer );
|
||||||
|
shutdown( *ssdpSock, SD_BOTH );
|
||||||
|
UpnpCloseSocket( *ssdpSock );
|
||||||
|
|
||||||
|
return UPNP_E_SOCKET_ERROR;
|
||||||
|
}
|
||||||
|
#endif /* BSD */
|
||||||
|
|
||||||
|
memset( &__ss, 0, sizeof( __ss ) );
|
||||||
|
ssdpAddr6->sin6_family = AF_INET6;
|
||||||
|
ssdpAddr6->sin6_addr = in6addr_any;
|
||||||
|
ssdpAddr6->sin6_scope_id = gIF_INDEX;
|
||||||
|
ssdpAddr6->sin6_port = htons( SSDP_PORT );
|
||||||
|
ret = bind( *ssdpSock, (struct sockaddr *)ssdpAddr6, sizeof(*ssdpAddr6) );
|
||||||
|
if ( ret == -1 ) {
|
||||||
|
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||||
|
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||||
|
"Error in bind(), addr=0x%032lX, port=%d: %s\n",
|
||||||
|
0lu, SSDP_PORT, errorBuffer );
|
||||||
|
shutdown( *ssdpSock, SD_BOTH );
|
||||||
|
UpnpCloseSocket( *ssdpSock );
|
||||||
|
|
||||||
|
return UPNP_E_SOCKET_BIND;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset( (void *)&ssdpMcastAddr, 0, sizeof(ssdpMcastAddr) );
|
||||||
|
ssdpMcastAddr.ipv6mr_interface = gIF_INDEX;
|
||||||
|
|
||||||
|
/* SITE LOCAL */
|
||||||
|
inet_pton( AF_INET6, SSDP_IPV6_SITELOCAL, &ssdpMcastAddr.ipv6mr_multiaddr );
|
||||||
|
ret = setsockopt( *ssdpSock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
|
||||||
|
(char *)&ssdpMcastAddr, sizeof(ssdpMcastAddr) );
|
||||||
|
if ( ret == -1 ) {
|
||||||
|
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||||
|
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||||
|
"Error in setsockopt() IPV6_JOIN_GROUP (join multicast group): %s\n",
|
||||||
|
errorBuffer );
|
||||||
|
shutdown( *ssdpSock, SD_BOTH );
|
||||||
|
UpnpCloseSocket( *ssdpSock );
|
||||||
|
|
||||||
|
return UPNP_E_SOCKET_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
onOff = 1;
|
||||||
|
ret = setsockopt( *ssdpSock, SOL_SOCKET, SO_BROADCAST,
|
||||||
|
(char*)&onOff, sizeof(onOff) );
|
||||||
|
if( ret == -1) {
|
||||||
|
strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
|
||||||
|
UpnpPrintf( UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
|
||||||
|
"Error in setsockopt() SO_BROADCAST (set broadcast): %s\n",
|
||||||
|
errorBuffer );
|
||||||
|
shutdown( *ssdpSock, SD_BOTH );
|
||||||
|
UpnpCloseSocket( *ssdpSock );
|
||||||
|
|
||||||
|
return UPNP_E_NETWORK_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return UPNP_E_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* EXCLUDE_SSDP */
|
#endif /* EXCLUDE_SSDP */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user