Example #1
0
static void
SendSSDPNotifies(int s, const char * host, unsigned short http_port,
                 unsigned int lifetime, int ipv6)
#endif
{
#ifdef ENABLE_IPV6
	struct sockaddr_storage sockname;
#else
	struct sockaddr_in sockname;
#endif
	socklen_t sockname_len;
	const char * dest_str;
	int i=0;
	char ver_str[4];

	memset(&sockname, 0, sizeof(sockname));
#ifdef ENABLE_IPV6
	if(ipv6)
	{
		struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockname;
		sockname_len = sizeof(struct sockaddr_in6);
		p->sin6_family = AF_INET6;
		p->sin6_port = htons(SSDP_PORT);
		inet_pton(AF_INET6, LL_SSDP_MCAST_ADDR, &(p->sin6_addr));
		dest_str = "[" LL_SSDP_MCAST_ADDR "]";
		/* TODO : also send to SL_SSDP_MCAST_ADDR and GL_SSDP_MCAST_ADDR ? */
		/* UPnP Device Architecture 1.1 :
		 * Devices MUST multicast SSDP messages for each of the UPnP-enabled
		 * interfaces. The scope of multicast SSDP messages MUST be
		 * link local FF02::C if the message is sent from a link local address.
		 * If the message is sent from a global address it MUST be multicast
		 * using either global scope FF0E::C or site local scope FF05::C.
		 * In networks with complex topologies and overlapping sites, use of
		 * global scope is RECOMMENDED. */
	}
	else
#endif
	{
		struct sockaddr_in *p = (struct sockaddr_in *)&sockname;
		sockname_len = sizeof(struct sockaddr_in);
		p->sin_family = AF_INET;
		p->sin_port = htons(SSDP_PORT);
		p->sin_addr.s_addr = inet_addr(SSDP_MCAST_ADDR);
		dest_str = SSDP_MCAST_ADDR;
	}

	while(known_service_types[i].s)
	{
		if(i==0)
			ver_str[0] = '\0';
		else
			snprintf(ver_str, sizeof(ver_str), "%d", known_service_types[i].version);
		SendSSDPNotify(s, (struct sockaddr *)&sockname, sockname_len, dest_str,
		               host, http_port,
#ifdef ENABLE_HTTPS
		               https_port,
#endif
		               known_service_types[i].s, ver_str,	/* NT: */
		               known_service_types[i].uuid, "::",
		               known_service_types[i].s, /* ver_str,	USN: */
		               lifetime);
		if(0==memcmp(known_service_types[i].s,
		             "urn:schemas-upnp-org:device", sizeof("urn:schemas-upnp-org:device")-1))
		{
			SendSSDPNotify(s, (struct sockaddr *)&sockname, sockname_len, dest_str,
			               host, http_port,
#ifdef ENABLE_HTTPS
			               https_port,
#endif
			               known_service_types[i].uuid, "",	/* NT: */
			               known_service_types[i].uuid, "", "", /* ver_str,	USN: */
			               lifetime);
		}
		i++;
	}
}
Example #2
0
static void
SendSSDPNotifies(int s, const char * host, unsigned short http_port,
                 unsigned int lifetime, int ipv6)
