Annotation of embedaddon/miniupnpd/upnpdescgen.c, revision 1.1.1.1
1.1 misho 1: /* $Id: upnpdescgen.c,v 1.51 2009/09/06 21:26:36 nanard Exp $ */
2: /* MiniUPnP project
3: * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4: * (c) 2006-2009 Thomas Bernard
5: * This software is subject to the conditions detailed
6: * in the LICENCE file provided within the distribution */
7:
8: #include <stdio.h>
9: #include <stdlib.h>
10: #include <string.h>
11:
12: #include "config.h"
13: #ifdef ENABLE_EVENTS
14: #include "getifaddr.h"
15: #include "upnpredirect.h"
16: #endif
17: #include "upnpdescgen.h"
18: #include "miniupnpdpath.h"
19: #include "upnpglobalvars.h"
20: #include "upnpdescstrings.h"
21:
22: static const char * const upnptypes[] =
23: {
24: "string",
25: "boolean",
26: "ui2",
27: "ui4"
28: };
29:
30: static const char * const upnpdefaultvalues[] =
31: {
32: 0,
33: "Unconfigured"
34: };
35:
36: static const char * const upnpallowedvalues[] =
37: {
38: 0, /* 0 */
39: "DSL", /* 1 */
40: "POTS",
41: "Cable",
42: "Ethernet",
43: 0,
44: "Up", /* 6 */
45: "Down",
46: "Initializing",
47: "Unavailable",
48: 0,
49: "TCP", /* 11 */
50: "UDP",
51: 0,
52: "Unconfigured", /* 14 */
53: "IP_Routed",
54: "IP_Bridged",
55: 0,
56: "Unconfigured", /* 18 */
57: "Connecting",
58: "Connected",
59: "PendingDisconnect",
60: "Disconnecting",
61: "Disconnected",
62: 0,
63: "ERROR_NONE", /* 25 */
64: 0,
65: "", /* 27 */
66: 0
67: };
68:
69: static const char xmlver[] =
70: "<?xml version=\"1.0\"?>\r\n";
71: static const char root_service[] =
72: "scpd xmlns=\"urn:schemas-upnp-org:service-1-0\"";
73: static const char root_device[] =
74: "root xmlns=\"urn:schemas-upnp-org:device-1-0\"";
75:
76: /* root Description of the UPnP Device
77: * fixed to match UPnP_IGD_InternetGatewayDevice 1.0.pdf
78: * presentationURL is only "recommended" but the router doesn't appears
79: * in "Network connections" in Windows XP if it is not present. */
80: static const struct XMLElt rootDesc[] =
81: {
82: /* 0 */
83: {root_device, INITHELPER(1,2)},
84: {"specVersion", INITHELPER(3,2)},
85: #if defined(ENABLE_L3F_SERVICE) || defined(HAS_DUMMY_SERVICE)
86: {"device", INITHELPER(5,13)},
87: #else
88: {"device", INITHELPER(5,12)},
89: #endif
90: {"/major", "1"},
91: {"/minor", "0"},
92: /* 5 */
93: {"/deviceType", "urn:schemas-upnp-org:device:InternetGatewayDevice:1"},
94: {"/friendlyName", ROOTDEV_FRIENDLYNAME}, /* required */
95: {"/manufacturer", ROOTDEV_MANUFACTURER}, /* required */
96: /* 8 */
97: {"/manufacturerURL", ROOTDEV_MANUFACTURERURL}, /* optional */
98: {"/modelDescription", ROOTDEV_MODELDESCRIPTION}, /* recommended */
99: {"/modelName", ROOTDEV_MODELNAME}, /* required */
100: {"/modelNumber", modelnumber},
101: {"/modelURL", ROOTDEV_MODELURL},
102: {"/serialNumber", serialnumber},
103: {"/UDN", uuidvalue}, /* required */
104: #if defined(ENABLE_L3F_SERVICE) || defined(HAS_DUMMY_SERVICE)
105: {"serviceList", INITHELPER(57,1)},
106: {"deviceList", INITHELPER(18,1)},
107: {"/presentationURL", presentationurl}, /* recommended */
108: #else
109: {"deviceList", INITHELPER(18,1)},
110: {"/presentationURL", presentationurl}, /* recommended */
111: {0,0},
112: #endif
113: /* 18 */
114: {"device", INITHELPER(19,13)},
115: /* 19 */
116: {"/deviceType", "urn:schemas-upnp-org:device:WANDevice:1"}, /* required */
117: {"/friendlyName", WANDEV_FRIENDLYNAME},
118: {"/manufacturer", WANDEV_MANUFACTURER},
119: {"/manufacturerURL", WANDEV_MANUFACTURERURL},
120: {"/modelDescription" , WANDEV_MODELDESCRIPTION},
121: {"/modelName", WANDEV_MODELNAME},
122: {"/modelNumber", WANDEV_MODELNUMBER},
123: {"/modelURL", WANDEV_MODELURL},
124: {"/serialNumber", serialnumber},
125: {"/UDN", uuidvalue},
126: {"/UPC", WANDEV_UPC},
127: /* 30 */
128: {"serviceList", INITHELPER(32,1)},
129: {"deviceList", INITHELPER(38,1)},
130: /* 32 */
131: {"service", INITHELPER(33,5)},
132: /* 33 */
133: {"/serviceType",
134: "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"},
135: /*{"/serviceId", "urn:upnp-org:serviceId:WANCommonInterfaceConfig"}, */
136: {"/serviceId", "urn:upnp-org:serviceId:WANCommonIFC1"}, /* required */
137: {"/controlURL", WANCFG_CONTROLURL},
138: {"/eventSubURL", WANCFG_EVENTURL},
139: {"/SCPDURL", WANCFG_PATH},
140: /* 38 */
141: {"device", INITHELPER(39,12)},
142: /* 39 */
143: {"/deviceType", "urn:schemas-upnp-org:device:WANConnectionDevice:1"},
144: {"/friendlyName", WANCDEV_FRIENDLYNAME},
145: {"/manufacturer", WANCDEV_MANUFACTURER},
146: {"/manufacturerURL", WANCDEV_MANUFACTURERURL},
147: {"/modelDescription", WANCDEV_MODELDESCRIPTION},
148: {"/modelName", WANCDEV_MODELNAME},
149: {"/modelNumber", WANCDEV_MODELNUMBER},
150: {"/modelURL", WANCDEV_MODELURL},
151: {"/serialNumber", serialnumber},
152: {"/UDN", uuidvalue},
153: {"/UPC", WANCDEV_UPC},
154: {"serviceList", INITHELPER(51,1)},
155: /* 51 */
156: {"service", INITHELPER(52,5)},
157: /* 52 */
158: {"/serviceType", "urn:schemas-upnp-org:service:WANIPConnection:1"},
159: /* {"/serviceId", "urn:upnp-org:serviceId:WANIPConnection"}, */
160: {"/serviceId", "urn:upnp-org:serviceId:WANIPConn1"},
161: {"/controlURL", WANIPC_CONTROLURL},
162: {"/eventSubURL", WANIPC_EVENTURL},
163: {"/SCPDURL", WANIPC_PATH},
164: /* 57 */
165: #ifdef HAS_DUMMY_SERVICE
166: {"service", INITHELPER(58,5)},
167: /* 58 */
168: {"/serviceType", "urn:schemas-dummy-com:service:Dummy:1"},
169: {"/serviceId", "urn:dummy-com:serviceId:dummy1"},
170: {"/controlURL", "/dummy"},
171: {"/eventSubURL", "/dummy"},
172: {"/SCPDURL", DUMMY_PATH},
173: #endif
174: #ifdef ENABLE_L3F_SERVICE
175: {"service", INITHELPER(58,5)},
176: /* 58 */
177: {"/serviceType", "urn:schemas-upnp-org:service:Layer3Forwarding:1"},
178: {"/serviceId", "urn:upnp-org:serviceId:Layer3Forwarding1"},
179: {"/controlURL", L3F_CONTROLURL}, /* The Layer3Forwarding service is only */
180: {"/eventSubURL", L3F_EVENTURL}, /* recommended, not mandatory */
181: {"/SCPDURL", L3F_PATH},
182: #endif
183: {0, 0}
184: };
185:
186: /* WANIPCn.xml */
187: /* see UPnP_IGD_WANIPConnection 1.0.pdf
188: static struct XMLElt scpdWANIPCn[] =
189: {
190: {root_service, {INITHELPER(1,2)}},
191: {0, {0}}
192: };
193: */
194: static const struct argument AddPortMappingArgs[] =
195: {
196: {1, 11},
197: {1, 12},
198: {1, 14},
199: {1, 13},
200: {1, 15},
201: {1, 9},
202: {1, 16},
203: {1, 10},
204: {0, 0}
205: };
206:
207: static const struct argument GetExternalIPAddressArgs[] =
208: {
209: {2, 7},
210: {0, 0}
211: };
212:
213: static const struct argument DeletePortMappingArgs[] =
214: {
215: {1, 11},
216: {1, 12},
217: {1, 14},
218: {0, 0}
219: };
220:
221: static const struct argument SetConnectionTypeArgs[] =
222: {
223: {1, 0},
224: {0, 0}
225: };
226:
227: static const struct argument GetConnectionTypeInfoArgs[] =
228: {
229: {2, 0},
230: {2, 1},
231: {0, 0}
232: };
233:
234: static const struct argument GetStatusInfoArgs[] =
235: {
236: {2, 2},
237: {2, 4},
238: {2, 3},
239: {0, 0}
240: };
241:
242: static const struct argument GetNATRSIPStatusArgs[] =
243: {
244: {2, 5},
245: {2, 6},
246: {0, 0}
247: };
248:
249: static const struct argument GetGenericPortMappingEntryArgs[] =
250: {
251: {1, 8},
252: {2, 11},
253: {2, 12},
254: {2, 14},
255: {2, 13},
256: {2, 15},
257: {2, 9},
258: {2, 16},
259: {2, 10},
260: {0, 0}
261: };
262:
263: static const struct argument GetSpecificPortMappingEntryArgs[] =
264: {
265: {1, 11},
266: {1, 12},
267: {1, 14},
268: {2, 13},
269: {2, 15},
270: {2, 9},
271: {2, 16},
272: {2, 10},
273: {0, 0}
274: };
275:
276: static const struct action WANIPCnActions[] =
277: {
278: {"AddPortMapping", AddPortMappingArgs}, /* R */
279: {"GetExternalIPAddress", GetExternalIPAddressArgs}, /* R */
280: {"DeletePortMapping", DeletePortMappingArgs}, /* R */
281: {"SetConnectionType", SetConnectionTypeArgs}, /* R */
282: {"GetConnectionTypeInfo", GetConnectionTypeInfoArgs}, /* R */
283: {"RequestConnection", 0}, /* R */
284: {"ForceTermination", 0}, /* R */
285: {"GetStatusInfo", GetStatusInfoArgs}, /* R */
286: {"GetNATRSIPStatus", GetNATRSIPStatusArgs}, /* R */
287: {"GetGenericPortMappingEntry", GetGenericPortMappingEntryArgs}, /* R */
288: {"GetSpecificPortMappingEntry", GetSpecificPortMappingEntryArgs}, /* R */
289: {0, 0}
290: };
291: /* R=Required, O=Optional */
292:
293: static const struct stateVar WANIPCnVars[] =
294: {
295: /* 0 */
296: {"ConnectionType", 0, 0/*1*/}, /* required */
297: {"PossibleConnectionTypes", 0|0x80, 0, 14, 15},
298: /* Required
299: * Allowed values : Unconfigured / IP_Routed / IP_Bridged */
300: {"ConnectionStatus", 0|0x80, 0/*1*/, 18, 20}, /* required */
301: /* Allowed Values : Unconfigured / Connecting(opt) / Connected
302: * PendingDisconnect(opt) / Disconnecting (opt)
303: * Disconnected */
304: {"Uptime", 3, 0}, /* Required */
305: {"LastConnectionError", 0, 0, 25}, /* required : */
306: /* Allowed Values : ERROR_NONE(req) / ERROR_COMMAND_ABORTED(opt)
307: * ERROR_NOT_ENABLED_FOR_INTERNET(opt)
308: * ERROR_USER_DISCONNECT(opt)
309: * ERROR_ISP_DISCONNECT(opt)
310: * ERROR_IDLE_DISCONNECT(opt)
311: * ERROR_FORCED_DISCONNECT(opt)
312: * ERROR_NO_CARRIER(opt)
313: * ERROR_IP_CONFIGURATION(opt)
314: * ERROR_UNKNOWN(opt) */
315: {"RSIPAvailable", 1, 0}, /* required */
316: {"NATEnabled", 1, 0}, /* required */
317: {"ExternalIPAddress", 0|0x80, 0, 0, 254}, /* required. Default : empty string */
318: {"PortMappingNumberOfEntries", 2|0x80, 0, 0, 253}, /* required >= 0 */
319: {"PortMappingEnabled", 1, 0}, /* Required */
320: {"PortMappingLeaseDuration", 3, 0}, /* required */
321: {"RemoteHost", 0, 0}, /* required. Default : empty string */
322: {"ExternalPort", 2, 0}, /* required */
323: {"InternalPort", 2, 0}, /* required */
324: {"PortMappingProtocol", 0, 0, 11}, /* required allowedValues: TCP/UDP */
325: {"InternalClient", 0, 0}, /* required */
326: {"PortMappingDescription", 0, 0}, /* required default: empty string */
327: {0, 0}
328: };
329:
330: static const struct serviceDesc scpdWANIPCn =
331: { WANIPCnActions, WANIPCnVars };
332:
333: /* WANCfg.xml */
334: /* See UPnP_IGD_WANCommonInterfaceConfig 1.0.pdf */
335:
336: static const struct argument GetCommonLinkPropertiesArgs[] =
337: {
338: {2, 0},
339: {2, 1},
340: {2, 2},
341: {2, 3},
342: {0, 0}
343: };
344:
345: static const struct argument GetTotalBytesSentArgs[] =
346: {
347: {2, 4},
348: {0, 0}
349: };
350:
351: static const struct argument GetTotalBytesReceivedArgs[] =
352: {
353: {2, 5},
354: {0, 0}
355: };
356:
357: static const struct argument GetTotalPacketsSentArgs[] =
358: {
359: {2, 6},
360: {0, 0}
361: };
362:
363: static const struct argument GetTotalPacketsReceivedArgs[] =
364: {
365: {2, 7},
366: {0, 0}
367: };
368:
369: static const struct action WANCfgActions[] =
370: {
371: {"GetCommonLinkProperties", GetCommonLinkPropertiesArgs}, /* Required */
372: {"GetTotalBytesSent", GetTotalBytesSentArgs}, /* optional */
373: {"GetTotalBytesReceived", GetTotalBytesReceivedArgs}, /* optional */
374: {"GetTotalPacketsSent", GetTotalPacketsSentArgs}, /* optional */
375: {"GetTotalPacketsReceived", GetTotalPacketsReceivedArgs}, /* optional */
376: {0, 0}
377: };
378:
379: /* See UPnP_IGD_WANCommonInterfaceConfig 1.0.pdf */
380: static const struct stateVar WANCfgVars[] =
381: {
382: {"WANAccessType", 0, 0, 1},
383: /* Allowed Values : DSL / POTS / Cable / Ethernet
384: * Default value : empty string */
385: {"Layer1UpstreamMaxBitRate", 3, 0},
386: {"Layer1DownstreamMaxBitRate", 3, 0},
387: {"PhysicalLinkStatus", 0|0x80, 0, 6, 6},
388: /* allowed values :
389: * Up / Down / Initializing (optional) / Unavailable (optionnal)
390: * no Default value
391: * Evented */
392: {"TotalBytesSent", 3, 0}, /* Optional */
393: {"TotalBytesReceived", 3, 0}, /* Optional */
394: {"TotalPacketsSent", 3, 0}, /* Optional */
395: {"TotalPacketsReceived", 3, 0},/* Optional */
396: /*{"MaximumActiveConnections", 2, 0}, // allowed Range value // OPTIONAL */
397: {0, 0}
398: };
399:
400: static const struct serviceDesc scpdWANCfg =
401: { WANCfgActions, WANCfgVars };
402:
403: #ifdef ENABLE_L3F_SERVICE
404: /* Read UPnP_IGD_Layer3Forwarding_1.0.pdf */
405: static const struct argument SetDefaultConnectionServiceArgs[] =
406: {
407: {1, 0}, /* in */
408: {0, 0}
409: };
410:
411: static const struct argument GetDefaultConnectionServiceArgs[] =
412: {
413: {2, 0}, /* out */
414: {0, 0}
415: };
416:
417: static const struct action L3FActions[] =
418: {
419: {"SetDefaultConnectionService", SetDefaultConnectionServiceArgs}, /* Req */
420: {"GetDefaultConnectionService", GetDefaultConnectionServiceArgs}, /* Req */
421: {0, 0}
422: };
423:
424: static const struct stateVar L3FVars[] =
425: {
426: {"DefaultConnectionService", 0|0x80, 0, 0, 255}, /* Required */
427: {0, 0}
428: };
429:
430: static const struct serviceDesc scpdL3F =
431: { L3FActions, L3FVars };
432: #endif
433:
434: /* strcat_str()
435: * concatenate the string and use realloc to increase the
436: * memory buffer if needed. */
437: static char *
438: strcat_str(char * str, int * len, int * tmplen, const char * s2)
439: {
440: int s2len;
441: s2len = (int)strlen(s2);
442: if(*tmplen <= (*len + s2len))
443: {
444: if(s2len < 256)
445: *tmplen += 256;
446: else
447: *tmplen += s2len + 1;
448: str = (char *)realloc(str, *tmplen);
449: }
450: /*strcpy(str + *len, s2); */
451: memcpy(str + *len, s2, s2len + 1);
452: *len += s2len;
453: return str;
454: }
455:
456: /* strcat_char() :
457: * concatenate a character and use realloc to increase the
458: * size of the memory buffer if needed */
459: static char *
460: strcat_char(char * str, int * len, int * tmplen, char c)
461: {
462: if(*tmplen <= (*len + 1))
463: {
464: *tmplen += 256;
465: str = (char *)realloc(str, *tmplen);
466: }
467: str[*len] = c;
468: (*len)++;
469: return str;
470: }
471:
472: /* iterative subroutine using a small stack
473: * This way, the progam stack usage is kept low */
474: static char *
475: genXML(char * str, int * len, int * tmplen,
476: const struct XMLElt * p)
477: {
478: unsigned short i, j;
479: unsigned long k;
480: int top;
481: const char * eltname, *s;
482: char c;
483: struct {
484: unsigned short i;
485: unsigned short j;
486: const char * eltname;
487: } pile[16]; /* stack */
488: top = -1;
489: i = 0; /* current node */
490: j = 1; /* i + number of nodes*/
491: for(;;)
492: {
493: eltname = p[i].eltname;
494: if(!eltname)
495: return str;
496: if(eltname[0] == '/')
497: {
498: if(p[i].data && p[i].data[0])
499: {
500: /*printf("<%s>%s<%s>\n", eltname+1, p[i].data, eltname); */
501: str = strcat_char(str, len, tmplen, '<');
502: str = strcat_str(str, len, tmplen, eltname+1);
503: str = strcat_char(str, len, tmplen, '>');
504: str = strcat_str(str, len, tmplen, p[i].data);
505: str = strcat_char(str, len, tmplen, '<');
506: str = strcat_str(str, len, tmplen, eltname);
507: str = strcat_char(str, len, tmplen, '>');
508: }
509: for(;;)
510: {
511: if(top < 0)
512: return str;
513: i = ++(pile[top].i);
514: j = pile[top].j;
515: /*printf(" pile[%d]\t%d %d\n", top, i, j); */
516: if(i==j)
517: {
518: /*printf("</%s>\n", pile[top].eltname); */
519: str = strcat_char(str, len, tmplen, '<');
520: str = strcat_char(str, len, tmplen, '/');
521: s = pile[top].eltname;
522: for(c = *s; c > ' '; c = *(++s))
523: str = strcat_char(str, len, tmplen, c);
524: str = strcat_char(str, len, tmplen, '>');
525: top--;
526: }
527: else
528: break;
529: }
530: }
531: else
532: {
533: /*printf("<%s>\n", eltname); */
534: str = strcat_char(str, len, tmplen, '<');
535: str = strcat_str(str, len, tmplen, eltname);
536: str = strcat_char(str, len, tmplen, '>');
537: k = (unsigned long)p[i].data;
538: i = k & 0xffff;
539: j = i + (k >> 16);
540: top++;
541: /*printf(" +pile[%d]\t%d %d\n", top, i, j); */
542: pile[top].i = i;
543: pile[top].j = j;
544: pile[top].eltname = eltname;
545: }
546: }
547: }
548:
549: /* genRootDesc() :
550: * - Generate the root description of the UPnP device.
551: * - the len argument is used to return the length of
552: * the returned string.
553: * - tmp_uuid argument is used to build the uuid string */
554: char *
555: genRootDesc(int * len)
556: {
557: char * str;
558: int tmplen;
559: tmplen = 2048;
560: str = (char *)malloc(tmplen);
561: if(str == NULL)
562: return NULL;
563: * len = strlen(xmlver);
564: /*strcpy(str, xmlver); */
565: memcpy(str, xmlver, *len + 1);
566: str = genXML(str, len, &tmplen, rootDesc);
567: str[*len] = '\0';
568: return str;
569: }
570:
571: /* genServiceDesc() :
572: * Generate service description with allowed methods and
573: * related variables. */
574: static char *
575: genServiceDesc(int * len, const struct serviceDesc * s)
576: {
577: int i, j;
578: const struct action * acts;
579: const struct stateVar * vars;
580: const struct argument * args;
581: const char * p;
582: char * str;
583: int tmplen;
584: tmplen = 2048;
585: str = (char *)malloc(tmplen);
586: if(str == NULL)
587: return NULL;
588: /*strcpy(str, xmlver); */
589: *len = strlen(xmlver);
590: memcpy(str, xmlver, *len + 1);
591:
592: acts = s->actionList;
593: vars = s->serviceStateTable;
594:
595: str = strcat_char(str, len, &tmplen, '<');
596: str = strcat_str(str, len, &tmplen, root_service);
597: str = strcat_char(str, len, &tmplen, '>');
598:
599: str = strcat_str(str, len, &tmplen,
600: "<specVersion><major>1</major><minor>0</minor></specVersion>");
601:
602: i = 0;
603: str = strcat_str(str, len, &tmplen, "<actionList>");
604: while(acts[i].name)
605: {
606: str = strcat_str(str, len, &tmplen, "<action><name>");
607: str = strcat_str(str, len, &tmplen, acts[i].name);
608: str = strcat_str(str, len, &tmplen, "</name>");
609: /* argument List */
610: args = acts[i].args;
611: if(args)
612: {
613: str = strcat_str(str, len, &tmplen, "<argumentList>");
614: j = 0;
615: while(args[j].dir)
616: {
617: str = strcat_str(str, len, &tmplen, "<argument><name>New");
618: p = vars[args[j].relatedVar].name;
619: if(0 == memcmp(p, "PortMapping", 11)
620: && 0 != memcmp(p + 11, "Description", 11)) {
621: if(0 == memcmp(p + 11, "NumberOfEntries", 15))
622: str = strcat_str(str, len, &tmplen, "PortMappingIndex");
623: else
624: str = strcat_str(str, len, &tmplen, p + 11);
625: } else {
626: str = strcat_str(str, len, &tmplen, p);
627: }
628: str = strcat_str(str, len, &tmplen, "</name><direction>");
629: str = strcat_str(str, len, &tmplen, args[j].dir==1?"in":"out");
630: str = strcat_str(str, len, &tmplen,
631: "</direction><relatedStateVariable>");
632: str = strcat_str(str, len, &tmplen, p);
633: str = strcat_str(str, len, &tmplen,
634: "</relatedStateVariable></argument>");
635: j++;
636: }
637: str = strcat_str(str, len, &tmplen,"</argumentList>");
638: }
639: str = strcat_str(str, len, &tmplen, "</action>");
640: /*str = strcat_char(str, len, &tmplen, '\n'); // TEMP ! */
641: i++;
642: }
643: str = strcat_str(str, len, &tmplen, "</actionList><serviceStateTable>");
644: i = 0;
645: while(vars[i].name)
646: {
647: str = strcat_str(str, len, &tmplen,
648: "<stateVariable sendEvents=\"");
649: #ifdef ENABLE_EVENTS
650: str = strcat_str(str, len, &tmplen, (vars[i].itype & 0x80)?"yes":"no");
651: #else
652: /* for the moment allways send no. Wait for SUBSCRIBE implementation
653: * before setting it to yes */
654: str = strcat_str(str, len, &tmplen, "no");
655: #endif
656: str = strcat_str(str, len, &tmplen, "\"><name>");
657: str = strcat_str(str, len, &tmplen, vars[i].name);
658: str = strcat_str(str, len, &tmplen, "</name><dataType>");
659: str = strcat_str(str, len, &tmplen, upnptypes[vars[i].itype & 0x0f]);
660: str = strcat_str(str, len, &tmplen, "</dataType>");
661: if(vars[i].iallowedlist)
662: {
663: str = strcat_str(str, len, &tmplen, "<allowedValueList>");
664: for(j=vars[i].iallowedlist; upnpallowedvalues[j]; j++)
665: {
666: str = strcat_str(str, len, &tmplen, "<allowedValue>");
667: str = strcat_str(str, len, &tmplen, upnpallowedvalues[j]);
668: str = strcat_str(str, len, &tmplen, "</allowedValue>");
669: }
670: str = strcat_str(str, len, &tmplen, "</allowedValueList>");
671: }
672: /*if(vars[i].defaultValue) */
673: if(vars[i].idefault)
674: {
675: str = strcat_str(str, len, &tmplen, "<defaultValue>");
676: /*str = strcat_str(str, len, &tmplen, vars[i].defaultValue); */
677: str = strcat_str(str, len, &tmplen, upnpdefaultvalues[vars[i].idefault]);
678: str = strcat_str(str, len, &tmplen, "</defaultValue>");
679: }
680: str = strcat_str(str, len, &tmplen, "</stateVariable>");
681: /*str = strcat_char(str, len, &tmplen, '\n'); // TEMP ! */
682: i++;
683: }
684: str = strcat_str(str, len, &tmplen, "</serviceStateTable></scpd>");
685: str[*len] = '\0';
686: return str;
687: }
688:
689: /* genWANIPCn() :
690: * Generate the WANIPConnection xml description */
691: char *
692: genWANIPCn(int * len)
693: {
694: return genServiceDesc(len, &scpdWANIPCn);
695: }
696:
697: /* genWANCfg() :
698: * Generate the WANInterfaceConfig xml description. */
699: char *
700: genWANCfg(int * len)
701: {
702: return genServiceDesc(len, &scpdWANCfg);
703: }
704:
705: #ifdef ENABLE_L3F_SERVICE
706: char *
707: genL3F(int * len)
708: {
709: return genServiceDesc(len, &scpdL3F);
710: }
711: #endif
712:
713: #ifdef ENABLE_EVENTS
714: static char *
715: genEventVars(int * len, const struct serviceDesc * s, const char * servns)
716: {
717: char tmp[16];
718: const struct stateVar * v;
719: char * str;
720: int tmplen;
721: tmplen = 512;
722: str = (char *)malloc(tmplen);
723: if(str == NULL)
724: return NULL;
725: *len = 0;
726: v = s->serviceStateTable;
727: str = strcat_str(str, len, &tmplen, "<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\" xmlns:s=\"");
728: str = strcat_str(str, len, &tmplen, servns);
729: str = strcat_str(str, len, &tmplen, "\">");
730: while(v->name) {
731: if(v->itype & 0x80) {
732: str = strcat_str(str, len, &tmplen, "<e:property><s:");
733: str = strcat_str(str, len, &tmplen, v->name);
734: str = strcat_str(str, len, &tmplen, ">");
735: //printf("<e:property><s:%s>", v->name);
736: switch(v->ieventvalue) {
737: case 0:
738: break;
739: case 253: /* Port mapping number of entries magical value */
740: snprintf(tmp, sizeof(tmp), "%d", upnp_get_portmapping_number_of_entries());
741: str = strcat_str(str, len, &tmplen, tmp);
742: break;
743: case 254: /* External ip address magical value */
744: if(use_ext_ip_addr)
745: str = strcat_str(str, len, &tmplen, use_ext_ip_addr);
746: else {
747: char ext_ip_addr[INET_ADDRSTRLEN];
748: if(getifaddr(ext_if_name, ext_ip_addr, INET_ADDRSTRLEN) < 0) {
749: str = strcat_str(str, len, &tmplen, "0.0.0.0");
750: } else {
751: str = strcat_str(str, len, &tmplen, ext_ip_addr);
752: }
753: }
754: /*str = strcat_str(str, len, &tmplen, "0.0.0.0");*/
755: break;
756: case 255: /* DefaultConnectionService magical value */
757: str = strcat_str(str, len, &tmplen, uuidvalue);
758: str = strcat_str(str, len, &tmplen, ":WANConnectionDevice:1,urn:upnp-org:serviceId:WANIPConn1");
759: //printf("%s:WANConnectionDevice:1,urn:upnp-org:serviceId:WANIPConn1", uuidvalue);
760: break;
761: default:
762: str = strcat_str(str, len, &tmplen, upnpallowedvalues[v->ieventvalue]);
763: //printf("%s", upnpallowedvalues[v->ieventvalue]);
764: }
765: str = strcat_str(str, len, &tmplen, "</s:");
766: str = strcat_str(str, len, &tmplen, v->name);
767: str = strcat_str(str, len, &tmplen, "></e:property>");
768: //printf("</s:%s></e:property>\n", v->name);
769: }
770: v++;
771: }
772: str = strcat_str(str, len, &tmplen, "</e:propertyset>");
773: //printf("</e:propertyset>\n");
774: //printf("\n");
775: //printf("%d\n", tmplen);
776: str[*len] = '\0';
777: return str;
778: }
779:
780: char *
781: getVarsWANIPCn(int * l)
782: {
783: return genEventVars(l,
784: &scpdWANIPCn,
785: "urn:schemas-upnp-org:service:WANIPConnection:1");
786: }
787:
788: char *
789: getVarsWANCfg(int * l)
790: {
791: return genEventVars(l,
792: &scpdWANCfg,
793: "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1");
794: }
795:
796: #ifdef ENABLE_L3F_SERVICE
797: char *
798: getVarsL3F(int * l)
799: {
800: return genEventVars(l,
801: &scpdL3F,
802: "urn:schemas-upnp-org:service:Layer3Forwarding:1");
803: }
804: #endif
805: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>