Example #1
0
int cmdtoken(char *args)
{
	if (args == NULL) {
		memset(nonce, 0x0, crypto_box_NONCEBYTES);
		makeblock(CODETOKEN, (uint8_t *) "AAAAAAAA", 8);
		receivedata(CMDTOKEN);
	} else if (!strncmp(args, "static", 6)) {
		printf("nonce is now static\n");
		staticnonce = 1;
	} else if (!strncmp(args, "dynamic", 7)) {
		printf("nonce is now dynamic\n");
		staticnonce = 0;
	}
	return (0);
}
Example #2
0
// supply the remote host with a command for execution
int cmdexec(char *args)
{
	uint8_t cmdmode;
	// if we don't get any commands to execute, return
	if (args == NULL) {
		return (1);
	}
	// remember to set the "silent" bit to tell the other end that we don't want output
	cmdmode = CODEEXEC;
	if (silent) {
		cmdmode = cmdmode | 0x80;
	}
	makeblock(cmdmode, (uint8_t *) args, strlen(args));
	//if we aren't in silent mode listen for output
	if (!silent) {
		receivedata(CMDEXEC);
	}
	updatenonce();
	return (0);
}
Example #3
0
/* ssdpDiscoverDevices() :
 * return a chained list of all devices found or NULL if
 * no devices was found.
 * It is up to the caller to free the chained list
 * delay is in millisecond (poll).
 * UDA v1.1 says :
 *   The TTL for the IP packet SHOULD default to 2 and
 *   SHOULD be configurable. */
struct UPNPDev *
ssdpDiscoverDevices(const char * const deviceTypes[],
                    int delay, const char * multicastif,
                    int localport,
                    int ipv6, unsigned char ttl,
                    int * error,
                    int searchalltypes)
{
	struct UPNPDev * tmp;
	struct UPNPDev * devlist = 0;
	unsigned int scope_id = 0;
	int opt = 1;
	static const char MSearchMsgFmt[] =
	"M-SEARCH * HTTP/1.1\r\n"
	"HOST: %s:" XSTR(SSDP_PORT) "\r\n"
	"ST: %s\r\n"
	"MAN: \"ssdp:discover\"\r\n"
	"MX: %u\r\n"
	"\r\n";
	int deviceIndex;
	char bufr[1536];	/* reception and emission buffer */
	int sudp;
	int n;
	struct sockaddr_storage sockudp_r;
	unsigned int mx;
#ifdef NO_GETADDRINFO
	struct sockaddr_storage sockudp_w;
#else
	int rv;
	struct addrinfo hints, *servinfo, *p;
#endif
#ifdef _WIN32
	MIB_IPFORWARDROW ip_forward;
	unsigned long _ttl = (unsigned long)ttl;
#endif
	int linklocal = 1;

	if(error)
		*error = MINISSDPC_UNKNOWN_ERROR;

	if(localport==UPNP_LOCAL_PORT_SAME)
		localport = SSDP_PORT;

#ifdef _WIN32
	sudp = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, IPPROTO_UDP);
#else
	sudp = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, 0);
#endif
	if(sudp < 0)
	{
		if(error)
			*error = MINISSDPC_SOCKET_ERROR;
		return NULL;
	}
	/* reception */
	memset(&sockudp_r, 0, sizeof(struct sockaddr_storage));
	if(ipv6) {
		struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_r;
		p->sin6_family = AF_INET6;
		if(localport > 0 && localport < 65536)
			p->sin6_port = htons((unsigned short)localport);
		p->sin6_addr = in6addr_any; /* in6addr_any is not available with MinGW32 3.4.2 */
	} else {
		struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_r;
		p->sin_family = AF_INET;
		if(localport > 0 && localport < 65536)
			p->sin_port = htons((unsigned short)localport);
		p->sin_addr.s_addr = INADDR_ANY;
	}
#ifdef _WIN32
/* This code could help us to use the right Network interface for
 * SSDP multicast traffic */
/* Get IP associated with the index given in the ip_forward struct
 * in order to give this ip to setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF) */
	if(!ipv6
	   && (GetBestRoute(inet_addr("223.255.255.255"), 0, &ip_forward) == NO_ERROR)) {
		DWORD dwRetVal = 0;
		PMIB_IPADDRTABLE pIPAddrTable;
		DWORD dwSize = 0;
#ifdef DEBUG
		IN_ADDR IPAddr;
#endif
		int i;
#ifdef DEBUG
		printf("ifIndex=%lu nextHop=%lx \n", ip_forward.dwForwardIfIndex, ip_forward.dwForwardNextHop);
#endif
		pIPAddrTable = (MIB_IPADDRTABLE *) malloc(sizeof (MIB_IPADDRTABLE));
		if(pIPAddrTable) {
			if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) {
				free(pIPAddrTable);
				pIPAddrTable = (MIB_IPADDRTABLE *) malloc(dwSize);
			}
		}
		if(pIPAddrTable) {
			dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 );
			if (dwRetVal == NO_ERROR) {
#ifdef DEBUG
				printf("\tNum Entries: %ld\n", pIPAddrTable->dwNumEntries);
#endif
				for (i=0; i < (int) pIPAddrTable->dwNumEntries; i++) {
#ifdef DEBUG
					printf("\n\tInterface Index[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwIndex);
					IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwAddr;
					printf("\tIP Address[%d]:     \t%s\n", i, inet_ntoa(IPAddr) );
					IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwMask;
					printf("\tSubnet Mask[%d]:    \t%s\n", i, inet_ntoa(IPAddr) );
					IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwBCastAddr;
					printf("\tBroadCast[%d]:      \t%s (%ld)\n", i, inet_ntoa(IPAddr), pIPAddrTable->table[i].dwBCastAddr);
					printf("\tReassembly size[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwReasmSize);
					printf("\tType and State[%d]:", i);
					printf("\n");
#endif
					if (pIPAddrTable->table[i].dwIndex == ip_forward.dwForwardIfIndex) {
						/* Set the address of this interface to be used */
						struct in_addr mc_if;
						memset(&mc_if, 0, sizeof(mc_if));
						mc_if.s_addr = pIPAddrTable->table[i].dwAddr;
						setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if));
						((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = pIPAddrTable->table[i].dwAddr;
#ifndef DEBUG
						break;
#endif
					}
				}
			}
			free(pIPAddrTable);
			pIPAddrTable = NULL;
		}
	}
#endif	/* _WIN32 */

#ifdef _WIN32
	if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof (opt)) < 0)
#else
	if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) < 0)
#endif
	{
		if(error)
			*error = MINISSDPC_SOCKET_ERROR;
		closesocket(sudp);
		return NULL;
	}

#ifdef _WIN32
	if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, (const char *)&_ttl, sizeof(_ttl)) < 0)
#else  /* _WIN32 */
	if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
#endif /* _WIN32 */
	{
		/* not a fatal error */
	}

	if(multicastif)
	{
		if(ipv6) {
#if !defined(_WIN32)
			/* according to MSDN, if_nametoindex() is supported since
			 * MS Windows Vista and MS Windows Server 2008.
			 * http://msdn.microsoft.com/en-us/library/bb408409%28v=vs.85%29.aspx */
			unsigned int ifindex = if_nametoindex(multicastif); /* eth0, etc. */
			if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)) < 0)
			{
			}
#else
#ifdef DEBUG
			printf("Setting of multicast interface not supported in IPv6 under Windows.\n");
#endif
#endif
		} else {
			struct in_addr mc_if;
			mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */
			if(mc_if.s_addr != INADDR_NONE)
			{
				((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr;
				if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0)
				{
				}
			} else {
#ifdef HAS_IP_MREQN
				/* was not an ip address, try with an interface name */
				struct ip_mreqn reqn;	/* only defined with -D_BSD_SOURCE or -D_GNU_SOURCE */
				memset(&reqn, 0, sizeof(struct ip_mreqn));
				reqn.imr_ifindex = if_nametoindex(multicastif);
				if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&reqn, sizeof(reqn)) < 0)
				{
				}
#elif !defined(_WIN32)
				struct ifreq ifr;
				int ifrlen = sizeof(ifr);
				strncpy(ifr.ifr_name, multicastif, IFNAMSIZ);
				ifr.ifr_name[IFNAMSIZ-1] = '\0';
				if(ioctl(sudp, SIOCGIFADDR, &ifr, &ifrlen) < 0)
				{
				}
				mc_if.s_addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
				if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0)
				{
				}
#else /* _WIN32 */
#ifdef DEBUG
				printf("Setting of multicast interface not supported with interface name.\n");
