示例#1
0
/************************************************************************
*	Function :	sock_destroy
*
*	Parameters :
*		INOUT SOCKINFO* info ;	Socket Information Object
*		int ShutdownMethod ;	How to shutdown the socket. Used by  
*								sockets's shutdown() 
*
*	Description :	Shutsdown the socket using the ShutdownMethod to 
*		indicate whether sends and receives on the socket will be 
*		dis-allowed. After shutting down the socket, closesocket is called
*		to release system resources used by the socket calls.
*
*	Return : int;
*		UPNP_E_SOCKET_ERROR on failure
*		UPNP_E_SUCCESS on success
*
*	Note :
************************************************************************/
int
sock_destroy( INOUT SOCKINFO * info,
              int ShutdownMethod )
{
    shutdown( info->socket, ShutdownMethod );
    if( UpnpCloseSocket( info->socket ) == -1 ) {
        return UPNP_E_SOCKET_ERROR;
    }

    return UPNP_E_SUCCESS;
}
示例#2
0
int SearchByTarget(int Mx, char *St, void *Cookie)
{
	char errorBuffer[ERROR_BUFFER_LEN];
	int *id = NULL;
	int ret = 0;
	char ReqBufv4[BUFSIZE];
#ifdef UPNP_ENABLE_IPV6
	char ReqBufv6[BUFSIZE];
	char ReqBufv6UlaGua[BUFSIZE];
#endif
	struct sockaddr_storage __ss_v4;
#ifdef UPNP_ENABLE_IPV6
	struct sockaddr_storage __ss_v6;
#endif
	struct sockaddr_in *destAddr4 = (struct sockaddr_in *)&__ss_v4;
#ifdef UPNP_ENABLE_IPV6
	struct sockaddr_in6 *destAddr6 = (struct sockaddr_in6 *)&__ss_v6;
#endif
	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);
	SOCKET max_fd = 0;
	int retVal;

	/*ThreadData *ThData; */
	ThreadPoolJob job;

	memset(&job, 0, sizeof(job));

	requestType = ssdp_request_type1(St);
	if (requestType == SSDP_SERROR)
		return UPNP_E_INVALID_PARAM;
	UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
		   "Inside SearchByTarget\n");
	timeTillRead = Mx;
	if (timeTillRead < MIN_SEARCH_TIME)
		timeTillRead = MIN_SEARCH_TIME;
	else if (timeTillRead > MAX_SEARCH_TIME)
		timeTillRead = MAX_SEARCH_TIME;
	retVal = CreateClientRequestPacket(ReqBufv4, sizeof(ReqBufv4), timeTillRead, St, AF_INET);
	if (retVal != UPNP_E_SUCCESS)
		return retVal;
#ifdef UPNP_ENABLE_IPV6
	retVal = CreateClientRequestPacket(ReqBufv6, sizeof(ReqBufv6), timeTillRead, St, AF_INET6);
	if (retVal != UPNP_E_SUCCESS)
		return retVal;
	retVal = CreateClientRequestPacketUlaGua(ReqBufv6UlaGua, sizeof(ReqBufv6UlaGua), timeTillRead, St, AF_INET6);
	if (retVal != UPNP_E_SUCCESS)
		return retVal;
#endif

	memset(&__ss_v4, 0, sizeof(__ss_v4));
	destAddr4->sin_family = (sa_family_t)AF_INET;
	inet_pton(AF_INET, SSDP_IP, &destAddr4->sin_addr);
	destAddr4->sin_port = htons(SSDP_PORT);

#ifdef UPNP_ENABLE_IPV6
	memset(&__ss_v6, 0, sizeof(__ss_v6));
	destAddr6->sin6_family = (sa_family_t)AF_INET6;
	inet_pton(AF_INET6, SSDP_IPV6_SITELOCAL, &destAddr6->sin6_addr);
	destAddr6->sin6_port = htons(SSDP_PORT);
	destAddr6->sin6_scope_id = gIF_INDEX;
