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

1.1     ! misho       1: /* $Id: upnpdescgen.c,v 1.51 2009/09/06 21:26:36 nanard Exp $ */
        !             2: /* MiniUPnP project
        !             3:  * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
        !             4:  * (c) 2006-2009 Thomas Bernard 
        !             5:  * This software is subject to the conditions detailed
        !             6:  * in the LICENCE file provided within the distribution */
        !             7: 
        !             8: #include <stdio.h>
        !             9: #include <stdlib.h>
        !            10: #include <string.h>
        !            11: 
        !            12: #include "config.h"
        !            13: #ifdef ENABLE_EVENTS
        !            14: #include "getifaddr.h"
        !            15: #include "upnpredirect.h"
        !            16: #endif
        !            17: #include "upnpdescgen.h"
        !            18: #include "miniupnpdpath.h"
        !            19: #include "upnpglobalvars.h"
        !            20: #include "upnpdescstrings.h"
        !            21: 
        !            22: static const char * const upnptypes[] =
        !            23: {
        !            24:        "string",
        !            25:        "boolean",
        !            26:        "ui2",
        !            27:        "ui4"
        !            28: };
        !            29: 
        !            30: static const char * const upnpdefaultvalues[] =
        !            31: {
        !            32:        0,
        !            33:        "Unconfigured"
        !            34: };
        !            35: 
        !            36: static const char * const upnpallowedvalues[] =
        !            37: {
        !            38:        0,              /* 0 */
        !            39:        "DSL",  /* 1 */
        !            40:        "POTS",
        !            41:        "Cable",
        !            42:        "Ethernet",
        !            43:        0,
        !            44:        "Up",   /* 6 */
        !            45:        "Down",
        !            46:        "Initializing",
        !            47:        "Unavailable",
        !            48:        0,
        !            49:        "TCP",  /* 11 */
        !            50:        "UDP",
        !            51:        0,
        !            52:        "Unconfigured", /* 14 */
        !            53:        "IP_Routed",
        !            54:        "IP_Bridged",
        !            55:        0,
        !            56:        "Unconfigured", /* 18 */
        !            57:        "Connecting",
        !            58:        "Connected",
        !            59:        "PendingDisconnect",
        !            60:        "Disconnecting",
        !            61:        "Disconnected",
        !            62:        0,
        !            63:        "ERROR_NONE",   /* 25 */
        !            64:        0,
        !            65:        "",             /* 27 */
        !            66:        0
        !            67: };
        !            68: 
        !            69: static const char xmlver[] = 
        !            70:        "<?xml version=\"1.0\"?>\r\n";
        !            71: static const char root_service[] =
        !            72:        "scpd xmlns=\"urn:schemas-upnp-org:service-1-0\"";
        !            73: static const char root_device[] = 
        !            74:        "root xmlns=\"urn:schemas-upnp-org:device-1-0\"";
        !            75: 
        !            76: /* root Description of the UPnP Device 
        !            77:  * fixed to match UPnP_IGD_InternetGatewayDevice 1.0.pdf 
        !            78:  * presentationURL is only "recommended" but the router doesn't appears
        !            79:  * in "Network connections" in Windows XP if it is not present. */
        !            80: static const struct XMLElt rootDesc[] =
        !            81: {
        !            82: /* 0 */
        !            83:        {root_device, INITHELPER(1,2)},
        !            84:        {"specVersion", INITHELPER(3,2)},
        !            85: #if defined(ENABLE_L3F_SERVICE) || defined(HAS_DUMMY_SERVICE)
        !            86:        {"device", INITHELPER(5,13)},
        !            87: #else
        !            88:        {"device", INITHELPER(5,12)},
        !            89: #endif
        !            90:        {"/major", "1"},
        !            91:        {"/minor", "0"},
        !            92: /* 5 */
        !            93:        {"/deviceType", "urn:schemas-upnp-org:device:InternetGatewayDevice:1"},
        !            94:        {"/friendlyName", ROOTDEV_FRIENDLYNAME},        /* required */
        !            95:        {"/manufacturer", ROOTDEV_MANUFACTURER},                /* required */
        !            96: /* 8 */
        !            97:        {"/manufacturerURL", ROOTDEV_MANUFACTURERURL},  /* optional */
        !            98:        {"/modelDescription", ROOTDEV_MODELDESCRIPTION}, /* recommended */
        !            99:        {"/modelName", ROOTDEV_MODELNAME},      /* required */
        !           100:        {"/modelNumber", modelnumber},
        !           101:        {"/modelURL", ROOTDEV_MODELURL},
        !           102:        {"/serialNumber", serialnumber},
        !           103:        {"/UDN", uuidvalue},    /* required */
        !           104: #if defined(ENABLE_L3F_SERVICE) || defined(HAS_DUMMY_SERVICE)
        !           105:        {"serviceList", INITHELPER(57,1)},
        !           106:        {"deviceList", INITHELPER(18,1)},
        !           107:        {"/presentationURL", presentationurl},  /* recommended */
        !           108: #else
        !           109:        {"deviceList", INITHELPER(18,1)},
        !           110:        {"/presentationURL", presentationurl},  /* recommended */
        !           111:        {0,0},
        !           112: #endif
        !           113: /* 18 */
        !           114:        {"device", INITHELPER(19,13)},
        !           115: /* 19 */
        !           116:        {"/deviceType", "urn:schemas-upnp-org:device:WANDevice:1"}, /* required */
        !           117:        {"/friendlyName", WANDEV_FRIENDLYNAME},
        !           118:        {"/manufacturer", WANDEV_MANUFACTURER},
        !           119:        {"/manufacturerURL", WANDEV_MANUFACTURERURL},
        !           120:        {"/modelDescription" , WANDEV_MODELDESCRIPTION},
        !           121:        {"/modelName", WANDEV_MODELNAME},
        !           122:        {"/modelNumber", WANDEV_MODELNUMBER},
        !           123:        {"/modelURL", WANDEV_MODELURL},
        !           124:        {"/serialNumber", serialnumber},
        !           125:        {"/UDN", uuidvalue},
        !           126:        {"/UPC", WANDEV_UPC},
        !           127: /* 30 */
        !           128:        {"serviceList", INITHELPER(32,1)},
        !           129:        {"deviceList", INITHELPER(38,1)},
        !           130: /* 32 */
        !           131:        {"service", INITHELPER(33,5)},
        !           132: /* 33 */
        !           133:        {"/serviceType",
        !           134:                        "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1"},
        !           135:        /*{"/serviceId", "urn:upnp-org:serviceId:WANCommonInterfaceConfig"}, */
        !           136:        {"/serviceId", "urn:upnp-org:serviceId:WANCommonIFC1"}, /* required */
        !           137:        {"/controlURL", WANCFG_CONTROLURL},
        !           138:        {"/eventSubURL", WANCFG_EVENTURL},
        !           139:        {"/SCPDURL", WANCFG_PATH},
        !           140: /* 38 */
        !           141:        {"device", INITHELPER(39,12)},
        !           142: /* 39 */
        !           143:        {"/deviceType", "urn:schemas-upnp-org:device:WANConnectionDevice:1"},
        !           144:        {"/friendlyName", WANCDEV_FRIENDLYNAME},
        !           145:        {"/manufacturer", WANCDEV_MANUFACTURER},
        !           146:        {"/manufacturerURL", WANCDEV_MANUFACTURERURL},
        !           147:        {"/modelDescription", WANCDEV_MODELDESCRIPTION},
        !           148:        {"/modelName", WANCDEV_MODELNAME},
        !           149:        {"/modelNumber", WANCDEV_MODELNUMBER},
        !           150:        {"/modelURL", WANCDEV_MODELURL},
        !           151:        {"/serialNumber", serialnumber},
        !           152:        {"/UDN", uuidvalue},
        !           153:        {"/UPC", WANCDEV_UPC},
        !           154:        {"serviceList", INITHELPER(51,1)},
        !           155: /* 51 */
        !           156:        {"service", INITHELPER(52,5)},
        !           157: /* 52 */
        !           158:        {"/serviceType", "urn:schemas-upnp-org:service:WANIPConnection:1"},
        !           159:        /* {"/serviceId", "urn:upnp-org:serviceId:WANIPConnection"}, */
        !           160:        {"/serviceId", "urn:upnp-org:serviceId:WANIPConn1"},
        !           161:        {"/controlURL", WANIPC_CONTROLURL},
        !           162:        {"/eventSubURL", WANIPC_EVENTURL},
        !           163:        {"/SCPDURL", WANIPC_PATH},
        !           164: /* 57 */
        !           165: #ifdef HAS_DUMMY_SERVICE
        !           166:        {"service", INITHELPER(58,5)},
        !           167: /* 58 */
        !           168:        {"/serviceType", "urn:schemas-dummy-com:service:Dummy:1"},
        !           169:        {"/serviceId", "urn:dummy-com:serviceId:dummy1"},
        !           170:        {"/controlURL", "/dummy"},
        !           171:        {"/eventSubURL", "/dummy"},
        !           172:        {"/SCPDURL", DUMMY_PATH},
        !           173: #endif
        !           174: #ifdef ENABLE_L3F_SERVICE
        !           175:        {"service", INITHELPER(58,5)},
        !           176: /* 58 */
        !           177:        {"/serviceType", "urn:schemas-upnp-org:service:Layer3Forwarding:1"},
        !           178:        {"/serviceId", "urn:upnp-org:serviceId:Layer3Forwarding1"},
        !           179:        {"/controlURL", L3F_CONTROLURL}, /* The Layer3Forwarding service is only */
        !           180:        {"/eventSubURL", L3F_EVENTURL}, /* recommended, not mandatory */
        !           181:        {"/SCPDURL", L3F_PATH},
        !           182: #endif
        !           183:        {0, 0}
        !           184: };
        !           185: 
        !           186: /* WANIPCn.xml */
        !           187: /* see UPnP_IGD_WANIPConnection 1.0.pdf
        !           188: static struct XMLElt scpdWANIPCn[] =
        !           189: {
        !           190:        {root_service, {INITHELPER(1,2)}},
        !           191:        {0, {0}}
        !           192: };
        !           193: */
        !           194: static const struct argument AddPortMappingArgs[] =
        !           195: {
        !           196:        {1, 11},
        !           197:        {1, 12},
        !           198:        {1, 14},
        !           199:        {1, 13},
        !           200:        {1, 15},
        !           201:        {1, 9},
        !           202:        {1, 16},
        !           203:        {1, 10},
        !           204:        {0, 0}
        !           205: };
        !           206: 
        !           207: static const struct argument GetExternalIPAddressArgs[] =
        !           208: {
        !           209:        {2, 7},
        !           210:        {0, 0}
        !           211: };
        !           212: 
        !           213: static const struct argument DeletePortMappingArgs[] = 
        !           214: {
        !           215:        {1, 11},
        !           216:        {1, 12},
        !           217:        {1, 14},
        !           218:        {0, 0}
        !           219: };
        !           220: 
        !           221: static const struct argument SetConnectionTypeArgs[] =
        !           222: {
        !           223:        {1, 0},
        !           224:        {0, 0}
        !           225: };
        !           226: 
        !           227: static const struct argument GetConnectionTypeInfoArgs[] =
        !           228: {
        !           229:        {2, 0},
        !           230:        {2, 1},
        !           231:        {0, 0}
        !           232: };
        !           233: 
        !           234: static const struct argument GetStatusInfoArgs[] =
        !           235: {
        !           236:        {2, 2},
        !           237:        {2, 4},
        !           238:        {2, 3},
        !           239:        {0, 0}
        !           240: };
        !           241: 
        !           242: static const struct argument GetNATRSIPStatusArgs[] =
        !           243: {
        !           244:        {2, 5},
        !           245:        {2, 6},
        !           246:        {0, 0}
        !           247: };
        !           248: 
        !           249: static const struct argument GetGenericPortMappingEntryArgs[] =
        !           250: {
        !           251:        {1, 8},
        !           252:        {2, 11},
        !           253:        {2, 12},
        !           254:        {2, 14},
        !           255:        {2, 13},
        !           256:        {2, 15},
        !           257:        {2, 9},
        !           258:        {2, 16},
        !           259:        {2, 10},
        !           260:        {0, 0}
        !           261: };
        !           262: 
        !           263: static const struct argument GetSpecificPortMappingEntryArgs[] =
        !           264: {
        !           265:        {1, 11},
        !           266:        {1, 12},
        !           267:        {1, 14},
        !           268:        {2, 13},
        !           269:        {2, 15},
        !           270:        {2, 9},
        !           271:        {2, 16},
        !           272:        {2, 10},
        !           273:        {0, 0}
        !           274: };
        !           275: 
        !           276: static const struct action WANIPCnActions[] =
        !           277: {
        !           278:        {"AddPortMapping", AddPortMappingArgs}, /* R */
        !           279:        {"GetExternalIPAddress", GetExternalIPAddressArgs}, /* R */
        !           280:        {"DeletePortMapping", DeletePortMappingArgs}, /* R */
        !           281:        {"SetConnectionType", SetConnectionTypeArgs}, /* R */
        !           282:        {"GetConnectionTypeInfo", GetConnectionTypeInfoArgs}, /* R */
        !           283:        {"RequestConnection", 0}, /* R */
        !           284:        {"ForceTermination", 0}, /* R */
        !           285:        {"GetStatusInfo", GetStatusInfoArgs}, /* R */
        !           286:        {"GetNATRSIPStatus", GetNATRSIPStatusArgs}, /* R */
        !           287:        {"GetGenericPortMappingEntry", GetGenericPortMappingEntryArgs}, /* R */
        !           288:        {"GetSpecificPortMappingEntry", GetSpecificPortMappingEntryArgs}, /* R */
        !           289:        {0, 0}
        !           290: };
        !           291: /* R=Required, O=Optional */
        !           292: 
        !           293: static const struct stateVar WANIPCnVars[] =
        !           294: {
        !           295: /* 0 */
        !           296:        {"ConnectionType", 0, 0/*1*/}, /* required */
        !           297:        {"PossibleConnectionTypes", 0|0x80, 0, 14, 15},
        !           298:         /* Required
        !           299:          * Allowed values : Unconfigured / IP_Routed / IP_Bridged */
        !           300:        {"ConnectionStatus", 0|0x80, 0/*1*/, 18, 20}, /* required */
        !           301:         /* Allowed Values : Unconfigured / Connecting(opt) / Connected
        !           302:          *                  PendingDisconnect(opt) / Disconnecting (opt)
        !           303:          *                  Disconnected */
        !           304:        {"Uptime", 3, 0},       /* Required */
        !           305:        {"LastConnectionError", 0, 0, 25},      /* required : */
        !           306:         /* Allowed Values : ERROR_NONE(req) / ERROR_COMMAND_ABORTED(opt)
        !           307:          *                  ERROR_NOT_ENABLED_FOR_INTERNET(opt)
        !           308:          *                  ERROR_USER_DISCONNECT(opt)
        !           309:          *                  ERROR_ISP_DISCONNECT(opt)
        !           310:          *                  ERROR_IDLE_DISCONNECT(opt)
        !           311:          *                  ERROR_FORCED_DISCONNECT(opt)
        !           312:          *                  ERROR_NO_CARRIER(opt)
        !           313:          *                  ERROR_IP_CONFIGURATION(opt)
        !           314:          *                  ERROR_UNKNOWN(opt) */
        !           315:        {"RSIPAvailable", 1, 0}, /* required */
        !           316:        {"NATEnabled", 1, 0},    /* required */
        !           317:        {"ExternalIPAddress", 0|0x80, 0, 0, 254}, /* required. Default : empty string */
        !           318:        {"PortMappingNumberOfEntries", 2|0x80, 0, 0, 253}, /* required >= 0 */
        !           319:        {"PortMappingEnabled", 1, 0}, /* Required */
        !           320:        {"PortMappingLeaseDuration", 3, 0}, /* required */
        !           321:        {"RemoteHost", 0, 0},   /* required. Default : empty string */
        !           322:        {"ExternalPort", 2, 0}, /* required */
        !           323:        {"InternalPort", 2, 0}, /* required */
        !           324:        {"PortMappingProtocol", 0, 0, 11}, /* required allowedValues: TCP/UDP */
        !           325:        {"InternalClient", 0, 0}, /* required */
        !           326:        {"PortMappingDescription", 0, 0}, /* required default: empty string */
        !           327:        {0, 0}
        !           328: };
        !           329: 
        !           330: static const struct serviceDesc scpdWANIPCn =
        !           331: { WANIPCnActions, WANIPCnVars };
        !           332: 
        !           333: /* WANCfg.xml */
        !           334: /* See UPnP_IGD_WANCommonInterfaceConfig 1.0.pdf */
        !           335: 
        !           336: static const struct argument GetCommonLinkPropertiesArgs[] =
        !           337: {
        !           338:        {2, 0},
        !           339:        {2, 1},
        !           340:        {2, 2},
        !           341:        {2, 3},
        !           342:        {0, 0}
        !           343: };
        !           344: 
        !           345: static const struct argument GetTotalBytesSentArgs[] =
        !           346: {
        !           347:        {2, 4},
        !           348:        {0, 0}
        !           349: };
        !           350: 
        !           351: static const struct argument GetTotalBytesReceivedArgs[] =
        !           352: {
        !           353:        {2, 5},
        !           354:        {0, 0}
        !           355: };
        !           356: 
        !           357: static const struct argument GetTotalPacketsSentArgs[] =
        !           358: {
        !           359:        {2, 6},
        !           360:        {0, 0}
        !           361: };
        !           362: 
        !           363: static const struct argument GetTotalPacketsReceivedArgs[] =
        !           364: {
        !           365:        {2, 7},
        !           366:        {0, 0}
        !           367: };
        !           368: 
        !           369: static const struct action WANCfgActions[] =
        !           370: {
        !           371:        {"GetCommonLinkProperties", GetCommonLinkPropertiesArgs}, /* Required */
        !           372:        {"GetTotalBytesSent", GetTotalBytesSentArgs},             /* optional */
        !           373:        {"GetTotalBytesReceived", GetTotalBytesReceivedArgs},     /* optional */
        !           374:        {"GetTotalPacketsSent", GetTotalPacketsSentArgs},         /* optional */
        !           375:        {"GetTotalPacketsReceived", GetTotalPacketsReceivedArgs}, /* optional */
        !           376:        {0, 0}
        !           377: };
        !           378: 
        !           379: /* See UPnP_IGD_WANCommonInterfaceConfig 1.0.pdf */
        !           380: static const struct stateVar WANCfgVars[] =
        !           381: {
        !           382:        {"WANAccessType", 0, 0, 1},
        !           383:        /* Allowed Values : DSL / POTS / Cable / Ethernet 
        !           384:         * Default value : empty string */
        !           385:        {"Layer1UpstreamMaxBitRate", 3, 0},
        !           386:        {"Layer1DownstreamMaxBitRate", 3, 0},
        !           387:        {"PhysicalLinkStatus", 0|0x80, 0, 6, 6},
        !           388:        /*  allowed values : 
        !           389:         *      Up / Down / Initializing (optional) / Unavailable (optionnal)
        !           390:         *  no Default value 
        !           391:         *  Evented */
        !           392:        {"TotalBytesSent", 3, 0},          /* Optional */
        !           393:        {"TotalBytesReceived", 3, 0},  /* Optional */
        !           394:        {"TotalPacketsSent", 3, 0},    /* Optional */
        !           395:        {"TotalPacketsReceived", 3, 0},/* Optional */
        !           396:        /*{"MaximumActiveConnections", 2, 0},   // allowed Range value // OPTIONAL */
        !           397:        {0, 0}
        !           398: };
        !           399: 
        !           400: static const struct serviceDesc scpdWANCfg =
        !           401: { WANCfgActions, WANCfgVars };
        !           402: 
        !           403: #ifdef ENABLE_L3F_SERVICE
        !           404: /* Read UPnP_IGD_Layer3Forwarding_1.0.pdf */
        !           405: static const struct argument SetDefaultConnectionServiceArgs[] =
        !           406: {
        !           407:        {1, 0}, /* in */
        !           408:        {0, 0}
        !           409: };
        !           410: 
        !           411: static const struct argument GetDefaultConnectionServiceArgs[] =
        !           412: {
        !           413:        {2, 0}, /* out */
        !           414:        {0, 0}
        !           415: };
        !           416: 
        !           417: static const struct action L3FActions[] =
        !           418: {
        !           419:        {"SetDefaultConnectionService", SetDefaultConnectionServiceArgs}, /* Req */
        !           420:        {"GetDefaultConnectionService", GetDefaultConnectionServiceArgs}, /* Req */
        !           421:        {0, 0}
        !           422: };
        !           423: 
        !           424: static const struct stateVar L3FVars[] =
        !           425: {
        !           426:        {"DefaultConnectionService", 0|0x80, 0, 0, 255}, /* Required */
        !           427:        {0, 0}
        !           428: };
        !           429: 
        !           430: static const struct serviceDesc scpdL3F =
        !           431: { L3FActions, L3FVars };
        !           432: #endif
        !           433: 
        !           434: /* strcat_str()
        !           435:  * concatenate the string and use realloc to increase the
        !           436:  * memory buffer if needed. */
        !           437: static char *
        !           438: strcat_str(char * str, int * len, int * tmplen, const char * s2)
        !           439: {
        !           440:        int s2len;
        !           441:        s2len = (int)strlen(s2);
        !           442:        if(*tmplen <= (*len + s2len))
        !           443:        {
        !           444:                if(s2len < 256)
        !           445:                        *tmplen += 256;
        !           446:                else
        !           447:                        *tmplen += s2len + 1;
        !           448:                str = (char *)realloc(str, *tmplen);
        !           449:        }
        !           450:        /*strcpy(str + *len, s2); */
        !           451:        memcpy(str + *len, s2, s2len + 1);
        !           452:        *len += s2len;
        !           453:        return str;
        !           454: }
        !           455: 
        !           456: /* strcat_char() :
        !           457:  * concatenate a character and use realloc to increase the
        !           458:  * size of the memory buffer if needed */
        !           459: static char *
        !           460: strcat_char(char * str, int * len, int * tmplen, char c)
        !           461: {
        !           462:        if(*tmplen <= (*len + 1))
        !           463:        {
        !           464:                *tmplen += 256;
        !           465:                str = (char *)realloc(str, *tmplen);
        !           466:        }
        !           467:        str[*len] = c;
        !           468:        (*len)++;
        !           469:        return str;
        !           470: }
        !           471: 
        !           472: /* iterative subroutine using a small stack
        !           473:  * This way, the progam stack usage is kept low */
        !           474: static char *
        !           475: genXML(char * str, int * len, int * tmplen,
        !           476:                    const struct XMLElt * p)
        !           477: {
        !           478:        unsigned short i, j;
        !           479:        unsigned long k;
        !           480:        int top;
        !           481:        const char * eltname, *s;
        !           482:        char c;
        !           483:        struct {
        !           484:                unsigned short i;
        !           485:                unsigned short j;
        !           486:                const char * eltname;
        !           487:        } pile[16]; /* stack */
        !           488:        top = -1;
        !           489:        i = 0;  /* current node */
        !           490:        j = 1;  /* i + number of nodes*/
        !           491:        for(;;)
        !           492:        {
        !           493:                eltname = p[i].eltname;
        !           494:                if(!eltname)
        !           495:                        return str;
        !           496:                if(eltname[0] == '/')
        !           497:                {
        !           498:                        if(p[i].data && p[i].data[0])
        !           499:                        {
        !           500:                                /*printf("<%s>%s<%s>\n", eltname+1, p[i].data, eltname); */
        !           501:                                str = strcat_char(str, len, tmplen, '<');
        !           502:                                str = strcat_str(str, len, tmplen, eltname+1);
        !           503:                                str = strcat_char(str, len, tmplen, '>');
        !           504:                                str = strcat_str(str, len, tmplen, p[i].data);
        !           505:                                str = strcat_char(str, len, tmplen, '<');
        !           506:                                str = strcat_str(str, len, tmplen, eltname);
        !           507:                                str = strcat_char(str, len, tmplen, '>');
        !           508:                        }
        !           509:                        for(;;)
        !           510:                        {
        !           511:                                if(top < 0)
        !           512:                                        return str;
        !           513:                                i = ++(pile[top].i);
        !           514:                                j = pile[top].j;
        !           515:                                /*printf("  pile[%d]\t%d %d\n", top, i, j); */
        !           516:                                if(i==j)
        !           517:                                {
        !           518:                                        /*printf("</%s>\n", pile[top].eltname); */
        !           519:                                        str = strcat_char(str, len, tmplen, '<');
        !           520:                                        str = strcat_char(str, len, tmplen, '/');
        !           521:                                        s = pile[top].eltname;
        !           522:                                        for(c = *s; c > ' '; c = *(++s))
        !           523:                                                str = strcat_char(str, len, tmplen, c);
        !           524:                                        str = strcat_char(str, len, tmplen, '>');
        !           525:                                        top--;
        !           526:                                }
        !           527:                                else
        !           528:                                        break;
        !           529:                        }
        !           530:                }
        !           531:                else
        !           532:                {
        !           533:                        /*printf("<%s>\n", eltname); */
        !           534:                        str = strcat_char(str, len, tmplen, '<');
        !           535:                        str = strcat_str(str, len, tmplen, eltname);
        !           536:                        str = strcat_char(str, len, tmplen, '>');
        !           537:                        k = (unsigned long)p[i].data;
        !           538:                        i = k & 0xffff;
        !           539:                        j = i + (k >> 16);
        !           540:                        top++;
        !           541:                        /*printf(" +pile[%d]\t%d %d\n", top, i, j); */
        !           542:                        pile[top].i = i;
        !           543:                        pile[top].j = j;
        !           544:                        pile[top].eltname = eltname;
        !           545:                }
        !           546:        }
        !           547: }
        !           548: 
        !           549: /* genRootDesc() :
        !           550:  * - Generate the root description of the UPnP device.
        !           551:  * - the len argument is used to return the length of
        !           552:  *   the returned string. 
        !           553:  * - tmp_uuid argument is used to build the uuid string */
        !           554: char *
        !           555: genRootDesc(int * len)
        !           556: {
        !           557:        char * str;
        !           558:        int tmplen;
        !           559:        tmplen = 2048;
        !           560:        str = (char *)malloc(tmplen);
        !           561:        if(str == NULL)
        !           562:                return NULL;
        !           563:        * len = strlen(xmlver);
        !           564:        /*strcpy(str, xmlver); */
        !           565:        memcpy(str, xmlver, *len + 1);
        !           566:        str = genXML(str, len, &tmplen, rootDesc);
        !           567:        str[*len] = '\0';
        !           568:        return str;
        !           569: }
        !           570: 
        !           571: /* genServiceDesc() :
        !           572:  * Generate service description with allowed methods and 
        !           573:  * related variables. */
        !           574: static char *
        !           575: genServiceDesc(int * len, const struct serviceDesc * s)
        !           576: {
        !           577:        int i, j;
        !           578:        const struct action * acts;
        !           579:        const struct stateVar * vars;
        !           580:        const struct argument * args;
        !           581:        const char * p;
        !           582:        char * str;
        !           583:        int tmplen;
        !           584:        tmplen = 2048;
        !           585:        str = (char *)malloc(tmplen);
        !           586:        if(str == NULL)
        !           587:                return NULL;
        !           588:        /*strcpy(str, xmlver); */
        !           589:        *len = strlen(xmlver);
        !           590:        memcpy(str, xmlver, *len + 1);
        !           591:        
        !           592:        acts = s->actionList;
        !           593:        vars = s->serviceStateTable;
        !           594: 
        !           595:        str = strcat_char(str, len, &tmplen, '<');
        !           596:        str = strcat_str(str, len, &tmplen, root_service);
        !           597:        str = strcat_char(str, len, &tmplen, '>');
        !           598: 
        !           599:        str = strcat_str(str, len, &tmplen,
        !           600:                "<specVersion><major>1</major><minor>0</minor></specVersion>");
        !           601: 
        !           602:        i = 0;
        !           603:        str = strcat_str(str, len, &tmplen, "<actionList>");
        !           604:        while(acts[i].name)
        !           605:        {
        !           606:                str = strcat_str(str, len, &tmplen, "<action><name>");
        !           607:                str = strcat_str(str, len, &tmplen, acts[i].name);
        !           608:                str = strcat_str(str, len, &tmplen, "</name>");
        !           609:                /* argument List */
        !           610:                args = acts[i].args;
        !           611:                if(args)
        !           612:                {
        !           613:                        str = strcat_str(str, len, &tmplen, "<argumentList>");
        !           614:                        j = 0;
        !           615:                        while(args[j].dir)
        !           616:                        {
        !           617:                                str = strcat_str(str, len, &tmplen, "<argument><name>New");
        !           618:                                p = vars[args[j].relatedVar].name;
        !           619:                                if(0 == memcmp(p, "PortMapping", 11)
        !           620:                                   && 0 != memcmp(p + 11, "Description", 11)) {
        !           621:                                        if(0 == memcmp(p + 11, "NumberOfEntries", 15))
        !           622:                                                str = strcat_str(str, len, &tmplen, "PortMappingIndex");
        !           623:                                        else
        !           624:                                                str = strcat_str(str, len, &tmplen, p + 11);
        !           625:                                } else {
        !           626:                                        str = strcat_str(str, len, &tmplen, p);
        !           627:                                }
        !           628:                                str = strcat_str(str, len, &tmplen, "</name><direction>");
        !           629:                                str = strcat_str(str, len, &tmplen, args[j].dir==1?"in":"out");
        !           630:                                str = strcat_str(str, len, &tmplen,
        !           631:                                                "</direction><relatedStateVariable>");
        !           632:                                str = strcat_str(str, len, &tmplen, p);
        !           633:                                str = strcat_str(str, len, &tmplen,
        !           634:                                                "</relatedStateVariable></argument>");
        !           635:                                j++;
        !           636:                        }
        !           637:                        str = strcat_str(str, len, &tmplen,"</argumentList>");
        !           638:                }
        !           639:                str = strcat_str(str, len, &tmplen, "</action>");
        !           640:                /*str = strcat_char(str, len, &tmplen, '\n'); // TEMP ! */
        !           641:                i++;
        !           642:        }
        !           643:        str = strcat_str(str, len, &tmplen, "</actionList><serviceStateTable>");
        !           644:        i = 0;
        !           645:        while(vars[i].name)
        !           646:        {
        !           647:                str = strcat_str(str, len, &tmplen,
        !           648:                                "<stateVariable sendEvents=\"");
        !           649: #ifdef ENABLE_EVENTS
        !           650:                str = strcat_str(str, len, &tmplen, (vars[i].itype & 0x80)?"yes":"no");
        !           651: #else
        !           652:                /* for the moment allways send no. Wait for SUBSCRIBE implementation
        !           653:                 * before setting it to yes */
        !           654:                str = strcat_str(str, len, &tmplen, "no");
        !           655: #endif
        !           656:                str = strcat_str(str, len, &tmplen, "\"><name>");
        !           657:                str = strcat_str(str, len, &tmplen, vars[i].name);
        !           658:                str = strcat_str(str, len, &tmplen, "</name><dataType>");
        !           659:                str = strcat_str(str, len, &tmplen, upnptypes[vars[i].itype & 0x0f]);
        !           660:                str = strcat_str(str, len, &tmplen, "</dataType>");
        !           661:                if(vars[i].iallowedlist)
        !           662:                {
        !           663:                  str = strcat_str(str, len, &tmplen, "<allowedValueList>");
        !           664:                  for(j=vars[i].iallowedlist; upnpallowedvalues[j]; j++)
        !           665:                  {
        !           666:                    str = strcat_str(str, len, &tmplen, "<allowedValue>");
        !           667:                    str = strcat_str(str, len, &tmplen, upnpallowedvalues[j]);
        !           668:                    str = strcat_str(str, len, &tmplen, "</allowedValue>");
        !           669:                  }
        !           670:                  str = strcat_str(str, len, &tmplen, "</allowedValueList>");
        !           671:                }
        !           672:                /*if(vars[i].defaultValue) */
        !           673:                if(vars[i].idefault)
        !           674:                {
        !           675:                  str = strcat_str(str, len, &tmplen, "<defaultValue>");
        !           676:                  /*str = strcat_str(str, len, &tmplen, vars[i].defaultValue); */
        !           677:                  str = strcat_str(str, len, &tmplen, upnpdefaultvalues[vars[i].idefault]);
        !           678:                  str = strcat_str(str, len, &tmplen, "</defaultValue>");
        !           679:                }
        !           680:                str = strcat_str(str, len, &tmplen, "</stateVariable>");
        !           681:                /*str = strcat_char(str, len, &tmplen, '\n'); // TEMP ! */
        !           682:                i++;
        !           683:        }
        !           684:        str = strcat_str(str, len, &tmplen, "</serviceStateTable></scpd>");
        !           685:        str[*len] = '\0';
        !           686:        return str;
        !           687: }
        !           688: 
        !           689: /* genWANIPCn() :
        !           690:  * Generate the WANIPConnection xml description */
        !           691: char *
        !           692: genWANIPCn(int * len)
        !           693: {
        !           694:        return genServiceDesc(len, &scpdWANIPCn);
        !           695: }
        !           696: 
        !           697: /* genWANCfg() :
        !           698:  * Generate the WANInterfaceConfig xml description. */
        !           699: char *
        !           700: genWANCfg(int * len)
        !           701: {
        !           702:        return genServiceDesc(len, &scpdWANCfg);
        !           703: }
        !           704: 
        !           705: #ifdef ENABLE_L3F_SERVICE
        !           706: char *
        !           707: genL3F(int * len)
        !           708: {
        !           709:        return genServiceDesc(len, &scpdL3F);
        !           710: }
        !           711: #endif
        !           712: 
        !           713: #ifdef ENABLE_EVENTS
        !           714: static char *
        !           715: genEventVars(int * len, const struct serviceDesc * s, const char * servns)
        !           716: {
        !           717:        char tmp[16];
        !           718:        const struct stateVar * v;
        !           719:        char * str;
        !           720:        int tmplen;
        !           721:        tmplen = 512;
        !           722:        str = (char *)malloc(tmplen);
        !           723:        if(str == NULL)
        !           724:                return NULL;
        !           725:        *len = 0;
        !           726:        v = s->serviceStateTable;
        !           727:        str = strcat_str(str, len, &tmplen, "<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\" xmlns:s=\"");
        !           728:        str = strcat_str(str, len, &tmplen, servns);
        !           729:        str = strcat_str(str, len, &tmplen, "\">");
        !           730:        while(v->name) {
        !           731:                if(v->itype & 0x80) {
        !           732:                        str = strcat_str(str, len, &tmplen, "<e:property><s:");
        !           733:                        str = strcat_str(str, len, &tmplen, v->name);
        !           734:                        str = strcat_str(str, len, &tmplen, ">");
        !           735:                        //printf("<e:property><s:%s>", v->name);
        !           736:                        switch(v->ieventvalue) {
        !           737:                        case 0:
        !           738:                                break;
        !           739:                        case 253:       /* Port mapping number of entries magical value */
        !           740:                                snprintf(tmp, sizeof(tmp), "%d", upnp_get_portmapping_number_of_entries());
        !           741:                                str = strcat_str(str, len, &tmplen, tmp);
        !           742:                                break;
        !           743:                        case 254:       /* External ip address magical value */
        !           744:                                if(use_ext_ip_addr)
        !           745:                                        str = strcat_str(str, len, &tmplen, use_ext_ip_addr);
        !           746:                                else {
        !           747:                                        char ext_ip_addr[INET_ADDRSTRLEN];
        !           748:                                        if(getifaddr(ext_if_name, ext_ip_addr, INET_ADDRSTRLEN) < 0) {
        !           749:                                                str = strcat_str(str, len, &tmplen, "0.0.0.0");
        !           750:                                        } else {
        !           751:                                                str = strcat_str(str, len, &tmplen, ext_ip_addr);
        !           752:                                        }
        !           753:                                }
        !           754:                                /*str = strcat_str(str, len, &tmplen, "0.0.0.0");*/
        !           755:                                break;
        !           756:                        case 255:       /* DefaultConnectionService magical value */
        !           757:                                str = strcat_str(str, len, &tmplen, uuidvalue);
        !           758:                                str = strcat_str(str, len, &tmplen, ":WANConnectionDevice:1,urn:upnp-org:serviceId:WANIPConn1");
        !           759:                                //printf("%s:WANConnectionDevice:1,urn:upnp-org:serviceId:WANIPConn1", uuidvalue);
        !           760:                                break;
        !           761:                        default:
        !           762:                                str = strcat_str(str, len, &tmplen, upnpallowedvalues[v->ieventvalue]);
        !           763:                                //printf("%s", upnpallowedvalues[v->ieventvalue]);
        !           764:                        }
        !           765:                        str = strcat_str(str, len, &tmplen, "</s:");
        !           766:                        str = strcat_str(str, len, &tmplen, v->name);
        !           767:                        str = strcat_str(str, len, &tmplen, "></e:property>");
        !           768:                        //printf("</s:%s></e:property>\n", v->name);
        !           769:                }
        !           770:                v++;
        !           771:        }
        !           772:        str = strcat_str(str, len, &tmplen, "</e:propertyset>");
        !           773:        //printf("</e:propertyset>\n");
        !           774:        //printf("\n");
        !           775:        //printf("%d\n", tmplen);
        !           776:        str[*len] = '\0';
        !           777:        return str;
        !           778: }
        !           779: 
        !           780: char *
        !           781: getVarsWANIPCn(int * l)
        !           782: {
        !           783:        return genEventVars(l,
        !           784:                         &scpdWANIPCn,
        !           785:                            "urn:schemas-upnp-org:service:WANIPConnection:1");
        !           786: }
        !           787: 
        !           788: char *
        !           789: getVarsWANCfg(int * l)
        !           790: {
        !           791:        return genEventVars(l,
        !           792:                            &scpdWANCfg,
        !           793:                            "urn:schemas-upnp-org:service:WANCommonInterfaceConfig:1");
        !           794: }
        !           795: 
        !           796: #ifdef ENABLE_L3F_SERVICE
        !           797: char *
        !           798: getVarsL3F(int * l)
        !           799: {
        !           800:        return genEventVars(l,
        !           801:                            &scpdL3F,
        !           802:                            "urn:schemas-upnp-org:service:Layer3Forwarding:1");
        !           803: }
        !           804: #endif
        !           805: #endif

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