version 1.1.1.1, 2012/02/21 23:16:22
|
version 1.1.1.2, 2013/07/22 00:36:10
|
Line 1
|
Line 1
|
/* $Id$ */ |
/* $Id$ */ |
/* Project : miniupnp |
/* Project : miniupnp |
|
* Web : http://miniupnp.free.fr/ |
* Author : Thomas BERNARD |
* Author : Thomas BERNARD |
* copyright (c) 2005-2011 Thomas Bernard | * copyright (c) 2005-2012 Thomas Bernard |
* This software is subjet to the conditions detailed in the |
* This software is subjet to the conditions detailed in the |
* provided LICENSE file. */ |
* provided LICENSE file. */ |
#define __EXTENSIONS__ 1 |
#define __EXTENSIONS__ 1 |
Line 16
|
Line 17
|
#endif |
#endif |
#endif |
#endif |
|
|
|
#if !defined(__DragonFly__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(MACOSX) && !defined(_WIN32) && !defined(__CYGWIN__) && !defined(__sun) |
|
#define HAS_IP_MREQN |
|
#endif |
|
|
#include <stdlib.h> |
#include <stdlib.h> |
#include <stdio.h> |
#include <stdio.h> |
#include <string.h> |
#include <string.h> |
#ifdef WIN32 | #ifdef _WIN32 |
/* Win32 Specific includes and defines */ |
/* Win32 Specific includes and defines */ |
#include <winsock2.h> |
#include <winsock2.h> |
#include <ws2tcpip.h> |
#include <ws2tcpip.h> |
#include <io.h> |
#include <io.h> |
#include <iphlpapi.h> |
#include <iphlpapi.h> |
#define snprintf _snprintf |
#define snprintf _snprintf |
|
#define strdup _strdup |
#ifndef strncasecmp |
#ifndef strncasecmp |
#if defined(_MSC_VER) && (_MSC_VER >= 1400) |
#if defined(_MSC_VER) && (_MSC_VER >= 1400) |
#define strncasecmp _memicmp |
#define strncasecmp _memicmp |
Line 34
|
Line 40
|
#endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ |
#endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */ |
#endif /* #ifndef strncasecmp */ |
#endif /* #ifndef strncasecmp */ |
#define MAXHOSTNAMELEN 64 |
#define MAXHOSTNAMELEN 64 |
#else /* #ifdef WIN32 */ | #else /* #ifdef _WIN32 */ |
/* Standard POSIX includes */ |
/* Standard POSIX includes */ |
#include <unistd.h> |
#include <unistd.h> |
#if defined(__amigaos__) && !defined(__amigaos4__) |
#if defined(__amigaos__) && !defined(__amigaos4__) |
Line 56
|
Line 62
|
#include <strings.h> |
#include <strings.h> |
#include <errno.h> |
#include <errno.h> |
#define closesocket close |
#define closesocket close |
#endif /* #else WIN32 */ | #endif /* #else _WIN32 */ |
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT |
#ifdef MINIUPNPC_SET_SOCKET_TIMEOUT |
#include <sys/time.h> |
#include <sys/time.h> |
#endif |
#endif |
Line 74
|
Line 80
|
#include "connecthostport.h" |
#include "connecthostport.h" |
#include "receivedata.h" |
#include "receivedata.h" |
|
|
#ifdef WIN32 | #ifdef _WIN32 |
#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError()); |
#define PRINT_SOCKET_ERROR(x) printf("Socket error: %s, %d\n", x, WSAGetLastError()); |
#else |
#else |
#define PRINT_SOCKET_ERROR(x) perror(x) |
#define PRINT_SOCKET_ERROR(x) perror(x) |
Line 184 char * simpleUPnPcommand2(int s, const char * url, con
|
Line 190 char * simpleUPnPcommand2(int s, const char * url, con
|
strncpy(p, "></" SOAPPREFIX ":Body></" SOAPPREFIX ":Envelope>\r\n", |
strncpy(p, "></" SOAPPREFIX ":Body></" SOAPPREFIX ":Envelope>\r\n", |
soapbody + sizeof(soapbody) - p); |
soapbody + sizeof(soapbody) - p); |
} |
} |
if(!parseURL(url, hostname, &port, &path)) return NULL; | if(!parseURL(url, hostname, &port, &path, NULL)) return NULL; |
if(s<0) | if(s < 0) { |
{ | s = connecthostport(hostname, port, 0); |
s = connecthostport(hostname, port); | if(s < 0) { |
if(s < 0) | /* failed to connect */ |
{ | |
return NULL; |
return NULL; |
} |
} |
} |
} |
Line 225 char * simpleUPnPcommand(int s, const char * url, cons
|
Line 230 char * simpleUPnPcommand(int s, const char * url, cons
|
{ |
{ |
char * buf; |
char * buf; |
|
|
|
#if 1 |
buf = simpleUPnPcommand2(s, url, service, action, args, bufsize, "1.1"); |
buf = simpleUPnPcommand2(s, url, service, action, args, bufsize, "1.1"); |
/* | #else |
buf = simpleUPnPcommand2(s, url, service, action, args, bufsize, "1.0"); |
buf = simpleUPnPcommand2(s, url, service, action, args, bufsize, "1.0"); |
if (!buf || *bufsize == 0) |
if (!buf || *bufsize == 0) |
{ |
{ |
Line 235 char * simpleUPnPcommand(int s, const char * url, cons
|
Line 241 char * simpleUPnPcommand(int s, const char * url, cons
|
#endif |
#endif |
buf = simpleUPnPcommand2(s, url, service, action, args, bufsize, "1.1"); |
buf = simpleUPnPcommand2(s, url, service, action, args, bufsize, "1.1"); |
} |
} |
*/ | #endif |
return buf; |
return buf; |
} |
} |
|
|
Line 322 upnpDiscover(int delay, const char * multicastif,
|
Line 328 upnpDiscover(int delay, const char * multicastif,
|
{ |
{ |
struct UPNPDev * tmp; |
struct UPNPDev * tmp; |
struct UPNPDev * devlist = 0; |
struct UPNPDev * devlist = 0; |
|
unsigned int scope_id = 0; |
int opt = 1; |
int opt = 1; |
static const char MSearchMsgFmt[] = | static const char MSearchMsgFmt[] = |
"M-SEARCH * HTTP/1.1\r\n" |
"M-SEARCH * HTTP/1.1\r\n" |
"HOST: %s:" XSTR(PORT) "\r\n" |
"HOST: %s:" XSTR(PORT) "\r\n" |
"ST: %s\r\n" |
"ST: %s\r\n" |
Line 353 upnpDiscover(int delay, const char * multicastif,
|
Line 360 upnpDiscover(int delay, const char * multicastif,
|
int rv; |
int rv; |
struct addrinfo hints, *servinfo, *p; |
struct addrinfo hints, *servinfo, *p; |
#endif |
#endif |
#ifdef WIN32 | #ifdef _WIN32 |
MIB_IPFORWARDROW ip_forward; |
MIB_IPFORWARDROW ip_forward; |
#endif |
#endif |
int linklocal = 1; |
int linklocal = 1; |
|
|
if(error) |
if(error) |
*error = UPNPDISCOVER_UNKNOWN_ERROR; |
*error = UPNPDISCOVER_UNKNOWN_ERROR; |
#if !defined(WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) | #if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) |
/* first try to get infos from minissdpd ! */ |
/* first try to get infos from minissdpd ! */ |
if(!minissdpdsock) |
if(!minissdpdsock) |
minissdpdsock = "/var/run/minissdpd.sock"; |
minissdpdsock = "/var/run/minissdpd.sock"; |
Line 378 upnpDiscover(int delay, const char * multicastif,
|
Line 385 upnpDiscover(int delay, const char * multicastif,
|
deviceIndex = 0; |
deviceIndex = 0; |
#endif |
#endif |
/* fallback to direct discovery */ |
/* fallback to direct discovery */ |
#ifdef WIN32 | #ifdef _WIN32 |
sudp = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, IPPROTO_UDP); |
sudp = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, IPPROTO_UDP); |
#else |
#else |
sudp = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, 0); |
sudp = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, 0); |
Line 405 upnpDiscover(int delay, const char * multicastif,
|
Line 412 upnpDiscover(int delay, const char * multicastif,
|
p->sin_port = htons(PORT); |
p->sin_port = htons(PORT); |
p->sin_addr.s_addr = INADDR_ANY; |
p->sin_addr.s_addr = INADDR_ANY; |
} |
} |
#ifdef WIN32 | #ifdef _WIN32 |
/* This code could help us to use the right Network interface for | /* This code could help us to use the right Network interface for |
* SSDP multicast traffic */ |
* SSDP multicast traffic */ |
/* Get IP associated with the index given in the ip_forward struct |
/* 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) */ |
* in order to give this ip to setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF) */ |
Line 465 upnpDiscover(int delay, const char * multicastif,
|
Line 472 upnpDiscover(int delay, const char * multicastif,
|
} |
} |
#endif |
#endif |
|
|
#ifdef WIN32 | #ifdef _WIN32 |
if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof (opt)) < 0) |
if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof (opt)) < 0) |
#else |
#else |
if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) < 0) |
if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) < 0) |
Line 480 upnpDiscover(int delay, const char * multicastif,
|
Line 487 upnpDiscover(int delay, const char * multicastif,
|
if(multicastif) |
if(multicastif) |
{ |
{ |
if(ipv6) { |
if(ipv6) { |
#if !defined(WIN32) | #if !defined(_WIN32) |
/* according to MSDN, if_nametoindex() is supported since |
/* according to MSDN, if_nametoindex() is supported since |
* MS Windows Vista and MS Windows Server 2008. |
* MS Windows Vista and MS Windows Server 2008. |
* http://msdn.microsoft.com/en-us/library/bb408409%28v=vs.85%29.aspx */ |
* http://msdn.microsoft.com/en-us/library/bb408409%28v=vs.85%29.aspx */ |
Line 497 upnpDiscover(int delay, const char * multicastif,
|
Line 504 upnpDiscover(int delay, const char * multicastif,
|
} else { |
} else { |
struct in_addr mc_if; |
struct in_addr mc_if; |
mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */ |
mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */ |
((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr; | if(mc_if.s_addr != INADDR_NONE) |
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 = 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 |
} |
} |
} |
} |
} |
} |
Line 563 upnpDiscover(int delay, const char * multicastif,
|
Line 588 upnpDiscover(int delay, const char * multicastif,
|
} |
} |
#else /* #ifdef NO_GETADDRINFO */ |
#else /* #ifdef NO_GETADDRINFO */ |
memset(&hints, 0, sizeof(hints)); |
memset(&hints, 0, sizeof(hints)); |
hints.ai_family = AF_UNSPEC; // AF_INET6 or AF_INET | hints.ai_family = AF_UNSPEC; /* AF_INET6 or AF_INET */ |
hints.ai_socktype = SOCK_DGRAM; |
hints.ai_socktype = SOCK_DGRAM; |
/*hints.ai_flags = */ |
/*hints.ai_flags = */ |
if ((rv = getaddrinfo(ipv6 |
if ((rv = getaddrinfo(ipv6 |
Line 572 upnpDiscover(int delay, const char * multicastif,
|
Line 597 upnpDiscover(int delay, const char * multicastif,
|
XSTR(PORT), &hints, &servinfo)) != 0) { |
XSTR(PORT), &hints, &servinfo)) != 0) { |
if(error) |
if(error) |
*error = UPNPDISCOVER_SOCKET_ERROR; |
*error = UPNPDISCOVER_SOCKET_ERROR; |
#ifdef WIN32 | #ifdef _WIN32 |
fprintf(stderr, "getaddrinfo() failed: %d\n", rv); |
fprintf(stderr, "getaddrinfo() failed: %d\n", rv); |
#else |
#else |
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); |
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); |
Line 582 upnpDiscover(int delay, const char * multicastif,
|
Line 607 upnpDiscover(int delay, const char * multicastif,
|
for(p = servinfo; p; p = p->ai_next) { |
for(p = servinfo; p; p = p->ai_next) { |
n = sendto(sudp, bufr, n, 0, p->ai_addr, p->ai_addrlen); |
n = sendto(sudp, bufr, n, 0, p->ai_addr, p->ai_addrlen); |
if (n < 0) { |
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"); |
PRINT_SOCKET_ERROR("sendto"); |
continue; |
continue; |
} |
} |
Line 595 upnpDiscover(int delay, const char * multicastif,
|
Line 627 upnpDiscover(int delay, const char * multicastif,
|
#endif /* #ifdef NO_GETADDRINFO */ |
#endif /* #ifdef NO_GETADDRINFO */ |
} |
} |
/* Waiting for SSDP REPLY packet to M-SEARCH */ |
/* Waiting for SSDP REPLY packet to M-SEARCH */ |
n = receivedata(sudp, bufr, sizeof(bufr), delay); | n = receivedata(sudp, bufr, sizeof(bufr), delay, &scope_id); |
if (n < 0) { |
if (n < 0) { |
/* error */ |
/* error */ |
if(error) |
if(error) |
Line 655 upnpDiscover(int delay, const char * multicastif,
|
Line 687 upnpDiscover(int delay, const char * multicastif,
|
tmp->buffer[urlsize] = '\0'; |
tmp->buffer[urlsize] = '\0'; |
memcpy(tmp->buffer + urlsize + 1, st, stsize); |
memcpy(tmp->buffer + urlsize + 1, st, stsize); |
tmp->buffer[urlsize+1+stsize] = '\0'; |
tmp->buffer[urlsize+1+stsize] = '\0'; |
|
tmp->scope_id = scope_id; |
devlist = tmp; |
devlist = tmp; |
} |
} |
} |
} |
Line 701 url_cpy_or_cat(char * dst, const char * src, int n)
|
Line 734 url_cpy_or_cat(char * dst, const char * src, int n)
|
|
|
/* Prepare the Urls for usage... |
/* Prepare the Urls for usage... |
*/ |
*/ |
LIBSPEC void GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data, | LIBSPEC void |
const char * descURL) | GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data, |
| const char * descURL, unsigned int scope_id) |
{ |
{ |
char * p; |
char * p; |
int n1, n2, n3, n4; |
int n1, n2, n3, n4; |
|
#ifdef IF_NAMESIZE |
|
char ifname[IF_NAMESIZE]; |
|
#else |
|
char scope_str[8]; |
|
#endif |
|
|
n1 = strlen(data->urlbase); |
n1 = strlen(data->urlbase); |
if(n1==0) |
if(n1==0) |
n1 = strlen(descURL); |
n1 = strlen(descURL); |
|
if(scope_id != 0) { |
|
#ifdef IF_NAMESIZE |
|
if(if_indextoname(scope_id, ifname)) { |
|
n1 += 3 + strlen(ifname); /* 3 == strlen(%25) */ |
|
} |
|
#else |
|
/* under windows, scope is numerical */ |
|
snprintf(scope_str, sizeof(scope_str), "%u", scope_id); |
|
#endif |
|
} |
n1 += 2; /* 1 byte more for Null terminator, 1 byte for '/' if needed */ |
n1 += 2; /* 1 byte more for Null terminator, 1 byte for '/' if needed */ |
n2 = n1; n3 = n1; n4 = n1; |
n2 = n1; n3 = n1; n4 = n1; |
n1 += strlen(data->first.scpdurl); |
n1 += strlen(data->first.scpdurl); |
Line 716 LIBSPEC void GetUPNPUrls(struct UPNPUrls * urls, struc
|
Line 766 LIBSPEC void GetUPNPUrls(struct UPNPUrls * urls, struc
|
n3 += strlen(data->CIF.controlurl); |
n3 += strlen(data->CIF.controlurl); |
n4 += strlen(data->IPv6FC.controlurl); |
n4 += strlen(data->IPv6FC.controlurl); |
|
|
|
/* allocate memory to store URLs */ |
urls->ipcondescURL = (char *)malloc(n1); |
urls->ipcondescURL = (char *)malloc(n1); |
urls->controlURL = (char *)malloc(n2); |
urls->controlURL = (char *)malloc(n2); |
urls->controlURL_CIF = (char *)malloc(n3); |
urls->controlURL_CIF = (char *)malloc(n3); |
urls->controlURL_6FC = (char *)malloc(n4); |
urls->controlURL_6FC = (char *)malloc(n4); |
/* maintenant on chope la desc du WANIPConnection */ | |
| /* strdup descURL */ |
| urls->rootdescURL = strdup(descURL); |
| |
| /* get description of WANIPConnection */ |
if(data->urlbase[0] != '\0') |
if(data->urlbase[0] != '\0') |
strncpy(urls->ipcondescURL, data->urlbase, n1); |
strncpy(urls->ipcondescURL, data->urlbase, n1); |
else |
else |
strncpy(urls->ipcondescURL, descURL, n1); |
strncpy(urls->ipcondescURL, descURL, n1); |
p = strchr(urls->ipcondescURL+7, '/'); |
p = strchr(urls->ipcondescURL+7, '/'); |
if(p) p[0] = '\0'; |
if(p) p[0] = '\0'; |
|
if(scope_id != 0) { |
|
if(0 == memcmp(urls->ipcondescURL, "http://[fe80:", 13)) { |
|
/* this is a linklocal IPv6 address */ |
|
p = strchr(urls->ipcondescURL, ']'); |
|
if(p) { |
|
/* insert %25<scope> into URL */ |
|
#ifdef IF_NAMESIZE |
|
memmove(p + 3 + strlen(ifname), p, strlen(p) + 1); |
|
memcpy(p, "%25", 3); |
|
memcpy(p + 3, ifname, strlen(ifname)); |
|
#else |
|
memmove(p + 3 + strlen(scope_str), p, strlen(p) + 1); |
|
memcpy(p, "%25", 3); |
|
memcpy(p + 3, scope_str, strlen(scope_str)); |
|
#endif |
|
} |
|
} |
|
} |
strncpy(urls->controlURL, urls->ipcondescURL, n2); |
strncpy(urls->controlURL, urls->ipcondescURL, n2); |
strncpy(urls->controlURL_CIF, urls->ipcondescURL, n3); |
strncpy(urls->controlURL_CIF, urls->ipcondescURL, n3); |
strncpy(urls->controlURL_6FC, urls->ipcondescURL, n4); |
strncpy(urls->controlURL_6FC, urls->ipcondescURL, n4); |
| |
url_cpy_or_cat(urls->ipcondescURL, data->first.scpdurl, n1); |
url_cpy_or_cat(urls->ipcondescURL, data->first.scpdurl, n1); |
|
|
url_cpy_or_cat(urls->controlURL, data->first.controlurl, n2); |
url_cpy_or_cat(urls->controlURL, data->first.controlurl, n2); |
Line 764 FreeUPNPUrls(struct UPNPUrls * urls)
|
Line 837 FreeUPNPUrls(struct UPNPUrls * urls)
|
urls->controlURL_CIF = 0; |
urls->controlURL_CIF = 0; |
free(urls->controlURL_6FC); |
free(urls->controlURL_6FC); |
urls->controlURL_6FC = 0; |
urls->controlURL_6FC = 0; |
|
free(urls->rootdescURL); |
|
urls->rootdescURL = 0; |
} |
} |
|
|
int |
int |
Line 785 UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGD
|
Line 860 UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGD
|
|
|
/* UPNP_GetValidIGD() : |
/* UPNP_GetValidIGD() : |
* return values : |
* return values : |
|
* -1 = Internal error |
* 0 = NO IGD found |
* 0 = NO IGD found |
* 1 = A valid connected IGD has been found |
* 1 = A valid connected IGD has been found |
* 2 = A valid IGD has been found but it reported as |
* 2 = A valid IGD has been found but it reported as |
Line 801 UPNP_GetValidIGD(struct UPNPDev * devlist,
|
Line 877 UPNP_GetValidIGD(struct UPNPDev * devlist,
|
struct IGDdatas * data, |
struct IGDdatas * data, |
char * lanaddr, int lanaddrlen) |
char * lanaddr, int lanaddrlen) |
{ |
{ |
char * descXML; | struct xml_desc { |
int descXMLsize = 0; | char * xml; |
| int size; |
| } * desc = NULL; |
struct UPNPDev * dev; |
struct UPNPDev * dev; |
int ndev = 0; |
int ndev = 0; |
int state; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */ | int i; |
| int state = -1; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */ |
if(!devlist) |
if(!devlist) |
{ |
{ |
#ifdef DEBUG |
#ifdef DEBUG |
Line 813 UPNP_GetValidIGD(struct UPNPDev * devlist,
|
Line 892 UPNP_GetValidIGD(struct UPNPDev * devlist,
|
#endif |
#endif |
return 0; |
return 0; |
} |
} |
|
for(dev = devlist; dev; dev = dev->pNext) |
|
ndev++; |
|
if(ndev > 0) |
|
{ |
|
desc = calloc(ndev, sizeof(struct xml_desc)); |
|
if(!desc) |
|
return -1; /* memory allocation error */ |
|
} |
for(state = 1; state <= 3; state++) |
for(state = 1; state <= 3; state++) |
{ |
{ |
for(dev = devlist; dev; dev = dev->pNext) | for(dev = devlist, i = 0; dev; dev = dev->pNext, i++) |
{ |
{ |
/* we should choose an internet gateway device. |
/* we should choose an internet gateway device. |
* with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */ |
* with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */ |
descXML = miniwget_getaddr(dev->descURL, &descXMLsize, | if(state == 1) |
lanaddr, lanaddrlen); | |
if(descXML) | |
{ |
{ |
ndev++; | desc[i].xml = miniwget_getaddr(dev->descURL, &(desc[i].size), |
| lanaddr, lanaddrlen, |
| dev->scope_id); |
| #ifdef DEBUG |
| if(!desc[i].xml) |
| { |
| printf("error getting XML description %s\n", dev->descURL); |
| } |
| #endif |
| } |
| if(desc[i].xml) |
| { |
memset(data, 0, sizeof(struct IGDdatas)); |
memset(data, 0, sizeof(struct IGDdatas)); |
memset(urls, 0, sizeof(struct UPNPUrls)); |
memset(urls, 0, sizeof(struct UPNPUrls)); |
parserootdesc(descXML, descXMLsize, data); | parserootdesc(desc[i].xml, desc[i].size, data); |
free(descXML); | |
descXML = NULL; | |
if(0==strcmp(data->CIF.servicetype, |
if(0==strcmp(data->CIF.servicetype, |
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1") |
"urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1") |
|| state >= 3 ) |
|| state >= 3 ) |
{ |
{ |
GetUPNPUrls(urls, data, dev->descURL); | GetUPNPUrls(urls, data, dev->descURL, dev->scope_id); |
|
|
#ifdef DEBUG |
#ifdef DEBUG |
printf("UPNPIGD_IsConnected(%s) = %d\n", |
printf("UPNPIGD_IsConnected(%s) = %d\n", |
Line 841 UPNP_GetValidIGD(struct UPNPDev * devlist,
|
Line 935 UPNP_GetValidIGD(struct UPNPDev * devlist,
|
UPNPIGD_IsConnected(urls, data)); |
UPNPIGD_IsConnected(urls, data)); |
#endif |
#endif |
if((state >= 2) || UPNPIGD_IsConnected(urls, data)) |
if((state >= 2) || UPNPIGD_IsConnected(urls, data)) |
return state; | goto free_and_return; |
FreeUPNPUrls(urls); |
FreeUPNPUrls(urls); |
if(data->second.servicetype[0] != '\0') { |
if(data->second.servicetype[0] != '\0') { |
#ifdef DEBUG |
#ifdef DEBUG |
Line 852 UPNP_GetValidIGD(struct UPNPDev * devlist,
|
Line 946 UPNP_GetValidIGD(struct UPNPDev * devlist,
|
memcpy(&data->tmp, &data->first, sizeof(struct IGDdatas_service)); |
memcpy(&data->tmp, &data->first, sizeof(struct IGDdatas_service)); |
memcpy(&data->first, &data->second, sizeof(struct IGDdatas_service)); |
memcpy(&data->first, &data->second, sizeof(struct IGDdatas_service)); |
memcpy(&data->second, &data->tmp, sizeof(struct IGDdatas_service)); |
memcpy(&data->second, &data->tmp, sizeof(struct IGDdatas_service)); |
GetUPNPUrls(urls, data, dev->descURL); | GetUPNPUrls(urls, data, dev->descURL, dev->scope_id); |
#ifdef DEBUG |
#ifdef DEBUG |
printf("UPNPIGD_IsConnected(%s) = %d\n", |
printf("UPNPIGD_IsConnected(%s) = %d\n", |
urls->controlURL, |
urls->controlURL, |
UPNPIGD_IsConnected(urls, data)); |
UPNPIGD_IsConnected(urls, data)); |
#endif |
#endif |
if((state >= 2) || UPNPIGD_IsConnected(urls, data)) |
if((state >= 2) || UPNPIGD_IsConnected(urls, data)) |
return state; | goto free_and_return; |
FreeUPNPUrls(urls); |
FreeUPNPUrls(urls); |
} |
} |
} |
} |
memset(data, 0, sizeof(struct IGDdatas)); |
memset(data, 0, sizeof(struct IGDdatas)); |
} |
} |
#ifdef DEBUG | } |
else | } |
{ | state = 0; |
printf("error getting XML description %s\n", dev->descURL); | free_and_return: |
| if(desc) { |
| for(i = 0; i < ndev; i++) { |
| if(desc[i].xml) { |
| free(desc[i].xml); |
} |
} |
#endif |
|
} |
} |
|
free(desc); |
} |
} |
return 0; | return state; |
} |
} |
|
|
/* UPNP_GetIGDFromUrl() |
/* UPNP_GetIGDFromUrl() |
Line 890 UPNP_GetIGDFromUrl(const char * rootdescurl,
|
Line 988 UPNP_GetIGDFromUrl(const char * rootdescurl,
|
char * descXML; |
char * descXML; |
int descXMLsize = 0; |
int descXMLsize = 0; |
descXML = miniwget_getaddr(rootdescurl, &descXMLsize, |
descXML = miniwget_getaddr(rootdescurl, &descXMLsize, |
lanaddr, lanaddrlen); | lanaddr, lanaddrlen, 0); |
if(descXML) { |
if(descXML) { |
memset(data, 0, sizeof(struct IGDdatas)); |
memset(data, 0, sizeof(struct IGDdatas)); |
memset(urls, 0, sizeof(struct UPNPUrls)); |
memset(urls, 0, sizeof(struct UPNPUrls)); |
parserootdesc(descXML, descXMLsize, data); |
parserootdesc(descXML, descXMLsize, data); |
free(descXML); |
free(descXML); |
descXML = NULL; |
descXML = NULL; |
GetUPNPUrls(urls, data, rootdescurl); | GetUPNPUrls(urls, data, rootdescurl, 0); |
return 1; |
return 1; |
} else { |
} else { |
return 0; |
return 0; |