Tomato 1.24
[tomato.git] / release / src / router / miniupnpd / upnpdescgen.c
blob4578a80c320fc36f21c0d5ccd157d1f828f9e233
1 /* $Id: upnpdescgen.c,v 1.50 2009/02/12 23:12:38 nanard Exp $ */
2 /* MiniUPnP project
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * (c) 2006-2008 Thomas Bernard
5 * This software is subject to the conditions detailed
6 * in the LICENCE file provided within the distribution */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
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"
22 static const char * const upnptypes[] =
24 "string",
25 "boolean",
26 "ui2",
27 "ui4"
30 static const char * const upnpdefaultvalues[] =
33 "Unconfigured"
36 static const char * const upnpallowedvalues[] =
38 0, /* 0 */
39 "DSL", /* 1 */
40 "POTS",
41 "Cable",
42 "Ethernet",
44 "Up", /* 6 */
45 "Down",
46 "Initializing",
47 "Unavailable",
49 "TCP", /* 11 */
50 "UDP",
52 "Unconfigured", /* 14 */
53 "IP_Routed",
54 "IP_Bridged",
56 "Unconfigured", /* 18 */
57 "Connecting",
58 "Connected",
59 "PendingDisconnect",
60 "Disconnecting",
61 "Disconnected",
63 "ERROR_NONE", /* 25 */
65 "", /* 27 */
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\"";
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[] =
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}
186 /* WANIPCn.xml */
187 /* see UPnP_IGD_WANIPConnection 1.0.pdf
188 static struct XMLElt scpdWANIPCn[] =
190 {root_service, {INITHELPER(1,2)}},
191 {0, {0}}
194 static const struct argument AddPortMappingArgs[] =
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}
207 static const struct argument GetExternalIPAddressArgs[] =
209 {2, 7},
210 {0, 0}
213 static const struct argument DeletePortMappingArgs[] =
215 {1, 11},
216 {1, 12},
217 {1, 14},
218 {0, 0}
221 static const struct argument SetConnectionTypeArgs[] =
223 {1, 0},
224 {0, 0}
227 static const struct argument GetConnectionTypeInfoArgs[] =
229 {2, 0},
230 {2, 1},
231 {0, 0}
234 static const struct argument GetStatusInfoArgs[] =
236 {2, 2},
237 {2, 4},
238 {2, 3},
239 {0, 0}
242 static const struct argument GetNATRSIPStatusArgs[] =
244 {2, 5},
245 {2, 6},
246 {0, 0}
249 static const struct argument GetGenericPortMappingEntryArgs[] =
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}
263 static const struct argument GetSpecificPortMappingEntryArgs[] =
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}
276 static const struct action WANIPCnActions[] =
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}
291 /* R=Required, O=Optional */
293 static const struct stateVar WANIPCnVars[] =
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}
330 static const struct serviceDesc scpdWANIPCn =
331 { WANIPCnActions, WANIPCnVars };
333 /* WANCfg.xml */
334 /* See UPnP_IGD_WANCommonInterfaceConfig 1.0.pdf */
336 static const struct argument GetCommonLinkPropertiesArgs[] =
338 {2, 0},
339 {2, 1},
340 {2, 2},
341 {2, 3},
342 {0, 0}
345 static const struct argument GetTotalBytesSentArgs[] =
347 {2, 4},
348 {0, 0}
351 static const struct argument GetTotalBytesReceivedArgs[] =
353 {2, 5},
354 {0, 0}
357 static const struct argument GetTotalPacketsSentArgs[] =
359 {2, 6},
360 {0, 0}
363 static const struct argument GetTotalPacketsReceivedArgs[] =
365 {2, 7},
366 {0, 0}
369 static const struct action WANCfgActions[] =
371 {"GetCommonLinkProperties", GetCommonLinkPropertiesArgs}, /* Required */
372 {"GetTotalBytesSent", GetTotalBytesSentArgs}, /* optional */
373 {"GetTotalBytesReceived", GetTotalBytesReceivedArgs}, /* optional */
374 {"GetTotalPacketsSent", GetTotalPacketsSentArgs}, /* optional */
375 {"GetTotalPacketsReceived", GetTotalPacketsReceivedArgs}, /* optional */
376 {0, 0}
379 /* See UPnP_IGD_WANCommonInterfaceConfig 1.0.pdf */
380 static const struct stateVar WANCfgVars[] =
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}
400 static const struct serviceDesc scpdWANCfg =
401 { WANCfgActions, WANCfgVars };
403 #ifdef ENABLE_L3F_SERVICE
404 /* Read UPnP_IGD_Layer3Forwarding_1.0.pdf */
405 static const struct argument SetDefaultConnectionServiceArgs[] =
407 {1, 0}, /* in */
408 {0, 0}
411 static const struct argument GetDefaultConnectionServiceArgs[] =
413 {2, 0}, /* out */
414 {0, 0}
417 static const struct action L3FActions[] =
419 {"SetDefaultConnectionService", SetDefaultConnectionServiceArgs}, /* Req */
420 {"GetDefaultConnectionService", GetDefaultConnectionServiceArgs}, /* Req */
421 {0, 0}
424 static const struct stateVar L3FVars[] =
426 {"DefaultConnectionService", 0|0x80, 0, 0, 255}, /* Required */
427 {0, 0}
430 static const struct serviceDesc scpdL3F =
431 { L3FActions, L3FVars };
432 #endif
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)
440 int s2len;
441 s2len = (int)strlen(s2);
442 if(*tmplen <= (*len + s2len))
444 if(s2len < 256)
445 *tmplen += 256;
446 else
447 *tmplen += s2len + 1;
448 str = (char *)realloc(str, *tmplen);
450 /*strcpy(str + *len, s2); */
451 memcpy(str + *len, s2, s2len + 1);
452 *len += s2len;
453 return str;
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)
462 if(*tmplen <= (*len + 1))
464 *tmplen += 256;
465 str = (char *)realloc(str, *tmplen);
467 str[*len] = c;
468 (*len)++;
469 return str;
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)
478 unsigned short i, j, k;
479 int top;
480 const char * eltname, *s;
481 char c;
482 struct {
483 unsigned short i;
484 unsigned short j;
485 const char * eltname;
486 } pile[16]; /* stack */
487 top = -1;
488 i = 0; /* current node */
489 j = 1; /* i + number of nodes*/
490 for(;;)
492 eltname = p[i].eltname;
493 if(!eltname)
494 return str;
495 if(eltname[0] == '/')
497 if(p[i].data && p[i].data[0])
499 /*printf("<%s>%s<%s>\n", eltname+1, p[i].data, eltname); */
500 str = strcat_char(str, len, tmplen, '<');
501 str = strcat_str(str, len, tmplen, eltname+1);
502 str = strcat_char(str, len, tmplen, '>');
503 str = strcat_str(str, len, tmplen, p[i].data);
504 str = strcat_char(str, len, tmplen, '<');
505 str = strcat_str(str, len, tmplen, eltname);
506 str = strcat_char(str, len, tmplen, '>');
508 for(;;)
510 if(top < 0)
511 return str;
512 i = ++(pile[top].i);
513 j = pile[top].j;
514 /*printf(" pile[%d]\t%d %d\n", top, i, j); */
515 if(i==j)
517 /*printf("</%s>\n", pile[top].eltname); */
518 str = strcat_char(str, len, tmplen, '<');
519 str = strcat_char(str, len, tmplen, '/');
520 s = pile[top].eltname;
521 for(c = *s; c > ' '; c = *(++s))
522 str = strcat_char(str, len, tmplen, c);
523 str = strcat_char(str, len, tmplen, '>');
524 top--;
526 else
527 break;
530 else
532 /*printf("<%s>\n", eltname); */
533 str = strcat_char(str, len, tmplen, '<');
534 str = strcat_str(str, len, tmplen, eltname);
535 str = strcat_char(str, len, tmplen, '>');
536 k = i;
537 /*i = p[k].index; */
538 /*j = i + p[k].nchild; */
539 i = (unsigned)p[k].data & 0xffff;
540 j = i + ((unsigned)p[k].data >> 16);
541 top++;
542 /*printf(" +pile[%d]\t%d %d\n", top, i, j); */
543 pile[top].i = i;
544 pile[top].j = j;
545 pile[top].eltname = eltname;
550 /* genRootDesc() :
551 * - Generate the root description of the UPnP device.
552 * - the len argument is used to return the length of
553 * the returned string.
554 * - tmp_uuid argument is used to build the uuid string */
555 char *
556 genRootDesc(int * len)
558 char * str;
559 int tmplen;
560 tmplen = 2048;
561 str = (char *)malloc(tmplen);
562 if(str == NULL)
563 return NULL;
564 * len = strlen(xmlver);
565 /*strcpy(str, xmlver); */
566 memcpy(str, xmlver, *len + 1);
567 str = genXML(str, len, &tmplen, rootDesc);
568 str[*len] = '\0';
569 return str;
572 /* genServiceDesc() :
573 * Generate service description with allowed methods and
574 * related variables. */
575 static char *
576 genServiceDesc(int * len, const struct serviceDesc * s)
578 int i, j;
579 const struct action * acts;
580 const struct stateVar * vars;
581 const struct argument * args;
582 const char * p;
583 char * str;
584 int tmplen;
585 tmplen = 2048;
586 str = (char *)malloc(tmplen);
587 if(str == NULL)
588 return NULL;
589 /*strcpy(str, xmlver); */
590 *len = strlen(xmlver);
591 memcpy(str, xmlver, *len + 1);
593 acts = s->actionList;
594 vars = s->serviceStateTable;
596 str = strcat_char(str, len, &tmplen, '<');
597 str = strcat_str(str, len, &tmplen, root_service);
598 str = strcat_char(str, len, &tmplen, '>');
600 str = strcat_str(str, len, &tmplen,
601 "<specVersion><major>1</major><minor>0</minor></specVersion>");
603 i = 0;
604 str = strcat_str(str, len, &tmplen, "<actionList>");
605 while(acts[i].name)
607 str = strcat_str(str, len, &tmplen, "<action><name>");
608 str = strcat_str(str, len, &tmplen, acts[i].name);
609 str = strcat_str(str, len, &tmplen, "</name>");
610 /* argument List */
611 args = acts[i].args;
612 if(args)
614 str = strcat_str(str, len, &tmplen, "<argumentList>");
615 j = 0;
616 while(args[j].dir)
618 str = strcat_str(str, len, &tmplen, "<argument><name>New");
619 p = vars[args[j].relatedVar].name;
620 if(0 == memcmp(p, "PortMapping", 11)
621 && 0 != memcmp(p + 11, "Description", 11)) {
622 if(0 == memcmp(p + 11, "NumberOfEntries", 15))
623 str = strcat_str(str, len, &tmplen, "PortMappingIndex");
624 else
625 str = strcat_str(str, len, &tmplen, p + 11);
626 } else {
627 str = strcat_str(str, len, &tmplen, p);
629 str = strcat_str(str, len, &tmplen, "</name><direction>");
630 str = strcat_str(str, len, &tmplen, args[j].dir==1?"in":"out");
631 str = strcat_str(str, len, &tmplen,
632 "</direction><relatedStateVariable>");
633 str = strcat_str(str, len, &tmplen, p);
634 str = strcat_str(str, len, &tmplen,
635 "</relatedStateVariable></argument>");
636 j++;
638 str = strcat_str(str, len, &tmplen,"</argumentList>");
640 str = strcat_str(str, len, &tmplen, "</action>");
641 /*str = strcat_char(str, len, &tmplen, '\n'); // TEMP ! */
642 i++;
644 str = strcat_str(str, len, &tmplen, "</actionList><serviceStateTable>");
645 i = 0;
646 while(vars[i].name)
648 str = strcat_str(str, len, &tmplen,
649 "<stateVariable sendEvents=\"");
650 #ifdef ENABLE_EVENTS
651 str = strcat_str(str, len, &tmplen, (vars[i].itype & 0x80)?"yes":"no");
652 #else
653 /* for the moment allways send no. Wait for SUBSCRIBE implementation
654 * before setting it to yes */
655 str = strcat_str(str, len, &tmplen, "no");
656 #endif
657 str = strcat_str(str, len, &tmplen, "\"><name>");
658 str = strcat_str(str, len, &tmplen, vars[i].name);
659 str = strcat_str(str, len, &tmplen, "</name><dataType>");
660 str = strcat_str(str, len, &tmplen, upnptypes[vars[i].itype & 0x0f]);
661 str = strcat_str(str, len, &tmplen, "</dataType>");
662 if(vars[i].iallowedlist)
664 str = strcat_str(str, len, &tmplen, "<allowedValueList>");
665 for(j=vars[i].iallowedlist; upnpallowedvalues[j]; j++)
667 str = strcat_str(str, len, &tmplen, "<allowedValue>");
668 str = strcat_str(str, len, &tmplen, upnpallowedvalues[j]);
669 str = strcat_str(str, len, &tmplen, "</allowedValue>");
671 str = strcat_str(str, len, &tmplen, "</allowedValueList>");
673 /*if(vars[i].defaultValue) */
674 if(vars[i].idefault)
676 str = strcat_str(str, len, &tmplen, "<defaultValue>");
677 /*str = strcat_str(str, len, &tmplen, vars[i].defaultValue); */
678 str = strcat_str(str, len, &tmplen, upnpdefaultvalues[vars[i].idefault]);
679 str = strcat_str(str, len, &tmplen, "</defaultValue>");
681 str = strcat_str(str, len, &tmplen, "</stateVariable>");
682 /*str = strcat_char(str, len, &tmplen, '\n'); // TEMP ! */
683 i++;
685 str = strcat_str(str, len, &tmplen, "</serviceStateTable></scpd>");
686 str[*len] = '\0';
687 return str;
690 /* genWANIPCn() :
691 * Generate the WANIPConnection xml description */
692 char *
693 genWANIPCn(int * len)
695 return genServiceDesc(len, &scpdWANIPCn);
698 /* genWANCfg() :
699 * Generate the WANInterfaceConfig xml description. */
700 char *
701 genWANCfg(int * len)
703 return genServiceDesc(len, &scpdWANCfg);
706 #ifdef ENABLE_L3F_SERVICE
707 char *
708 genL3F(int * len)
710 return genServiceDesc(len, &scpdL3F);
712 #endif
714 #ifdef ENABLE_EVENTS
715 static char *
716 genEventVars(int * len, const struct serviceDesc * s, const char * servns)
718 char tmp[16];
719 const struct stateVar * v;
720 char * str;
721 int tmplen;
722 tmplen = 512;
723 str = (char *)malloc(tmplen);
724 if(str == NULL)
725 return NULL;
726 *len = 0;
727 v = s->serviceStateTable;
728 str = strcat_str(str, len, &tmplen, "<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\" xmlns:s=\"");
729 str = strcat_str(str, len, &tmplen, servns);
730 str = strcat_str(str, len, &tmplen, "\">");
731 while(v->name) {
732 if(v->itype & 0x80) {
733 str = strcat_str(str, len, &tmplen, "<e:property><s:");
734 str = strcat_str(str, len, &tmplen, v->name);
735 str = strcat_str(str, len, &tmplen, ">");
736 //printf("<e:property><s:%s>", v->name);
737 switch(v->ieventvalue) {
738 case 0:
739 break;
740 case 253: /* Port mapping number of entries magical value */
741 snprintf(tmp, sizeof(tmp), "%d", upnp_get_portmapping_number_of_entries());
742 str = strcat_str(str, len, &tmplen, tmp);
743 break;
744 case 254: /* External ip address magical value */
745 if(use_ext_ip_addr)
746 str = strcat_str(str, len, &tmplen, use_ext_ip_addr);
747 else {
748 char ext_ip_addr[INET_ADDRSTRLEN];
749 if(getifaddr(ext_if_name, ext_ip_addr, INET_ADDRSTRLEN) < 0) {
750 str = strcat_str(str, len, &tmplen, "0.0.0.0");
751 } else {
752 str = strcat_str(str, len, &tmplen, ext_ip_addr);
755 /*str = strcat_str(str, len, &tmplen, "0.0.0.0");*/
756 break;
757 case 255: /* DefaultConnectionService magical value */
758 str = strcat_str(str, len, &tmplen, uuidvalue);
759 str = strcat_str(str, len, &tmplen, ":WANConnectionDevice:1,urn:upnp-org:serviceId:WANIPConn1");
760 //printf("%s:WANConnectionDevice:1,urn:upnp-org:serviceId:WANIPConn1", uuidvalue);
761 break;
762 default:
763 str = strcat_str(str, len, &tmplen, upnpallowedvalues[v->ieventvalue]);
764 //printf("%s", upnpallowedvalues[v->ieventvalue]);
766 str = strcat_str(str, len, &tmplen, "</s:");
767 str = strcat_str(str, len, &tmplen, v->name);
768 str = strcat_str(str, len, &tmplen, "></e:property>");
769 //printf("</s:%s></e:property>\n", v->name);
771 v++;
773 str = strcat_str(str, len, &tmplen, "</e:propertyset>");
774 //printf("</e:propertyset>\n");
775 //printf("\n");
776 //printf("%d\n", tmplen);
777 str[*len] = '\0';
778 return str;
781 char *
782 getVarsWANIPCn(int * l)
784 return genEventVars(l,
785 &scpdWANIPCn,
786 "urn:schemas-upnp-org:service:WANIPConnection:1");
789 char *
790 getVarsWANCfg(int * l)
792 return genEventVars(l,
793 &scpdWANCfg,
794 "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1");
797 #ifdef ENABLE_L3F_SERVICE
798 char *
799 getVarsL3F(int * l)
801 return genEventVars(l,
802 &scpdL3F,
803 "urn:schemas-upnp-org:service:Layer3Forwarding:1");
805 #endif
806 #endif