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