Annotation of embedaddon/miniupnpd/miniupnpc/src/miniupnpc.c, revision 1.1.1.1
1.1 misho 1: /* $Id: miniupnpc.c,v 1.159 2021/03/02 23:36:32 nanard Exp $ */
2: /* vim: tabstop=4 shiftwidth=4 noexpandtab
3: * Project : miniupnp
4: * Web : http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
5: * Author : Thomas BERNARD
6: * copyright (c) 2005-2021 Thomas Bernard
7: * This software is subjet to the conditions detailed in the
8: * provided LICENSE file. */
9: #include <stdlib.h>
10: #include <stdio.h>
11: #include <string.h>
12: #ifdef _WIN32
13: /* Win32 Specific includes and defines */
14: #include <winsock2.h>
15: #include <ws2tcpip.h>
16: #include <io.h>
17: #include <iphlpapi.h>
18: #include "win32_snprintf.h"
19: #define strdup _strdup
20: #ifndef strncasecmp
21: #if defined(_MSC_VER) && (_MSC_VER >= 1400)
22: #define strncasecmp _memicmp
23: #else /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
24: #define strncasecmp memicmp
25: #endif /* defined(_MSC_VER) && (_MSC_VER >= 1400) */
26: #endif /* #ifndef strncasecmp */
27: #define MAXHOSTNAMELEN 64
28: #else /* #ifdef _WIN32 */
29: /* Standard POSIX includes */
30: #include <unistd.h>
31: #if defined(__amigaos__) && !defined(__amigaos4__)
32: /* Amiga OS 3 specific stuff */
33: #define socklen_t int
34: #else
35: #include <sys/select.h>
36: #endif
37: #include <sys/socket.h>
38: #include <sys/types.h>
39: #include <sys/param.h>
40: #include <netinet/in.h>
41: #include <arpa/inet.h>
42: #include <netdb.h>
43: #include <net/if.h>
44: #if !defined(__amigaos__) && !defined(__amigaos4__)
45: #include <poll.h>
46: #endif
47: #include <strings.h>
48: #include <errno.h>
49: #define closesocket close
50: #endif /* #else _WIN32 */
51: #ifdef __GNU__
52: #define MAXHOSTNAMELEN 64
53: #endif
54:
55:
56: #include "miniupnpc.h"
57: #include "minissdpc.h"
58: #include "miniwget.h"
59: #include "miniwget_private.h"
60: #include "minisoap.h"
61: #include "minixml.h"
62: #include "upnpcommands.h"
63: #include "connecthostport.h"
64: #include "addr_is_reserved.h"
65:
66: /* compare the beginning of a string with a constant string */
67: #define COMPARE(str, cstr) (0==strncmp(str, cstr, sizeof(cstr) - 1))
68:
69: #ifndef MAXHOSTNAMELEN
70: #define MAXHOSTNAMELEN 64
71: #endif
72:
73: #define SOAPPREFIX "s"
74: #define SERVICEPREFIX "u"
75: #define SERVICEPREFIX2 'u'
76:
77: /* root description parsing */
78: MINIUPNP_LIBSPEC void parserootdesc(const char * buffer, int bufsize, struct IGDdatas * data)
79: {
80: struct xmlparser parser;
81: /* xmlparser object */
82: parser.xmlstart = buffer;
83: parser.xmlsize = bufsize;
84: parser.data = data;
85: parser.starteltfunc = IGDstartelt;
86: parser.endeltfunc = IGDendelt;
87: parser.datafunc = IGDdata;
88: parser.attfunc = 0;
89: parsexml(&parser);
90: #ifdef DEBUG
91: printIGD(data);
92: #endif
93: }
94:
95: /* simpleUPnPcommand2 :
96: * not so simple !
97: * return values :
98: * pointer - OK
99: * NULL - error */
100: static char *
101: simpleUPnPcommand2(SOCKET s, const char * url, const char * service,
102: const char * action, struct UPNParg * args,
103: int * bufsize, const char * httpversion)
104: {
105: char hostname[MAXHOSTNAMELEN+1];
106: unsigned short port = 0;
107: char * path;
108: char soapact[128];
109: char soapbody[2048];
110: int soapbodylen;
111: char * buf;
112: int n;
113: int status_code;
114:
115: *bufsize = 0;
116: snprintf(soapact, sizeof(soapact), "%s#%s", service, action);
117: if(args==NULL)
118: {
119: soapbodylen = snprintf(soapbody, sizeof(soapbody),
120: "<?xml version=\"1.0\"?>\r\n"
121: "<" SOAPPREFIX ":Envelope "
122: "xmlns:" SOAPPREFIX "=\"http://schemas.xmlsoap.org/soap/envelope/\" "
123: SOAPPREFIX ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
124: "<" SOAPPREFIX ":Body>"
125: "<" SERVICEPREFIX ":%s xmlns:" SERVICEPREFIX "=\"%s\">"
126: "</" SERVICEPREFIX ":%s>"
127: "</" SOAPPREFIX ":Body></" SOAPPREFIX ":Envelope>"
128: "\r\n", action, service, action);
129: if ((unsigned int)soapbodylen >= sizeof(soapbody))
130: return NULL;
131: }
132: else
133: {
134: char * p;
135: const char * pe, * pv;
136: const char * const pend = soapbody + sizeof(soapbody);
137: soapbodylen = snprintf(soapbody, sizeof(soapbody),
138: "<?xml version=\"1.0\"?>\r\n"
139: "<" SOAPPREFIX ":Envelope "
140: "xmlns:" SOAPPREFIX "=\"http://schemas.xmlsoap.org/soap/envelope/\" "
141: SOAPPREFIX ":encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
142: "<" SOAPPREFIX ":Body>"
143: "<" SERVICEPREFIX ":%s xmlns:" SERVICEPREFIX "=\"%s\">",
144: action, service);
145: if ((unsigned int)soapbodylen >= sizeof(soapbody))
146: return NULL;
147: p = soapbody + soapbodylen;
148: while(args->elt)
149: {
150: if(p >= pend) /* check for space to write next byte */
151: return NULL;
152: *(p++) = '<';
153:
154: pe = args->elt;
155: while(p < pend && *pe)
156: *(p++) = *(pe++);
157:
158: if(p >= pend) /* check for space to write next byte */
159: return NULL;
160: *(p++) = '>';
161:
162: if((pv = args->val))
163: {
164: while(p < pend && *pv)
165: *(p++) = *(pv++);
166: }
167:
168: if((p+2) > pend) /* check for space to write next 2 bytes */
169: return NULL;
170: *(p++) = '<';
171: *(p++) = '/';
172:
173: pe = args->elt;
174: while(p < pend && *pe)
175: *(p++) = *(pe++);
176:
177: if(p >= pend) /* check for space to write next byte */
178: return NULL;
179: *(p++) = '>';
180:
181: args++;
182: }
183: if((p+4) > pend) /* check for space to write next 4 bytes */
184: return NULL;
185: *(p++) = '<';
186: *(p++) = '/';
187: *(p++) = SERVICEPREFIX2;
188: *(p++) = ':';
189:
190: pe = action;
191: while(p < pend && *pe)
192: *(p++) = *(pe++);
193:
194: strncpy(p, "></" SOAPPREFIX ":Body></" SOAPPREFIX ":Envelope>\r\n",
195: pend - p);
196: if(soapbody[sizeof(soapbody)-1]) /* strncpy pads buffer with 0s, so if it doesn't end in 0, could not fit full string */
197: return NULL;
198: }
199: if(!parseURL(url, hostname, &port, &path, NULL)) return NULL;
200: if(ISINVALID(s)) {
201: s = connecthostport(hostname, port, 0);
202: if(ISINVALID(s)) {
203: /* failed to connect */
204: return NULL;
205: }
206: }
207:
208: n = soapPostSubmit(s, path, hostname, port, soapact, soapbody, httpversion);
209: if(n<=0) {
210: #ifdef DEBUG
211: printf("Error sending SOAP request\n");
212: #endif
213: closesocket(s);
214: return NULL;
215: }
216:
217: buf = getHTTPResponse(s, bufsize, &status_code);
218: #ifdef DEBUG
219: if(*bufsize > 0 && buf)
220: {
221: printf("HTTP %d SOAP Response :\n%.*s\n", status_code, *bufsize, buf);
222: }
223: else
224: {
225: printf("HTTP %d, empty SOAP response. size=%d\n", status_code, *bufsize);
226: }
227: #endif
228: closesocket(s);
229: return buf;
230: }
231:
232: /* simpleUPnPcommand :
233: * not so simple !
234: * return values :
235: * pointer - OK
236: * NULL - error */
237: char *
238: simpleUPnPcommand(int s, const char * url, const char * service,
239: const char * action, struct UPNParg * args,
240: int * bufsize)
241: {
242: char * buf;
243:
244: #if 1
245: buf = simpleUPnPcommand2((SOCKET)s, url, service, action, args, bufsize, "1.1");
246: #else
247: buf = simpleUPnPcommand2((SOCKET)s, url, service, action, args, bufsize, "1.0");
248: if (!buf || *bufsize == 0)
249: {
250: #if DEBUG
251: printf("Error or no result from SOAP request; retrying with HTTP/1.1\n");
252: #endif
253: buf = simpleUPnPcommand2((SOCKET)s, url, service, action, args, bufsize, "1.1");
254: }
255: #endif
256: return buf;
257: }
258:
259: /* upnpDiscoverDevices() :
260: * return a chained list of all devices found or NULL if
261: * no devices was found.
262: * It is up to the caller to free the chained list
263: * delay is in millisecond (poll).
264: * UDA v1.1 says :
265: * The TTL for the IP packet SHOULD default to 2 and
266: * SHOULD be configurable. */
267: MINIUPNP_LIBSPEC struct UPNPDev *
268: upnpDiscoverDevices(const char * const deviceTypes[],
269: int delay, const char * multicastif,
270: const char * minissdpdsock, int localport,
271: int ipv6, unsigned char ttl,
272: int * error,
273: int searchalltypes)
274: {
275: struct UPNPDev * tmp;
276: struct UPNPDev * devlist = 0;
277: #if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__)
278: int deviceIndex;
279: #endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */
280:
281: if(error)
282: *error = UPNPDISCOVER_UNKNOWN_ERROR;
283: #if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__)
284: /* first try to get infos from minissdpd ! */
285: if(!minissdpdsock)
286: minissdpdsock = "/var/run/minissdpd.sock";
287: if(minissdpdsock[0] != '\0') {
288: for(deviceIndex = 0; deviceTypes[deviceIndex]; deviceIndex++) {
289: struct UPNPDev * minissdpd_devlist;
290: int only_rootdevice = 1;
291: minissdpd_devlist = getDevicesFromMiniSSDPD(deviceTypes[deviceIndex],
292: minissdpdsock, 0);
293: if(minissdpd_devlist) {
294: #ifdef DEBUG
295: printf("returned by MiniSSDPD: %s\t%s\n",
296: minissdpd_devlist->st, minissdpd_devlist->descURL);
297: #endif /* DEBUG */
298: if(!strstr(minissdpd_devlist->st, "rootdevice"))
299: only_rootdevice = 0;
300: for(tmp = minissdpd_devlist; tmp->pNext != NULL; tmp = tmp->pNext) {
301: #ifdef DEBUG
302: printf("returned by MiniSSDPD: %s\t%s\n",
303: tmp->pNext->st, tmp->pNext->descURL);
304: #endif /* DEBUG */
305: if(!strstr(tmp->st, "rootdevice"))
306: only_rootdevice = 0;
307: }
308: tmp->pNext = devlist;
309: devlist = minissdpd_devlist;
310: if(!searchalltypes && !only_rootdevice)
311: break;
312: }
313: }
314: }
315: for(tmp = devlist; tmp != NULL; tmp = tmp->pNext) {
316: /* We return what we have found if it was not only a rootdevice */
317: if(!strstr(tmp->st, "rootdevice")) {
318: if(error)
319: *error = UPNPDISCOVER_SUCCESS;
320: return devlist;
321: }
322: }
323: #else /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */
324: (void)minissdpdsock; /* unused */
325: #endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */
326:
327: /* direct discovery if minissdpd responses are not sufficient */
328: {
329: struct UPNPDev * discovered_devlist;
330: discovered_devlist = ssdpDiscoverDevices(deviceTypes, delay, multicastif, localport,
331: ipv6, ttl, error, searchalltypes);
332: if(devlist == NULL)
333: devlist = discovered_devlist;
334: else {
335: for(tmp = devlist; tmp->pNext != NULL; tmp = tmp->pNext);
336: tmp->pNext = discovered_devlist;
337: }
338: }
339: return devlist;
340: }
341:
342: /* upnpDiscover() Discover IGD device */
343: MINIUPNP_LIBSPEC struct UPNPDev *
344: upnpDiscover(int delay, const char * multicastif,
345: const char * minissdpdsock, int localport,
346: int ipv6, unsigned char ttl,
347: int * error)
348: {
349: static const char * const deviceList[] = {
350: #if 0
351: "urn:schemas-upnp-org:device:InternetGatewayDevice:2",
352: "urn:schemas-upnp-org:service:WANIPConnection:2",
353: #endif
354: "urn:schemas-upnp-org:device:InternetGatewayDevice:1",
355: "urn:schemas-upnp-org:service:WANIPConnection:1",
356: "urn:schemas-upnp-org:service:WANPPPConnection:1",
357: "upnp:rootdevice",
358: /*"ssdp:all",*/
359: 0
360: };
361: return upnpDiscoverDevices(deviceList,
362: delay, multicastif, minissdpdsock, localport,
363: ipv6, ttl, error, 0);
364: }
365:
366: /* upnpDiscoverAll() Discover all UPnP devices */
367: MINIUPNP_LIBSPEC struct UPNPDev *
368: upnpDiscoverAll(int delay, const char * multicastif,
369: const char * minissdpdsock, int localport,
370: int ipv6, unsigned char ttl,
371: int * error)
372: {
373: static const char * const deviceList[] = {
374: /*"upnp:rootdevice",*/
375: "ssdp:all",
376: 0
377: };
378: return upnpDiscoverDevices(deviceList,
379: delay, multicastif, minissdpdsock, localport,
380: ipv6, ttl, error, 0);
381: }
382:
383: /* upnpDiscoverDevice() Discover a specific device */
384: MINIUPNP_LIBSPEC struct UPNPDev *
385: upnpDiscoverDevice(const char * device, int delay, const char * multicastif,
386: const char * minissdpdsock, int localport,
387: int ipv6, unsigned char ttl,
388: int * error)
389: {
390: const char * const deviceList[] = {
391: device,
392: 0
393: };
394: return upnpDiscoverDevices(deviceList,
395: delay, multicastif, minissdpdsock, localport,
396: ipv6, ttl, error, 0);
397: }
398:
399: static char *
400: build_absolute_url(const char * baseurl, const char * descURL,
401: const char * url, unsigned int scope_id)
402: {
403: size_t l, n;
404: char * s;
405: const char * base;
406: char * p;
407: #if defined(IF_NAMESIZE) && !defined(_WIN32)
408: char ifname[IF_NAMESIZE];
409: #else /* defined(IF_NAMESIZE) && !defined(_WIN32) */
410: char scope_str[8];
411: #endif /* defined(IF_NAMESIZE) && !defined(_WIN32) */
412:
413: if( (url[0] == 'h')
414: &&(url[1] == 't')
415: &&(url[2] == 't')
416: &&(url[3] == 'p')
417: &&(url[4] == ':')
418: &&(url[5] == '/')
419: &&(url[6] == '/'))
420: return strdup(url);
421: base = (baseurl[0] == '\0') ? descURL : baseurl;
422: n = strlen(base);
423: if(n > 7) {
424: p = strchr(base + 7, '/');
425: if(p)
426: n = p - base;
427: }
428: l = n + strlen(url) + 1;
429: if(url[0] != '/')
430: l++;
431: if(scope_id != 0) {
432: #if defined(IF_NAMESIZE) && !defined(_WIN32)
433: if(if_indextoname(scope_id, ifname)) {
434: l += 3 + strlen(ifname); /* 3 == strlen(%25) */
435: }
436: #else /* defined(IF_NAMESIZE) && !defined(_WIN32) */
437: /* under windows, scope is numerical */
438: l += 3 + snprintf(scope_str, sizeof(scope_str), "%u", scope_id);
439: #endif /* defined(IF_NAMESIZE) && !defined(_WIN32) */
440: }
441: s = malloc(l);
442: if(s == NULL) return NULL;
443: memcpy(s, base, n);
444: if(scope_id != 0) {
445: s[n] = '\0';
446: if(n > 13 && 0 == memcmp(s, "http://[fe80:", 13)) {
447: /* this is a linklocal IPv6 address */
448: p = strchr(s, ']');
449: if(p) {
450: /* insert %25<scope> into URL */
451: #if defined(IF_NAMESIZE) && !defined(_WIN32)
452: memmove(p + 3 + strlen(ifname), p, strlen(p) + 1);
453: memcpy(p, "%25", 3);
454: memcpy(p + 3, ifname, strlen(ifname));
455: n += 3 + strlen(ifname);
456: #else /* defined(IF_NAMESIZE) && !defined(_WIN32) */
457: memmove(p + 3 + strlen(scope_str), p, strlen(p) + 1);
458: memcpy(p, "%25", 3);
459: memcpy(p + 3, scope_str, strlen(scope_str));
460: n += 3 + strlen(scope_str);
461: #endif /* defined(IF_NAMESIZE) && !defined(_WIN32) */
462: }
463: }
464: }
465: if(url[0] != '/')
466: s[n++] = '/';
467: memcpy(s + n, url, l - n);
468: return s;
469: }
470:
471: /* Prepare the Urls for usage...
472: */
473: MINIUPNP_LIBSPEC void
474: GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data,
475: const char * descURL, unsigned int scope_id)
476: {
477: /* strdup descURL */
478: urls->rootdescURL = strdup(descURL);
479:
480: /* get description of WANIPConnection */
481: urls->ipcondescURL = build_absolute_url(data->urlbase, descURL,
482: data->first.scpdurl, scope_id);
483: urls->controlURL = build_absolute_url(data->urlbase, descURL,
484: data->first.controlurl, scope_id);
485: urls->controlURL_CIF = build_absolute_url(data->urlbase, descURL,
486: data->CIF.controlurl, scope_id);
487: urls->controlURL_6FC = build_absolute_url(data->urlbase, descURL,
488: data->IPv6FC.controlurl, scope_id);
489:
490: #ifdef DEBUG
491: printf("urls->ipcondescURL='%s'\n", urls->ipcondescURL);
492: printf("urls->controlURL='%s'\n", urls->controlURL);
493: printf("urls->controlURL_CIF='%s'\n", urls->controlURL_CIF);
494: printf("urls->controlURL_6FC='%s'\n", urls->controlURL_6FC);
495: #endif
496: }
497:
498: MINIUPNP_LIBSPEC void
499: FreeUPNPUrls(struct UPNPUrls * urls)
500: {
501: if(!urls)
502: return;
503: free(urls->controlURL);
504: urls->controlURL = 0;
505: free(urls->ipcondescURL);
506: urls->ipcondescURL = 0;
507: free(urls->controlURL_CIF);
508: urls->controlURL_CIF = 0;
509: free(urls->controlURL_6FC);
510: urls->controlURL_6FC = 0;
511: free(urls->rootdescURL);
512: urls->rootdescURL = 0;
513: }
514:
515: int
516: UPNPIGD_IsConnected(struct UPNPUrls * urls, struct IGDdatas * data)
517: {
518: char status[64];
519: unsigned int uptime;
520: status[0] = '\0';
521: UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype,
522: status, &uptime, NULL);
523: if(0 == strcmp("Connected", status))
524: return 1;
525: else if(0 == strcmp("Up", status)) /* Also accept "Up" */
526: return 1;
527: else
528: return 0;
529: }
530:
531:
532: /* UPNP_GetValidIGD() :
533: * return values :
534: * -1 = Internal error
535: * 0 = NO IGD found
536: * 1 = A valid connected IGD has been found
537: * 2 = A valid IGD has been found but it reported as
538: * not connected
539: * 3 = an UPnP device has been found but was not recognized as an IGD
540: *
541: * In any positive non zero return case, the urls and data structures
542: * passed as parameters are set. Don't forget to call FreeUPNPUrls(urls) to
543: * free allocated memory.
544: */
545: MINIUPNP_LIBSPEC int
546: UPNP_GetValidIGD(struct UPNPDev * devlist,
547: struct UPNPUrls * urls,
548: struct IGDdatas * data,
549: char * lanaddr, int lanaddrlen)
550: {
551: struct xml_desc {
552: char lanaddr[40];
553: char * xml;
554: int size;
555: int is_igd;
556: } * desc = NULL;
557: struct UPNPDev * dev;
558: int ndev = 0;
559: int i;
560: int state = -1; /* state 1 : IGD connected. State 2 : IGD. State 3 : anything */
561: char extIpAddr[16];
562: int status_code = -1;
563:
564: if(!devlist)
565: {
566: #ifdef DEBUG
567: printf("Empty devlist\n");
568: #endif
569: return 0;
570: }
571: /* counting total number of devices in the list */
572: for(dev = devlist; dev; dev = dev->pNext)
573: ndev++;
574: /* ndev is always > 0 */
575: desc = calloc(ndev, sizeof(struct xml_desc));
576: if(!desc)
577: return -1; /* memory allocation error */
578: /* Step 1 : downloading descriptions and testing type */
579: for(dev = devlist, i = 0; dev; dev = dev->pNext, i++)
580: {
581: /* we should choose an internet gateway device.
582: * with st == urn:schemas-upnp-org:device:InternetGatewayDevice:1 */
583: desc[i].xml = miniwget_getaddr(dev->descURL, &(desc[i].size),
584: desc[i].lanaddr, sizeof(desc[i].lanaddr),
585: dev->scope_id, &status_code);
586: #ifdef DEBUG
587: if(!desc[i].xml)
588: {
589: printf("error getting XML description %s\n", dev->descURL);
590: }
591: #endif
592: if(desc[i].xml)
593: {
594: memset(data, 0, sizeof(struct IGDdatas));
595: memset(urls, 0, sizeof(struct UPNPUrls));
596: parserootdesc(desc[i].xml, desc[i].size, data);
597: if(COMPARE(data->CIF.servicetype,
598: "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:"))
599: {
600: desc[i].is_igd = 1;
601: }
602: }
603: }
604: /* iterate the list to find a device depending on state */
605: for(state = 1; state <= 3; state++)
606: {
607: for(dev = devlist, i = 0; dev; dev = dev->pNext, i++)
608: {
609: if(desc[i].xml)
610: {
611: memset(data, 0, sizeof(struct IGDdatas));
612: memset(urls, 0, sizeof(struct UPNPUrls));
613: parserootdesc(desc[i].xml, desc[i].size, data);
614: if(desc[i].is_igd || state >= 3 )
615: {
616: int is_connected;
617:
618: GetUPNPUrls(urls, data, dev->descURL, dev->scope_id);
619:
620: /* in state 2 and 3 we don't test if device is connected ! */
621: if(state >= 2)
622: goto free_and_return;
623: is_connected = UPNPIGD_IsConnected(urls, data);
624: #ifdef DEBUG
625: printf("UPNPIGD_IsConnected(%s) = %d\n",
626: urls->controlURL, is_connected);
627: #endif
628: /* checks that status is connected AND there is a external IP address assigned */
629: if(is_connected &&
630: (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) {
631: if(!addr_is_reserved(extIpAddr))
632: goto free_and_return;
633: }
634: FreeUPNPUrls(urls);
635: if(data->second.servicetype[0] != '\0') {
636: #ifdef DEBUG
637: printf("We tried %s, now we try %s !\n",
638: data->first.servicetype, data->second.servicetype);
639: #endif
640: /* swaping WANPPPConnection and WANIPConnection ! */
641: memcpy(&data->tmp, &data->first, sizeof(struct IGDdatas_service));
642: memcpy(&data->first, &data->second, sizeof(struct IGDdatas_service));
643: memcpy(&data->second, &data->tmp, sizeof(struct IGDdatas_service));
644: GetUPNPUrls(urls, data, dev->descURL, dev->scope_id);
645: is_connected = UPNPIGD_IsConnected(urls, data);
646: #ifdef DEBUG
647: printf("UPNPIGD_IsConnected(%s) = %d\n",
648: urls->controlURL, is_connected);
649: #endif
650: if(is_connected &&
651: (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, extIpAddr) == 0)) {
652: if(!addr_is_reserved(extIpAddr))
653: goto free_and_return;
654: }
655: FreeUPNPUrls(urls);
656: }
657: }
658: memset(data, 0, sizeof(struct IGDdatas));
659: }
660: }
661: }
662: state = 0;
663: free_and_return:
664: if (lanaddr != NULL && state >= 1 && state <= 3 && i < ndev)
665: strncpy(lanaddr, desc[i].lanaddr, lanaddrlen);
666: for(i = 0; i < ndev; i++)
667: free(desc[i].xml);
668: free(desc);
669: return state;
670: }
671:
672: /* UPNP_GetIGDFromUrl()
673: * Used when skipping the discovery process.
674: * return value :
675: * 0 - Not ok
676: * 1 - OK */
677: int
678: UPNP_GetIGDFromUrl(const char * rootdescurl,
679: struct UPNPUrls * urls,
680: struct IGDdatas * data,
681: char * lanaddr, int lanaddrlen)
682: {
683: char * descXML;
684: int descXMLsize = 0;
685:
686: descXML = miniwget_getaddr(rootdescurl, &descXMLsize,
687: lanaddr, lanaddrlen, 0, NULL);
688: if(descXML) {
689: memset(data, 0, sizeof(struct IGDdatas));
690: memset(urls, 0, sizeof(struct UPNPUrls));
691: parserootdesc(descXML, descXMLsize, data);
692: free(descXML);
693: GetUPNPUrls(urls, data, rootdescurl, 0);
694: return 1;
695: } else {
696: return 0;
697: }
698: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>