#endif
#endif /* #ifdef HAS_IP_MREQN / !defined(_WIN32) */
			}
		}
	}

	/* Before sending the packed, we first "bind" in order to be able
	 * to receive the response */
	if (bind(sudp, (const struct sockaddr *)&sockudp_r,
	         ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) != 0)
	{
		if(error)
			*error = MINISSDPC_SOCKET_ERROR;
		closesocket(sudp);
		return NULL;
	}

	if(error)
		*error = MINISSDPC_SUCCESS;
	/* Calculating maximum response time in seconds */
	mx = ((unsigned int)delay) / 1000u;
	if(mx == 0) {
		mx = 1;
		delay = 1000;
	}
	/* receiving SSDP response packet */
	for(deviceIndex = 0; deviceTypes[deviceIndex]; deviceIndex++) {
		/* sending the SSDP M-SEARCH packet */
		n = snprintf(bufr, sizeof(bufr),
		             MSearchMsgFmt,
		             ipv6 ?
		             (linklocal ? "[" UPNP_MCAST_LL_ADDR "]" :  "[" UPNP_MCAST_SL_ADDR "]")
		             : UPNP_MCAST_ADDR,
		             deviceTypes[deviceIndex], mx);
		if ((unsigned int)n >= sizeof(bufr)) {
			if(error)
				*error = MINISSDPC_MEMORY_ERROR;
			goto error;
		}
#ifdef DEBUG
		/*printf("Sending %s", bufr);*/
		printf("Sending M-SEARCH request to %s with ST: %s\n",
		       ipv6 ?
		       (linklocal ? "[" UPNP_MCAST_LL_ADDR "]" :  "[" UPNP_MCAST_SL_ADDR "]")
		       : UPNP_MCAST_ADDR,
		       deviceTypes[deviceIndex]);
#endif
#ifdef NO_GETADDRINFO
		/* the following code is not using getaddrinfo */
		/* emission */
		memset(&sockudp_w, 0, sizeof(struct sockaddr_storage));
		if(ipv6) {
			struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_w;
			p->sin6_family = AF_INET6;
			p->sin6_port = htons(SSDP_PORT);
			inet_pton(AF_INET6,
			          linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR,
			          &(p->sin6_addr));
		} else {
			struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_w;
			p->sin_family = AF_INET;
			p->sin_port = htons(SSDP_PORT);
			p->sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR);
		}
		n = sendto(sudp, bufr, n, 0, &sockudp_w,
		           ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
		if (n < 0) {
			if(error)
				*error = MINISSDPC_SOCKET_ERROR;
			break;
		}
#else /* #ifdef NO_GETADDRINFO */
		memset(&hints, 0, sizeof(hints));
		hints.ai_family = AF_UNSPEC; /* AF_INET6 or AF_INET */
		hints.ai_socktype = SOCK_DGRAM;
		/*hints.ai_flags = */
		if ((rv = getaddrinfo_retro(ipv6
		                      ? (linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR)
		                      : UPNP_MCAST_ADDR,
		                      XSTR(SSDP_PORT), &hints, &servinfo)) != 0) {
			if(error)
				*error = MINISSDPC_SOCKET_ERROR;
#ifdef _WIN32
			fprintf(stderr, "getaddrinfo() failed: %d\n", rv);
#else
			fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
#endif
			break;
		}
		for(p = servinfo; p; p = p->ai_next) {
			n = (int)sendto(sudp, bufr, n, 0, p->ai_addr, p->ai_addrlen);
			if (n < 0) {
#ifdef DEBUG
				char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
				if (getnameinfo(p->ai_addr, p->ai_addrlen, hbuf, sizeof(hbuf), sbuf,
				                sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
					fprintf(stderr, "host:%s port:%s\n", hbuf, sbuf);
				}
#endif
				continue;
			}
		}
		freeaddrinfo(servinfo);
		if(n < 0) {
			if(error)
				*error = MINISSDPC_SOCKET_ERROR;
			break;
		}
#endif /* #ifdef NO_GETADDRINFO */
		/* Waiting for SSDP REPLY packet to M-SEARCH
		 * if searchalltypes is set, enter the loop only
		 * when the last deviceType is reached */
		if(!searchalltypes || !deviceTypes[deviceIndex + 1]) do {
			n = receivedata(sudp, bufr, sizeof(bufr), delay, &scope_id);
			if (n < 0) {
				/* error */
				if(error)
					*error = MINISSDPC_SOCKET_ERROR;
				goto error;
			} else if (n == 0) {
				/* no data or Time Out */
#ifdef DEBUG
				printf("NODATA or TIMEOUT\n");
#endif /* DEBUG */
				if (devlist && !searchalltypes) {
					/* found some devices, stop now*/
					if(error)
						*error = MINISSDPC_SUCCESS;
					goto error;
				}
			} else {
				const char * descURL=NULL;
				int urlsize=0;
				const char * st=NULL;
				int stsize=0;
				const char * usn=NULL;
				int usnsize=0;
				parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize, &usn, &usnsize);
				if(st&&descURL) {
#ifdef DEBUG
					printf("M-SEARCH Reply:\n  ST: %.*s\n  USN: %.*s\n  Location: %.*s\n",
					       stsize, st, usnsize, (usn?usn:""), urlsize, descURL);
#endif /* DEBUG */
					for(tmp=devlist; tmp; tmp = tmp->pNext) {
						if(memcmp(tmp->descURL, descURL, urlsize) == 0 &&
						   tmp->descURL[urlsize] == '\0' &&
						   memcmp(tmp->st, st, stsize) == 0 &&
						   tmp->st[stsize] == '\0' &&
						   (usnsize == 0 || memcmp(tmp->usn, usn, usnsize) == 0) &&
						   tmp->usn[usnsize] == '\0')
							break;
					}
					/* at the exit of the loop above, tmp is null if
					 * no duplicate device was found */
					if(tmp)
						continue;
					tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize+usnsize);
					if(!tmp) {
						/* memory allocation error */
						if(error)
							*error = MINISSDPC_MEMORY_ERROR;
						goto error;
					}
					tmp->pNext = devlist;
					tmp->descURL = tmp->buffer;
					tmp->st = tmp->buffer + 1 + urlsize;
					tmp->usn = tmp->st + 1 + stsize;
					memcpy(tmp->buffer, descURL, urlsize);
					tmp->buffer[urlsize] = '\0';
					memcpy(tmp->st, st, stsize);
					tmp->buffer[urlsize+1+stsize] = '\0';
					if(usn != NULL)
						memcpy(tmp->usn, usn, usnsize);
					tmp->buffer[urlsize+1+stsize+1+usnsize] = '\0';
					tmp->scope_id = scope_id;
					devlist = tmp;
				}
			}
		} while(n > 0);
		if(ipv6) {
			/* switch linklocal flag */
			if(linklocal) {
				linklocal = 0;
				--deviceIndex;
			} else {
				linklocal = 1;
			}
		}
	}
error:
	closesocket(sudp);
	return devlist;
}
Example #4
0
/* upnpDiscover() :
 * return a chained list of all devices found or NULL if
 * no devices was found.
 * It is up to the caller to free the chained list
 * delay is in millisecond (poll) */
LIBSPEC struct UPNPDev *
upnpDiscover(int delay, const char * multicastif,
             const char * minissdpdsock, int sameport,
             int ipv6,
             int * error)
{
	struct UPNPDev * tmp;
	struct UPNPDev * devlist = 0;
	unsigned int scope_id = 0;
	int opt = 1;
	static const char MSearchMsgFmt[] =
	"M-SEARCH * HTTP/1.1\r\n"
	"HOST: %s:" XSTR(PORT) "\r\n"
	"ST: %s\r\n"
	"MAN: \"ssdp:discover\"\r\n"
	"MX: %u\r\n"
	"\r\n";
	static const char * const deviceList[] = {
#if 0
		"urn:schemas-upnp-org:device:InternetGatewayDevice:2",
		"urn:schemas-upnp-org:service:WANIPConnection:2",
#endif
		"urn:schemas-upnp-org:device:InternetGatewayDevice:1",
		"urn:schemas-upnp-org:service:WANIPConnection:1",
		"urn:schemas-upnp-org:service:WANPPPConnection:1",
		"upnp:rootdevice",
		0
	};
	int deviceIndex = 0;
	char bufr[1536];	/* reception and emission buffer */
	int sudp;
	int n;
	struct sockaddr_storage sockudp_r;
	unsigned int mx;
#ifdef NO_GETADDRINFO
	struct sockaddr_storage sockudp_w;
#else
	int rv;
	struct addrinfo hints, *servinfo, *p;
#endif
#ifdef _WIN32
	MIB_IPFORWARDROW ip_forward;
#endif
	int linklocal = 1;

	if(error)
		*error = UPNPDISCOVER_UNKNOWN_ERROR;
	/* fallback to direct discovery */
#ifdef _WIN32
	sudp = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, IPPROTO_UDP);
#else
	sudp = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, 0);
#endif
	if(sudp < 0)
	{
		if(error)
			*error = UPNPDISCOVER_SOCKET_ERROR;
		PRINT_SOCKET_ERROR("socket");
		return NULL;
	}
	/* reception */
	memset(&sockudp_r, 0, sizeof(struct sockaddr_storage));
	if(ipv6) {
		struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_r;
		p->sin6_family = AF_INET6;
		if(sameport)
			p->sin6_port = htons(PORT);
		p->sin6_addr = in6addr_any; /* in6addr_any is not available with MinGW32 3.4.2 */
	} else {
		struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_r;
		p->sin_family = AF_INET;
		if(sameport)
			p->sin_port = htons(PORT);
		p->sin_addr.s_addr = INADDR_ANY;
	}
#ifdef _WIN32
/* This code could help us to use the right Network interface for
 * SSDP multicast traffic */
/* Get IP associated with the index given in the ip_forward struct
 * in order to give this ip to setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF) */
	if(!ipv6
	   && (GetBestRoute(inet_addr("223.255.255.255"), 0, &ip_forward) == NO_ERROR)) {
		DWORD dwRetVal = 0;
		PMIB_IPADDRTABLE pIPAddrTable;
		DWORD dwSize = 0;
#ifdef DEBUG
		IN_ADDR IPAddr;
#endif
		int i;
#ifdef DEBUG
		printf("ifIndex=%lu nextHop=%lx \n", ip_forward.dwForwardIfIndex, ip_forward.dwForwardNextHop);
#endif
		pIPAddrTable = (MIB_IPADDRTABLE *) malloc(sizeof (MIB_IPADDRTABLE));
		if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) {
			free(pIPAddrTable);
			pIPAddrTable = (MIB_IPADDRTABLE *) malloc(dwSize);
		}
		if(pIPAddrTable) {
			dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 );