#endif
{
#ifdef ENABLE_IPV6
	struct sockaddr_storage sockname;
	/* UDA 1.1 AnnexA and UDA 2.0 only allow/define the use of
	 * Link-Local and Site-Local multicast scopes */
	static struct { const char * p1, * p2; } const mcast_addrs[] =
		{ { LL_SSDP_MCAST_ADDR, "[" LL_SSDP_MCAST_ADDR "]" },	/* Link Local */
		  { SL_SSDP_MCAST_ADDR, "[" SL_SSDP_MCAST_ADDR "]" },	/* Site Local */
#ifndef UPNP_STRICT
		  { GL_SSDP_MCAST_ADDR, "[" GL_SSDP_MCAST_ADDR "]" },	/* Global */
#endif /* ! UPNP_STRICT */
		  { NULL, NULL } };
	int j;
#else /* ENABLE_IPV6 */
	struct sockaddr_in sockname;
#endif /* ENABLE_IPV6 */
	socklen_t sockname_len;
	const char * dest_str;
	int i;
	char ver_str[4];
#ifndef ENABLE_IPV6
	UNUSED(ipv6);
#endif /* ENABLE_IPV6 */

	memset(&sockname, 0, sizeof(sockname));
#ifdef ENABLE_IPV6
	/* first iterate destinations for this LAN interface (only 1 for IPv4) */
	for(j = 0; (mcast_addrs[j].p1 != 0 && ipv6) || j < 1; j++) {
		if(ipv6) {
			struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockname;
			sockname_len = sizeof(struct sockaddr_in6);
			p->sin6_family = AF_INET6;
			p->sin6_port = htons(SSDP_PORT);
			inet_pton(AF_INET6, mcast_addrs[j].p1, &(p->sin6_addr));
			dest_str = mcast_addrs[j].p2;
			/* UPnP Device Architecture 1.1 :
			 * Devices MUST multicast SSDP messages for each of the UPnP-enabled
			 * interfaces. The scope of multicast SSDP messages MUST be
			 * link local FF02::C if the message is sent from a link local address.
			 * If the message is sent from a global address it MUST be multicast
			 * using either global scope FF0E::C or site local scope FF05::C.
			 * In networks with complex topologies and overlapping sites, use of
			 * global scope is RECOMMENDED. */
		} else {
#else /* ENABLE_IPV6 */
		{
#endif /* ENABLE_IPV6 */
			/* IPv4 */
			struct sockaddr_in *p = (struct sockaddr_in *)&sockname;
			sockname_len = sizeof(struct sockaddr_in);
			p->sin_family = AF_INET;
			p->sin_port = htons(SSDP_PORT);
			p->sin_addr.s_addr = inet_addr(SSDP_MCAST_ADDR);
			dest_str = SSDP_MCAST_ADDR;
		}

		/* iterate all services / devices */
		for(i = 0; known_service_types[i].s; i++) {
			if(i==0)
				ver_str[0] = '\0';
			else
				snprintf(ver_str, sizeof(ver_str), "%d", known_service_types[i].version);
			SendSSDPNotify(s, (struct sockaddr *)&sockname, sockname_len, dest_str,
			               host, http_port,
#ifdef ENABLE_HTTPS
			               https_port,
#endif
			               known_service_types[i].s, ver_str,	/* NT: */
			               known_service_types[i].uuid, "::",
			               known_service_types[i].s, /* ver_str,	USN: */
			               lifetime);
			/* for devices, also send NOTIFY on the uuid */
			if(0==memcmp(known_service_types[i].s,
			             "urn:schemas-upnp-org:device", sizeof("urn:schemas-upnp-org:device")-1)) {
				SendSSDPNotify(s, (struct sockaddr *)&sockname, sockname_len, dest_str,
				               host, http_port,
#ifdef ENABLE_HTTPS
				               https_port,
#endif
				               known_service_types[i].uuid, "",	/* NT: */
				               known_service_types[i].uuid, "", "", /* ver_str,	USN: */
				               lifetime);
			}
		} /* for(i = 0; known_service_types[i].s; i++) */
#ifdef ENABLE_IPV6
	} /* for(j = 0; (mcast_addrs[j].p1 != 0 && ipv6) || j < 1; j++) */
#endif /* ENABLE_IPV6 */
}

/* SendSSDPNotifies2() sends SSDP NOTIFY packets on all interfaces
 * for all destinations, all devices / services */
void
SendSSDPNotifies2(int * sockets,
                  unsigned short http_port,
#ifdef ENABLE_HTTPS
                  unsigned short https_port,
#endif
                  unsigned int lifetime)
{
	int i;
	struct lan_addr_s * lan_addr;
	for(i = 0, lan_addr = lan_addrs.lh_first;
	    lan_addr != NULL;
	    lan_addr = lan_addr->list.le_next) {
		SendSSDPNotifies(sockets[i], lan_addr->str, http_port,
#ifdef ENABLE_HTTPS
		                 https_port,
#endif
		                 lifetime, 0);
		i++;
#ifdef ENABLE_IPV6
		if(sockets[i] >= 0) {
			SendSSDPNotifies(sockets[i], ipv6_addr_for_http_with_brackets, http_port,
#ifdef ENABLE_HTTPS
			                 https_port,
#endif
			                 lifetime, 1);
		}
		i++;
#endif	/* ENABLE_IPV6 */
	}
}