/************************************************************************ * 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; }
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; }
/*! * \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; }
/*! * \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; }
/*! * \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; }
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; }
/*! * \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; }