#ifdef DEBUG
			printf("\tNum Entries: %ld\n", pIPAddrTable->dwNumEntries);
#endif
			for (i=0; i < (int) pIPAddrTable->dwNumEntries; i++) {
#ifdef DEBUG
				printf("\n\tInterface Index[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwIndex);
				IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwAddr;
				printf("\tIP Address[%d]:     \t%s\n", i, inet_ntoa(IPAddr) );
				IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwMask;
				printf("\tSubnet Mask[%d]:    \t%s\n", i, inet_ntoa(IPAddr) );
				IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwBCastAddr;
				printf("\tBroadCast[%d]:      \t%s (%ld)\n", i, inet_ntoa(IPAddr), pIPAddrTable->table[i].dwBCastAddr);
				printf("\tReassembly size[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwReasmSize);
				printf("\tType and State[%d]:", i);
				printf("\n");
#endif
				if (pIPAddrTable->table[i].dwIndex == ip_forward.dwForwardIfIndex) {
					/* Set the address of this interface to be used */
					struct in_addr mc_if;
					memset(&mc_if, 0, sizeof(mc_if));
					mc_if.s_addr = pIPAddrTable->table[i].dwAddr;
					if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) {
						PRINT_SOCKET_ERROR("setsockopt");
					}
					((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = pIPAddrTable->table[i].dwAddr;
#ifndef DEBUG
					break;
#endif
				}
			}
			free(pIPAddrTable);
			pIPAddrTable = NULL;
		}
	}
#endif

#ifdef _WIN32
	if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof (opt)) < 0)
#else
	if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) < 0)
#endif
	{
		if(error)
			*error = UPNPDISCOVER_SOCKET_ERROR;
		PRINT_SOCKET_ERROR("setsockopt");
		return NULL;
	}

	if(multicastif)
	{
		if(ipv6) {
#if !defined(_WIN32)
			/* according to MSDN, if_nametoindex() is supported since
			 * MS Windows Vista and MS Windows Server 2008.
			 * http://msdn.microsoft.com/en-us/library/bb408409%28v=vs.85%29.aspx */
			unsigned int ifindex = if_nametoindex(multicastif); /* eth0, etc. */
			if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(&ifindex)) < 0)
			{
				PRINT_SOCKET_ERROR("setsockopt");
			}
#else
#ifdef DEBUG
			printf("Setting of multicast interface not supported in IPv6 under Windows.\n");
#endif
#endif
		} else {
			struct in_addr mc_if;
			mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */
			if(mc_if.s_addr != INADDR_NONE)
			{
				((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr;
				if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0)
				{
					PRINT_SOCKET_ERROR("setsockopt");
				}
			} else {
#ifdef HAS_IP_MREQN
				/* was not an ip address, try with an interface name */
				struct ip_mreqn reqn;	/* only defined with -D_BSD_SOURCE or -D_GNU_SOURCE */
				memset(&reqn, 0, sizeof(struct ip_mreqn));
				reqn.imr_ifindex = if_nametoindex(multicastif);
				if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&reqn, sizeof(reqn)) < 0)
				{
					PRINT_SOCKET_ERROR("setsockopt");
				}
#else
#ifdef DEBUG
				printf("Setting of multicast interface not supported with interface name.\n");
#endif
#endif
			}
		}
	}

	/* Avant d'envoyer le paquet on bind pour recevoir la reponse */
    if (bind(sudp, (const struct sockaddr *)&sockudp_r,
	         ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) != 0)
	{
		if(error)
			*error = UPNPDISCOVER_SOCKET_ERROR;
        PRINT_SOCKET_ERROR("bind");
		closesocket(sudp);
		return NULL;
    }

	if(error)
		*error = UPNPDISCOVER_SUCCESS;
	/* Calculating maximum response time in seconds */
	mx = ((unsigned int)delay) / 1000u;
	/* receiving SSDP response packet */
	for(n = 0; deviceList[deviceIndex]; deviceIndex++)
	{
	if(n == 0)
	{
		/* sending the SSDP M-SEARCH packet */
		n = snprintf(bufr, sizeof(bufr),
		             MSearchMsgFmt,
		             ipv6 ?
		             (linklocal ? "[" UPNP_MCAST_LL_ADDR "]" :  "[" UPNP_MCAST_SL_ADDR "]")
		             : UPNP_MCAST_ADDR,
		             deviceList[deviceIndex], mx);
#ifdef DEBUG
		printf("Sending %s", bufr);
#endif
#ifdef NO_GETADDRINFO
		/* the following code is not using getaddrinfo */
		/* emission */
		memset(&sockudp_w, 0, sizeof(struct sockaddr_storage));
		if(ipv6) {
			struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_w;
			p->sin6_family = AF_INET6;
			p->sin6_port = htons(PORT);
			inet_pton(AF_INET6,
			          linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR,
			          &(p->sin6_addr));
		} else {
			struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_w;
			p->sin_family = AF_INET;
			p->sin_port = htons(PORT);
			p->sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR);
		}
		n = sendto(sudp, bufr, n, 0,
		           &sockudp_w,
		           ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
		if (n < 0) {
			if(error)
				*error = UPNPDISCOVER_SOCKET_ERROR;
			PRINT_SOCKET_ERROR("sendto");
			break;
		}
#else /* #ifdef NO_GETADDRINFO */
		memset(&hints, 0, sizeof(hints));
		hints.ai_family = AF_UNSPEC; /* AF_INET6 or AF_INET */
		hints.ai_socktype = SOCK_DGRAM;
		/*hints.ai_flags = */
		if ((rv = getaddrinfo(ipv6
		                      ? (linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR)
		                      : UPNP_MCAST_ADDR,
		                      XSTR(PORT), &hints, &servinfo)) != 0) {
			if(error)
				*error = UPNPDISCOVER_SOCKET_ERROR;
#ifdef _WIN32
		    fprintf(stderr, "getaddrinfo() failed: %d\n", rv);
#else
		    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
#endif
			break;
		}
		for(p = servinfo; p; p = p->ai_next) {
			n = sendto(sudp, bufr, n, 0, p->ai_addr, p->ai_addrlen);
			if (n < 0) {
#ifdef DEBUG
				char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
				if (getnameinfo(p->ai_addr, p->ai_addrlen, hbuf, sizeof(hbuf), sbuf,
						sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
					fprintf(stderr, "host:%s port:%s\n", hbuf, sbuf);
				}
#endif
				PRINT_SOCKET_ERROR("sendto");
				continue;
			}
		}
		freeaddrinfo(servinfo);
		if(n < 0) {
			if(error)
				*error = UPNPDISCOVER_SOCKET_ERROR;
			break;
		}
#endif /* #ifdef NO_GETADDRINFO */
	}
	/* Waiting for SSDP REPLY packet to M-SEARCH */
	n = receivedata(sudp, bufr, sizeof(bufr), delay, &scope_id);
	if (n < 0) {
		/* error */
		if(error)
			*error = UPNPDISCOVER_SOCKET_ERROR;
		break;
	} else if (n == 0) {
		/* no data or Time Out */
		if (devlist) {
			/* no more device type to look for... */
			if(error)
				*error = UPNPDISCOVER_SUCCESS;
			break;
		}
		if(ipv6) {
			if(linklocal) {
				linklocal = 0;
				--deviceIndex;
			} else {
				linklocal = 1;
			}
		}
	} else {
		const char * descURL=NULL;
		int urlsize=0;
		const char * st=NULL;
		int stsize=0;
        /*printf("%d byte(s) :\n%s\n", n, bufr);*/ /* affichage du message */
		parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize);
		if(st&&descURL)
		{
#ifdef DEBUG
			printf("M-SEARCH Reply:\nST: %.*s\nLocation: %.*s\n",
			       stsize, st, urlsize, descURL);
#endif
			for(tmp=devlist; tmp; tmp = tmp->pNext) {
				if(memcmp(tmp->descURL, descURL, urlsize) == 0 &&
				   tmp->descURL[urlsize] == '\0' &&
				   memcmp(tmp->st, st, stsize) == 0 &&
				   tmp->st[stsize] == '\0')
					break;
			}
			/* at the exit of the loop above, tmp is null if
			 * no duplicate device was found */
			if(tmp)
				continue;
			tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize);
			if(!tmp) {
				/* memory allocation error */
				if(error)
					*error = UPNPDISCOVER_MEMORY_ERROR;
				break;
			}
			tmp->pNext = devlist;
			tmp->descURL = tmp->buffer;
			tmp->st = tmp->buffer + 1 + urlsize;
			memcpy(tmp->buffer, descURL, urlsize);
			tmp->buffer[urlsize] = '\0';
			memcpy(tmp->buffer + urlsize + 1, st, stsize);
			tmp->buffer[urlsize+1+stsize] = '\0';
			tmp->scope_id = scope_id;
			devlist = tmp;
		}
	}
	}
	closesocket(sudp);
	return devlist;
}
Example #5
0
/*
 * Read a HTTP response from a socket.
 * Process Content-Length and Transfer-encoding headers.
 * return a pointer to the content buffer, which length is saved
 * to the length parameter.
 */