#endif

	/* add search criteria to list */
	HandleLock();
	if (GetClientHandleInfo(&handle, &ctrlpt_info) != HND_CLIENT) {
		HandleUnlock();
		return UPNP_E_INTERNAL_ERROR;
	}
	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);
	/* 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();
	/* 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);
	}
#ifdef UPNP_ENABLE_IPV6
	if (gSsdpReqSocket6 != INVALID_SOCKET) {
		setsockopt(gSsdpReqSocket6, IPPROTO_IPV6, IPV6_MULTICAST_IF,
			   (char *)&gIF_INDEX, sizeof(gIF_INDEX));
		FD_SET(gSsdpReqSocket6, &wrSet);
		max_fd = max(max_fd, gSsdpReqSocket6);
	}
#endif
	ret = select(max_fd + 1, NULL, &wrSet, NULL, NULL);
	if (ret == -1) {
		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);
#ifdef UPNP_ENABLE_IPV6
		shutdown(gSsdpReqSocket6, SD_BOTH);
		UpnpCloseSocket(gSsdpReqSocket6);
#endif
		return UPNP_E_INTERNAL_ERROR;
	}
#ifdef UPNP_ENABLE_IPV6
	if (gSsdpReqSocket6 != INVALID_SOCKET &&
	    FD_ISSET(gSsdpReqSocket6, &wrSet)) {
		int NumCopy = 0;

		while (NumCopy < NUM_SSDP_COPY) {
			UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
				   ">>> SSDP SEND M-SEARCH >>>\n%s\n",
				   ReqBufv6UlaGua);
			sendto(gSsdpReqSocket6,
			       ReqBufv6UlaGua, strlen(ReqBufv6UlaGua), 0,
			       (struct sockaddr *)&__ss_v6,
			       sizeof(struct sockaddr_in6));
			NumCopy++;
			imillisleep(SSDP_PAUSE);
		}
		NumCopy = 0;
		inet_pton(AF_INET6, SSDP_IPV6_LINKLOCAL, &destAddr6->sin6_addr);
		while (NumCopy < NUM_SSDP_COPY) {
			UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
				   ">>> SSDP SEND M-SEARCH >>>\n%s\n",
				   ReqBufv6);
			sendto(gSsdpReqSocket6,
			       ReqBufv6, strlen(ReqBufv6), 0,
			       (struct sockaddr *)&__ss_v6,
			       sizeof(struct sockaddr_in6));
			NumCopy++;
			imillisleep(SSDP_PAUSE);
		}
	}
#endif /* IPv6 */
	if (gSsdpReqSocket4 != INVALID_SOCKET &&
	    FD_ISSET(gSsdpReqSocket4, &wrSet)) {
		int NumCopy = 0;
		while (NumCopy < NUM_SSDP_COPY) {
			UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
				   ">>> SSDP SEND M-SEARCH >>>\n%s\n",
				   ReqBufv4);
			sendto(gSsdpReqSocket4,
			       ReqBufv4, strlen(ReqBufv4), 0,
			       (struct sockaddr *)&__ss_v4,
			       sizeof(struct sockaddr_in));
			NumCopy++;
			imillisleep(SSDP_PAUSE);
		}
	}

	return 1;
}
示例#3
0
/*!
 * \brief Works as a request handler which passes the HTTP request string
 * to multicast channel.
 *
 * \return UPNP_E_SUCCESS if successful else appropriate error.
 */
