File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / miniupnpd / upnpdescgen.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Jul 22 00:32:35 2013 UTC (11 years, 5 months ago) by misho
Branches: miniupnpd, elwix, MAIN
CVS tags: v1_8p0, v1_8, HEAD
1.8

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>