void *
getHTTPResponse(int s, int * size, int * status_code)
{
	char buf[2048];
	int n;
	int endofheaders = 0;
	int chunked = 0;
	int content_length = -1;
	unsigned int chunksize = 0;
	unsigned int bytestocopy = 0;
	/* buffers : */
	char * header_buf;
	unsigned int header_buf_len = 2048;
	unsigned int header_buf_used = 0;
	char * content_buf;
	unsigned int content_buf_len = 2048;
	unsigned int content_buf_used = 0;
	char chunksize_buf[32];
	unsigned int chunksize_buf_index;
#ifdef DEBUG
	char * reason_phrase = NULL;
	int reason_phrase_len = 0;
#endif

	if(status_code) *status_code = -1;
	header_buf = malloc(header_buf_len);
	if(header_buf == NULL)
	{
#ifdef DEBUG
		fprintf(stderr, "%s: Memory allocation error\n", "getHTTPResponse");
#endif /* DEBUG */
		*size = -1;
		return NULL;
	}
	content_buf = malloc(content_buf_len);
	if(content_buf == NULL)
	{
		free(header_buf);
#ifdef DEBUG
		fprintf(stderr, "%s: Memory allocation error\n", "getHTTPResponse");
#endif /* DEBUG */
		*size = -1;
		return NULL;
	}
	chunksize_buf[0] = '\0';
	chunksize_buf_index = 0;

	while((n = receivedata(s, buf, 2048, 5000, NULL)) > 0)
	{
		if(endofheaders == 0)
		{
			int i;
			int linestart=0;
			int colon=0;
			int valuestart=0;
			if(header_buf_used + n > header_buf_len) {
				char * tmp = realloc(header_buf, header_buf_used + n);
				if(tmp == NULL) {
					/* memory allocation error */
					free(header_buf);
					free(content_buf);
					*size = -1;
					return NULL;
				}
				header_buf = tmp;
				header_buf_len = header_buf_used + n;
			}
			memcpy(header_buf + header_buf_used, buf, n);
			header_buf_used += n;
			/* search for CR LF CR LF (end of headers)
			 * recognize also LF LF */
			i = 0;
			while(i < ((int)header_buf_used-1) && (endofheaders == 0)) {
				if(header_buf[i] == '\r') {
					i++;
					if(header_buf[i] == '\n') {
						i++;
						if(i < (int)header_buf_used && header_buf[i] == '\r') {
							i++;
							if(i < (int)header_buf_used && header_buf[i] == '\n') {
								endofheaders = i+1;
							}
						}
					}
				} else if(header_buf[i] == '\n') {
					i++;
					if(header_buf[i] == '\n') {
						endofheaders = i+1;
					}
				}
				i++;
			}
			if(endofheaders == 0)
				continue;
			/* parse header lines */
			for(i = 0; i < endofheaders - 1; i++) {
				if(linestart > 0 && colon <= linestart && header_buf[i]==':')
				{
					colon = i;
					while(i < (endofheaders-1)
					      && (header_buf[i+1] == ' ' || header_buf[i+1] == '\t'))
						i++;
					valuestart = i + 1;
				}
				/* detecting end of line */
				else if(header_buf[i]=='\r' || header_buf[i]=='\n')
				{
					if(linestart == 0 && status_code)
					{
						/* Status line
						 * HTTP-Version SP Status-Code SP Reason-Phrase CRLF */
						int sp;
						for(sp = 0; sp < i; sp++)
							if(header_buf[sp] == ' ')
							{
								if(*status_code < 0)
									*status_code = atoi(header_buf + sp + 1);
								else
								{
#ifdef DEBUG
									reason_phrase = header_buf + sp + 1;
									reason_phrase_len = i - sp - 1;
#endif
									break;
								}
							}
#ifdef DEBUG
						printf("HTTP status code = %d, Reason phrase = %.*s\n",
						       *status_code, reason_phrase_len, reason_phrase);
#endif
					}
					else if(colon > linestart && valuestart > colon)
					{
#ifdef DEBUG
						printf("header='%.*s', value='%.*s'\n",
						       colon-linestart, header_buf+linestart,
						       i-valuestart, header_buf+valuestart);
#endif
						if(0==strncasecmp(header_buf+linestart, "content-length", colon-linestart))
						{
							content_length = atoi(header_buf+valuestart);
#ifdef DEBUG
							printf("Content-Length: %d\n", content_length);
#endif
						}
						else if(0==strncasecmp(header_buf+linestart, "transfer-encoding", colon-linestart)
						   && 0==strncasecmp(header_buf+valuestart, "chunked", 7))
						{
#ifdef DEBUG
							printf("chunked transfer-encoding!\n");
#endif
							chunked = 1;
						}
					}
					while((i < (int)header_buf_used) && (header_buf[i]=='\r' || header_buf[i] == '\n'))
						i++;
					linestart = i;
					colon = linestart;
					valuestart = 0;
				}
			}
			/* copy the remaining of the received data back to buf */
			n = header_buf_used - endofheaders;
			memcpy(buf, header_buf + endofheaders, n);
			/* if(headers) */
		}
		if(endofheaders)
		{
			/* content */
			if(chunked)
			{
				int i = 0;
				while(i < n)
				{
					if(chunksize == 0)
					{
						/* reading chunk size */
						if(chunksize_buf_index == 0) {
							/* skipping any leading CR LF */
							if(i<n && buf[i] == '\r') i++;
							if(i<n && buf[i] == '\n') i++;
						}
						while(i<n && isxdigit(buf[i])
						     && chunksize_buf_index < (sizeof(chunksize_buf)-1))
						{
							chunksize_buf[chunksize_buf_index++] = buf[i];
							chunksize_buf[chunksize_buf_index] = '\0';
							i++;
						}
						while(i<n && buf[i] != '\r' && buf[i] != '\n')
							i++; /* discarding chunk-extension */
						if(i<n && buf[i] == '\r') i++;
						if(i<n && buf[i] == '\n') {
							unsigned int j;
							for(j = 0; j < chunksize_buf_index; j++) {
							if(chunksize_buf[j] >= '0'
							   && chunksize_buf[j] <= '9')
								chunksize = (chunksize << 4) + (chunksize_buf[j] - '0');
							else
								chunksize = (chunksize << 4) + ((chunksize_buf[j] | 32) - 'a' + 10);
							}
							chunksize_buf[0] = '\0';
							chunksize_buf_index = 0;
							i++;
						} else {
							/* not finished to get chunksize */
							continue;
						}
#ifdef DEBUG
						printf("chunksize = %u (%x)\n", chunksize, chunksize);
#endif
						if(chunksize == 0)
						{
#ifdef DEBUG
							printf("end of HTTP content - %d %d\n", i, n);
							/*printf("'%.*s'\n", n-i, buf+i);*/
#endif
							goto end_of_stream;
						}
					}
					bytestocopy = ((int)chunksize < (n - i))?chunksize:(unsigned int)(n - i);
					if((content_buf_used + bytestocopy) > content_buf_len)
					{
						char * tmp;
						if(content_length >= (int)(content_buf_used + bytestocopy)) {
							content_buf_len = content_length;
						} else {
							content_buf_len = content_buf_used + bytestocopy;
						}
						tmp = realloc(content_buf, content_buf_len);
						if(tmp == NULL) {
							/* memory allocation error */
							free(content_buf);
							free(header_buf);
							*size = -1;
							return NULL;
						}
						content_buf = tmp;
					}
					memcpy(content_buf + content_buf_used, buf + i, bytestocopy);
					content_buf_used += bytestocopy;
					i += bytestocopy;
					chunksize -= bytestocopy;
				}
			}
			else
			{
				/* not chunked */
				if(content_length > 0
				   && (int)(content_buf_used + n) > content_length) {
					/* skipping additional bytes */
					n = content_length - content_buf_used;
				}
				if(content_buf_used + n > content_buf_len)
				{
					char * tmp;
					if(content_length >= (int)(content_buf_used + n)) {
						content_buf_len = content_length;
					} else {
						content_buf_len = content_buf_used + n;
					}
					tmp = realloc(content_buf, content_buf_len);
					if(tmp == NULL) {
						/* memory allocation error */
						free(content_buf);
						free(header_buf);
						*size = -1;
						return NULL;
					}
					content_buf = tmp;
				}
				memcpy(content_buf + content_buf_used, buf, n);
				content_buf_used += n;
			}
		}
		/* use the Content-Length header value if available */
		if(content_length > 0 && (int)content_buf_used >= content_length)
		{
#ifdef DEBUG
			printf("End of HTTP content\n");
#endif
			break;
		}
	}
end_of_stream:
	free(header_buf); header_buf = NULL;
	*size = content_buf_used;
	if(content_buf_used == 0)
	{
		free(content_buf);
		content_buf = NULL;
	}
	return content_buf;
}
Example #6
0
int  rev_data_struct()
{
    char buff[100];
    memset(buff,0,100);
    DEBUG_printf("r_connect = %d.\n",r_connect);
    if((recvbytes = receivedata(ssl,sockfd,&package.pkg_head,2)) == -1)         //At the beginning of two bytes
    {
        DEBUG_printf("recv data failed1.\n");
        r_connect = 0;//the failure of receiving data prove the break of connection,mark it at here.
        clear_recv(deal_package);
        ClearQueue(&Q_cmd);//clear the comdmand queue when failed to receive data.
        ClearQueue(&Q_respond);//clear the comdmand queue when failed to receive data.
        return 0;
        //perror("recv");
        //exit(1);
    }
    DEBUG_printf("recv package.pkg_head:%s.\n",package.pkg_head);
    package.pkg_head[recvbytes]='\0';
    if(recvbytes==0)
    {
        DEBUG_printf("the first two byte not 00   it is 0\n");
        return 0;
    }
    else if(strcmp(package.pkg_head,"00")!=0)
    return -1;  //bad package
    if((recvbytes = receivedata(ssl,sockfd,&package.pkg_cmd,2)) == -1) //Command two bytes
    {
        r_connect = 0;
        return 0;
        //perror("recv");
        //exit(1);
    }
    if(recvbytes==0)
        return 0;
    else if(recvbytes!=2)
        return -1; //bad package
    package.pkg_cmd[recvbytes]='\0';
    DEBUG_printf("rev from server cmd = \n%s\n",package.pkg_cmd);
    unsigned char nonce_len[2];
    if ((recvbytes = receivedata(ssl,sockfd,&nonce_len,2)) == -1)  //two bytes of the lenth of body
    {
        r_connect = 0;
        return 0;
        //perror("recv");
        //exit(1);
    }
    if(recvbytes==0)
        return 0;
    else if(recvbytes!=2)
        return -1; //bad package
    int sum;
    //DEBUG_printf("pkg_body_len[0]=%c\n",package.pkg_body_len[0]);
    //DEBUG_printf("pkg_body_len[1]=%c\n",package.pkg_body_len[1]);
    sum=nonce_len[0]*256+nonce_len[1];                              // Calculate the length of the body
    DEBUG_printf("rev from server sum=\n%d\n",sum);
    //memset(package.pkg_body,0,BUFFER_SIZE);
    if(sum==0)
    {
        package.pkg_nonce[0]='\0';
    }
    else
    {
        if ((recvbytes = receivedata(ssl,sockfd,&package.pkg_nonce,sum)) == -1)  //According to the receiving body length
        {
            r_connect = 0;
            return 0;
            //perror("recv");
            //exit(1);
        }
        package.pkg_nonce[sum]='\0';
        DEBUG_printf("recvbytes:%d,sum:%d,pkgnonce=%s\n",recvbytes,sum,package.pkg_nonce);
        if(recvbytes==0)
        {
            r_connect = 0;
            return 0;
        }
        else
        {
            if(recvbytes!=sum)                                 //Judge whether the body of the received meet the requirements
            {
                DEBUG_printf("PAKGE ERROR!!!!!\n");
                return -1;
                //exit(1);
            }
        }
    }
    return 1;
}//*/
Example #7
0
/*
 * Read a HTTP response from a socket.
 * Process Content-Length and Transfer-encoding headers.
 */