static int NewRequestHandler(
	/*! [in] Ip address, to send the reply. */
	struct sockaddr *DestAddr,
	/*! [in] Number of packet to be sent. */
	int NumPacket,
	/*! [in] . */
	char **RqPacket)
{
	char errorBuffer[ERROR_BUFFER_LEN];
	SOCKET ReplySock;
	socklen_t socklen = sizeof(struct sockaddr_storage);
	int Index;
	unsigned long replyAddr = inet_addr(gIF_IPV4);
	/* a/c to UPNP Spec */
	int ttl = 4;
#ifdef INET_IPV6
	int hops = 1;
#endif
	char buf_ntop[INET6_ADDRSTRLEN];
	int ret = UPNP_E_SUCCESS;

	ReplySock = socket((int)DestAddr->sa_family, SOCK_DGRAM, 0);
	if (ReplySock == INVALID_SOCKET) {
		strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
		UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
			   "SSDP_LIB: New Request Handler:"
			   "Error in socket(): %s\n", errorBuffer);

		return UPNP_E_OUTOF_SOCKET;
	}

	switch (DestAddr->sa_family) {
	case AF_INET:
		inet_ntop(AF_INET, &((struct sockaddr_in *)DestAddr)->sin_addr,
			  buf_ntop, sizeof(buf_ntop));
		setsockopt(ReplySock, IPPROTO_IP, IP_MULTICAST_IF,
			   (char *)&replyAddr, sizeof(replyAddr));
		setsockopt(ReplySock, IPPROTO_IP, IP_MULTICAST_TTL,
			   (char *)&ttl, sizeof(int));
		socklen = sizeof(struct sockaddr_in);
		break;
#ifdef INET_IPV6
	case AF_INET6:
		inet_ntop(AF_INET6,
			  &((struct sockaddr_in6 *)DestAddr)->sin6_addr,
			  buf_ntop, sizeof(buf_ntop));
		setsockopt(ReplySock, IPPROTO_IPV6, IPV6_MULTICAST_IF,
			   (char *)&gIF_INDEX, sizeof(gIF_INDEX));
		setsockopt(ReplySock, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
			   (char *)&hops, sizeof(hops));
		break;
#endif
	default:
		UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
			   "Invalid destination address specified.");
		ret = UPNP_E_NETWORK_ERROR;
		goto end_NewRequestHandler;
	}

	for (Index = 0; Index < NumPacket; Index++) {
		ssize_t rc;
		UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
			   ">>> SSDP SEND to %s >>>\n%s\n",
			   buf_ntop, *(RqPacket + Index));
		rc = sendto(ReplySock, *(RqPacket + Index),
			    strlen(*(RqPacket + Index)), 0, DestAddr, socklen);
		if (rc == -1) {
			strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
			UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
				   "SSDP_LIB: New Request Handler:"
				   "Error in socket(): %s\n", errorBuffer);
			ret = UPNP_E_SOCKET_WRITE;
			goto end_NewRequestHandler;
		}
	}

 end_NewRequestHandler:
	if (shutdown(ReplySock, SD_BOTH) == -1) {
		strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
		UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
			   "Error in shutdown: %s\n", errorBuffer);
	}
	UpnpCloseSocket(ReplySock);

	return ret;
}
示例#4
0
/*!
 * \brief This function ...
 */
static int create_ssdp_sock_v6(
	/* [] SSDP IPv6 socket to be created. */
	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 == INVALID_SOCKET) {
		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);
		ret = UPNP_E_SOCKET_ERROR;
		goto error_handler;
	}
#if (defined(BSD) && !defined(__GNU__)) || 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);
		ret = UPNP_E_SOCKET_ERROR;
		goto error_handler;
	}
#endif /* BSD, __OSX__, __APPLE__ */
	onOff = 1;
	ret = setsockopt(*ssdpSock, IPPROTO_IPV6, IPV6_V6ONLY,
			 (char *)&onOff, sizeof(onOff));
	if (ret == -1) {
		strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
		UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
			   "Error in setsockopt() IPV6_V6ONLY: %s\n",
			   errorBuffer);
		ret = UPNP_E_SOCKET_ERROR;
		goto error_handler;
	}
	memset(&__ss, 0, sizeof(__ss));
	ssdpAddr6->sin6_family = (sa_family_t)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);
		ret = UPNP_E_SOCKET_BIND;
		goto error_handler;
	}
	memset((void *)&ssdpMcastAddr, 0, sizeof(ssdpMcastAddr));
	ssdpMcastAddr.ipv6mr_interface = gIF_INDEX;
	inet_pton(AF_INET6, SSDP_IPV6_LINKLOCAL,
		  &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);
		ret = UPNP_E_SOCKET_ERROR;
		goto error_handler;
	}
	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);
		ret = UPNP_E_NETWORK_ERROR;
		goto error_handler;
	}
	ret = UPNP_E_SUCCESS;

