* 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
|
||||
*******************************************************************************
|
||||
|
||||
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>
|
||||
* upnp/src/genlib/miniserver/miniserver.c: Fix for IPV6 ULA/GUA issues.
|
||||
|
||||
|
@ -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
|
||||
|
@ -291,6 +291,61 @@ NewRequestHandler( IN struct sockaddr *DestAddr,
|
||||
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
|
||||
*
|
||||
@ -312,85 +367,92 @@ NewRequestHandler( IN struct sockaddr *DestAddr,
|
||||
* Returns: void
|
||||
*
|
||||
***************************************************************************/
|
||||
void
|
||||
CreateServicePacket( IN int msg_type,
|
||||
IN char *nt,
|
||||
IN char *usn,
|
||||
IN char *location,
|
||||
IN int duration,
|
||||
OUT char **packet,
|
||||
IN int AddressFamily)
|
||||
void CreateServicePacket(
|
||||
IN int msg_type,
|
||||
IN char *nt,
|
||||
IN char *usn,
|
||||
IN char *location,
|
||||
IN int duration,
|
||||
OUT char **packet,
|
||||
IN int AddressFamily)
|
||||
{
|
||||
int ret_code;
|
||||
char *nts;
|
||||
membuffer buf;
|
||||
int ret_code;
|
||||
char *nts;
|
||||
membuffer buf;
|
||||
|
||||
//Notf=0 means service shutdown,
|
||||
//Notf=1 means service advertisement, Notf =2 means reply
|
||||
/* Notf == 0 means service shutdown,
|
||||
* Notf == 1 means service advertisement,
|
||||
* Notf == 2 means reply */
|
||||
membuffer_init(&buf);
|
||||
buf.size_inc = 30;
|
||||
*packet = NULL;
|
||||
|
||||
membuffer_init( &buf );
|
||||
buf.size_inc = 30;
|
||||
if (msg_type == MSGTYPE_REPLY) {
|
||||
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 ) {
|
||||
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;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* Function : DeviceAdvertisement
|
||||
*
|
||||
@ -436,7 +498,9 @@ DeviceAdvertisement( IN char *DevType,
|
||||
DestAddr4->sin_port = htons( SSDP_PORT );
|
||||
} else if( AddressFamily == 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_scope_id = gIF_INDEX;
|
||||
} else {
|
||||
@ -683,7 +747,9 @@ ServiceAdvertisement( IN char *Udn,
|
||||
DestAddr4->sin_port = htons( SSDP_PORT );
|
||||
} else if( AddressFamily == 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_scope_id = gIF_INDEX;
|
||||
} else {
|
||||
@ -787,7 +853,9 @@ ServiceShutdown( IN char *Udn,
|
||||
DestAddr4->sin_port = htons( SSDP_PORT );
|
||||
} else if( AddressFamily == 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_scope_id = gIF_INDEX;
|
||||
} else {
|
||||
@ -855,7 +923,9 @@ DeviceShutdown( IN char *DevType,
|
||||
DestAddr4->sin_port = htons( SSDP_PORT );
|
||||
} else if( AddressFamily == 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_scope_id = gIF_INDEX;
|
||||
} else {
|
||||
|
@ -56,6 +56,7 @@ CLIENTONLY( SOCKET gSsdpReqSocket6 = INVALID_SOCKET; )
|
||||
void RequestHandler();
|
||||
int create_ssdp_sock_v4( SOCKET* ssdpSock );
|
||||
int create_ssdp_sock_v6( SOCKET* ssdpSock );
|
||||
int create_ssdp_sock_v6_ula_gua( SOCKET* ssdpSock );
|
||||
#if INCLUDE_CLIENT_APIS
|
||||
int create_ssdp_sock_reqv4( SOCKET* ssdpReqSock );
|
||||
int create_ssdp_sock_reqv6( SOCKET* ssdpReqSock );
|
||||
@ -260,15 +261,31 @@ int AdvertiseAndReply(
|
||||
}
|
||||
case SSDP_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__,
|
||||
"DeviceType=%s and search devType=%s MATCH\n",
|
||||
devType, DeviceType);
|
||||
SendReply(DestAddr, devType, 0, UDNstr,
|
||||
SInfo->DescURL, defaultExp, 1);
|
||||
SendReply(DestAddr, devType, 0, UDNstr, SInfo->DescURL, defaultExp, 1);
|
||||
#endif
|
||||
} else {
|
||||
UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
|
||||
"DeviceType=%s and search devType=%s"
|
||||
" DID NOT MATCH\n",
|
||||
"DeviceType=%s and search devType=%s DID NOT MATCH\n",
|
||||
devType, DeviceType);
|
||||
}
|
||||
break;
|
||||
@ -346,9 +363,33 @@ int AdvertiseAndReply(
|
||||
break;
|
||||
case SSDP_SERVICE:
|
||||
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))) {
|
||||
ServiceReply(DestAddr, servType,
|
||||
UDNstr, SInfo->DescURL, defaultExp);
|
||||
UpnpPrintf(UPNP_INFO, API, __FILE__, __LINE__,
|
||||
"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;
|
||||
@ -614,35 +655,38 @@ free_ssdp_event_handler_data( void *the_data )
|
||||
* Returns: xboolean
|
||||
* returns TRUE if msg is valid else FALSE
|
||||
***************************************************************************/
|
||||
static UPNP_INLINE xboolean
|
||||
valid_ssdp_msg( IN http_message_t * hmsg )
|
||||
static UPNP_INLINE xboolean valid_ssdp_msg(IN http_message_t *hmsg)
|
||||
{
|
||||
memptr hdr_value;
|
||||
|
||||
// check for valid methods - NOTIFY or M-SEARCH
|
||||
if( hmsg->method != HTTPMETHOD_NOTIFY &&
|
||||
hmsg->method != HTTPMETHOD_MSEARCH
|
||||
&& hmsg->request_method != HTTPMETHOD_MSEARCH ) {
|
||||
return FALSE;
|
||||
}
|
||||
if( hmsg->request_method != HTTPMETHOD_MSEARCH ) {
|
||||
// check PATH == *
|
||||
if( hmsg->uri.type != RELATIVE ||
|
||||
strncmp( "*", hmsg->uri.pathquery.buff,
|
||||
hmsg->uri.pathquery.size ) != 0 ) {
|
||||
return FALSE;
|
||||
}
|
||||
// check HOST header
|
||||
if( ( httpmsg_find_hdr( hmsg, HDR_HOST, &hdr_value ) == NULL ) ||
|
||||
( ( memptr_cmp( &hdr_value, "239.255.255.250:1900" ) != 0 ) &&
|
||||
( memptr_cmp( &hdr_value, "[FF02::C]:1900" ) != 0 ) )
|
||||
) {
|
||||
UpnpPrintf( UPNP_INFO, SSDP, __FILE__, __LINE__,
|
||||
"Invalid HOST header from SSDP message\n" );
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE; // passed quick check
|
||||
/* check for valid methods - NOTIFY or M-SEARCH */
|
||||
if (hmsg->method != HTTPMETHOD_NOTIFY &&
|
||||
hmsg->method != HTTPMETHOD_MSEARCH &&
|
||||
hmsg->request_method != HTTPMETHOD_MSEARCH) {
|
||||
return FALSE;
|
||||
}
|
||||
if (hmsg->request_method != HTTPMETHOD_MSEARCH) {
|
||||
/* check PATH == "*" */
|
||||
if (hmsg->uri.type != RELATIVE ||
|
||||
strncmp("*", hmsg->uri.pathquery.buff, hmsg->uri.pathquery.size) != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
/* check HOST header */
|
||||
if (httpmsg_find_hdr(hmsg, HDR_HOST, &hdr_value) == NULL ||
|
||||
(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, "[FF05::C]:1900") != 0 &&
|
||||
memptr_cmp(&hdr_value, "[ff05::c]:1900") != 0)) {
|
||||
UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
|
||||
"Invalid HOST header from SSDP message\n");
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* passed quick check */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
@ -850,69 +894,92 @@ readFromSSDPSocket( SOCKET socket )
|
||||
* Returns: int
|
||||
* 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
|
||||
// Create the IPv4 socket for SSDP REQUESTS
|
||||
if( strlen( gIF_IPV4 ) > 0 ) {
|
||||
retVal = create_ssdp_sock_reqv4( &out->ssdpReqSock4 );
|
||||
if( retVal != UPNP_E_SUCCESS ) {
|
||||
return retVal;
|
||||
}
|
||||
// For use by ssdp control point.
|
||||
gSsdpReqSocket4 = out->ssdpReqSock4;
|
||||
} else {
|
||||
out->ssdpReqSock4 = INVALID_SOCKET;
|
||||
}
|
||||
/* Create the IPv4 socket for SSDP REQUESTS */
|
||||
if(strlen(gIF_IPV4) > 0) {
|
||||
retVal = create_ssdp_sock_reqv4(&out->ssdpReqSock4);
|
||||
if(retVal != UPNP_E_SUCCESS) {
|
||||
return retVal;
|
||||
}
|
||||
/* For use by ssdp control point. */
|
||||
gSsdpReqSocket4 = out->ssdpReqSock4;
|
||||
} else {
|
||||
out->ssdpReqSock4 = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
// Create the IPv6 socket for SSDP REQUESTS
|
||||
if( strlen( gIF_IPV6 ) > 0 ) {
|
||||
retVal = create_ssdp_sock_reqv6( &out->ssdpReqSock6 );
|
||||
if( retVal != UPNP_E_SUCCESS ) {
|
||||
CLIENTONLY( shutdown( out->ssdpReqSock4, SD_BOTH ); )
|
||||
CLIENTONLY( UpnpCloseSocket( out->ssdpReqSock4 ); )
|
||||
return retVal;
|
||||
}
|
||||
// For use by ssdp control point.
|
||||
gSsdpReqSocket6 = out->ssdpReqSock6;
|
||||
} else {
|
||||
out->ssdpReqSock6 = INVALID_SOCKET;
|
||||
}
|
||||
/* Create the IPv6 socket for SSDP REQUESTS */
|
||||
if (strlen(gIF_IPV6) > 0) {
|
||||
retVal = create_ssdp_sock_reqv6(&out->ssdpReqSock6);
|
||||
if (retVal != UPNP_E_SUCCESS) {
|
||||
shutdown(out->ssdpReqSock4, SD_BOTH);
|
||||
UpnpCloseSocket(out->ssdpReqSock4);
|
||||
return retVal;
|
||||
}
|
||||
/* For use by ssdp control point. */
|
||||
gSsdpReqSocket6 = out->ssdpReqSock6;
|
||||
} else {
|
||||
out->ssdpReqSock6 = INVALID_SOCKET;
|
||||
}
|
||||
#endif /* INCLUDE_CLIENT_APIS */
|
||||
|
||||
// Create the IPv4 socket for SSDP
|
||||
if( strlen( gIF_IPV4 ) > 0 ) {
|
||||
retVal = create_ssdp_sock_v4( &out->ssdpSock4 );
|
||||
if( retVal != UPNP_E_SUCCESS ) {
|
||||
CLIENTONLY( shutdown( out->ssdpReqSock4, SD_BOTH ); )
|
||||
CLIENTONLY( UpnpCloseSocket( out->ssdpReqSock4 ); )
|
||||
CLIENTONLY( shutdown( out->ssdpReqSock6, SD_BOTH ); )
|
||||
CLIENTONLY( UpnpCloseSocket( out->ssdpReqSock6 ); )
|
||||
return retVal;
|
||||
}
|
||||
} else {
|
||||
out->ssdpSock4 = INVALID_SOCKET;
|
||||
}
|
||||
/* Create the IPv4 socket for SSDP */
|
||||
if (strlen(gIF_IPV4) > 0) {
|
||||
retVal = create_ssdp_sock_v4(&out->ssdpSock4);
|
||||
if (retVal != UPNP_E_SUCCESS) {
|
||||
#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->ssdpSock4 = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
// Create the IPv6 socket for SSDP
|
||||
if( strlen( gIF_IPV6 ) > 0 ) {
|
||||
retVal = create_ssdp_sock_v6( &out->ssdpSock6 );
|
||||
if( retVal != UPNP_E_SUCCESS ) {
|
||||
shutdown( out->ssdpSock4, SD_BOTH );
|
||||
UpnpCloseSocket( out->ssdpSock4 );
|
||||
CLIENTONLY( shutdown( out->ssdpReqSock4, SD_BOTH ); )
|
||||
CLIENTONLY( UpnpCloseSocket( out->ssdpReqSock4 ); )
|
||||
CLIENTONLY( shutdown( out->ssdpReqSock6, SD_BOTH ); )
|
||||
CLIENTONLY( UpnpCloseSocket( out->ssdpReqSock6 ); )
|
||||
return retVal;
|
||||
}
|
||||
} else {
|
||||
out->ssdpSock6 = INVALID_SOCKET;
|
||||
}
|
||||
/* Create the IPv6 socket for SSDP */
|
||||
if (strlen(gIF_IPV6) > 0) {
|
||||
retVal = create_ssdp_sock_v6(&out->ssdpSock6);
|
||||
if (retVal != UPNP_E_SUCCESS) {
|
||||
shutdown(out->ssdpSock4, SD_BOTH);
|
||||
UpnpCloseSocket(out->ssdpSock4);
|
||||
#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->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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* 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 */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user