void *
getHTTPResponse(int s, int * size)
{
	char buf[2048];
	int n;
	int endofheaders = 0;
	int chunked = 0;
	int content_length = -1;
	unsigned int chunksize = 0;
	unsigned int bytestocopy = 0;
	/* buffers : */
	char * header_buf;
	int header_buf_len = 2048;
	int header_buf_used = 0;
	char * content_buf;
	int content_buf_len = 2048;
	int content_buf_used = 0;
	char chunksize_buf[32];
	int chunksize_buf_index;

	header_buf = malloc(header_buf_len);
	content_buf = malloc(content_buf_len);
	chunksize_buf[0] = '\0';
	chunksize_buf_index = 0;

	while((n = receivedata(s, buf, 2048, 5000)) > 0)
	{
		if(endofheaders == 0)
		{
			int i;
			int linestart=0;
			int colon=0;
			int valuestart=0;
			if(header_buf_used + n > header_buf_len) {
				header_buf = realloc(header_buf, header_buf_used + n);
				header_buf_len = header_buf_used + n;
			}
			memcpy(header_buf + header_buf_used, buf, n);
			header_buf_used += n;
			/* search for CR LF CR LF (end of headers)
			 * recognize also LF LF */
			i = 0;
			while(i < (header_buf_used-1) && (endofheaders == 0)) {
				if(header_buf[i] == '\r') {
					i++;
					if(header_buf[i] == '\n') {
						i++;
						if(i < header_buf_used && header_buf[i] == '\r') {
							i++;
							if(i < header_buf_used && header_buf[i] == '\n') {
								endofheaders = i+1;
							}
						}
					}
				} else if(header_buf[i] == '\n') {
					i++;
					if(header_buf[i] == '\n') {
						endofheaders = i+1;
					}
				}
				i++;
			}
			if(endofheaders == 0)
				continue;
			/* parse header lines */
			for(i = 0; i < endofheaders - 1; i++) {
				if(colon <= linestart && header_buf[i]==':')
				{
					colon = i;
					while(i < (endofheaders-1)
					      && (header_buf[i+1] == ' ' || header_buf[i+1] == '\t'))
						i++;
					valuestart = i + 1;
				}
				/* detecting end of line */
				else if(header_buf[i]=='\r' || header_buf[i]=='\n')
				{
					if(colon > linestart && valuestart > colon)
					{
#ifdef DEBUG
						printf("header='%.*s', value='%.*s'\n",
						       colon-linestart, header_buf+linestart,
						       i-valuestart, header_buf+valuestart);
#endif
						if(0==strncasecmp(header_buf+linestart, "content-length", colon-linestart))
						{
							content_length = atoi(header_buf+valuestart);
#ifdef DEBUG
							printf("Content-Length: %d\n", content_length);
#endif
						}
						else if(0==strncasecmp(header_buf+linestart, "transfer-encoding", colon-linestart)
						   && 0==strncasecmp(header_buf+valuestart, "chunked", 7))
						{
#ifdef DEBUG
							printf("chunked transfer-encoding!\n");
#endif
							chunked = 1;
						}
					}
					while(header_buf[i]=='\r' || header_buf[i] == '\n')
						i++;
					linestart = i;
					colon = linestart;
					valuestart = 0;
				} 
			}
			/* copy the remaining of the received data back to buf */
			n = header_buf_used - endofheaders;
			memcpy(buf, header_buf + endofheaders, n);
			/* if(headers) */
		}
		if(endofheaders)
		{
			/* content */
			if(chunked)
			{
				int i = 0;
				while(i < n)
				{
					if(chunksize == 0)
					{
						/* reading chunk size */
						if(chunksize_buf_index == 0) {
							/* skipping any leading CR LF */
							if(i<n && buf[i] == '\r') i++;
							if(i<n && buf[i] == '\n') i++;
						}
						while(i<n && isxdigit(buf[i]))
						{
							chunksize_buf[chunksize_buf_index++] = buf[i];
							chunksize_buf[chunksize_buf_index] = '\0';
							i++;
						}
						while(i<n && buf[i] != '\r' && buf[i] != '\n')
							i++; /* discarding chunk-extension */
						if(i<n && buf[i] == '\r') i++;
						if(i<n && buf[i] == '\n') {
							int j;
							for(j = 0; j < chunksize_buf_index; j++) {
							if(chunksize_buf[j] >= '0'
							   && chunksize_buf[j] <= '9')
								chunksize = (chunksize << 4) + (chunksize_buf[j] - '0');
							else
								chunksize = (chunksize << 4) + ((chunksize_buf[j] | 32) - 'a' + 10);
							}
							chunksize_buf[0] = '\0';
							chunksize_buf_index = 0;
							i++;
						} else {
							/* not finished to get chunksize */
							continue;
						}
#ifdef DEBUG
						printf("chunksize = %u (%x)\n", chunksize, chunksize);
#endif
						if(chunksize == 0)
						{
#ifdef DEBUG
							printf("end of HTTP content - %d %d\n", i, n);
							/*printf("'%.*s'\n", n-i, buf+i);*/
#endif
							goto end_of_stream;
						}
					}
					bytestocopy = ((int)chunksize < n - i)?chunksize:(n - i);
					if((int)(content_buf_used + bytestocopy) > content_buf_len)
					{
						content_buf = (char *)realloc((void *)content_buf, 
						                              content_buf_used + bytestocopy);
						content_buf_len = content_buf_used + bytestocopy;
					}
					memcpy(content_buf + content_buf_used, buf + i, bytestocopy);
					content_buf_used += bytestocopy;
					i += bytestocopy;
					chunksize -= bytestocopy;
				}
			}
			else
			{
				/* not chunked */
				if(content_buf_used + n > content_buf_len)
				{
					content_buf = (char *)realloc((void *)content_buf, 
					                              content_buf_used + n);
					content_buf_len = content_buf_used + n;
				}
				memcpy(content_buf + content_buf_used, buf, n);
				content_buf_used += n;
			}
		}
		/* use the Content-Length header value if available */
		if(content_length > 0 && content_buf_used >= content_length)
		{
#ifdef DEBUG
			printf("End of HTTP content\n");
#endif
			break;
		}
	}
end_of_stream:
	free(header_buf); header_buf = NULL;
	*size = content_buf_used;
	if(content_buf_used == 0)
	{
		free(content_buf);
		content_buf = NULL;
	}
	return content_buf;
}
Example #8
0
/* *workleft is always set, even when return indicated error.
 * (workleft < 0 when critical)*/
