Annotation of embedaddon/miniupnpd/upnpdescgen.c, revision 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>