Annotation of embedaddon/miniupnpd/miniupnpd/upnpdescgen.c, revision 1.1.1.1

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

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