static retvalue readwrite(struct aptmethodrun *run, /*@out@*/int *workleft) {
	int maxfd, v;
	fd_set readfds, writefds;
	struct aptmethod *method;
	retvalue result, r;

	/* First calculate what to look at: */
	FD_ZERO(&readfds);
	FD_ZERO(&writefds);
	maxfd = 0;
	*workleft = 0;
	for (method = run->methods ; method != NULL ; method = method->next) {
		if (method->status == ams_ok &&
		    (method->command != NULL || method->nexttosend != NULL)) {
			FD_SET(method->mstdin, &writefds);
			if (method->mstdin > maxfd)
				maxfd = method->mstdin;
			(*workleft)++;
			if (verbose > 19)
				fprintf(stderr, "want to write to '%s'\n",
						method->baseuri);
		}
		if (method->status == ams_waitforcapabilities ||
				(method->status == ams_ok &&
				method->tobedone != NULL)) {
			FD_SET(method->mstdout, &readfds);
			if (method->mstdout > maxfd)
				maxfd = method->mstdout;
			(*workleft)++;
			if (verbose > 19)
				fprintf(stderr, "want to read from '%s'\n",
						method->baseuri);
		}
	}

	if (*workleft == 0)
		return RET_NOTHING;

	// TODO: think about a timeout...
	v = select(maxfd + 1, &readfds, &writefds, NULL, NULL);
	if (v < 0) {
		int e = errno;
		//TODO: handle (e == EINTR) && interrupted() specially
		fprintf(stderr, "Select returned error %d: %s\n",
				e, strerror(e));
		*workleft = -1;
		// TODO: what to do here?
		return RET_ERRNO(e);
	}

	result = RET_NOTHING;

	maxfd = 0;
	for (method = run->methods ; method != NULL ; method = method->next) {
		if (method->mstdout != -1 &&
				FD_ISSET(method->mstdout, &readfds)) {
			r = receivedata(method);
			RET_UPDATE(result, r);
		}
		if (method->mstdin != -1 &&
				FD_ISSET(method->mstdin, &writefds)) {
			r = senddata(method);
			RET_UPDATE(result, r);
		}
	}
	return result;
}
Example #9
0
/* ssdpDiscoverDevices() :
 * return a chained list of all devices found or NULL if
 * no devices was found.
 * It is up to the caller to free the chained list
 * delay is in millisecond (poll).
 * UDA v1.1 says :
 *   The TTL for the IP packet SHOULD default to 2 and
 *   SHOULD be configurable. */
struct UPNPDev *
ssdpDiscoverDevices(const char * const deviceTypes[],
                    int delay, const char * multicastif,
                    int localport,
                    int ipv6, unsigned char ttl,
                    int * error,
                    int searchalltypes)
{
	struct UPNPDev * tmp;
	struct UPNPDev * devlist = 0;
	unsigned int scope_id = 0;
	int opt = 1;
	static const char MSearchMsgFmt[] =
	"M-SEARCH * HTTP/1.1\r\n"
	"HOST: %s:" XSTR(SSDP_PORT) "\r\n"
	"ST: %s\r\n"
	"MAN: \"ssdp:discover\"\r\n"
	"MX: %u\r\n"
	"\r\n";
	int deviceIndex;
	char bufr[1536];	/* reception and emission buffer */
	SOCKET sudp;
	int n;
	struct sockaddr_storage sockudp_r;
	unsigned int mx;
#ifdef NO_GETADDRINFO
	struct sockaddr_storage sockudp_w;
#else
	int rv;
	struct addrinfo hints, *servinfo, *p;
#endif
#ifdef _WIN32
	unsigned long _ttl = (unsigned long)ttl;
#endif
	int linklocal = 1;
	int sentok;

	if(error)
		*error = MINISSDPC_UNKNOWN_ERROR;

	if(localport==UPNP_LOCAL_PORT_SAME)
		localport = SSDP_PORT;

#ifdef _WIN32
	sudp = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, IPPROTO_UDP);
#else
	sudp = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, 0);
#endif
	if(ISINVALID(sudp))
	{
		if(error)
			*error = MINISSDPC_SOCKET_ERROR;
		PRINT_SOCKET_ERROR("socket");
		return NULL;
	}
	/* reception */
	memset(&sockudp_r, 0, sizeof(struct sockaddr_storage));
	if(ipv6) {
		struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_r;
		p->sin6_family = AF_INET6;
		if(localport > 0 && localport < 65536)
			p->sin6_port = htons((unsigned short)localport);
		p->sin6_addr = in6addr_any; /* in6addr_any is not available with MinGW32 3.4.2 */
	} else {
		struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_r;
		p->sin_family = AF_INET;
		if(localport > 0 && localport < 65536)
			p->sin_port = htons((unsigned short)localport);
		p->sin_addr.s_addr = INADDR_ANY;
	}
#ifdef _WIN32
/* This code could help us to use the right Network interface for
 * SSDP multicast traffic */
/* Get IP associated with the index given in the ip_forward struct
 * in order to give this ip to setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF) */
	if(!ipv6) {
		DWORD ifbestidx;
		SOCKADDR_IN destAddr;
		memset(&destAddr, 0, sizeof(destAddr));
		destAddr.sin_family = AF_INET;
		destAddr.sin_addr.s_addr = inet_addr("223.255.255.255");
		destAddr.sin_port = 0;
		if (GetBestInterfaceEx((struct sockaddr *)&destAddr, &ifbestidx) == NO_ERROR) {
			DWORD dwRetVal = 0;
			PIP_ADAPTER_ADDRESSES pAddresses = NULL;
			ULONG outBufLen = 0;
			ULONG Iterations = 0;
			PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
			PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL;

			outBufLen = 15360;
			do {
				pAddresses = (IP_ADAPTER_ADDRESSES *) HeapAlloc(GetProcessHeap(), 0, outBufLen);
				if (pAddresses == NULL) {
					break;
				}

				dwRetVal = GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_PREFIX, NULL, pAddresses, &outBufLen);

				if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
					HeapFree(GetProcessHeap(), 0, pAddresses);
					pAddresses = NULL;
				} else {
					break;
				}
				Iterations++;
			} while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (Iterations < 3));

			if (dwRetVal == NO_ERROR) {
				pCurrAddresses = pAddresses;
				while (pCurrAddresses) {
#ifdef DEBUG
					int i;
					PIP_ADAPTER_MULTICAST_ADDRESS pMulticast = NULL;
					PIP_ADAPTER_ANYCAST_ADDRESS pAnycast = NULL;

					printf("\tIfIndex (IPv4 interface): %u\n", pCurrAddresses->IfIndex);
					printf("\tAdapter name: %s\n", pCurrAddresses->AdapterName);
					pUnicast = pCurrAddresses->FirstUnicastAddress;
					if (pUnicast != NULL) {
						for (i = 0; pUnicast != NULL; i++) {
							IPAddr.S_un.S_addr = (u_long) pUnicast->Address;
							printf("\tIP Address[%d]:     \t%s\n", i, inet_ntoa(IPAddr) );
							pUnicast = pUnicast->Next;
						}
						printf("\tNumber of Unicast Addresses: %d\n", i);
					}
					pAnycast = pCurrAddresses->FirstAnycastAddress;
					if (pAnycast) {
						for (i = 0; pAnycast != NULL; i++) {
							IPAddr.S_un.S_addr = (u_long) pAnyCast->Address;
							printf("\tAnycast Address[%d]:     \t%s\n", i, inet_ntoa(IPAddr) );
							pAnycast = pAnycast->Next;
						}
						printf("\tNumber of Anycast Addresses: %d\n", i);
					}
					pMulticast = pCurrAddresses->FirstMulticastAddress;
					if (pMulticast) {
						for (i = 0; pMulticast != NULL; i++) {
							IPAddr.S_un.S_addr = (u_long) pMultiCast->Address;
							printf("\tMulticast Address[%d]:     \t%s\n", i, inet_ntoa(IPAddr) );
						}
					}
					printf("\n");
#endif
					pUnicast = pCurrAddresses->FirstUnicastAddress;
					if (pCurrAddresses->IfIndex == ifbestidx && pUnicast != NULL) {
						SOCKADDR_IN *ipv4 = (SOCKADDR_IN *)(pUnicast->Address.lpSockaddr);
						/* Set the address of this interface to be used */
						struct in_addr mc_if;
						memset(&mc_if, 0, sizeof(mc_if));
						mc_if.s_addr = ipv4->sin_addr.s_addr;
						if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) {
							PRINT_SOCKET_ERROR("setsockopt");
						}
						((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = ipv4->sin_addr.s_addr;
#ifndef DEBUG
						break;
#endif
					}
					pCurrAddresses = pCurrAddresses->Next;
				}
			}
			if (pAddresses != NULL) {
				HeapFree(GetProcessHeap(), 0, pAddresses);
				pAddresses = NULL;
			}
		}
	}
#endif	/* _WIN32 */

#ifdef _WIN32
	if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof (opt)) < 0)
#else
	if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) < 0)
#endif
	{
		if(error)
			*error = MINISSDPC_SOCKET_ERROR;
		PRINT_SOCKET_ERROR("setsockopt(SO_REUSEADDR,...)");
		return NULL;
	}

	if(ipv6) {
#ifdef _WIN32
		DWORD mcastHops = ttl;
		if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (const char *)&mcastHops, sizeof(mcastHops)) < 0)
#else  /* _WIN32 */
		int mcastHops = ttl;
		if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &mcastHops, sizeof(mcastHops)) < 0)