error_handler:
	if (ret != UPNP_E_SUCCESS) {
		if (shutdown(*ssdpSock, SD_BOTH) == -1) {
			strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
			UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
				   "Error in shutdown: %s\n", errorBuffer);
		}
		UpnpCloseSocket(*ssdpSock);
	}

	return ret;
}
示例#5
0
/*!
 * \brief
 */
static int create_ssdp_sock_v4(
	/*! [] SSDP IPv4 socket to be created. */
	SOCKET *ssdpSock)
{
	char errorBuffer[ERROR_BUFFER_LEN];
	int onOff;
	struct ip_mreq ssdpMcastAddr;
	struct sockaddr_storage __ss;
	struct sockaddr_in *ssdpAddr4 = (struct sockaddr_in *)&__ss;
    int i;
	int ret = 0;

	*ssdpSock = socket(AF_INET, SOCK_DGRAM, 0);
	if (*ssdpSock == INVALID_SOCKET) {
		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);
		ret = UPNP_E_SOCKET_ERROR;
		goto error_handler;
	}
#if (defined(BSD) && !defined(__GNU__)) || 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);
		ret = UPNP_E_SOCKET_ERROR;
		goto error_handler;
	}
#endif /* BSD, __OSX__, __APPLE__ */
	memset(&__ss, 0, sizeof(__ss));
	ssdpAddr4->sin_family = (sa_family_t)AF_INET;
	ssdpAddr4->sin_addr.s_addr = htonl(INADDR_ANY);
	ssdpAddr4->sin_port = htons(SSDP_PORT);
	ret = bind(*ssdpSock, (struct sockaddr *)ssdpAddr4, sizeof(*ssdpAddr4));
	if (ret == -1) {
		strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
		UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
			   "Error in bind(), addr=0x%08X, port=%d: %s\n",
			   INADDR_ANY, SSDP_PORT, errorBuffer);
		ret = UPNP_E_SOCKET_BIND;
		goto error_handler;
	}
    ret = UPNP_E_SOCKET_ERROR;
    for (i = 0; gIFIP_IPV4[i] && (i < MAX_INTERFACES); i++) {
        memset((void *)&ssdpMcastAddr, 0, sizeof(struct ip_mreq));
        ssdpMcastAddr.imr_interface.s_addr = inet_addr(gIFIP_IPV4[i]);
        ssdpMcastAddr.imr_multiaddr.s_addr = inet_addr(SSDP_IP);
        ret = setsockopt(*ssdpSock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
                 (char *)&ssdpMcastAddr, sizeof(struct ip_mreq));
        if (ret == -1) {
            strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
            UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
                   "Error in setsockopt() IP_ADD_MEMBERSHIP (join multicast group): %s\n",
                   errorBuffer);
        }
        else
            ret = UPNP_E_SUCCESS;
    }
    if (ret != UPNP_E_SUCCESS)
        goto error_handler;
	ret = UPNP_E_SUCCESS;

error_handler:
	if (ret != UPNP_E_SUCCESS) {
		if (shutdown(*ssdpSock, SD_BOTH) == -1) {
			strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
			UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
				   "Error in shutdown: %s\n", errorBuffer);
                }
                UpnpCloseSocket(*ssdpSock);
	}

	return ret;
}
示例#6
0
int get_ssdp_sockets(MiniServerSockArray * out)
{
	int retVal;

#ifdef INCLUDE_CLIENT_APIS
	out->ssdpReqSock4 = INVALID_SOCKET;
	out->ssdpReqSock6 = INVALID_SOCKET;
	/* Create the IPv4 socket for SSDP REQUESTS */
    if (gIFIP_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 */
#ifdef UPNP_ENABLE_IPV6
	if (strlen(gIF_IPV6) > (size_t)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 /* IPv6 */
#endif /* INCLUDE_CLIENT_APIS */
	/* Create the IPv4 socket for SSDP */
    if (gIFIP_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 /* INCLUDE_CLIENT_APIS */
			return retVal;
		}
	} else
		out->ssdpSock4 = INVALID_SOCKET;
	/* Create the IPv6 socket for SSDP */
#ifdef UPNP_ENABLE_IPV6
	if (strlen(gIF_IPV6) > (size_t)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 /* INCLUDE_CLIENT_APIS */
			return retVal;
		}
	} else
		out->ssdpSock6 = INVALID_SOCKET;
	if (strlen(gIF_IPV6_ULA_GUA) > (size_t)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 /* INCLUDE_CLIENT_APIS */
			return retVal;
		}
	} else
		out->ssdpSock6UlaGua = INVALID_SOCKET;
