Annotation of embedaddon/miniupnpd/miniupnpd/upnpdescgen.c, revision 1.1.1.1
1.1 misho 1: /* $Id: upnpdescgen.c,v 1.91 2022/10/16 05:49:41 nanard Exp $ */
2: /* vim: tabstop=4 shiftwidth=4 noexpandtab
3: * MiniUPnP project
4: * http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/
5: * (c) 2006-2021 Thomas Bernard
6: * This software is subject to the conditions detailed
7: * in the LICENCE file provided within the distribution */
8:
9: #include <stdio.h>
10: #include <stdlib.h>
11: #include <string.h>
12: #include <syslog.h>
13:
14: #include "config.h"
15: #ifdef ENABLE_EVENTS
16: #include "getifaddr.h"
17: #include "upnpredirect.h"
18: #endif
19: #include "upnpdescgen.h"
20: #include "miniupnpdpath.h"
21: #include "upnpglobalvars.h"
22: #include "upnpdescstrings.h"
23: #include "upnpurns.h"
24: #include "getconnstatus.h"
25: #include "macros.h"
26:
27:
28: /* Event magical values codes */
29: #define SETUPREADY_MAGICALVALUE (248)
30: #define CONNECTIONSTATUS_MAGICALVALUE (249)
31: #define FIREWALLENABLED_MAGICALVALUE (250)
32: #define INBOUNDPINHOLEALLOWED_MAGICALVALUE (251)
33: #define SYSTEMUPDATEID_MAGICALVALUE (252)
34: #define PORTMAPPINGNUMBEROFENTRIES_MAGICALVALUE (253)
35: #define EXTERNALIPADDRESS_MAGICALVALUE (254)
36: #define DEFAULTCONNECTIONSERVICE_MAGICALVALUE (255)
37:
38:
39: static const char * const upnptypes[] =
40: {
41: "string",
42: "boolean",
43: "ui2",
44: "ui4",
45: "bin.base64"
46: };
47:
48: static const char * const upnpdefaultvalues[] =
49: {
50: 0,
51: "IP_Routed"/*"Unconfigured"*/, /* 1 default value for ConnectionType */
52: "3600", /* 2 default value for PortMappingLeaseDuration */
53: "Unconfigured", /* 3 default value for ConnectionStatus */
54: "0", /* 4 default value for RSIPAvailable */
55: "1", /* 5 default value for NATEnabled */
56: "ERROR_NONE", /* 6 default value for LastConnectionError */
57: };
58:
59: static const char * const upnpallowedvalues[] =
60: {
61: 0, /* 0 */
62: "DSL", /* 1 */
63: "POTS",
64: "Cable",
65: "Ethernet",
66: 0,
67: "Up", /* 6 */
68: "Down",
69: "Initializing",
70: "Unavailable",
71: 0,
72: "TCP", /* 11 */
73: "UDP",
74: 0,
75: "Unconfigured", /* 14 */
76: "IP_Routed",
77: "IP_Bridged",
78: 0,
79: "Unconfigured", /* 18 */
80: "Connecting",
81: "Connected",
82: "PendingDisconnect",
83: "Disconnecting",
84: "Disconnected",
85: 0,
86: "ERROR_NONE", /* 25 */
87: /* Optionals values :
88: * ERROR_COMMAND_ABORTED
89: * ERROR_NOT_ENABLED_FOR_INTERNET
90: * ERROR_USER_DISCONNECT
91: * ERROR_ISP_DISCONNECT
92: * ERROR_IDLE_DISCONNECT
93: * ERROR_FORCED_DISCONNECT
94: * ERROR_NO_CARRIER
95: * ERROR_IP_CONFIGURATION
96: * ERROR_UNKNOWN */
97: 0,
98: "", /* 27 */
99: 0
100: };
101:
102: static const int upnpallowedranges[] = {
103: 0,
104: /* 1 PortMappingLeaseDuration */
105: 0,
106: 604800,
107: /* 3 InternalPort */
108: 1,
109: 65535,
110: /* 5 LeaseTime */
111: 1,
112: 86400,
113: /* 7 OutboundPinholeTimeout */
114: 100,
115: 200,
116: };
117:
118: static const char * magicargname[] = {
119: 0,
120: "StartPort", /* 1 */
121: "EndPort", /* 2 */
122: "RemoteHost", /* 3 */
123: "RemotePort", /* 4 */
124: "InternalClient", /* 5 */
125: "InternalPort", /* 6 */
126: "IsWorking", /* 7 */
127: #ifdef ENABLE_DP_SERVICE
128: "ProtocolType", /* 8 */
129: "InMessage", /* 9 */
130: "OutMessage", /* 10 */
131: "ProtocolList", /* 11 */
132: "RoleList", /* 12 */
133: #endif /* ENABLE_DP_SERVICE */
134: };
135:
136: static const char xmlver[] =
137: "<?xml version=\"1.0\"?>\r\n";
138: static const char root_service[] =
139: "scpd xmlns=\"urn:schemas-upnp-org:service-1-0\"";
140: static const char root_device[] =
141: "root xmlns=\"urn:schemas-upnp-org:device-1-0\"";
142:
143: /* root Description of the UPnP Device
144: * fixed to match UPnP_IGD_InternetGatewayDevice 1.0.pdf
145: * Needs to be checked with UPnP-gw-InternetGatewayDevice-v2-Device.pdf
146: * presentationURL is only "recommended" but the router doesn't appears
147: * in "Network connections" in Windows XP if it is not present. */
148: static const struct XMLElt rootDesc[] =
149: {
150: /* 0 */
151: {root_device, INITHELPER(1,2)},
152: {"specVersion", INITHELPER(3,2)},
153: #if defined(ENABLE_L3F_SERVICE) || defined(HAS_DUMMY_SERVICE) || defined(ENABLE_DP_SERVICE)
154: {"device", INITHELPER(5,13)},
155: #else
156: {"device", INITHELPER(5,12)},
157: #endif
158: {"/major", UPNP_VERSION_MAJOR_STR},
159: {"/minor", UPNP_VERSION_MINOR_STR},
160: /* 5 */
161: {"/deviceType", DEVICE_TYPE_IGD},
162: /* urn:schemas-upnp-org:device:InternetGatewayDevice:1 or 2 */
163: #ifdef ENABLE_MANUFACTURER_INFO_CONFIGURATION
164: {"/friendlyName", friendly_name/*ROOTDEV_FRIENDLYNAME*/}, /* required */
165: {"/manufacturer", manufacturer_name/*ROOTDEV_MANUFACTURER*/}, /* required */
166: /* 8 */
167: {"/manufacturerURL", manufacturer_url/*ROOTDEV_MANUFACTURERURL*/}, /* optional */
168: {"/modelDescription", model_description/*ROOTDEV_MODELDESCRIPTION*/}, /* recommended */
169: {"/modelName", model_name/*ROOTDEV_MODELNAME*/}, /* required */
170: {"/modelNumber", modelnumber},
171: {"/modelURL", model_url/*ROOTDEV_MODELURL*/},
172: #else
173: {"/friendlyName", ROOTDEV_FRIENDLYNAME}, /* required */
174: {"/manufacturer", ROOTDEV_MANUFACTURER}, /* required */
175: /* 8 */
176: {"/manufacturerURL", ROOTDEV_MANUFACTURERURL}, /* optional */
177: {"/modelDescription", ROOTDEV_MODELDESCRIPTION}, /* recommended */
178: {"/modelName", ROOTDEV_MODELNAME}, /* required */
179: {"/modelNumber", modelnumber},
180: {"/modelURL", ROOTDEV_MODELURL},
181: #endif
182: {"/serialNumber", serialnumber},
183: {"/UDN", uuidvalue_igd}, /* required */
184: /* see if /UPC is needed. */
185: #ifdef ENABLE_6FC_SERVICE
186: #define SERVICES_OFFSET 63
187: #else
188: #define SERVICES_OFFSET 58
189: #endif
190: #if defined(ENABLE_L3F_SERVICE) || defined(HAS_DUMMY_SERVICE) || defined(ENABLE_DP_SERVICE)
191: /* here we dening Services for the root device :
192: * L3F and DUMMY and DeviceProtection */
193: #ifdef ENABLE_L3F_SERVICE
194: #define NSERVICES1 1
195: #else
196: #define NSERVICES1 0
197: #endif
198: #ifdef HAS_DUMMY_SERVICE
199: #define NSERVICES2 1
200: #else
201: #define NSERVICES2 0
202: #endif
203: #ifdef ENABLE_DP_SERVICE
204: #define NSERVICES3 1
205: #else
206: #define NSERVICES3 0
207: #endif
208: #define NSERVICES (NSERVICES1+NSERVICES2+NSERVICES3)
209: {"serviceList", INITHELPER(SERVICES_OFFSET,NSERVICES)},
210: {"deviceList", INITHELPER(18,1)},
211: {"/presentationURL", presentationurl}, /* recommended */
212: #else
213: {"deviceList", INITHELPER(18,1)},
214: {"/presentationURL", presentationurl}, /* recommended */
215: {0,0},
216: #endif
217: /* 18 */
218: {"device", INITHELPER(19,13)},
219: /* 19 */
220: {"/deviceType", DEVICE_TYPE_WAN}, /* required */
221: /* urn:schemas-upnp-org:device:WANDevice:1 or 2 */
222: {"/friendlyName", WANDEV_FRIENDLYNAME},
223: {"/manufacturer", WANDEV_MANUFACTURER},
224: {"/manufacturerURL", WANDEV_MANUFACTURERURL},
225: {"/modelDescription" , WANDEV_MODELDESCRIPTION},
226: {"/modelName", WANDEV_MODELNAME},
227: {"/modelNumber", WANDEV_MODELNUMBER},
228: {"/modelURL", WANDEV_MODELURL},
229: {"/serialNumber", serialnumber},
230: {"/UDN", uuidvalue_wan},
231: {"/UPC", WANDEV_UPC}, /* UPC (=12 digit barcode) is optional */
232: /* 30 */
233: {"serviceList", INITHELPER(32,1)},
234: {"deviceList", INITHELPER(38,1)},
235: /* 32 */
236: {"service", INITHELPER(33,5)},
237: /* 33 */
238: {"/serviceType",
239: "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"},
240: /*{"/serviceId", "urn:upnp-org:serviceId:WANCommonInterfaceConfig"}, */
241: {"/serviceId", "urn:upnp-org:serviceId:WANCommonIFC1"}, /* required */
242: {"/SCPDURL", WANCFG_PATH},
243: {"/controlURL", WANCFG_CONTROLURL},
244: {"/eventSubURL", WANCFG_EVENTURL},
245: /* 38 */
246: {"device", INITHELPER(39,12)},
247: /* 39 */
248: {"/deviceType", DEVICE_TYPE_WANC},
249: /* urn:schemas-upnp-org:device:WANConnectionDevice:1 or 2 */
250: {"/friendlyName", WANCDEV_FRIENDLYNAME},
251: {"/manufacturer", WANCDEV_MANUFACTURER},
252: {"/manufacturerURL", WANCDEV_MANUFACTURERURL},
253: {"/modelDescription", WANCDEV_MODELDESCRIPTION},
254: {"/modelName", WANCDEV_MODELNAME},
255: {"/modelNumber", WANCDEV_MODELNUMBER},
256: {"/modelURL", WANCDEV_MODELURL},
257: {"/serialNumber", serialnumber},
258: {"/UDN", uuidvalue_wcd},
259: {"/UPC", WANCDEV_UPC}, /* UPC (=12 digit Barcode) is optional */
260: #ifdef ENABLE_6FC_SERVICE
261: {"serviceList", INITHELPER(51,2)},
262: #else
263: {"serviceList", INITHELPER(51,1)},
264: #endif
265: /* 51 */
266: {"service", INITHELPER(53,5)},
267: {"service", INITHELPER(58,5)},
268: /* 53 */
269: {"/serviceType", SERVICE_TYPE_WANIPC},
270: /* urn:schemas-upnp-org:service:WANIPConnection:2 for v2 */
271: {"/serviceId", SERVICE_ID_WANIPC},
272: /* urn:upnp-org:serviceId:WANIPConn1 or 2 */
273: {"/SCPDURL", WANIPC_PATH},
274: {"/controlURL", WANIPC_CONTROLURL},
275: {"/eventSubURL", WANIPC_EVENTURL},
276: #ifdef ENABLE_6FC_SERVICE
277: /* 58 */
278: {"/serviceType", "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1"},
279: {"/serviceId", "urn:upnp-org:serviceId:WANIPv6Firewall1"},
280: {"/SCPDURL", WANIP6FC_PATH},
281: {"/controlURL", WANIP6FC_CONTROLURL},
282: {"/eventSubURL", WANIP6FC_EVENTURL},
283: #endif
284: /* 58 / 63 = SERVICES_OFFSET*/
285: #if defined(HAS_DUMMY_SERVICE) || defined(ENABLE_L3F_SERVICE) || defined(ENABLE_DP_SERVICE)
286: {"service", INITHELPER(SERVICES_OFFSET+2,5)},
287: {"service", INITHELPER(SERVICES_OFFSET+7,5)},
288: #endif
289: #ifdef HAS_DUMMY_SERVICE
290: /* 60 / 65 = SERVICES_OFFSET+2 */
291: {"/serviceType", "urn:schemas-dummy-com:service:Dummy:1"},
292: {"/serviceId", "urn:dummy-com:serviceId:dummy1"},
293: {"/SCPDURL", DUMMY_PATH},
294: {"/controlURL", "/dummy"},
295: {"/eventSubURL", "/dummy"},
296: #endif
297: #ifdef ENABLE_L3F_SERVICE
298: /* 60 / 65 = SERVICES_OFFSET+2 */
299: {"/serviceType", "urn:schemas-upnp-org:service:Layer3Forwarding:1"},
300: {"/serviceId", "urn:upnp-org:serviceId:L3Forwarding1"},
301: {"/SCPDURL", L3F_PATH},
302: {"/controlURL", L3F_CONTROLURL}, /* The Layer3Forwarding service is only */
303: {"/eventSubURL", L3F_EVENTURL}, /* recommended, not mandatory */
304: #endif
305: #ifdef ENABLE_DP_SERVICE
306: /* InternetGatewayDevice v2 :
307: * it is RECOMMEDED that DeviceProtection service is implemented and applied.
308: * If DeviceProtection is not implemented and applied, it is RECOMMENDED
309: * that control points are able to access only actions and parameters defined
310: * as Public role. */
311: /* 65 / 70 = SERVICES_OFFSET+7 */
312: {"/serviceType", "urn:schemas-upnp-org:service:DeviceProtection:1"},
313: {"/serviceId", "urn:upnp-org:serviceId:DeviceProtection1"},
314: {"/SCPDURL", DP_PATH},
315: {"/controlURL", DP_CONTROLURL},
316: {"/eventSubURL", DP_EVENTURL},
317: #endif
318: {0, 0}
319: };
320:
321: /* WANIPCn.xml */
322: /* see UPnP_IGD_WANIPConnection 1.0.pdf
323: static struct XMLElt scpdWANIPCn[] =
324: {
325: {root_service, {INITHELPER(1,2)}},
326: {0, {0}}
327: };
328: */
329: static const struct argument AddPortMappingArgs[] =
330: {
331: {1, 11}, /* RemoteHost */
332: {1, 12}, /* ExternalPort */
333: {1, 14}, /* PortMappingProtocol */
334: {1, 13}, /* InternalPort */
335: {1, 15}, /* InternalClient */
336: {1, 9}, /* PortMappingEnabled */
337: {1, 16}, /* PortMappingDescription */
338: {1, 10}, /* PortMappingLeaseDuration */
339: {0, 0}
340: };
341:
342: #ifdef IGD_V2
343: static const struct argument AddAnyPortMappingArgs[] =
344: {
345: {1, 11}, /* RemoteHost */
346: {1, 12}, /* ExternalPort */
347: {1, 14}, /* PortMappingProtocol */
348: {1, 13}, /* InternalPort */
349: {1, 15}, /* InternalClient */
350: {1, 9}, /* PortMappingEnabled */
351: {1, 16}, /* PortMappingDescription */
352: {1, 10}, /* PortMappingLeaseDuration */
353: {2, 12}, /* NewReservedPort / ExternalPort */
354: {0, 0}
355: };
356:
357: static const struct argument DeletePortMappingRangeArgs[] =
358: {
359: {1|(1<<2), 12}, /* NewStartPort / ExternalPort */
360: {1|(2<<2), 12}, /* NewEndPort / ExternalPort */
361: {1, 14}, /* NewProtocol / PortMappingProtocol */
362: {1, 18}, /* NewManage / A_ARG_TYPE_Manage */
363: {0, 0}
364: };
365:
366: static const struct argument GetListOfPortMappingsArgs[] =
367: {
368: {1|(1<<2), 12}, /* NewStartPort / ExternalPort */
369: {1|(2<<2), 12}, /* NewEndPort / ExternalPort */
370: {1, 14}, /* NewProtocol / PortMappingProtocol */
371: {1, 18}, /* NewManage / A_ARG_TYPE_Manage */
372: {1, 8}, /* NewNumberOfPorts / PortMappingNumberOfEntries */
373: {2, 19}, /* NewPortListing / A_ARG_TYPE_PortListing */
374: {0, 0}
375: };
376: #endif
377:
378: static const struct argument GetExternalIPAddressArgs[] =
379: {
380: {2, 7},
381: {0, 0}
382: };
383:
384: static const struct argument DeletePortMappingArgs[] =
385: {
386: {1, 11}, /* RemoteHost */
387: {1, 12}, /* ExternalPort */
388: {1, 14}, /* PortMappingProtocol */
389: {0, 0}
390: };
391:
392: static const struct argument SetConnectionTypeArgs[] =
393: {
394: {1, 0},
395: {0, 0}
396: };
397:
398: static const struct argument GetConnectionTypeInfoArgs[] =
399: {
400: {2, 0},
401: {2, 1},
402: {0, 0}
403: };
404:
405: static const struct argument GetStatusInfoArgs[] =
406: {
407: {2, 2},
408: {2, 4},
409: {2, 3},
410: {0, 0}
411: };
412:
413: static const struct argument GetNATRSIPStatusArgs[] =
414: {
415: {2, 5},
416: {2, 6},
417: {0, 0}
418: };
419:
420: static const struct argument GetGenericPortMappingEntryArgs[] =
421: {
422: {1, 8},
423: {2, 11},
424: {2, 12},
425: {2, 14},
426: {2, 13},
427: {2, 15},
428: {2, 9},
429: {2, 16},
430: {2, 10},
431: {0, 0}
432: };
433:
434: static const struct argument GetSpecificPortMappingEntryArgs[] =
435: {
436: {1, 11},
437: {1, 12},
438: {1, 14},
439: {2, 13},
440: {2, 15},
441: {2, 9},
442: {2, 16},
443: {2, 10},
444: {0, 0}
445: };
446:
447: static const struct action WANIPCnActions[] =
448: {
449: {"SetConnectionType", SetConnectionTypeArgs}, /* R */
450: {"GetConnectionTypeInfo", GetConnectionTypeInfoArgs}, /* R */
451: {"RequestConnection", 0}, /* R */
452: /*{"RequestTermination", 0},*/ /* O */
453: {"ForceTermination", 0}, /* R */
454: /*{"SetAutoDisconnectTime", 0},*/ /* O */
455: /*{"SetIdleDisconnectTime", 0},*/ /* O */
456: /*{"SetWarnDisconnectDelay", 0}, */ /* O */
457: {"GetStatusInfo", GetStatusInfoArgs}, /* R */
458: /*GetAutoDisconnectTime*/ /* O */
459: /*GetIdleDisconnectTime*/ /* O */
460: /*GetWarnDisconnectDelay*/ /* O */
461: {"GetNATRSIPStatus", GetNATRSIPStatusArgs}, /* R */
462: {"GetGenericPortMappingEntry", GetGenericPortMappingEntryArgs}, /* R */
463: {"GetSpecificPortMappingEntry", GetSpecificPortMappingEntryArgs}, /* R */
464: {"AddPortMapping", AddPortMappingArgs}, /* R */
465: {"DeletePortMapping", DeletePortMappingArgs}, /* R */
466: {"GetExternalIPAddress", GetExternalIPAddressArgs}, /* R */
467: #ifdef IGD_V2
468: {"DeletePortMappingRange", DeletePortMappingRangeArgs}, /* R, IGD v2 */
469: {"GetListOfPortMappings", GetListOfPortMappingsArgs}, /* R, IGD v2 */
470: {"AddAnyPortMapping", AddAnyPortMappingArgs}, /* R, IGD v2 */
471: #endif
472: #if 0
473: {"AddPortMapping", AddPortMappingArgs}, /* R */
474: {"GetExternalIPAddress", GetExternalIPAddressArgs}, /* R */
475: {"DeletePortMapping", DeletePortMappingArgs}, /* R */
476: {"SetConnectionType", SetConnectionTypeArgs}, /* R */
477: {"GetConnectionTypeInfo", GetConnectionTypeInfoArgs}, /* R */
478: {"RequestConnection", 0}, /* R */
479: {"ForceTermination", 0}, /* R */
480: {"GetStatusInfo", GetStatusInfoArgs}, /* R */
481: {"GetNATRSIPStatus", GetNATRSIPStatusArgs}, /* R */
482: {"GetGenericPortMappingEntry", GetGenericPortMappingEntryArgs}, /* R */
483: {"GetSpecificPortMappingEntry", GetSpecificPortMappingEntryArgs}, /* R */
484: /* added in v2 UPnP-gw-WANIPConnection-v2-Service.pdf */
485: #ifdef IGD_V2
486: {"AddAnyPortMapping", AddAnyPortMappingArgs},
487: {"DeletePortMappingRange", DeletePortMappingRangeArgs},
488: {"GetListOfPortMappings", GetListOfPortMappingsArgs},
489: #endif
490: #endif
491: {0, 0}
492: };
493: /* R=Required, O=Optional */
494:
495: /* ignore "warning: missing initializer" */
496: #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
497:
498: /* struct stateVar :
499: * {name, itype(&event), idefault, iallowedlist, ieventvalue} */
500: static const struct stateVar WANIPCnVars[] =
501: {
502: /* 0 */
503: #if 0
504: {"ConnectionType", 0, 0/*1*/}, /* required */
505: {"PossibleConnectionTypes", 0|0x80, 0, 14, 15},
506: #elif 0
507: {"ConnectionType", 0, 1, 14, 15}, /* required */
508: {"PossibleConnectionTypes", 0|0x80, 0, 0, 15},
509: #else
510: {"ConnectionType", 0, 1, 0, 15}, /* required */
511: {"PossibleConnectionTypes", 0|0x80, 0, 14, 15},
512: #endif
513: /* Required
514: * Allowed values : Unconfigured / IP_Routed / IP_Bridged */
515: {"ConnectionStatus", 0|0x80, 3, 18,
516: CONNECTIONSTATUS_MAGICALVALUE }, /* required */
517: /* Allowed Values : Unconfigured / Connecting(opt) / Connected
518: * PendingDisconnect(opt) / Disconnecting (opt)
519: * Disconnected */
520: {"Uptime", 3, 0}, /* Required */
521: {"LastConnectionError", 0, 6, 25}, /* required : */
522: /* Allowed Values : ERROR_NONE(req) / ERROR_COMMAND_ABORTED(opt)
523: * ERROR_NOT_ENABLED_FOR_INTERNET(opt)
524: * ERROR_USER_DISCONNECT(opt)
525: * ERROR_ISP_DISCONNECT(opt)
526: * ERROR_IDLE_DISCONNECT(opt)
527: * ERROR_FORCED_DISCONNECT(opt)
528: * ERROR_NO_CARRIER(opt)
529: * ERROR_IP_CONFIGURATION(opt)
530: * ERROR_UNKNOWN(opt) */
531: {"RSIPAvailable", 1, 4}, /* required */
532: {"NATEnabled", 1, 5}, /* required */
533: {"ExternalIPAddress", 0|0x80, 0, 0,
534: EXTERNALIPADDRESS_MAGICALVALUE}, /* required. Default : empty string */
535: {"PortMappingNumberOfEntries", 2|0x80, 0, 0,
536: PORTMAPPINGNUMBEROFENTRIES_MAGICALVALUE}, /* required >= 0 */
537: {"PortMappingEnabled", 1, 0}, /* Required */
538: /* 10 */
539: {"PortMappingLeaseDuration", 3, 2, 1}, /* required */
540: {"RemoteHost", 0, 0}, /* required. Default : empty string */
541: {"ExternalPort", 2, 0}, /* required */
542: {"InternalPort", 2, 0, 3}, /* required */
543: {"PortMappingProtocol", 0, 0, 11}, /* required allowedValues: TCP/UDP */
544: {"InternalClient", 0, 0}, /* required */
545: {"PortMappingDescription", 0, 0}, /* required default: empty string */
546: /* added in v2 UPnP-gw-WANIPConnection-v2-Service.pdf */
547: #ifdef IGD_V2
548: {"SystemUpdateID", 3|0x80, 0, 0, SYSTEMUPDATEID_MAGICALVALUE},
549: {"A_ARG_TYPE_Manage", 1, 0},
550: {"A_ARG_TYPE_PortListing", 0, 0},
551: #endif
552: {0, 0}
553: };
554:
555: static const struct serviceDesc scpdWANIPCn =
556: { WANIPCnActions, WANIPCnVars };
557:
558: /* WANCfg.xml */
559: /* See UPnP_IGD_WANCommonInterfaceConfig 1.0.pdf */
560:
561: static const struct argument GetCommonLinkPropertiesArgs[] =
562: {
563: {2, 0},
564: {2, 1},
565: {2, 2},
566: {2, 3},
567: {0, 0}
568: };
569:
570: static const struct argument GetTotalBytesSentArgs[] =
571: {
572: {2, 4},
573: {0, 0}
574: };
575:
576: static const struct argument GetTotalBytesReceivedArgs[] =
577: {
578: {2, 5},
579: {0, 0}
580: };
581:
582: static const struct argument GetTotalPacketsSentArgs[] =
583: {
584: {2, 6},
585: {0, 0}
586: };
587:
588: static const struct argument GetTotalPacketsReceivedArgs[] =
589: {
590: {2, 7},
591: {0, 0}
592: };
593:
594: static const struct action WANCfgActions[] =
595: {
596: {"GetCommonLinkProperties", GetCommonLinkPropertiesArgs}, /* Required */
597: {"GetTotalBytesSent", GetTotalBytesSentArgs}, /* optional */
598: {"GetTotalBytesReceived", GetTotalBytesReceivedArgs}, /* optional */
599: {"GetTotalPacketsSent", GetTotalPacketsSentArgs}, /* optional */
600: {"GetTotalPacketsReceived", GetTotalPacketsReceivedArgs}, /* optional */
601: {0, 0}
602: };
603:
604: /* See UPnP_IGD_WANCommonInterfaceConfig 1.0.pdf */
605: static const struct stateVar WANCfgVars[] =
606: {
607: {"WANAccessType", 0, 0, 1},
608: /* Allowed Values : DSL / POTS / Cable / Ethernet
609: * Default value : empty string */
610: {"Layer1UpstreamMaxBitRate", 3, 0},
611: {"Layer1DownstreamMaxBitRate", 3, 0},
612: {"PhysicalLinkStatus", 0|0x80, 0, 6, 6},
613: /* allowed values :
614: * Up / Down / Initializing (optional) / Unavailable (optionnal)
615: * no Default value
616: * Evented */
617: {"TotalBytesSent", 3, 0}, /* Optional */
618: {"TotalBytesReceived", 3, 0}, /* Optional */
619: {"TotalPacketsSent", 3, 0}, /* Optional */
620: {"TotalPacketsReceived", 3, 0},/* Optional */
621: /*{"MaximumActiveConnections", 2, 0}, // allowed Range value // OPTIONAL */
622: /*{"WANAccessProvider", 0, 0},*/ /* Optional */
623: {0, 0}
624: };
625:
626: static const struct serviceDesc scpdWANCfg =
627: { WANCfgActions, WANCfgVars };
628:
629: #ifdef ENABLE_L3F_SERVICE
630: /* Read UPnP_IGD_Layer3Forwarding_1.0.pdf */
631: static const struct argument SetDefaultConnectionServiceArgs[] =
632: {
633: {1, 0}, /* in */
634: {0, 0}
635: };
636:
637: static const struct argument GetDefaultConnectionServiceArgs[] =
638: {
639: {2, 0}, /* out */
640: {0, 0}
641: };
642:
643: static const struct action L3FActions[] =
644: {
645: {"SetDefaultConnectionService", SetDefaultConnectionServiceArgs}, /* Req */
646: {"GetDefaultConnectionService", GetDefaultConnectionServiceArgs}, /* Req */
647: {0, 0}
648: };
649:
650: static const struct stateVar L3FVars[] =
651: {
652: {"DefaultConnectionService", 0|0x80, 0, 0,
653: DEFAULTCONNECTIONSERVICE_MAGICALVALUE}, /* Required */
654: {0, 0}
655: };
656:
657: static const struct serviceDesc scpdL3F =
658: { L3FActions, L3FVars };
659: #endif
660:
661: #ifdef ENABLE_6FC_SERVICE
662: /* see UPnP-gw-WANIPv6FirewallControl-v1-Service.pdf */
663: static const struct argument GetFirewallStatusArgs[] =
664: {
665: {2|0x80, 0}, /* OUT : FirewallEnabled */
666: {2|0x80, 6}, /* OUT : InboundPinholeAllowed */
667: {0, 0}
668: };
669:
670: static const struct argument GetOutboundPinholeTimeoutArgs[] =
671: {
672: {1|0x80|(3<<2), 1}, /* RemoteHost IN A_ARG_TYPE_IPv6Address */
673: {1|0x80|(4<<2), 2}, /* RemotePort IN A_ARG_TYPE_Port */
674: {1|0x80|(5<<2), 1}, /* InternalClient IN A_ARG_TYPE_IPv6Address */
675: {1|0x80|(6<<2), 2}, /* InternalPort IN A_ARG_TYPE_Port */
676: {1|0x80, 3}, /* Protocol IN A_ARG_TYPE_Protocol */
677: {2|0x80, 7}, /* OutboundPinholeTimeout OUT A_ARG_TYPE_OutboundPinholeTimeout */
678: {0, 0}
679: };
680:
681: static const struct argument AddPinholeArgs[] =
682: {
683: {1|0x80|(3<<2), 1}, /* RemoteHost IN A_ARG_TYPE_IPv6Address */
684: {1|0x80|(4<<2), 2}, /* RemotePort IN A_ARG_TYPE_Port */
685: {1|0x80|(5<<2), 1}, /* InternalClient IN A_ARG_TYPE_IPv6Address */
686: {1|0x80|(6<<2), 2}, /* InternalPort IN A_ARG_TYPE_Port */
687: {1|0x80, 3}, /* Protocol IN A_ARG_TYPE_Protocol */
688: {1|0x80, 5}, /* LeaseTime IN A_ARG_TYPE_LeaseTime */
689: {2|0x80, 4}, /* UniqueID OUT A_ARG_TYPE_UniqueID */
690: {0, 0}
691: };
692:
693: static const struct argument UpdatePinholeArgs[] =
694: {
695: {1|0x80, 4}, /* UniqueID IN A_ARG_TYPE_UniqueID */
696: {1, 5}, /* LeaseTime IN A_ARG_TYPE_LeaseTime */
697: {0, 0}
698: };
699:
700: static const struct argument DeletePinholeArgs[] =
701: {
702: {1|0x80, 4}, /* UniqueID IN A_ARG_TYPE_UniqueID */
703: {0, 0}
704: };
705:
706: static const struct argument GetPinholePacketsArgs[] =
707: {
708: {1|0x80, 4}, /* UniqueID IN A_ARG_TYPE_UniqueID */
709: {2|0x80, 9}, /* PinholePackets OUT A_ARG_TYPE_PinholePackets */
710: {0, 0}
711: };
712:
713: static const struct argument CheckPinholeWorkingArgs[] =
714: {
715: {1|0x80, 4}, /* UniqueID IN A_ARG_TYPE_UniqueID */
716: {2|0x80|(7<<2), 8}, /* IsWorking OUT A_ARG_TYPE_Boolean */
717: {0, 0}
718: };
719:
720: static const struct action IPv6FCActions[] =
721: {
722: {"GetFirewallStatus", GetFirewallStatusArgs}, /* Req */
723: {"GetOutboundPinholeTimeout", GetOutboundPinholeTimeoutArgs}, /* Opt */
724: {"AddPinhole", AddPinholeArgs}, /* Req */
725: {"UpdatePinhole", UpdatePinholeArgs}, /* Req */
726: {"DeletePinhole", DeletePinholeArgs}, /* Req */
727: {"GetPinholePackets", GetPinholePacketsArgs}, /* Req */
728: {"CheckPinholeWorking", CheckPinholeWorkingArgs}, /* Opt */
729: {0, 0}
730: };
731:
732: static const struct stateVar IPv6FCVars[] =
733: {
734: {"FirewallEnabled", 1|0x80, 0, 0,
735: FIREWALLENABLED_MAGICALVALUE}, /* Required */
736: {"A_ARG_TYPE_IPv6Address", 0, 0, 0, 0}, /* Required */
737: {"A_ARG_TYPE_Port", 2, 0, 0, 0}, /* Required */
738: {"A_ARG_TYPE_Protocol", 2, 0, 0, 0}, /* Required */
739: /* 4 */
740: {"A_ARG_TYPE_UniqueID", 2, 0, 0, 0}, /* Required */
741: {"A_ARG_TYPE_LeaseTime", 3, 0, 5, 0}, /* Required */
742: {"InboundPinholeAllowed", 1|0x80, 0, 0,
743: INBOUNDPINHOLEALLOWED_MAGICALVALUE}, /* Required */
744: {"A_ARG_TYPE_OutboundPinholeTimeout", 3, 0, 7, 0}, /* Optional */
745: /* 8 */
746: {"A_ARG_TYPE_Boolean", 1, 0, 0, 0}, /* Optional */
747: {"A_ARG_TYPE_PinholePackets", 3, 0, 0, 0}, /* Required */
748: {0, 0}
749: };
750:
751: static const struct serviceDesc scpd6FC =
752: { IPv6FCActions, IPv6FCVars };
753: #endif
754:
755: #ifdef ENABLE_DP_SERVICE
756: /* UPnP-gw-DeviceProtection-v1-Service.pdf */
757:
758: static const struct argument SendSetupMessageArgs[] =
759: {
760: {1|0x80|(8<<2), 6}, /* ProtocolType : in ProtocolType / A_ARG_TYPE_String */
761: {1|0x80|(9<<2), 5}, /* InMessage : in InMessage / A_ARG_TYPE_Base64 */
762: {2|0x80|(10<<2), 5}, /* OutMessage : out OutMessage / A_ARG_TYPE_Base64 */
763: {0, 0}
764: };
765:
766: static const struct argument GetSupportedProtocolsArgs[] =
767: {
768: {2|0x80|(11<<2), 1}, /* ProtocolList : out ProtocolList / SupportedProtocols */
769: {0, 0}
770: };
771:
772: static const struct argument GetAssignedRolesArgs[] =
773: {
774: {2|0x80|(12<<2), 6}, /* RoleList : out RoleList / A_ARG_TYPE_String */
775: {0, 0}
776: };
777:
778: static const struct action DPActions[] =
779: {
780: {"SendSetupMessage", SendSetupMessageArgs},
781: {"GetSupportedProtocols", GetSupportedProtocolsArgs},
782: {"GetAssignedRoles", GetAssignedRolesArgs},
783: {0, 0}
784: };
785:
786: static const struct stateVar DPVars[] =
787: {
788: {"SetupReady", 1|0x80, 0, 0, SETUPREADY_MAGICALVALUE},
789: {"SupportedProtocols", 0},
790: {"A_ARG_TYPE_ACL", 0},
791: {"A_ARG_TYPE_IdentityList", 0},
792: {"A_ARG_TYPE_Identity", 0},
793: {"A_ARG_TYPE_Base64", 4},
794: {"A_ARG_TYPE_String", 0},
795: {0, 0}
796: };
797:
798: static const struct serviceDesc scpdDP =
799: { DPActions, DPVars };
800: #endif
801:
802: /* strcat_str()
803: * concatenate the string and use realloc to increase the
804: * memory buffer if needed. */
805: static char *
806: strcat_str(char * str, int * len, int * tmplen, const char * s2)
807: {
808: int s2len;
809: int newlen;
810: char * p;
811:
812: s2len = (int)strlen(s2);
813: if(*tmplen <= (*len + s2len))
814: {
815: if(s2len < 256)
816: newlen = *tmplen + 256;
817: else
818: newlen = *tmplen + s2len + 1;
819: p = (char *)realloc(str, newlen);
820: if(p == NULL) /* handle a failure of realloc() */
821: {
822: syslog(LOG_ERR, "strcat_str: Failed to realloc %d bytes", newlen);
823: return str;
824: }
825: str = p;
826: *tmplen = newlen;
827: }
828: /*strcpy(str + *len, s2); */
829: memcpy(str + *len, s2, s2len + 1);
830: *len += s2len;
831: return str;
832: }
833:
834: /* strcat_char() :
835: * concatenate a character and use realloc to increase the
836: * size of the memory buffer if needed */
837: static char *
838: strcat_char(char * str, int * len, int * tmplen, char c)
839: {
840: char * p;
841:
842: if(*tmplen <= (*len + 1))
843: {
844: *tmplen += 256;
845: p = (char *)realloc(str, *tmplen);
846: if(p == NULL) /* handle a failure of realloc() */
847: {
848: syslog(LOG_ERR, "strcat_char: Failed to realloc %d bytes", *tmplen);
849: *tmplen -= 256;
850: return str;
851: }
852: str = p;
853: }
854: str[*len] = c;
855: (*len)++;
856: return str;
857: }
858:
859: /* strcat_int()
860: * concatenate the string representation of the integer.
861: * call strcat_char() */
862: static char *
863: strcat_int(char * str, int * len, int * tmplen, int i)
864: {
865: char buf[16];
866: int j;
867:
868: if(i < 0) {
869: str = strcat_char(str, len, tmplen, '-');
870: i = -i;
871: } else if(i == 0) {
872: /* special case for 0 */
873: str = strcat_char(str, len, tmplen, '0');
874: return str;
875: }
876: j = 0;
877: while(i && j < (int)sizeof(buf)) {
878: buf[j++] = '0' + (i % 10);
879: i = i / 10;
880: }
881: while(j > 0) {
882: str = strcat_char(str, len, tmplen, buf[--j]);
883: }
884: return str;
885: }
886:
887: /* iterative subroutine using a small stack
888: * This way, the progam stack usage is kept low */
889: static char *
890: genXML(char * str, int * len, int * tmplen,
891: const struct XMLElt * p,
892: int force_igd1)
893: {
894: #define GENXML_STACK_SIZE 16
895: unsigned short i, j;
896: int top;
897: const char * eltname, *s;
898: char c;
899: struct {
900: unsigned short i;
901: unsigned short j;
902: const char * eltname;
903: } pile[GENXML_STACK_SIZE]; /* stack */
904: #if !defined(IGD_V2)
905: UNUSED(force_igd1);
906: #endif
907:
908: top = -1;
909: i = 0; /* current node */
910: j = 1; /* i + number of nodes*/
911: for(;;)
912: {
913: eltname = p[i].eltname;
914: if(!eltname)
915: return str;
916: if(eltname[0] == '/')
917: {
918: /* leaf node */
919: if(p[i].data && p[i].data[0])
920: {
921: /*printf("<%s>%s<%s>\n", eltname+1, p[i].data, eltname); */
922: str = strcat_char(str, len, tmplen, '<');
923: str = strcat_str(str, len, tmplen, eltname+1);
924: str = strcat_char(str, len, tmplen, '>');
925: #ifdef RANDOMIZE_URLS
926: if(p[i].data[0] == '/')
927: {
928: /* prepend all URL paths with a "random" value */
929: str = strcat_char(str, len, tmplen, '/');
930: str = strcat_str(str, len, tmplen, random_url);
931: }
932: #endif /* RANDOMIZE_URLS */
933: str = strcat_str(str, len, tmplen, p[i].data);
934: #ifdef IGD_V2
935: /* checking a single 'u' saves us 4 strcmp() calls most of the time */
936: if (force_igd1 && (p[i].data[0] == 'u'))
937: {
938: if ((strcmp(p[i].data, DEVICE_TYPE_IGD) == 0) ||
939: (strcmp(p[i].data, DEVICE_TYPE_WAN) == 0) ||
940: (strcmp(p[i].data, DEVICE_TYPE_WANC) == 0) ||
941: (strcmp(p[i].data, SERVICE_TYPE_WANIPC) == 0) )
942: {
943: str[*len - 1] = '1'; /* Change the version number to 1 */
944: }
945: }
946: #endif
947: str = strcat_char(str, len, tmplen, '<');
948: str = strcat_str(str, len, tmplen, eltname);
949: str = strcat_char(str, len, tmplen, '>');
950: }
951: #ifdef IGD_V2
952: unstack:
953: #endif
954: for(;;)
955: {
956: if(top < 0)
957: return str;
958: i = ++(pile[top].i);
959: j = pile[top].j;
960: /*printf(" pile[%d]\t%d %d\n", top, i, j); */
961: if(i==j)
962: {
963: /*printf("</%s>\n", pile[top].eltname); */
964: str = strcat_char(str, len, tmplen, '<');
965: str = strcat_char(str, len, tmplen, '/');
966: s = pile[top].eltname;
967: for(c = *s; c > ' '; c = *(++s))
968: str = strcat_char(str, len, tmplen, c);
969: str = strcat_char(str, len, tmplen, '>');
970: top--;
971: }
972: else
973: break;
974: }
975: }
976: else
977: {
978: unsigned long k = (unsigned long)p[i].data;
979: #ifdef IGD_V2
980: if((force_igd1 && (p[k & 0xffff].eltname[0] == '/')) &&
981: (strcmp(p[k & 0xffff].data, "urn:schemas-upnp-org:service:DeviceProtection:1") == 0 ||
982: strcmp(p[k & 0xffff].data, "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1") == 0)) {
983: /* Skip the child element */
984: goto unstack;
985: }
986: #endif
987: /* node with child(ren) */
988: /*printf("<%s>\n", eltname); */
989: str = strcat_char(str, len, tmplen, '<');
990: str = strcat_str(str, len, tmplen, eltname);
991: if(memcmp(eltname, "root ", 5) == 0) {
992: char configid_str[16];
993: /* add configId attribute, required by UDA 1.1 */
994: snprintf(configid_str, sizeof(configid_str), "\"%u\"", upnp_configid);
995: str = strcat_str(str, len, tmplen, " configId=");
996: str = strcat_str(str, len, tmplen, configid_str);
997: }
998: str = strcat_char(str, len, tmplen, '>');
999: i = k & 0xffff;
1000: j = i + (k >> 16);
1001: if(top < (GENXML_STACK_SIZE - 1)) {
1002: top++;
1003: /*printf(" +pile[%d]\t%d %d\n", top, i, j); */
1004: pile[top].i = i;
1005: pile[top].j = j;
1006: pile[top].eltname = eltname;
1007: #ifdef DEBUG
1008: } else {
1009: fprintf(stderr, "*** GenXML(): stack OVERFLOW ***\n");
1010: #endif /* DEBUG */
1011: }
1012: }
1013: }
1014: }
1015:
1016: /* genRootDesc() :
1017: * - Generate the root description of the UPnP device.
1018: * - the len argument is used to return the length of
1019: * the returned string.
1020: * - tmp_uuid argument is used to build the uuid string */
1021: char *
1022: genRootDesc(int * len, int force_igd1)
1023: {
1024: char * str;
1025: int tmplen;
1026: tmplen = 2048;
1027: str = (char *)malloc(tmplen);
1028: if(str == NULL)
1029: return NULL;
1030: * len = strlen(xmlver);
1031: /*strcpy(str, xmlver); */
1032: memcpy(str, xmlver, *len + 1);
1033: str = genXML(str, len, &tmplen, rootDesc, force_igd1);
1034: str[*len] = '\0';
1035: return str;
1036: }
1037:
1038: /* genServiceDesc() :
1039: * Generate service description with allowed methods and
1040: * related variables. */
1041: static char *
1042: genServiceDesc(int * len, const struct serviceDesc * s, int force_igd1)
1043: {
1044: int i, j;
1045: const struct action * acts;
1046: const struct stateVar * vars;
1047: const struct argument * args;
1048: char * str;
1049: int tmplen;
1050: #if !defined(IGD_V2)
1051: UNUSED(force_igd1);
1052: #endif
1053:
1054: tmplen = 2048;
1055: str = (char *)malloc(tmplen);
1056: if(str == NULL)
1057: return NULL;
1058: /*strcpy(str, xmlver); */
1059: *len = strlen(xmlver);
1060: memcpy(str, xmlver, *len + 1);
1061:
1062: acts = s->actionList;
1063: vars = s->serviceStateTable;
1064:
1065: str = strcat_char(str, len, &tmplen, '<');
1066: str = strcat_str(str, len, &tmplen, root_service);
1067: str = strcat_char(str, len, &tmplen, '>');
1068:
1069: str = strcat_str(str, len, &tmplen,
1070: "<specVersion><major>" UPNP_VERSION_MAJOR_STR "</major>"
1071: "<minor>" UPNP_VERSION_MINOR_STR "</minor></specVersion>");
1072:
1073: i = 0;
1074: str = strcat_str(str, len, &tmplen, "<actionList>");
1075: while(acts[i].name)
1076: {
1077: #if defined(IGD_V2)
1078: /* fake a IGD v1 for Microsoft clients :
1079: * no DeletePortMappingRange, GetListOfPortMappings, AddAnyPortMapping */
1080: if (force_igd1 && strcmp(acts[i].name, "DeletePortMappingRange") == 0)
1081: break;
1082: #endif
1083: str = strcat_str(str, len, &tmplen, "<action><name>");
1084: str = strcat_str(str, len, &tmplen, acts[i].name);
1085: str = strcat_str(str, len, &tmplen, "</name>");
1086: /* argument List */
1087: args = acts[i].args;
1088: if(args)
1089: {
1090: str = strcat_str(str, len, &tmplen, "<argumentList>");
1091: j = 0;
1092: while(args[j].dir)
1093: {
1094: const char * p;
1095: size_t plen;
1096: str = strcat_str(str, len, &tmplen, "<argument><name>");
1097: if((args[j].dir & 0x80) == 0) {
1098: str = strcat_str(str, len, &tmplen, "New");
1099: }
1100: p = vars[args[j].relatedVar].name;
1101: plen = strlen(p);
1102: if(args[j].dir & 0x7c) {
1103: /* use magic values ... */
1104: str = strcat_str(str, len, &tmplen, magicargname[(args[j].dir & 0x7c) >> 2]);
1105: } else if(plen >= 11 && 0 == memcmp(p, "PortMapping", 11)
1106: && (plen < 22 || 0 != memcmp(p + 11, "Description", 11))) {
1107: if(plen >= (11+15) && 0 == memcmp(p + 11, "NumberOfEntries", 15)) {
1108: /* PortMappingNumberOfEntries */
1109: #ifdef IGD_V2
1110: if(0 == memcmp(acts[i].name, "GetListOfPortMappings", 22)) {
1111: str = strcat_str(str, len, &tmplen, "NumberOfPorts");
1112: } else {
1113: str = strcat_str(str, len, &tmplen, "PortMappingIndex");
1114: }
1115: #else
1116: str = strcat_str(str, len, &tmplen, "PortMappingIndex");
1117: #endif
1118: } else {
1119: /* PortMappingEnabled
1120: * PortMappingLeaseDuration
1121: * PortMappingProtocol */
1122: str = strcat_str(str, len, &tmplen, p + 11);
1123: }
1124: #ifdef IGD_V2
1125: } else if(plen >= 11 && 0 == memcmp(p, "A_ARG_TYPE_", 11)) {
1126: str = strcat_str(str, len, &tmplen, p + 11);
1127: } else if(plen >= 13 && 0 == memcmp(p, "ExternalPort", 13)
1128: && args[j].dir == 2
1129: && 0 == memcmp(acts[i].name, "AddAnyPortMapping", 18)) {
1130: str = strcat_str(str, len, &tmplen, "ReservedPort");
1131: #endif
1132: } else {
1133: str = strcat_str(str, len, &tmplen, p);
1134: }
1135: str = strcat_str(str, len, &tmplen, "</name><direction>");
1136: str = strcat_str(str, len, &tmplen, (args[j].dir&0x03)==1?"in":"out");
1137: str = strcat_str(str, len, &tmplen,
1138: "</direction><relatedStateVariable>");
1139: str = strcat_str(str, len, &tmplen, p);
1140: str = strcat_str(str, len, &tmplen,
1141: "</relatedStateVariable></argument>");
1142: j++;
1143: }
1144: str = strcat_str(str, len, &tmplen,"</argumentList>");
1145: }
1146: str = strcat_str(str, len, &tmplen, "</action>");
1147: /*str = strcat_char(str, len, &tmplen, '\n'); // TEMP ! */
1148: i++;
1149: }
1150: str = strcat_str(str, len, &tmplen, "</actionList><serviceStateTable>");
1151: i = 0;
1152: while(vars[i].name)
1153: {
1154: str = strcat_str(str, len, &tmplen,
1155: "<stateVariable sendEvents=\"");
1156: #ifdef ENABLE_EVENTS
1157: str = strcat_str(str, len, &tmplen, (vars[i].itype & 0x80)?"yes":"no");
1158: #else
1159: /* for the moment always send no. Wait for SUBSCRIBE implementation
1160: * before setting it to yes */
1161: str = strcat_str(str, len, &tmplen, "no");
1162: #endif
1163: str = strcat_str(str, len, &tmplen, "\"><name>");
1164: str = strcat_str(str, len, &tmplen, vars[i].name);
1165: str = strcat_str(str, len, &tmplen, "</name><dataType>");
1166: str = strcat_str(str, len, &tmplen, upnptypes[vars[i].itype & 0x0f]);
1167: str = strcat_str(str, len, &tmplen, "</dataType>");
1168: /*if(vars[i].defaultValue) */
1169: if(vars[i].idefault)
1170: {
1171: str = strcat_str(str, len, &tmplen, "<defaultValue>");
1172: /*str = strcat_str(str, len, &tmplen, vars[i].defaultValue); */
1173: str = strcat_str(str, len, &tmplen, upnpdefaultvalues[vars[i].idefault]);
1174: str = strcat_str(str, len, &tmplen, "</defaultValue>");
1175: }
1176: if(vars[i].iallowedlist)
1177: {
1178: if((vars[i].itype & 0x0f) == 0)
1179: {
1180: /* string */
1181: str = strcat_str(str, len, &tmplen, "<allowedValueList>");
1182: for(j=vars[i].iallowedlist; upnpallowedvalues[j]; j++)
1183: {
1184: str = strcat_str(str, len, &tmplen, "<allowedValue>");
1185: str = strcat_str(str, len, &tmplen, upnpallowedvalues[j]);
1186: str = strcat_str(str, len, &tmplen, "</allowedValue>");
1187: }
1188: str = strcat_str(str, len, &tmplen, "</allowedValueList>");
1189: } else {
1190: /* ui2 and ui4 */
1191: str = strcat_str(str, len, &tmplen, "<allowedValueRange><minimum>");
1192: str = strcat_int(str, len, &tmplen, upnpallowedranges[vars[i].iallowedlist]);
1193: str = strcat_str(str, len, &tmplen, "</minimum><maximum>");
1194: str = strcat_int(str, len, &tmplen, upnpallowedranges[vars[i].iallowedlist+1]);
1195: str = strcat_str(str, len, &tmplen, "</maximum></allowedValueRange>");
1196: }
1197: }
1198: str = strcat_str(str, len, &tmplen, "</stateVariable>");
1199: /*str = strcat_char(str, len, &tmplen, '\n'); // TEMP ! */
1200: i++;
1201: }
1202: str = strcat_str(str, len, &tmplen, "</serviceStateTable></scpd>");
1203: str[*len] = '\0';
1204: return str;
1205: }
1206:
1207: /* genWANIPCn() :
1208: * Generate the WANIPConnection xml description */
1209: char *
1210: genWANIPCn(int * len, int force_igd1)
1211: {
1212: return genServiceDesc(len, &scpdWANIPCn, force_igd1);
1213: }
1214:
1215: /* genWANCfg() :
1216: * Generate the WANInterfaceConfig xml description. */
1217: char *
1218: genWANCfg(int * len, int force_igd1)
1219: {
1220: return genServiceDesc(len, &scpdWANCfg, force_igd1);
1221: }
1222:
1223: #ifdef ENABLE_L3F_SERVICE
1224: char *
1225: genL3F(int * len, int force_igd1)
1226: {
1227: return genServiceDesc(len, &scpdL3F, force_igd1);
1228: }
1229: #endif
1230:
1231: #ifdef ENABLE_6FC_SERVICE
1232: char *
1233: gen6FC(int * len, int force_igd1)
1234: {
1235: return genServiceDesc(len, &scpd6FC, force_igd1);
1236: }
1237: #endif
1238:
1239: #ifdef ENABLE_DP_SERVICE
1240: char *
1241: genDP(int * len, int force_igd1)
1242: {
1243: return genServiceDesc(len, &scpdDP, force_igd1);
1244: }
1245: #endif
1246:
1247: #ifdef ENABLE_EVENTS
1248: static char *
1249: genEventVars(int * len, const struct serviceDesc * s)
1250: {
1251: char tmp[16];
1252: const struct stateVar * v;
1253: char * str;
1254: int tmplen;
1255: tmplen = 512;
1256: str = (char *)malloc(tmplen);
1257: if(str == NULL)
1258: return NULL;
1259: *len = 0;
1260: v = s->serviceStateTable;
1261: str = strcat_str(str, len, &tmplen, "<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\">");
1262: while(v->name) {
1263: if(v->itype & 0x80) {
1264: str = strcat_str(str, len, &tmplen, "<e:property><");
1265: str = strcat_str(str, len, &tmplen, v->name);
1266: str = strcat_str(str, len, &tmplen, ">");
1267: /*printf("<e:property><%s>", v->name);*/
1268: switch(v->ieventvalue) {
1269: case 0:
1270: break;
1271: #ifdef ENABLE_DP_SERVICE
1272: case SETUPREADY_MAGICALVALUE:
1273: /* always ready for setup */
1274: snprintf(tmp, sizeof(tmp), "%d", 1);
1275: str = strcat_str(str, len, &tmplen, tmp);
1276: break;
1277: #endif
1278: case CONNECTIONSTATUS_MAGICALVALUE:
1279: /* or get_wan_connection_status_str(ext_if_name) */
1280: str = strcat_str(str, len, &tmplen,
1281: upnpallowedvalues[18 + get_wan_connection_status(ext_if_name)]);
1282: break;
1283: #ifdef ENABLE_6FC_SERVICE
1284: case FIREWALLENABLED_MAGICALVALUE:
1285: /* see 2.4.2 of UPnP-gw-WANIPv6FirewallControl-v1-Service.pdf */
1286: snprintf(tmp, sizeof(tmp), "%d",
1287: GETFLAG(IPV6FCFWDISABLEDMASK) ? 0 : 1);
1288: str = strcat_str(str, len, &tmplen, tmp);
1289: break;
1290: case INBOUNDPINHOLEALLOWED_MAGICALVALUE:
1291: /* see 2.4.3 of UPnP-gw-WANIPv6FirewallControl-v1-Service.pdf */
1292: snprintf(tmp, sizeof(tmp), "%d",
1293: GETFLAG(IPV6FCINBOUNDDISALLOWEDMASK) ? 0 : 1);
1294: str = strcat_str(str, len, &tmplen, tmp);
1295: break;
1296: #endif
1297: #ifdef IGD_V2
1298: case SYSTEMUPDATEID_MAGICALVALUE:
1299: /* Please read section 2.3.23 SystemUpdateID
1300: * of UPnP-gw-WANIPConnection-v2-Service.pdf */
1301: snprintf(tmp, sizeof(tmp), "%d",
1302: 1/* system update id */);
1303: str = strcat_str(str, len, &tmplen, tmp);
1304: break;
1305: #endif
1306: case PORTMAPPINGNUMBEROFENTRIES_MAGICALVALUE:
1307: /* Port mapping number of entries magical value */
1308: snprintf(tmp, sizeof(tmp), "%d",
1309: upnp_get_portmapping_number_of_entries());
1310: str = strcat_str(str, len, &tmplen, tmp);
1311: break;
1312: case EXTERNALIPADDRESS_MAGICALVALUE:
1313: /* External ip address magical value */
1314: if(use_ext_ip_addr)
1315: str = strcat_str(str, len, &tmplen, use_ext_ip_addr);
1316: else {
1317: struct in_addr addr;
1318: char ext_ip_addr[INET_ADDRSTRLEN];
1319: if(getifaddr(ext_if_name, ext_ip_addr, INET_ADDRSTRLEN, &addr, NULL) < 0 || addr_is_reserved(&addr)) {
1320: str = strcat_str(str, len, &tmplen, "0.0.0.0");
1321: } else {
1322: str = strcat_str(str, len, &tmplen, ext_ip_addr);
1323: }
1324: }
1325: break;
1326: case DEFAULTCONNECTIONSERVICE_MAGICALVALUE:
1327: /* DefaultConnectionService magical value */
1328: str = strcat_str(str, len, &tmplen, uuidvalue_wcd);
1329: #ifdef IGD_V2
1330: str = strcat_str(str, len, &tmplen, ":WANConnectionDevice:2,urn:upnp-org:serviceId:WANIPConn1");
1331: #else
1332: str = strcat_str(str, len, &tmplen, ":WANConnectionDevice:1,urn:upnp-org:serviceId:WANIPConn1");
1333: #endif
1334: break;
1335: default:
1336: str = strcat_str(str, len, &tmplen, upnpallowedvalues[v->ieventvalue]);
1337: }
1338: str = strcat_str(str, len, &tmplen, "</");
1339: str = strcat_str(str, len, &tmplen, v->name);
1340: str = strcat_str(str, len, &tmplen, "></e:property>");
1341: /*printf("</%s></e:property>\n", v->name);*/
1342: }
1343: v++;
1344: }
1345: str = strcat_str(str, len, &tmplen, "</e:propertyset>");
1346: #if 0
1347: printf("</e:propertyset>\n");
1348: printf("\n");
1349: printf("%d\n", tmplen);
1350: #endif
1351: str[*len] = '\0';
1352: return str;
1353: }
1354:
1355: char *
1356: getVarsWANIPCn(int * l)
1357: {
1358: return genEventVars(l,
1359: &scpdWANIPCn);
1360: }
1361:
1362: char *
1363: getVarsWANCfg(int * l)
1364: {
1365: return genEventVars(l,
1366: &scpdWANCfg);
1367: }
1368:
1369: #ifdef ENABLE_L3F_SERVICE
1370: char *
1371: getVarsL3F(int * l)
1372: {
1373: return genEventVars(l,
1374: &scpdL3F);
1375: }
1376: #endif
1377:
1378: #ifdef ENABLE_6FC_SERVICE
1379: char *
1380: getVars6FC(int * l)
1381: {
1382: return genEventVars(l,
1383: &scpd6FC);
1384: }
1385: #endif
1386:
1387: #ifdef ENABLE_DP_SERVICE
1388: char *
1389: getVarsDP(int * l)
1390: {
1391: return genEventVars(l,
1392: &scpdDP);
1393: }
1394: #endif
1395:
1396: #endif /* ENABLE_EVENTS */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>