#endif /* _WIN32 */
		{
			PRINT_SOCKET_ERROR("setsockopt(IPV6_MULTICAST_HOPS,...)");
		}
	} else {
#ifdef _WIN32
		if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, (const char *)&_ttl, sizeof(_ttl)) < 0)
#else  /* _WIN32 */
		if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0)
#endif /* _WIN32 */
		{
			/* not a fatal error */
			PRINT_SOCKET_ERROR("setsockopt(IP_MULTICAST_TTL,...)");
		}
	}

	if(multicastif)
	{
		if(ipv6) {
#if !defined(_WIN32)
			/* according to MSDN, if_nametoindex() is supported since
			 * MS Windows Vista and MS Windows Server 2008.
			 * http://msdn.microsoft.com/en-us/library/bb408409%28v=vs.85%29.aspx */
			unsigned int ifindex = if_nametoindex(multicastif); /* eth0, etc. */
			if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)) < 0)
			{
				PRINT_SOCKET_ERROR("setsockopt IPV6_MULTICAST_IF");
			}
#else
#ifdef DEBUG
			printf("Setting of multicast interface not supported in IPv6 under Windows.\n");
#endif
#endif
		} else {
			struct in_addr mc_if;
#if defined(_WIN32) && (_WIN32_WINNT >= _WIN32_WINNT_VISTA)
			InetPtonA(AF_INET, multicastif, &mc_if);
#else
			mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */
#endif
			if(mc_if.s_addr != INADDR_NONE)
			{
				((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr;
				if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0)
				{
					PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF");
				}
			} else {
#ifdef HAS_IP_MREQN
				/* was not an ip address, try with an interface name */
				struct ip_mreqn reqn;	/* only defined with -D_BSD_SOURCE or -D_GNU_SOURCE */
				memset(&reqn, 0, sizeof(struct ip_mreqn));
				reqn.imr_ifindex = if_nametoindex(multicastif);
				if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&reqn, sizeof(reqn)) < 0)
				{
					PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF");
				}
#elif !defined(_WIN32)
				struct ifreq ifr;
				int ifrlen = sizeof(ifr);
				strncpy(ifr.ifr_name, multicastif, IFNAMSIZ);
				ifr.ifr_name[IFNAMSIZ-1] = '\0';
				if(ioctl(sudp, SIOCGIFADDR, &ifr, &ifrlen) < 0)
				{
					PRINT_SOCKET_ERROR("ioctl(...SIOCGIFADDR...)");
				}
				mc_if.s_addr = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
				if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0)
				{
					PRINT_SOCKET_ERROR("setsockopt IP_MULTICAST_IF");
				}
#else /* _WIN32 */
#ifdef DEBUG
				printf("Setting of multicast interface not supported with interface name.\n");
#endif
#endif /* #ifdef HAS_IP_MREQN / !defined(_WIN32) */
			}
		}
	}

	/* Before sending the packed, we first "bind" in order to be able
	 * to receive the response */
	if (bind(sudp, (const struct sockaddr *)&sockudp_r,
	         ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) != 0)
	{
		if(error)
			*error = MINISSDPC_SOCKET_ERROR;
		PRINT_SOCKET_ERROR("bind");
		closesocket(sudp);
		return NULL;
	}

	if(error)
		*error = MINISSDPC_SUCCESS;
	/* Calculating maximum response time in seconds */
	mx = ((unsigned int)delay) / 1000u;
	if(mx == 0) {
		mx = 1;
		delay = 1000;
	}
	/* receiving SSDP response packet */
	for(deviceIndex = 0; deviceTypes[deviceIndex]; deviceIndex++) {
		sentok = 0;
		/* sending the SSDP M-SEARCH packet */
		n = snprintf(bufr, sizeof(bufr),
		             MSearchMsgFmt,
		             ipv6 ?
		             (linklocal ? "[" UPNP_MCAST_LL_ADDR "]" :  "[" UPNP_MCAST_SL_ADDR "]")
		             : UPNP_MCAST_ADDR,
		             deviceTypes[deviceIndex], mx);
		if ((unsigned int)n >= sizeof(bufr)) {
			if(error)
				*error = MINISSDPC_MEMORY_ERROR;
			goto error;
		}
#ifdef DEBUG
		/*printf("Sending %s", bufr);*/
		printf("Sending M-SEARCH request to %s with ST: %s\n",
		       ipv6 ?
		       (linklocal ? "[" UPNP_MCAST_LL_ADDR "]" :  "[" UPNP_MCAST_SL_ADDR "]")
		       : UPNP_MCAST_ADDR,
		       deviceTypes[deviceIndex]);
#endif
#ifdef NO_GETADDRINFO
		/* the following code is not using getaddrinfo */
		/* emission */
		memset(&sockudp_w, 0, sizeof(struct sockaddr_storage));
		if(ipv6) {
			struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_w;
			p->sin6_family = AF_INET6;
			p->sin6_port = htons(SSDP_PORT);
			inet_pton(AF_INET6,
			          linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR,
			          &(p->sin6_addr));
		} else {
			struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_w;
			p->sin_family = AF_INET;
			p->sin_port = htons(SSDP_PORT);
			p->sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR);
		}
		n = sendto(sudp, bufr, n, 0, &sockudp_w,
		           ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in));
		if (n < 0) {
			if(error)
				*error = MINISSDPC_SOCKET_ERROR;
			PRINT_SOCKET_ERROR("sendto");
		} else {
			sentok = 1;
		}
#else /* #ifdef NO_GETADDRINFO */
		memset(&hints, 0, sizeof(hints));
		hints.ai_family = AF_UNSPEC; /* AF_INET6 or AF_INET */
		hints.ai_socktype = SOCK_DGRAM;
		/*hints.ai_flags = */
		if ((rv = getaddrinfo(ipv6
		                      ? (linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR)
		                      : UPNP_MCAST_ADDR,
		                      XSTR(SSDP_PORT), &hints, &servinfo)) != 0) {
			if(error)
				*error = MINISSDPC_SOCKET_ERROR;
#ifdef _WIN32
			fprintf(stderr, "getaddrinfo() failed: %d\n", rv);
#else
			fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
#endif
			break;
		}
		for(p = servinfo; p; p = p->ai_next) {
			n = sendto(sudp, bufr, n, 0, p->ai_addr, MSC_CAST_INT p->ai_addrlen);
			if (n < 0) {
#ifdef DEBUG
				char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
				if (getnameinfo(p->ai_addr, p->ai_addrlen, hbuf, sizeof(hbuf), sbuf,
				                sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
					fprintf(stderr, "host:%s port:%s\n", hbuf, sbuf);
				}
#endif
				PRINT_SOCKET_ERROR("sendto");
				continue;
			} else {
				sentok = 1;
			}
		}
		freeaddrinfo(servinfo);
		if(!sentok) {
			if(error)
				*error = MINISSDPC_SOCKET_ERROR;
		}
#endif /* #ifdef NO_GETADDRINFO */
		/* Waiting for SSDP REPLY packet to M-SEARCH
		 * if searchalltypes is set, enter the loop only
		 * when the last deviceType is reached */
		if((sentok && !searchalltypes) || !deviceTypes[deviceIndex + 1]) do {
			n = receivedata(sudp, bufr, sizeof(bufr), delay, &scope_id);
			if (n < 0) {
				/* error */
				if(error)
					*error = MINISSDPC_SOCKET_ERROR;
				goto error;
			} else if (n == 0) {
				/* no data or Time Out */
#ifdef DEBUG
				printf("NODATA or TIMEOUT\n");
#endif /* DEBUG */
				if (devlist && !searchalltypes) {
					/* found some devices, stop now*/
					if(error)
						*error = MINISSDPC_SUCCESS;
					goto error;
				}
			} else {
				const char * descURL=NULL;
				int urlsize=0;
				const char * st=NULL;
				int stsize=0;
				const char * usn=NULL;
				int usnsize=0;
				parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize, &usn, &usnsize);
				if(st&&descURL) {
#ifdef DEBUG
					printf("M-SEARCH Reply:\n  ST: %.*s\n  USN: %.*s\n  Location: %.*s\n",
					       stsize, st, usnsize, (usn?usn:""), urlsize, descURL);
#endif /* DEBUG */
					for(tmp=devlist; tmp; tmp = tmp->pNext) {
						if(memcmp(tmp->descURL, descURL, urlsize) == 0 &&
						   tmp->descURL[urlsize] == '\0' &&
						   memcmp(tmp->st, st, stsize) == 0 &&
						   tmp->st[stsize] == '\0' &&
						   (usnsize == 0 || memcmp(tmp->usn, usn, usnsize) == 0) &&
						   tmp->usn[usnsize] == '\0')
							break;
					}
					/* at the exit of the loop above, tmp is null if
					 * no duplicate device was found */
					if(tmp)
						continue;
					tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize+usnsize);
					if(!tmp) {
						/* memory allocation error */
						if(error)
							*error = MINISSDPC_MEMORY_ERROR;
						goto error;
					}
					tmp->pNext = devlist;
					tmp->descURL = tmp->buffer;
					tmp->st = tmp->buffer + 1 + urlsize;
					tmp->usn = tmp->st + 1 + stsize;
					memcpy(tmp->buffer, descURL, urlsize);
					tmp->buffer[urlsize] = '\0';
					memcpy(tmp->st, st, stsize);
					tmp->buffer[urlsize+1+stsize] = '\0';
					if(usn != NULL)
						memcpy(tmp->usn, usn, usnsize);
					tmp->buffer[urlsize+1+stsize+1+usnsize] = '\0';
					tmp->scope_id = scope_id;
					devlist = tmp;
				}
			}
		} while(n > 0);
		if(ipv6) {
			/* switch linklocal flag */
			if(linklocal) {
				linklocal = 0;
				--deviceIndex;
			} else {
				linklocal = 1;
			}
		}
	}