#endif /* UPNP_ENABLE_IPV6 */

	return UPNP_E_SUCCESS;
}
示例#7
0
/*!
 * \brief
 */
static int create_ssdp_sock_v4(
	/*! [] SSDP IPv4 socket to be created. */
	SOCKET *ssdpSock)
{
	char errorBuffer[ERROR_BUFFER_LEN];
	int onOff;
	u_char ttl = 4;
	struct ip_mreq ssdpMcastAddr;
	struct sockaddr_storage __ss;
	struct sockaddr_in *ssdpAddr4 = (struct sockaddr_in *)&__ss;
	int ret = 0;
	struct in_addr addr;

	*ssdpSock = socket(AF_INET, 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, __OSX__, __APPLE__ */
	memset(&__ss, 0, sizeof(__ss));
	ssdpAddr4->sin_family = AF_INET;
	ssdpAddr4->sin_addr.s_addr = htonl(INADDR_ANY);
	ssdpAddr4->sin_port = htons(SSDP_PORT);
	ret = bind(*ssdpSock, (struct sockaddr *)ssdpAddr4, sizeof(*ssdpAddr4));
	if (ret == -1) {
		strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
		UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
			   "Error in bind(), addr=0x%08X, port=%d: %s\n",
			   INADDR_ANY, SSDP_PORT, errorBuffer);
		shutdown(*ssdpSock, SD_BOTH);
		UpnpCloseSocket(*ssdpSock);

		return UPNP_E_SOCKET_BIND;
	}
	memset((void *)&ssdpMcastAddr, 0, sizeof(struct ip_mreq));
	ssdpMcastAddr.imr_interface.s_addr = inet_addr(gIF_IPV4);
	ssdpMcastAddr.imr_multiaddr.s_addr = inet_addr(SSDP_IP);
	ret = setsockopt(*ssdpSock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
			 (char *)&ssdpMcastAddr, sizeof(struct ip_mreq));
	if (ret == -1) {
		strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
		UpnpPrintf(UPNP_CRITICAL, SSDP, __FILE__, __LINE__,
			   "Error in setsockopt() IP_ADD_MEMBERSHIP (join multicast group): %s\n",
			   errorBuffer);
		shutdown(*ssdpSock, SD_BOTH);
		UpnpCloseSocket(*ssdpSock);

		return UPNP_E_SOCKET_ERROR;
	}
	/* Set multicast interface. */
	memset((void *)&addr, 0, sizeof(struct in_addr));
	addr.s_addr = inet_addr(gIF_IPV4);
	ret = setsockopt(*ssdpSock, IPPROTO_IP, IP_MULTICAST_IF,
			 (char *)&addr, sizeof addr);
	if (ret == -1) {
		strerror_r(errno, errorBuffer, ERROR_BUFFER_LEN);
		UpnpPrintf(UPNP_INFO, SSDP, __FILE__, __LINE__,
			   "Error in setsockopt() IP_MULTICAST_IF (set multicast interface): %s\n",
			   errorBuffer);
		/* This is probably not a critical error, so let's continue. */
	}
	/* result is not checked becuase it will fail in WinMe and Win9x. */
	ret = setsockopt(*ssdpSock, IPPROTO_IP,
			 IP_MULTICAST_TTL, &ttl, sizeof(ttl));
	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;
}