File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / miniupnpd / upnpdescgen.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:55:57 2012 UTC (12 years, 2 months ago) by misho
Branches: miniupnpd, elwix, MAIN
CVS tags: v1_6elwix, HEAD
miniupnpd 1.6+patches

    1: /* $Id: upnpdescgen.c,v 1.1.1.2 2012/05/29 12:55:57 misho Exp $ */
    2: /* MiniUPnP project
    3:  * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
    4:  * (c) 2006-2011 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", 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},
  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},
  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*/
  433: 	/*GetIdleDisconnectTime*/
  434: 	/*GetWarnDisconnectDelay*/
  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: static const struct stateVar WANIPCnVars[] =
  470: {
  471: /* 0 */
  472: #if 0
  473: 	{"ConnectionType", 0, 0/*1*/}, /* required */
  474: 	{"PossibleConnectionTypes", 0|0x80, 0, 14, 15},
  475: #endif
  476: 	{"ConnectionType", 0, 1, 14, 15}, /* required */
  477: 	{"PossibleConnectionTypes", 0|0x80, 0, 0, 15},
  478: 	 /* Required
  479: 	  * Allowed values : Unconfigured / IP_Routed / IP_Bridged */
  480: 	{"ConnectionStatus", 0|0x80, 0/*1*/, 18,
  481: 	 CONNECTIONSTATUS_MAGICALVALUE }, /* required */
  482: 	 /* Allowed Values : Unconfigured / Connecting(opt) / Connected
  483: 	  *                  PendingDisconnect(opt) / Disconnecting (opt)
  484: 	  *                  Disconnected */
  485: 	{"Uptime", 3, 0},	/* Required */
  486: 	{"LastConnectionError", 0, 0, 25},	/* required : */
  487: 	 /* Allowed Values : ERROR_NONE(req) / ERROR_COMMAND_ABORTED(opt)
  488: 	  *                  ERROR_NOT_ENABLED_FOR_INTERNET(opt)
  489: 	  *                  ERROR_USER_DISCONNECT(opt)
  490: 	  *                  ERROR_ISP_DISCONNECT(opt)
  491: 	  *                  ERROR_IDLE_DISCONNECT(opt)
  492: 	  *                  ERROR_FORCED_DISCONNECT(opt)
  493: 	  *                  ERROR_NO_CARRIER(opt)
  494: 	  *                  ERROR_IP_CONFIGURATION(opt)
  495: 	  *                  ERROR_UNKNOWN(opt) */
  496: 	{"RSIPAvailable", 1, 0}, /* required */
  497: 	{"NATEnabled", 1, 0},    /* required */
  498: 	{"ExternalIPAddress", 0|0x80, 0, 0,
  499: 	 EXTERNALIPADDRESS_MAGICALVALUE}, /* required. Default : empty string */
  500: 	{"PortMappingNumberOfEntries", 2|0x80, 0, 0,
  501: 	 PORTMAPPINGNUMBEROFENTRIES_MAGICALVALUE}, /* required >= 0 */
  502: 	{"PortMappingEnabled", 1, 0}, /* Required */
  503: /* 10 */
  504: 	{"PortMappingLeaseDuration", 3, 2, 1}, /* required */
  505: 	/* TODO : for IGD v2 : 
  506: 	 * <stateVariable sendEvents="no">
  507: 	 *   <name>PortMappingLeaseDuration</name>
  508: 	 *   <dataType>ui4</dataType>
  509: 	 *   <defaultValue>Vendor-defined</defaultValue>
  510: 	 *   <allowedValueRange>
  511: 	 *      <minimum>0</minimum>
  512: 	 *      <maximum>604800</maximum>
  513: 	 *   </allowedValueRange>
  514: 	 * </stateVariable> */
  515: 	{"RemoteHost", 0, 0},   /* required. Default : empty string */
  516: 	{"ExternalPort", 2, 0}, /* required */
  517: 	{"InternalPort", 2, 0, 3}, /* required */
  518: 	{"PortMappingProtocol", 0, 0, 11}, /* required allowedValues: TCP/UDP */
  519: 	{"InternalClient", 0, 0}, /* required */
  520: 	{"PortMappingDescription", 0, 0}, /* required default: empty string */
  521: /* added in v2 UPnP-gw-WANIPConnection-v2-Service.pdf */
  522: #ifdef IGD_V2
  523: 	{"SystemUpdateID", 3|0x80, 0, 0, SYSTEMUPDATEID_MAGICALVALUE},
  524: 	{"A_ARG_TYPE_Manage", 1, 0},
  525: 	{"A_ARG_TYPE_PortListing", 0, 0},
  526: #endif
  527: 	{0, 0}
  528: };
  529: 
  530: static const struct serviceDesc scpdWANIPCn =
  531: { WANIPCnActions, WANIPCnVars };
  532: 
  533: /* WANCfg.xml */
  534: /* See UPnP_IGD_WANCommonInterfaceConfig 1.0.pdf */
  535: 
  536: static const struct argument GetCommonLinkPropertiesArgs[] =
  537: {
  538: 	{2, 0},
  539: 	{2, 1},
  540: 	{2, 2},
  541: 	{2, 3},
  542: 	{0, 0}
  543: };
  544: 
  545: static const struct argument GetTotalBytesSentArgs[] =
  546: {
  547: 	{2, 4},
  548: 	{0, 0}
  549: };
  550: 
  551: static const struct argument GetTotalBytesReceivedArgs[] =
  552: {
  553: 	{2, 5},
  554: 	{0, 0}
  555: };
  556: 
  557: static const struct argument GetTotalPacketsSentArgs[] =
  558: {
  559: 	{2, 6},
  560: 	{0, 0}
  561: };
  562: 
  563: static const struct argument GetTotalPacketsReceivedArgs[] =
  564: {
  565: 	{2, 7},
  566: 	{0, 0}
  567: };
  568: 
  569: static const struct action WANCfgActions[] =
  570: {
  571: 	{"GetCommonLinkProperties", GetCommonLinkPropertiesArgs}, /* Required */
  572: 	{"GetTotalBytesSent", GetTotalBytesSentArgs},             /* optional */
  573: 	{"GetTotalBytesReceived", GetTotalBytesReceivedArgs},     /* optional */
  574: 	{"GetTotalPacketsSent", GetTotalPacketsSentArgs},         /* optional */
  575: 	{"GetTotalPacketsReceived", GetTotalPacketsReceivedArgs}, /* optional */
  576: 	{0, 0}
  577: };
  578: 
  579: /* See UPnP_IGD_WANCommonInterfaceConfig 1.0.pdf */
  580: static const struct stateVar WANCfgVars[] =
  581: {
  582: 	{"WANAccessType", 0, 0, 1},
  583: 	/* Allowed Values : DSL / POTS / Cable / Ethernet 
  584: 	 * Default value : empty string */
  585: 	{"Layer1UpstreamMaxBitRate", 3, 0},
  586: 	{"Layer1DownstreamMaxBitRate", 3, 0},
  587: 	{"PhysicalLinkStatus", 0|0x80, 0, 6, 6},
  588: 	/*  allowed values : 
  589: 	 *      Up / Down / Initializing (optional) / Unavailable (optionnal)
  590: 	 *  no Default value 
  591: 	 *  Evented */
  592: 	{"TotalBytesSent", 3, 0},	   /* Optional */
  593: 	{"TotalBytesReceived", 3, 0},  /* Optional */
  594: 	{"TotalPacketsSent", 3, 0},    /* Optional */
  595: 	{"TotalPacketsReceived", 3, 0},/* Optional */
  596: 	/*{"MaximumActiveConnections", 2, 0},	// allowed Range value // OPTIONAL */
  597: 	/*{"WANAccessProvider", 0, 0},*/   /* Optional */
  598: 	{0, 0}
  599: };
  600: 
  601: static const struct serviceDesc scpdWANCfg =
  602: { WANCfgActions, WANCfgVars };
  603: 
  604: #ifdef ENABLE_L3F_SERVICE
  605: /* Read UPnP_IGD_Layer3Forwarding_1.0.pdf */
  606: static const struct argument SetDefaultConnectionServiceArgs[] =
  607: {
  608: 	{1, 0}, /* in */
  609: 	{0, 0}
  610: };
  611: 
  612: static const struct argument GetDefaultConnectionServiceArgs[] =
  613: {
  614: 	{2, 0}, /* out */
  615: 	{0, 0}
  616: };
  617: 
  618: static const struct action L3FActions[] =
  619: {
  620: 	{"SetDefaultConnectionService", SetDefaultConnectionServiceArgs}, /* Req */
  621: 	{"GetDefaultConnectionService", GetDefaultConnectionServiceArgs}, /* Req */
  622: 	{0, 0}
  623: };
  624: 
  625: static const struct stateVar L3FVars[] =
  626: {
  627: 	{"DefaultConnectionService", 0|0x80, 0, 0,
  628: 	 DEFAULTCONNECTIONSERVICE_MAGICALVALUE}, /* Required */
  629: 	{0, 0}
  630: };
  631: 
  632: static const struct serviceDesc scpdL3F =
  633: { L3FActions, L3FVars };
  634: #endif
  635: 
  636: #ifdef ENABLE_6FC_SERVICE
  637: /* see UPnP-gw-WANIPv6FirewallControl-v1-Service.pdf */
  638: static const struct argument GetFirewallStatusArgs[] =
  639: {
  640: 	{2|0x80, 0}, /* OUT : FirewallEnabled */
  641: 	{2|0x80, 6}, /* OUT : InboundPinholeAllowed */
  642: 	{0, 0}
  643: };
  644: 
  645: static const struct argument GetOutboundPinholeTimeoutArgs[] =
  646: {
  647: 	{1|0x80|(3<<2), 1}, /* RemoteHost IN A_ARG_TYPE_IPv6Address */
  648: 	{1|0x80|(4<<2), 2}, /* RemotePort IN A_ARG_TYPE_Port */
  649: 	{1|0x80|(5<<2), 1}, /* InternalClient IN A_ARG_TYPE_IPv6Address */
  650: 	{1|0x80|(6<<2), 2}, /* InternalPort IN A_ARG_TYPE_Port */
  651: 	{1|0x80, 3}, /* Protocol IN A_ARG_TYPE_Protocol */
  652: 	{2|0x80, 7}, /* OutboundPinholeTimeout OUT A_ARG_TYPE_OutboundPinholeTimeout */
  653: 	{0, 0}
  654: };
  655: 
  656: static const struct argument AddPinholeArgs[] =
  657: {
  658: 	{1|0x80|(3<<2), 1}, /* RemoteHost IN A_ARG_TYPE_IPv6Address */
  659: 	{1|0x80|(4<<2), 2}, /* RemotePort IN A_ARG_TYPE_Port */
  660: 	{1|0x80|(5<<2), 1}, /* InternalClient IN A_ARG_TYPE_IPv6Address */
  661: 	{1|0x80|(6<<2), 2}, /* InternalPort IN A_ARG_TYPE_Port */
  662: 	{1|0x80, 3}, /* Protocol IN A_ARG_TYPE_Protocol */
  663: 	{1|0x80, 5}, /* LeaseTime IN A_ARG_TYPE_LeaseTime */
  664: 	{2|0x80, 4}, /* UniqueID OUT A_ARG_TYPE_UniqueID */
  665: 	{0, 0}
  666: };
  667: 
  668: static const struct argument UpdatePinholeArgs[] =
  669: {
  670: 	{1|0x80, 4}, /* UniqueID IN A_ARG_TYPE_UniqueID */
  671: 	{1, 5}, /* LeaseTime IN A_ARG_TYPE_LeaseTime */
  672: 	{0, 0}
  673: };
  674: 
  675: static const struct argument DeletePinholeArgs[] =
  676: {
  677: 	{1|0x80, 4}, /* UniqueID IN A_ARG_TYPE_UniqueID */
  678: 	{0, 0}
  679: };
  680: 
  681: static const struct argument GetPinholePacketsArgs[] =
  682: {
  683: 	{1|0x80, 4}, /* UniqueID IN A_ARG_TYPE_UniqueID */
  684: 	{2|0x80, 9}, /* PinholePackets OUT A_ARG_TYPE_PinholePackets */
  685: 	{0, 0}
  686: };
  687: 
  688: static const struct argument CheckPinholeWorkingArgs[] =
  689: {
  690: 	{1|0x80, 4}, /* UniqueID IN A_ARG_TYPE_UniqueID */
  691: 	{2|0x80|(7<<2), 8}, /* IsWorking OUT A_ARG_TYPE_Boolean */
  692: 	{0, 0}
  693: };
  694: 
  695: static const struct action IPv6FCActions[] =
  696: {
  697: 	{"GetFirewallStatus", GetFirewallStatusArgs}, /* Req */
  698: 	{"GetOutboundPinholeTimeout", GetOutboundPinholeTimeoutArgs}, /* Opt */
  699: 	{"AddPinhole", AddPinholeArgs}, /* Req */
  700: 	{"UpdatePinhole", UpdatePinholeArgs}, /* Req */
  701: 	{"DeletePinhole", DeletePinholeArgs}, /* Req */
  702: 	{"GetPinholePackets", GetPinholePacketsArgs}, /* Req */
  703: 	{"CheckPinholeWorking", CheckPinholeWorkingArgs}, /* Opt */
  704: 	{0, 0}
  705: };
  706: 
  707: static const struct stateVar IPv6FCVars[] =
  708: {
  709: 	{"FirewallEnabled", 1|0x80, 0, 0,
  710: 	 FIREWALLENABLED_MAGICALVALUE}, /* Required */
  711: 	{"A_ARG_TYPE_IPv6Address", 0, 0, 0, 0}, /* Required */
  712: 	{"A_ARG_TYPE_Port", 2, 0, 0, 0}, /* Required */
  713: 	{"A_ARG_TYPE_Protocol", 2, 0, 0, 0}, /* Required */
  714: /* 4 */
  715: 	{"A_ARG_TYPE_UniqueID", 2, 0, 0, 0}, /* Required */
  716: 	{"A_ARG_TYPE_LeaseTime", 3, 0, 5, 0}, /* Required */
  717: 	{"InboundPinholeAllowed", 1|0x80, 0, 0,
  718: 	 INBOUNDPINHOLEALLOWED_MAGICALVALUE}, /* Required */
  719: 	{"A_ARG_TYPE_OutboundPinholeTimeout", 3, 0, 7, 0}, /* Optional */
  720: /* 8 */
  721: 	{"A_ARG_TYPE_Boolean", 1, 0, 0, 0}, /* Optional */
  722: 	{"A_ARG_TYPE_PinholePackets", 3, 0, 0, 0}, /* Required */
  723: 	{0, 0}
  724: };
  725: 
  726: static const struct serviceDesc scpd6FC =
  727: { IPv6FCActions, IPv6FCVars };
  728: #endif
  729: 
  730: #ifdef ENABLE_DP_SERVICE
  731: /* UPnP-gw-DeviceProtection-v1-Service.pdf */
  732: static const struct action DPActions[] =
  733: {
  734: 	{"SendSetupMessage", 0},
  735: 	{"GetSupportedProtocols", 0},
  736: 	{"GetAssignedRoles", 0},
  737: 	{0, 0}
  738: };
  739: 
  740: static const struct stateVar DPVars[] =
  741: {
  742: 	{"SetupReady", 1|0x80},
  743: 	{"SupportedProtocols", 0},
  744: 	{"A_ARG_TYPE_ACL", 0},
  745: 	{"A_ARG_TYPE_IdentityList", 0},
  746: 	{"A_ARG_TYPE_Identity", 0},
  747: 	{"A_ARG_TYPE_Base64", 4},
  748: 	{"A_ARG_TYPE_String", 0},
  749: 	{0, 0}
  750: };
  751: 
  752: static const struct serviceDesc scpdDP =
  753: { DPActions, DPVars };
  754: #endif
  755: 
  756: /* strcat_str()
  757:  * concatenate the string and use realloc to increase the
  758:  * memory buffer if needed. */
  759: static char *
  760: strcat_str(char * str, int * len, int * tmplen, const char * s2)
  761: {
  762: 	int s2len;
  763: 	int newlen;
  764: 	char * p;
  765: 
  766: 	s2len = (int)strlen(s2);
  767: 	if(*tmplen <= (*len + s2len))
  768: 	{
  769: 		if(s2len < 256)
  770: 			newlen = *tmplen + 256;
  771: 		else
  772: 			newlen = *tmplen + s2len + 1;
  773: 		p = (char *)realloc(str, newlen);
  774: 		if(p == NULL) /* handle a failure of realloc() */
  775: 			return str;
  776: 		str = p;
  777: 		*tmplen = newlen;
  778: 	}
  779: 	/*strcpy(str + *len, s2); */
  780: 	memcpy(str + *len, s2, s2len + 1);
  781: 	*len += s2len;
  782: 	return str;
  783: }
  784: 
  785: /* strcat_char() :
  786:  * concatenate a character and use realloc to increase the
  787:  * size of the memory buffer if needed */
  788: static char *
  789: strcat_char(char * str, int * len, int * tmplen, char c)
  790: {
  791: 	char * p;
  792: 
  793: 	if(*tmplen <= (*len + 1))
  794: 	{
  795: 		*tmplen += 256;
  796: 		p = (char *)realloc(str, *tmplen);
  797: 		if(p == NULL) /* handle a failure of realloc() */
  798: 		{
  799: 			*tmplen -= 256;
  800: 			return str;
  801: 		}
  802: 		str = p;
  803: 	}
  804: 	str[*len] = c;
  805: 	(*len)++;
  806: 	return str;
  807: }
  808: 
  809: /* strcat_int()
  810:  * concatenate the string representation of the integer.
  811:  * call strcat_char() */
  812: static char *
  813: strcat_int(char * str, int * len, int * tmplen, int i)
  814: {
  815: 	char buf[16];
  816: 	int j;
  817: 
  818: 	if(i < 0) {
  819: 		str = strcat_char(str, len, tmplen, '-');
  820: 		i = -i;
  821: 	} else if(i == 0) {
  822: 		/* special case for 0 */
  823: 		str = strcat_char(str, len, tmplen, '0');
  824: 		return str;
  825: 	}
  826: 	j = 0;
  827: 	while(i && j < sizeof(buf)) {
  828: 		buf[j++] = '0' + (i % 10);
  829: 		i = i / 10;
  830: 	}
  831: 	while(j > 0) {
  832: 		str = strcat_char(str, len, tmplen, buf[--j]);
  833: 	}
  834: 	return str;
  835: }
  836: 
  837: /* iterative subroutine using a small stack
  838:  * This way, the progam stack usage is kept low */
  839: static char *
  840: genXML(char * str, int * len, int * tmplen,
  841:                    const struct XMLElt * p)
  842: {
  843: 	unsigned short i, j;
  844: 	unsigned long k;
  845: 	int top;
  846: 	const char * eltname, *s;
  847: 	char c;
  848: 	struct {
  849: 		unsigned short i;
  850: 		unsigned short j;
  851: 		const char * eltname;
  852: 	} pile[16]; /* stack */
  853: 	top = -1;
  854: 	i = 0;	/* current node */
  855: 	j = 1;	/* i + number of nodes*/
  856: 	for(;;)
  857: 	{
  858: 		eltname = p[i].eltname;
  859: 		if(!eltname)
  860: 			return str;
  861: 		if(eltname[0] == '/')
  862: 		{
  863: 			if(p[i].data && p[i].data[0])
  864: 			{
  865: 				/*printf("<%s>%s<%s>\n", eltname+1, p[i].data, eltname); */
  866: 				str = strcat_char(str, len, tmplen, '<');
  867: 				str = strcat_str(str, len, tmplen, eltname+1);
  868: 				str = strcat_char(str, len, tmplen, '>');
  869: 				str = strcat_str(str, len, tmplen, p[i].data);
  870: 				str = strcat_char(str, len, tmplen, '<');
  871: 				str = strcat_str(str, len, tmplen, eltname);
  872: 				str = strcat_char(str, len, tmplen, '>');
  873: 			}
  874: 			for(;;)
  875: 			{
  876: 				if(top < 0)
  877: 					return str;
  878: 				i = ++(pile[top].i);
  879: 				j = pile[top].j;
  880: 				/*printf("  pile[%d]\t%d %d\n", top, i, j); */
  881: 				if(i==j)
  882: 				{
  883: 					/*printf("</%s>\n", pile[top].eltname); */
  884: 					str = strcat_char(str, len, tmplen, '<');
  885: 					str = strcat_char(str, len, tmplen, '/');
  886: 					s = pile[top].eltname;
  887: 					for(c = *s; c > ' '; c = *(++s))
  888: 						str = strcat_char(str, len, tmplen, c);
  889: 					str = strcat_char(str, len, tmplen, '>');
  890: 					top--;
  891: 				}
  892: 				else
  893: 					break;
  894: 			}
  895: 		}
  896: 		else
  897: 		{
  898: 			/*printf("<%s>\n", eltname); */
  899: 			str = strcat_char(str, len, tmplen, '<');
  900: 			str = strcat_str(str, len, tmplen, eltname);
  901: 			str = strcat_char(str, len, tmplen, '>');
  902: 			k = (unsigned long)p[i].data;
  903: 			i = k & 0xffff;
  904: 			j = i + (k >> 16);
  905: 			top++;
  906: 			/*printf(" +pile[%d]\t%d %d\n", top, i, j); */
  907: 			pile[top].i = i;
  908: 			pile[top].j = j;
  909: 			pile[top].eltname = eltname;
  910: 		}
  911: 	}
  912: }
  913: 
  914: /* genRootDesc() :
  915:  * - Generate the root description of the UPnP device.
  916:  * - the len argument is used to return the length of
  917:  *   the returned string. 
  918:  * - tmp_uuid argument is used to build the uuid string */
  919: char *
  920: genRootDesc(int * len)
  921: {
  922: 	char * str;
  923: 	int tmplen;
  924: 	tmplen = 2048;
  925: 	str = (char *)malloc(tmplen);
  926: 	if(str == NULL)
  927: 		return NULL;
  928: 	* len = strlen(xmlver);
  929: 	/*strcpy(str, xmlver); */
  930: 	memcpy(str, xmlver, *len + 1);
  931: 	str = genXML(str, len, &tmplen, rootDesc);
  932: 	str[*len] = '\0';
  933: 	return str;
  934: }
  935: 
  936: /* genServiceDesc() :
  937:  * Generate service description with allowed methods and 
  938:  * related variables. */
  939: static char *
  940: genServiceDesc(int * len, const struct serviceDesc * s)
  941: {
  942: 	int i, j;
  943: 	const struct action * acts;
  944: 	const struct stateVar * vars;
  945: 	const struct argument * args;
  946: 	const char * p;
  947: 	char * str;
  948: 	int tmplen;
  949: 	tmplen = 2048;
  950: 	str = (char *)malloc(tmplen);
  951: 	if(str == NULL)
  952: 		return NULL;
  953: 	/*strcpy(str, xmlver); */
  954: 	*len = strlen(xmlver);
  955: 	memcpy(str, xmlver, *len + 1);
  956: 	
  957: 	acts = s->actionList;
  958: 	vars = s->serviceStateTable;
  959: 
  960: 	str = strcat_char(str, len, &tmplen, '<');
  961: 	str = strcat_str(str, len, &tmplen, root_service);
  962: 	str = strcat_char(str, len, &tmplen, '>');
  963: 
  964: 	str = strcat_str(str, len, &tmplen,
  965: 		"<specVersion><major>1</major><minor>0</minor></specVersion>");
  966: 
  967: 	i = 0;
  968: 	str = strcat_str(str, len, &tmplen, "<actionList>");
  969: 	while(acts[i].name)
  970: 	{
  971: 		str = strcat_str(str, len, &tmplen, "<action><name>");
  972: 		str = strcat_str(str, len, &tmplen, acts[i].name);
  973: 		str = strcat_str(str, len, &tmplen, "</name>");
  974: 		/* argument List */
  975: 		args = acts[i].args;
  976: 		if(args)
  977: 		{
  978: 			str = strcat_str(str, len, &tmplen, "<argumentList>");
  979: 			j = 0;
  980: 			while(args[j].dir)
  981: 			{
  982: 				str = strcat_str(str, len, &tmplen, "<argument><name>");
  983: 				if((args[j].dir & 0x80) == 0) {
  984: 					str = strcat_str(str, len, &tmplen, "New");
  985: 				}
  986: 				p = vars[args[j].relatedVar].name;
  987: 				if(args[j].dir & 0x7c) {
  988: 					/* use magic values ... */
  989: 					str = strcat_str(str, len, &tmplen, magicargname[(args[j].dir & 0x7c) >> 2]);
  990: 				} else if(0 == memcmp(p, "PortMapping", 11)
  991: 				   && 0 != memcmp(p + 11, "Description", 11)) {
  992: 					if(0 == memcmp(p + 11, "NumberOfEntries", 15)) {
  993: 						/* PortMappingNumberOfEntries */
  994: #ifdef IGD_V2
  995: 						if(0 == memcmp(acts[i].name, "GetListOfPortMappings", 22)) {
  996: 							str = strcat_str(str, len, &tmplen, "NumberOfPorts");
  997: 						} else {
  998: 							str = strcat_str(str, len, &tmplen, "PortMappingIndex");
  999: 						}
 1000: #else
 1001: 						str = strcat_str(str, len, &tmplen, "PortMappingIndex");
 1002: #endif
 1003: 					} else {
 1004: 						/* PortMappingEnabled
 1005: 						 * PortMappingLeaseDuration
 1006: 						 * PortMappingProtocol */
 1007: 						str = strcat_str(str, len, &tmplen, p + 11);
 1008: 					}
 1009: #ifdef IGD_V2
 1010: 				} else if(0 == memcmp(p, "A_ARG_TYPE_", 11)) {
 1011: 					str = strcat_str(str, len, &tmplen, p + 11);
 1012: 				} else if(0 == memcmp(p, "ExternalPort", 13)
 1013: 				          && args[j].dir == 2
 1014: 				          && 0 == memcmp(acts[i].name, "AddAnyPortMapping", 18)) {
 1015: 					str = strcat_str(str, len, &tmplen, "ReservedPort");
 1016: #endif
 1017: 				} else {
 1018: 					str = strcat_str(str, len, &tmplen, p);
 1019: 				}
 1020: 				str = strcat_str(str, len, &tmplen, "</name><direction>");
 1021: 				str = strcat_str(str, len, &tmplen, (args[j].dir&0x03)==1?"in":"out");
 1022: 				str = strcat_str(str, len, &tmplen,
 1023: 						"</direction><relatedStateVariable>");
 1024: 				str = strcat_str(str, len, &tmplen, p);
 1025: 				str = strcat_str(str, len, &tmplen,
 1026: 						"</relatedStateVariable></argument>");
 1027: 				j++;
 1028: 			}
 1029: 			str = strcat_str(str, len, &tmplen,"</argumentList>");
 1030: 		}
 1031: 		str = strcat_str(str, len, &tmplen, "</action>");
 1032: 		/*str = strcat_char(str, len, &tmplen, '\n'); // TEMP ! */
 1033: 		i++;
 1034: 	}
 1035: 	str = strcat_str(str, len, &tmplen, "</actionList><serviceStateTable>");
 1036: 	i = 0;
 1037: 	while(vars[i].name)
 1038: 	{
 1039: 		str = strcat_str(str, len, &tmplen,
 1040: 				"<stateVariable sendEvents=\"");
 1041: #ifdef ENABLE_EVENTS
 1042: 		str = strcat_str(str, len, &tmplen, (vars[i].itype & 0x80)?"yes":"no");
 1043: #else
 1044: 		/* for the moment always send no. Wait for SUBSCRIBE implementation
 1045: 		 * before setting it to yes */
 1046: 		str = strcat_str(str, len, &tmplen, "no");
 1047: #endif
 1048: 		str = strcat_str(str, len, &tmplen, "\"><name>");
 1049: 		str = strcat_str(str, len, &tmplen, vars[i].name);
 1050: 		str = strcat_str(str, len, &tmplen, "</name><dataType>");
 1051: 		str = strcat_str(str, len, &tmplen, upnptypes[vars[i].itype & 0x0f]);
 1052: 		str = strcat_str(str, len, &tmplen, "</dataType>");
 1053: 		if(vars[i].iallowedlist)
 1054: 		{
 1055: 		  if((vars[i].itype & 0x0f) == 0)
 1056: 		  {
 1057: 		    /* string */
 1058: 		    str = strcat_str(str, len, &tmplen, "<allowedValueList>");
 1059: 		    for(j=vars[i].iallowedlist; upnpallowedvalues[j]; j++)
 1060: 		    {
 1061: 		      str = strcat_str(str, len, &tmplen, "<allowedValue>");
 1062: 		      str = strcat_str(str, len, &tmplen, upnpallowedvalues[j]);
 1063: 		      str = strcat_str(str, len, &tmplen, "</allowedValue>");
 1064: 		    }
 1065: 		    str = strcat_str(str, len, &tmplen, "</allowedValueList>");
 1066: 		  } else {
 1067: 		    /* ui2 and ui4 */
 1068: 		    str = strcat_str(str, len, &tmplen, "<allowedValueRange><minimum>");
 1069: 			str = strcat_int(str, len, &tmplen, upnpallowedranges[vars[i].iallowedlist]);
 1070: 		    str = strcat_str(str, len, &tmplen, "</minimum><maximum>");
 1071: 			str = strcat_int(str, len, &tmplen, upnpallowedranges[vars[i].iallowedlist+1]);
 1072: 		    str = strcat_str(str, len, &tmplen, "</maximum></allowedValueRange>");
 1073: 		  }
 1074: 		}
 1075: 		/*if(vars[i].defaultValue) */
 1076: 		if(vars[i].idefault)
 1077: 		{
 1078: 		  str = strcat_str(str, len, &tmplen, "<defaultValue>");
 1079: 		  /*str = strcat_str(str, len, &tmplen, vars[i].defaultValue); */
 1080: 		  str = strcat_str(str, len, &tmplen, upnpdefaultvalues[vars[i].idefault]);
 1081: 		  str = strcat_str(str, len, &tmplen, "</defaultValue>");
 1082: 		}
 1083: 		str = strcat_str(str, len, &tmplen, "</stateVariable>");
 1084: 		/*str = strcat_char(str, len, &tmplen, '\n'); // TEMP ! */
 1085: 		i++;
 1086: 	}
 1087: 	str = strcat_str(str, len, &tmplen, "</serviceStateTable></scpd>");
 1088: 	str[*len] = '\0';
 1089: 	return str;
 1090: }
 1091: 
 1092: /* genWANIPCn() :
 1093:  * Generate the WANIPConnection xml description */
 1094: char *
 1095: genWANIPCn(int * len)
 1096: {
 1097: 	return genServiceDesc(len, &scpdWANIPCn);
 1098: }
 1099: 
 1100: /* genWANCfg() :
 1101:  * Generate the WANInterfaceConfig xml description. */
 1102: char *
 1103: genWANCfg(int * len)
 1104: {
 1105: 	return genServiceDesc(len, &scpdWANCfg);
 1106: }
 1107: 
 1108: #ifdef ENABLE_L3F_SERVICE
 1109: char *
 1110: genL3F(int * len)
 1111: {
 1112: 	return genServiceDesc(len, &scpdL3F);
 1113: }
 1114: #endif
 1115: 
 1116: #ifdef ENABLE_6FC_SERVICE
 1117: char *
 1118: gen6FC(int * len)
 1119: {
 1120: 	return genServiceDesc(len, &scpd6FC);
 1121: }
 1122: #endif
 1123: 
 1124: #ifdef ENABLE_DP_SERVICE
 1125: char *
 1126: genDP(int * len)
 1127: {
 1128: 	return genServiceDesc(len, &scpdDP);
 1129: }
 1130: #endif
 1131: 
 1132: #ifdef ENABLE_EVENTS
 1133: static char *
 1134: genEventVars(int * len, const struct serviceDesc * s, const char * servns)
 1135: {
 1136: 	char tmp[16];
 1137: 	const struct stateVar * v;
 1138: 	char * str;
 1139: 	int tmplen;
 1140: 	tmplen = 512;
 1141: 	str = (char *)malloc(tmplen);
 1142: 	if(str == NULL)
 1143: 		return NULL;
 1144: 	*len = 0;
 1145: 	v = s->serviceStateTable;
 1146: 	str = strcat_str(str, len, &tmplen, "<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\" xmlns:s=\"");
 1147: 	str = strcat_str(str, len, &tmplen, servns);
 1148: 	str = strcat_str(str, len, &tmplen, "\">");
 1149: 	while(v->name) {
 1150: 		if(v->itype & 0x80) {
 1151: 			str = strcat_str(str, len, &tmplen, "<e:property><s:");
 1152: 			str = strcat_str(str, len, &tmplen, v->name);
 1153: 			str = strcat_str(str, len, &tmplen, ">");
 1154: 			//printf("<e:property><s:%s>", v->name);
 1155: 			switch(v->ieventvalue) {
 1156: 			case 0:
 1157: 				break;
 1158: 			case CONNECTIONSTATUS_MAGICALVALUE:
 1159: 				/* or get_wan_connection_status_str(ext_if_name) */
 1160: 				str = strcat_str(str, len, &tmplen,
 1161: 				   upnpallowedvalues[18 + get_wan_connection_status(ext_if_name)]);
 1162: 				break;
 1163: #ifdef ENABLE_6FC_SERVICE
 1164: 			case FIREWALLENABLED_MAGICALVALUE:
 1165: 				/* see 2.4.2 of UPnP-gw-WANIPv6FirewallControl-v1-Service.pdf */
 1166: 				snprintf(tmp, sizeof(tmp), "%d",
 1167: 				         ipv6fc_firewall_enabled);
 1168: 				str = strcat_str(str, len, &tmplen, tmp);
 1169: 				break;
 1170: 			case INBOUNDPINHOLEALLOWED_MAGICALVALUE:
 1171: 				/* see 2.4.3 of UPnP-gw-WANIPv6FirewallControl-v1-Service.pdf */
 1172: 				snprintf(tmp, sizeof(tmp), "%d",
 1173: 				         ipv6fc_inbound_pinhole_allowed);
 1174: 				str = strcat_str(str, len, &tmplen, tmp);
 1175: 				break;
 1176: #endif
 1177: #ifdef IGD_V2
 1178: 			case SYSTEMUPDATEID_MAGICALVALUE:
 1179: 				/* Please read section 2.3.23 SystemUpdateID
 1180: 				 * of UPnP-gw-WANIPConnection-v2-Service.pdf */
 1181: 				snprintf(tmp, sizeof(tmp), "%d",
 1182: 				         1/* system update id */);
 1183: 				str = strcat_str(str, len, &tmplen, tmp);
 1184: 				break;
 1185: #endif
 1186: 			case PORTMAPPINGNUMBEROFENTRIES_MAGICALVALUE:
 1187: 				/* Port mapping number of entries magical value */
 1188: 				snprintf(tmp, sizeof(tmp), "%d",
 1189: 				         upnp_get_portmapping_number_of_entries());
 1190: 				str = strcat_str(str, len, &tmplen, tmp);
 1191: 				break;
 1192: 			case EXTERNALIPADDRESS_MAGICALVALUE:
 1193: 				/* External ip address magical value */
 1194: 				if(use_ext_ip_addr)
 1195: 					str = strcat_str(str, len, &tmplen, use_ext_ip_addr);
 1196: 				else {
 1197: 					char ext_ip_addr[INET_ADDRSTRLEN];
 1198: 					if(getifaddr(ext_if_name, ext_ip_addr, INET_ADDRSTRLEN) < 0) {
 1199: 						str = strcat_str(str, len, &tmplen, "0.0.0.0");
 1200: 					} else {
 1201: 						str = strcat_str(str, len, &tmplen, ext_ip_addr);
 1202: 					}
 1203: 				}
 1204: 				break;
 1205: 			case DEFAULTCONNECTIONSERVICE_MAGICALVALUE:
 1206: 				/* DefaultConnectionService magical value */
 1207: 				str = strcat_str(str, len, &tmplen, uuidvalue);
 1208: 				str = strcat_str(str, len, &tmplen, ":WANConnectionDevice:1,urn:upnp-org:serviceId:WANIPConn1");
 1209: 				break;
 1210: 			default:
 1211: 				str = strcat_str(str, len, &tmplen, upnpallowedvalues[v->ieventvalue]);
 1212: 			}
 1213: 			str = strcat_str(str, len, &tmplen, "</s:");
 1214: 			str = strcat_str(str, len, &tmplen, v->name);
 1215: 			str = strcat_str(str, len, &tmplen, "></e:property>");
 1216: 			//printf("</s:%s></e:property>\n", v->name);
 1217: 		}
 1218: 		v++;
 1219: 	}
 1220: 	str = strcat_str(str, len, &tmplen, "</e:propertyset>");
 1221: 	//printf("</e:propertyset>\n");
 1222: 	//printf("\n");
 1223: 	//printf("%d\n", tmplen);
 1224: 	str[*len] = '\0';
 1225: 	return str;
 1226: }
 1227: 
 1228: char *
 1229: getVarsWANIPCn(int * l)
 1230: {
 1231: 	return genEventVars(l,
 1232:                         &scpdWANIPCn,
 1233: 	                    SERVICE_TYPE_WANIPC);
 1234: }
 1235: 
 1236: char *
 1237: getVarsWANCfg(int * l)
 1238: {
 1239: 	return genEventVars(l,
 1240: 	                    &scpdWANCfg,
 1241: 	                    "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1");
 1242: }
 1243: 
 1244: #ifdef ENABLE_L3F_SERVICE
 1245: char *
 1246: getVarsL3F(int * l)
 1247: {
 1248: 	return genEventVars(l,
 1249: 	                    &scpdL3F,
 1250: 	                    "urn:schemas-upnp-org:service:Layer3Forwarding:1");
 1251: }
 1252: #endif
 1253: 
 1254: #ifdef ENABLE_6FC_SERVICE
 1255: char *
 1256: getVars6FC(int * l)
 1257: {
 1258: 	return genEventVars(l,
 1259: 	                    &scpd6FC,
 1260: 	                    "urn:schemas-upnp-org:service:WANIPv6FirewallControl:1");
 1261: }
 1262: #endif
 1263: 
 1264: #ifdef ENABLE_DP_SERVICE
 1265: char *
 1266: getVarsDP(int * l)
 1267: {
 1268: 	return genEventVars(l,
 1269: 	                    &scpdDP,
 1270: 	                    "urn:schemas-upnp-org:service:DeviceProtection:1");
 1271: }
 1272: #endif
 1273: 
 1274: #endif /* ENABLE_EVENTS */

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