error:
	closesocket(sudp);
	return devlist;
}
Example #10
0
/* upnpDiscover() :
 * return a chained list of all devices found or NULL if
 * no devices was found.
 * It is up to the caller to free the chained list
 * delay is in millisecond (poll) */
struct UPNPDev *
upnpDiscover(int delay, const char * multicastif,
             const char * minissdpdsock, int sameport,
             int ipv6, //unused in psp port
             int * error)
{
	struct UPNPDev * tmp;
	struct UPNPDev * devlist = 0;
	int opt = 1;
	static const char MSearchMsgFmt[] = 
	"M-SEARCH * HTTP/1.1\r\n"
	"HOST: %s:" XSTR(PORT) "\r\n"
	"ST: %s\r\n"
	"MAN: \"ssdp:discover\"\r\n"
	"MX: %u\r\n"
	"\r\n";
	static const char * const deviceList[] = {
#if 0
		"urn:schemas-upnp-org:device:InternetGatewayDevice:2",
		"urn:schemas-upnp-org:service:WANIPConnection:2",
#endif
		"urn:schemas-upnp-org:device:InternetGatewayDevice:1",
		"urn:schemas-upnp-org:service:WANIPConnection:1",
		"urn:schemas-upnp-org:service:WANPPPConnection:1",
		"upnp:rootdevice",
		0
	};
	int deviceIndex = 0;
	char bufr[1536];	/* reception and emission buffer */
	int sudp;
	int n;
	SceNetInetSockaddrIn sockudp_r;
	unsigned int mx;
	SceNetInetSockaddrIn sockudp_w;
	int linklocal = 1;

	if(error)
		*error = UPNPDISCOVER_UNKNOWN_ERROR;

	/* fallback to direct discovery */
	//sudp = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, 0);
	sudp = sceNetInetSocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if(sudp < 0)
	{
		if(error)
			*error = UPNPDISCOVER_SOCKET_ERROR;
		return NULL;
	}
	
	/* reception */
	memset(&sockudp_r, 0, sizeof(SceNetInetSockaddrIn));

	SceNetInetSockaddrIn * p = (SceNetInetSockaddrIn *)&sockudp_r;
	p->sin_family = AF_INET;
	if(sameport)
		p->sin_port = sceNetHtons(PORT);
	p->sin_addr = INADDR_ANY;


	// Enable Port Re-use
	sceNetInetSetsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
	sceNetInetSetsockopt(sudp, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt));
	
	/* Avant d'envoyer le paquet on bind pour recevoir la reponse */
    if (sceNetInetBind(sudp, (const struct SceNetInetSockaddr *)&sockudp_r,
	         sizeof(SceNetInetSockaddrIn)) != 0)
	{
		if(error)
			*error = UPNPDISCOVER_SOCKET_ERROR;
		sceNetInetClose(sudp);
		return NULL;
    }

	if(error)
		*error = UPNPDISCOVER_SUCCESS;
	/* Calculating maximum response time in seconds */
	mx = ((unsigned int)delay) / 1000u;
	/* receiving SSDP response packet */
	for(n = 0; deviceList[deviceIndex]; deviceIndex++)
	{
	if(n == 0)
	{
		/* sending the SSDP M-SEARCH packet */
		n = snprintf(bufr, sizeof(bufr),
		             MSearchMsgFmt,
		             UPNP_MCAST_ADDR,
		             deviceList[deviceIndex], mx);

		/* the following code is not using getaddrinfo */
		/* emission */
		memset(&sockudp_w, 0, sizeof(SceNetInetSockaddrIn));

		SceNetInetSockaddrIn * p = (SceNetInetSockaddrIn *)&sockudp_w;
		p->sin_family = AF_INET;
		p->sin_port = sceNetHtons(PORT);
		sceNetInetInetAton(UPNP_MCAST_ADDR, &p->sin_addr);
		
		n = sceNetInetSendto(sudp, bufr, n, 0,
		           (SceNetInetSockaddr *)&sockudp_w,
		           sizeof(SceNetInetSockaddrIn));
		if (n < 0) {
			if(error)
				*error = UPNPDISCOVER_SOCKET_ERROR;
			break;
		}
	}
	/* Waiting for SSDP REPLY packet to M-SEARCH */
	n = receivedata(sudp, bufr, sizeof(bufr), delay);
	if (n < 0) {
		/* error */
		if(error)
			*error = UPNPDISCOVER_SOCKET_ERROR;
		break;
	} else if (n == 0) {
		/* no data or Time Out */
		if (devlist) {
			/* no more device type to look for... */
			if(error)
				*error = UPNPDISCOVER_SUCCESS;
			break;
		}
		if(ipv6) {
			if(linklocal) {
				linklocal = 0;
				--deviceIndex;
			} else {
				linklocal = 1;
			}
		}
	} else {
		const char * descURL=NULL;
		int urlsize=0;
		const char * st=NULL;
		int stsize=0;
        /*printf("%d byte(s) :\n%s\n", n, bufr);*/ /* affichage du message */
		parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize);
		if(st&&descURL)
		{
			for(tmp=devlist; tmp; tmp = tmp->pNext) {
				if(memcmp(tmp->descURL, descURL, urlsize) == 0 &&
				   tmp->descURL[urlsize] == '\0' &&
				   memcmp(tmp->st, st, stsize) == 0 &&
				   tmp->st[stsize] == '\0')
					break;
			}
			/* at the exit of the loop above, tmp is null if
			 * no duplicate device was found */
			if(tmp)
				continue;
			tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize);
			if(!tmp) {
				/* memory allocation error */
				if(error)
					*error = UPNPDISCOVER_MEMORY_ERROR;
				break;
			}
			tmp->pNext = devlist;
			tmp->descURL = tmp->buffer;
			tmp->st = tmp->buffer + 1 + urlsize;
			memcpy(tmp->buffer, descURL, urlsize);
			tmp->buffer[urlsize] = '\0';
			memcpy(tmp->buffer + urlsize + 1, st, stsize);
			tmp->buffer[urlsize+1+stsize] = '\0';
			devlist = tmp;
		}
	}
	}
	sceNetInetClose(sudp);
	return devlist;
}
Example #11
0
/* Function that carries out read/write operations */
static int spim_io(const struct spi_slave *slave, struct spim_buffer *first,
			struct spim_buffer *second)
{
	u32 reg, base;
	int i, trans_count, ret;
	struct spim_buffer *transaction[2];
	struct img_spi_slave *img_slave = get_img_slave(slave);

	base = img_slave->base;

	ret = check_buffers(slave, first, second);
	if (ret)
		return ret;

	/*
	 * Soft reset peripheral internals, this will terminate any
	 * pending transactions
	 */
	write32_x(base + SPFI_CONTROL_REG_OFFSET, SPIM_SOFT_RESET_MASK);
	write32_x(base + SPFI_CONTROL_REG_OFFSET, 0);
	/* Port state register */
	reg = read32_x(base +  SPFI_PORT_STATE_REG_OFFSET);
	reg = spi_write_reg_field(reg, SPFI_PORT_SELECT, slave->cs);
	write32_x(base + SPFI_PORT_STATE_REG_OFFSET, reg);
	/* Set transaction register */
	reg = transaction_reg_setup(first, second);
	write32_x(base + SPFI_TRANSACTION_REG_OFFSET, reg);
	/* Clear status */
	write32_x(base + SPFI_INT_CLEAR_REG_OFFSET, 0xffffffff);
	/* Set control register */
	reg = control_reg_setup(first, second);
	write32_x(base + SPFI_CONTROL_REG_OFFSET, reg);
	/* First transaction always exists */
	transaction[0] = first;
	trans_count = 1;
	/* Is there a second transaction? */
	if (second) {
		transaction[1] = second;
		trans_count++;
	}
	/* Now write/read FIFO's */
	for (i = 0; i < trans_count; i++)
		/* Which transaction to execute, "Send" or "Get"? */
		if (transaction[i]->isread) {
			/* Get */
			ret = receivedata(slave, transaction[i]->buffer,
					transaction[i]->size);
			if (ret) {
				printk(BIOS_ERR,
					"%s: Error: receive data failed.\n",
					__func__);
				return ret;
			}
		} else {
			/* Send */
			ret = transmitdata(slave, transaction[i]->buffer,
					transaction[i]->size);
			if (ret) {
				printk(BIOS_ERR,
					"%s: Error: transmit data failed.\n",
					__func__);
				return ret;
			}
		}

	/* Wait for end of the transaction */
	ret = wait_status(base + SPFI_INT_STATUS_REG_OFFSET,
				SPFI_ALLDONE_SHIFT);
	if (ret)
		return ret;
	/*
	 * Soft reset peripheral internals, this will terminate any
	 * pending transactions
	 */
	write32_x(base + SPFI_CONTROL_REG_OFFSET, SPIM_SOFT_RESET_MASK);
	write32_x(base + SPFI_CONTROL_REG_OFFSET, 0);

	return SPIM_OK;
}