Annotation of embedaddon/miniupnpd/miniupnpc/src/upnpc.c, revision 1.1.1.1

1.1       misho       1: /* $Id: upnpc.c,v 1.131 2022/02/19 23:22:54 nanard Exp $ */
                      2: /* Project : miniupnp
                      3:  * Author : Thomas Bernard
                      4:  * Copyright (c) 2005-2023 Thomas Bernard
                      5:  * This software is subject to the conditions detailed in the
                      6:  * LICENCE file provided in this distribution. */
                      7: 
                      8: #include <stdio.h>
                      9: #include <stdlib.h>
                     10: #include <string.h>
                     11: #include <time.h>
                     12: #ifdef _WIN32
                     13: #include <winsock2.h>
                     14: #include "win32_snprintf.h"
                     15: #else
                     16: /* for IPPROTO_TCP / IPPROTO_UDP */
                     17: #include <netinet/in.h>
                     18: #endif
                     19: #include <ctype.h>
                     20: #include "miniwget.h"
                     21: #include "miniupnpc.h"
                     22: #include "upnpcommands.h"
                     23: #include "portlistingparse.h"
                     24: #include "upnperrors.h"
                     25: #include "miniupnpcstrings.h"
                     26: 
                     27: /* protofix() checks if protocol is "UDP" or "TCP"
                     28:  * returns NULL if not */
                     29: const char * protofix(const char * proto)
                     30: {
                     31:        static const char proto_tcp[4] = { 'T', 'C', 'P', 0};
                     32:        static const char proto_udp[4] = { 'U', 'D', 'P', 0};
                     33:        int i, b;
                     34:        for(i=0, b=1; i<4; i++)
                     35:                b = b && (   (proto[i] == proto_tcp[i])
                     36:                          || (proto[i] == (proto_tcp[i] | 32)) );
                     37:        if(b)
                     38:                return proto_tcp;
                     39:        for(i=0, b=1; i<4; i++)
                     40:                b = b && (   (proto[i] == proto_udp[i])
                     41:                          || (proto[i] == (proto_udp[i] | 32)) );
                     42:        if(b)
                     43:                return proto_udp;
                     44:        return 0;
                     45: }
                     46: 
                     47: /* is_int() checks if parameter is an integer or not
                     48:  * 1 for integer
                     49:  * 0 for not an integer */
                     50: int is_int(char const* s)
                     51: {
                     52:        if(s == NULL)
                     53:                return 0;
                     54:        while(*s) {
                     55:                /* #define isdigit(c) ((c) >= '0' && (c) <= '9') */
                     56:                if(!isdigit(*s))
                     57:                        return 0;
                     58:                s++;
                     59:        }
                     60:        return 1;
                     61: }
                     62: 
                     63: static void DisplayInfos(struct UPNPUrls * urls,
                     64:                          struct IGDdatas * data)
                     65: {
                     66:        char externalIPAddress[40];
                     67:        char connectionType[64];
                     68:        char status[64];
                     69:        char lastconnerr[64];
                     70:        unsigned int uptime = 0;
                     71:        unsigned int brUp, brDown;
                     72:        time_t timenow, timestarted;
                     73:        int r;
                     74:        if(UPNP_GetConnectionTypeInfo(urls->controlURL,
                     75:                                      data->first.servicetype,
                     76:                                      connectionType) != UPNPCOMMAND_SUCCESS)
                     77:                printf("GetConnectionTypeInfo failed.\n");
                     78:        else
                     79:                printf("Connection Type : %s\n", connectionType);
                     80:        if(UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype,
                     81:                              status, &uptime, lastconnerr) != UPNPCOMMAND_SUCCESS)
                     82:                printf("GetStatusInfo failed.\n");
                     83:        else
                     84:                printf("Status : %s, uptime=%us, LastConnectionError : %s\n",
                     85:                       status, uptime, lastconnerr);
                     86:        if(uptime > 0) {
                     87:                timenow = time(NULL);
                     88:                timestarted = timenow - uptime;
                     89:                printf("  Time started : %s", ctime(&timestarted));
                     90:        }
                     91:        if(UPNP_GetLinkLayerMaxBitRates(urls->controlURL_CIF, data->CIF.servicetype,
                     92:                                        &brDown, &brUp) != UPNPCOMMAND_SUCCESS) {
                     93:                printf("GetLinkLayerMaxBitRates failed.\n");
                     94:        } else {
                     95:                printf("MaxBitRateDown : %u bps", brDown);
                     96:                if(brDown >= 1000000) {
                     97:                        printf(" (%u.%u Mbps)", brDown / 1000000, (brDown / 100000) % 10);
                     98:                } else if(brDown >= 1000) {
                     99:                        printf(" (%u Kbps)", brDown / 1000);
                    100:                }
                    101:                printf("   MaxBitRateUp %u bps", brUp);
                    102:                if(brUp >= 1000000) {
                    103:                        printf(" (%u.%u Mbps)", brUp / 1000000, (brUp / 100000) % 10);
                    104:                } else if(brUp >= 1000) {
                    105:                        printf(" (%u Kbps)", brUp / 1000);
                    106:                }
                    107:                printf("\n");
                    108:        }
                    109:        r = UPNP_GetExternalIPAddress(urls->controlURL,
                    110:                                  data->first.servicetype,
                    111:                                                          externalIPAddress);
                    112:        if(r != UPNPCOMMAND_SUCCESS) {
                    113:                printf("GetExternalIPAddress failed. (errorcode=%d)\n", r);
                    114:        } else if(!externalIPAddress[0]) {
                    115:                printf("GetExternalIPAddress failed. (empty string)\n");
                    116:        } else {
                    117:                printf("ExternalIPAddress = %s\n", externalIPAddress);
                    118:        }
                    119: }
                    120: 
                    121: static void GetConnectionStatus(struct UPNPUrls * urls,
                    122:                                struct IGDdatas * data)
                    123: {
                    124:        unsigned int bytessent, bytesreceived, packetsreceived, packetssent;
                    125:        DisplayInfos(urls, data);
                    126:        bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, data->CIF.servicetype);
                    127:        bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, data->CIF.servicetype);
                    128:        packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, data->CIF.servicetype);
                    129:        packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, data->CIF.servicetype);
                    130:        printf("Bytes:   Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived);
                    131:        printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived);
                    132: }
                    133: 
                    134: static void ListRedirections(struct UPNPUrls * urls,
                    135:                              struct IGDdatas * data)
                    136: {
                    137:        int r;
                    138:        unsigned short i = 0;
                    139:        char index[6];
                    140:        char intClient[40];
                    141:        char intPort[6];
                    142:        char extPort[6];
                    143:        char protocol[4];
                    144:        char desc[80];
                    145:        char enabled[6];
                    146:        char rHost[64];
                    147:        char duration[16];
                    148:        /*unsigned int num=0;
                    149:        UPNP_GetPortMappingNumberOfEntries(urls->controlURL, data->servicetype, &num);
                    150:        printf("PortMappingNumberOfEntries : %u\n", num);*/
                    151:        printf(" i protocol exPort->inAddr:inPort description remoteHost leaseTime\n");
                    152:        do {
                    153:                snprintf(index, 6, "%hu", i);
                    154:                rHost[0] = '\0'; enabled[0] = '\0';
                    155:                duration[0] = '\0'; desc[0] = '\0';
                    156:                extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0';
                    157:                r = UPNP_GetGenericPortMappingEntry(urls->controlURL,
                    158:                                               data->first.servicetype,
                    159:                                               index,
                    160:                                               extPort, intClient, intPort,
                    161:                                                                           protocol, desc, enabled,
                    162:                                                                           rHost, duration);
                    163:                if(r==0)
                    164:                /*
                    165:                        printf("%02hu - %s %s->%s:%s\tenabled=%s leaseDuration=%s\n"
                    166:                               "     desc='%s' rHost='%s'\n",
                    167:                               i, protocol, extPort, intClient, intPort,
                    168:                                   enabled, duration,
                    169:                                   desc, rHost);
                    170:                                   */
                    171:                        printf("%2hu %s %5s->%s:%-5s '%s' '%s' %s\n",
                    172:                               i, protocol, extPort, intClient, intPort,
                    173:                               desc, rHost, duration);
                    174:                else
                    175:                        printf("GetGenericPortMappingEntry() returned %d (%s)\n",
                    176:                               r, strupnperror(r));
                    177:        } while(r == 0 && i++ < 65535);
                    178: }
                    179: 
                    180: static void NewListRedirections(struct UPNPUrls * urls,
                    181:                                 struct IGDdatas * data)
                    182: {
                    183:        int r;
                    184:        int i = 0;
                    185:        struct PortMappingParserData pdata;
                    186:        struct PortMapping * pm;
                    187: 
                    188:        memset(&pdata, 0, sizeof(struct PortMappingParserData));
                    189:        r = UPNP_GetListOfPortMappings(urls->controlURL,
                    190:                                    data->first.servicetype,
                    191:                                       "0",
                    192:                                       "65535",
                    193:                                       "TCP",
                    194:                                       "1000",
                    195:                                       &pdata);
                    196:        if(r == UPNPCOMMAND_SUCCESS)
                    197:        {
                    198:                printf(" i protocol exPort->inAddr:inPort description remoteHost leaseTime\n");
                    199:                for(pm = pdata.l_head; pm != NULL; pm = pm->l_next)
                    200:                {
                    201:                        printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n",
                    202:                               i, pm->protocol, pm->externalPort, pm->internalClient,
                    203:                               pm->internalPort,
                    204:                               pm->description, pm->remoteHost,
                    205:                               (unsigned)pm->leaseTime);
                    206:                        i++;
                    207:                }
                    208:                FreePortListing(&pdata);
                    209:        }
                    210:        else
                    211:        {
                    212:                printf("GetListOfPortMappings() returned %d (%s)\n",
                    213:                       r, strupnperror(r));
                    214:        }
                    215:        r = UPNP_GetListOfPortMappings(urls->controlURL,
                    216:                                    data->first.servicetype,
                    217:                                       "0",
                    218:                                       "65535",
                    219:                                       "UDP",
                    220:                                       "1000",
                    221:                                       &pdata);
                    222:        if(r == UPNPCOMMAND_SUCCESS)
                    223:        {
                    224:                for(pm = pdata.l_head; pm != NULL; pm = pm->l_next)
                    225:                {
                    226:                        printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n",
                    227:                               i, pm->protocol, pm->externalPort, pm->internalClient,
                    228:                               pm->internalPort,
                    229:                               pm->description, pm->remoteHost,
                    230:                               (unsigned)pm->leaseTime);
                    231:                        i++;
                    232:                }
                    233:                FreePortListing(&pdata);
                    234:        }
                    235:        else
                    236:        {
                    237:                printf("GetListOfPortMappings() returned %d (%s)\n",
                    238:                       r, strupnperror(r));
                    239:        }
                    240: }
                    241: 
                    242: /* Test function
                    243:  * 1 - get connection type
                    244:  * 2 - get extenal ip address
                    245:  * 3 - Add port mapping
                    246:  * 4 - get this port mapping from the IGD */
                    247: static int SetRedirectAndTest(struct UPNPUrls * urls,
                    248:                               struct IGDdatas * data,
                    249:                               const char * iaddr,
                    250:                               const char * iport,
                    251:                               const char * eport,
                    252:                               const char * proto,
                    253:                               const char * leaseDuration,
                    254:                               const char * remoteHost,
                    255:                               const char * description,
                    256:                               int addAny)
                    257: {
                    258:        char externalIPAddress[40];
                    259:        char intClient[40];
                    260:        char intPort[6];
                    261:        char reservedPort[6];
                    262:        char duration[16];
                    263:        int r;
                    264: 
                    265:        if(!iaddr || !iport || !eport || !proto)
                    266:        {
                    267:                fprintf(stderr, "Wrong arguments\n");
                    268:                return -1;
                    269:        }
                    270:        proto = protofix(proto);
                    271:        if(!proto)
                    272:        {
                    273:                fprintf(stderr, "invalid protocol\n");
                    274:                return -1;
                    275:        }
                    276: 
                    277:        r = UPNP_GetExternalIPAddress(urls->controlURL,
                    278:                                      data->first.servicetype,
                    279:                                      externalIPAddress);
                    280:        if(r!=UPNPCOMMAND_SUCCESS)
                    281:                printf("GetExternalIPAddress failed.\n");
                    282:        else
                    283:                printf("ExternalIPAddress = %s\n", externalIPAddress);
                    284: 
                    285:        if (addAny) {
                    286:                r = UPNP_AddAnyPortMapping(urls->controlURL, data->first.servicetype,
                    287:                                           eport, iport, iaddr, description,
                    288:                                           proto, remoteHost, leaseDuration, reservedPort);
                    289:                if(r==UPNPCOMMAND_SUCCESS)
                    290:                        eport = reservedPort;
                    291:                else
                    292:                        printf("AddAnyPortMapping(%s, %s, %s) failed with code %d (%s)\n",
                    293:                               eport, iport, iaddr, r, strupnperror(r));
                    294:        } else {
                    295:                r = UPNP_AddPortMapping(urls->controlURL, data->first.servicetype,
                    296:                                        eport, iport, iaddr, description,
                    297:                                        proto, remoteHost, leaseDuration);
                    298:                if(r!=UPNPCOMMAND_SUCCESS) {
                    299:                        printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
                    300:                               eport, iport, iaddr, r, strupnperror(r));
                    301:                        return -2;
                    302:        }
                    303:        }
                    304: 
                    305:        r = UPNP_GetSpecificPortMappingEntry(urls->controlURL,
                    306:                                             data->first.servicetype,
                    307:                                             eport, proto, remoteHost,
                    308:                                             intClient, intPort, NULL/*desc*/,
                    309:                                             NULL/*enabled*/, duration);
                    310:        if(r!=UPNPCOMMAND_SUCCESS) {
                    311:                printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n",
                    312:                       r, strupnperror(r));
                    313:                return -2;
                    314:        } else {
                    315:                printf("InternalIP:Port = %s:%s\n", intClient, intPort);
                    316:                printf("external %s:%s %s is redirected to internal %s:%s (duration=%s)\n",
                    317:                       externalIPAddress, eport, proto, intClient, intPort, duration);
                    318:        }
                    319:        return 0;
                    320: }
                    321: 
                    322: static int
                    323: RemoveRedirect(struct UPNPUrls * urls,
                    324:                struct IGDdatas * data,
                    325:                const char * eport,
                    326:                const char * proto,
                    327:                const char * remoteHost)
                    328: {
                    329:        int r;
                    330:        if(!proto || !eport)
                    331:        {
                    332:                fprintf(stderr, "invalid arguments\n");
                    333:                return -1;
                    334:        }
                    335:        proto = protofix(proto);
                    336:        if(!proto)
                    337:        {
                    338:                fprintf(stderr, "protocol invalid\n");
                    339:                return -1;
                    340:        }
                    341:        r = UPNP_DeletePortMapping(urls->controlURL, data->first.servicetype, eport, proto, remoteHost);
                    342:        if(r!=UPNPCOMMAND_SUCCESS) {
                    343:                printf("UPNP_DeletePortMapping() failed with code : %d\n", r);
                    344:                return -2;
                    345:        }else {
                    346:                printf("UPNP_DeletePortMapping() returned : %d\n", r);
                    347:        }
                    348:        return 0;
                    349: }
                    350: 
                    351: static int
                    352: RemoveRedirectRange(struct UPNPUrls * urls,
                    353:                    struct IGDdatas * data,
                    354:                    const char * ePortStart, char const * ePortEnd,
                    355:                    const char * proto, const char * manage)
                    356: {
                    357:        int r;
                    358: 
                    359:        if (!manage)
                    360:                manage = "0";
                    361: 
                    362:        if(!proto || !ePortStart || !ePortEnd)
                    363:        {
                    364:                fprintf(stderr, "invalid arguments\n");
                    365:                return -1;
                    366:        }
                    367:        proto = protofix(proto);
                    368:        if(!proto)
                    369:        {
                    370:                fprintf(stderr, "protocol invalid\n");
                    371:                return -1;
                    372:        }
                    373:        r = UPNP_DeletePortMappingRange(urls->controlURL, data->first.servicetype, ePortStart, ePortEnd, proto, manage);
                    374:        if(r!=UPNPCOMMAND_SUCCESS) {
                    375:                printf("UPNP_DeletePortMappingRange() failed with code : %d\n", r);
                    376:                return -2;
                    377:        }else {
                    378:                printf("UPNP_DeletePortMappingRange() returned : %d\n", r);
                    379:        }
                    380:        return 0;
                    381: }
                    382: 
                    383: /* IGD:2, functions for service WANIPv6FirewallControl:1 */
                    384: static void GetFirewallStatus(struct UPNPUrls * urls, struct IGDdatas * data)
                    385: {
                    386:        unsigned int bytessent, bytesreceived, packetsreceived, packetssent;
                    387:        int firewallEnabled = 0, inboundPinholeAllowed = 0;
                    388: 
                    389:        UPNP_GetFirewallStatus(urls->controlURL_6FC, data->IPv6FC.servicetype, &firewallEnabled, &inboundPinholeAllowed);
                    390:        printf("FirewallEnabled: %d & Inbound Pinhole Allowed: %d\n", firewallEnabled, inboundPinholeAllowed);
                    391:        printf("GetFirewallStatus:\n   Firewall Enabled: %s\n   Inbound Pinhole Allowed: %s\n", (firewallEnabled)? "Yes":"No", (inboundPinholeAllowed)? "Yes":"No");
                    392: 
                    393:        bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, data->CIF.servicetype);
                    394:        bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, data->CIF.servicetype);
                    395:        packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, data->CIF.servicetype);
                    396:        packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, data->CIF.servicetype);
                    397:        printf("Bytes:   Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived);
                    398:        printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived);
                    399: }
                    400: 
                    401: /* Test function
                    402:  * 1 - Add pinhole
                    403:  * 2 - Check if pinhole is working from the IGD side */
                    404: static void SetPinholeAndTest(struct UPNPUrls * urls, struct IGDdatas * data,
                    405:                                        const char * remoteaddr, const char * eport,
                    406:                                        const char * intaddr, const char * iport,
                    407:                                        const char * proto, const char * lease_time)
                    408: {
                    409:        char uniqueID[8];
                    410:        /*int isWorking = 0;*/
                    411:        int r;
                    412:        char proto_tmp[8];
                    413: 
                    414:        if(!intaddr || !remoteaddr || !iport || !eport || !proto || !lease_time)
                    415:        {
                    416:                fprintf(stderr, "Wrong arguments\n");
                    417:                return;
                    418:        }
                    419:        if(atoi(proto) == 0)
                    420:        {
                    421:                const char * protocol;
                    422:                protocol = protofix(proto);
                    423:                if(protocol && (strcmp("TCP", protocol) == 0))
                    424:                {
                    425:                        snprintf(proto_tmp, sizeof(proto_tmp), "%d", IPPROTO_TCP);
                    426:                        proto = proto_tmp;
                    427:                }
                    428:                else if(protocol && (strcmp("UDP", protocol) == 0))
                    429:                {
                    430:                        snprintf(proto_tmp, sizeof(proto_tmp), "%d", IPPROTO_UDP);
                    431:                        proto = proto_tmp;
                    432:                }
                    433:                else
                    434:                {
                    435:                        fprintf(stderr, "invalid protocol\n");
                    436:                        return;
                    437:                }
                    438:        }
                    439:        r = UPNP_AddPinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, remoteaddr, eport, intaddr, iport, proto, lease_time, uniqueID);
                    440:        if(r!=UPNPCOMMAND_SUCCESS)
                    441:                printf("AddPinhole([%s]:%s -> [%s]:%s) failed with code %d (%s)\n",
                    442:                       remoteaddr, eport, intaddr, iport, r, strupnperror(r));
                    443:        else
                    444:        {
                    445:                printf("AddPinhole: ([%s]:%s -> [%s]:%s) / Pinhole ID = %s\n",
                    446:                       remoteaddr, eport, intaddr, iport, uniqueID);
                    447:                /*r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->servicetype_6FC, uniqueID, &isWorking);
                    448:                if(r!=UPNPCOMMAND_SUCCESS)
                    449:                        printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r));
                    450:                printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No");*/
                    451:        }
                    452: }
                    453: 
                    454: /* Test function
                    455:  * 1 - Check if pinhole is working from the IGD side
                    456:  * 2 - Update pinhole */
                    457: static void GetPinholeAndUpdate(struct UPNPUrls * urls, struct IGDdatas * data,
                    458:                                        const char * uniqueID, const char * lease_time)
                    459: {
                    460:        int isWorking = 0;
                    461:        int r;
                    462: 
                    463:        if(!uniqueID || !lease_time)
                    464:        {
                    465:                fprintf(stderr, "Wrong arguments\n");
                    466:                return;
                    467:        }
                    468:        r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &isWorking);
                    469:        printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No");
                    470:        if(r!=UPNPCOMMAND_SUCCESS)
                    471:                printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r));
                    472:        if(isWorking || r==709)
                    473:        {
                    474:                r = UPNP_UpdatePinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, lease_time);
                    475:                printf("UpdatePinhole: Pinhole ID = %s with Lease Time: %s\n", uniqueID, lease_time);
                    476:                if(r!=UPNPCOMMAND_SUCCESS)
                    477:                        printf("UpdatePinhole: ID (%s) failed with code %d (%s)\n", uniqueID, r, strupnperror(r));
                    478:        }
                    479: }
                    480: 
                    481: /* Test function
                    482:  * Get pinhole timeout
                    483:  */
                    484: static void GetPinholeOutboundTimeout(struct UPNPUrls * urls, struct IGDdatas * data,
                    485:                                        const char * remoteaddr, const char * eport,
                    486:                                        const char * intaddr, const char * iport,
                    487:                                        const char * proto)
                    488: {
                    489:        int timeout = 0;
                    490:        int r;
                    491: 
                    492:        if(!intaddr || !remoteaddr || !iport || !eport || !proto)
                    493:        {
                    494:                fprintf(stderr, "Wrong arguments\n");
                    495:                return;
                    496:        }
                    497: 
                    498:        r = UPNP_GetOutboundPinholeTimeout(urls->controlURL_6FC, data->IPv6FC.servicetype, remoteaddr, eport, intaddr, iport, proto, &timeout);
                    499:        if(r!=UPNPCOMMAND_SUCCESS)
                    500:                printf("GetOutboundPinholeTimeout([%s]:%s -> [%s]:%s) failed with code %d (%s)\n",
                    501:                       intaddr, iport, remoteaddr, eport, r, strupnperror(r));
                    502:        else
                    503:                printf("GetOutboundPinholeTimeout: ([%s]:%s -> [%s]:%s) / Timeout = %d\n", intaddr, iport, remoteaddr, eport, timeout);
                    504: }
                    505: 
                    506: static void
                    507: GetPinholePackets(struct UPNPUrls * urls,
                    508:                struct IGDdatas * data, const char * uniqueID)
                    509: {
                    510:        int r, pinholePackets = 0;
                    511:        if(!uniqueID)
                    512:        {
                    513:                fprintf(stderr, "invalid arguments\n");
                    514:                return;
                    515:        }
                    516:        r = UPNP_GetPinholePackets(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &pinholePackets);
                    517:        if(r!=UPNPCOMMAND_SUCCESS)
                    518:                printf("GetPinholePackets() failed with code %d (%s)\n", r, strupnperror(r));
                    519:        else
                    520:                printf("GetPinholePackets: Pinhole ID = %s / PinholePackets = %d\n", uniqueID, pinholePackets);
                    521: }
                    522: 
                    523: static void
                    524: CheckPinhole(struct UPNPUrls * urls,
                    525:                struct IGDdatas * data, const char * uniqueID)
                    526: {
                    527:        int r, isWorking = 0;
                    528:        if(!uniqueID)
                    529:        {
                    530:                fprintf(stderr, "invalid arguments\n");
                    531:                return;
                    532:        }
                    533:        r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &isWorking);
                    534:        if(r!=UPNPCOMMAND_SUCCESS)
                    535:                printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r));
                    536:        else
                    537:                printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No");
                    538: }
                    539: 
                    540: static void
                    541: RemovePinhole(struct UPNPUrls * urls,
                    542:                struct IGDdatas * data, const char * uniqueID)
                    543: {
                    544:        int r;
                    545:        if(!uniqueID)
                    546:        {
                    547:                fprintf(stderr, "invalid arguments\n");
                    548:                return;
                    549:        }
                    550:        r = UPNP_DeletePinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID);
                    551:        printf("UPNP_DeletePinhole() returned : %d\n", r);
                    552: }
                    553: 
                    554: 
                    555: /* sample upnp client program */
                    556: int main(int argc, char ** argv)
                    557: {
                    558:        char command = 0;
                    559:        char ** commandargv = 0;
                    560:        int commandargc = 0;
                    561:        struct UPNPDev * devlist = 0;
                    562:        char lanaddr[64] = "unset";     /* my ip address on the LAN */
                    563:        int i;
                    564:        const char * rootdescurl = 0;
                    565:        const char * multicastif = 0;
                    566:        const char * minissdpdpath = 0;
                    567:        int localport = UPNP_LOCAL_PORT_ANY;
                    568:        int retcode = 0;
                    569:        int error = 0;
                    570:        int ipv6 = 0;
                    571:        int ignore = 0;
                    572:        unsigned char ttl = 2;  /* defaulting to 2 */
                    573:        const char * description = 0;
                    574: 
                    575: #ifdef _WIN32
                    576:        WSADATA wsaData;
                    577:        int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
                    578:        if(nResult != NO_ERROR)
                    579:        {
                    580:                fprintf(stderr, "WSAStartup() failed.\n");
                    581:                return -1;
                    582:        }
                    583: #endif
                    584:     printf("upnpc : miniupnpc library test client, version %s.\n", MINIUPNPC_VERSION_STRING);
                    585:        printf(" (c) 2005-2023 Thomas Bernard.\n");
                    586:     printf("Go to http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/\n"
                    587:               "for more information.\n");
                    588:        /* command line processing */
                    589:        for(i=1; i<argc; i++)
                    590:        {
                    591:                if(0 == strcmp(argv[i], "--help") || 0 == strcmp(argv[i], "-h"))
                    592:                {
                    593:                        command = 0;
                    594:                        break;
                    595:                }
                    596:                if(argv[i][0] == '-')
                    597:                {
                    598:                        if(argv[i][1] == 'u')
                    599:                                rootdescurl = argv[++i];
                    600:                        else if(argv[i][1] == 'm')
                    601:                        {
                    602:                                multicastif = argv[++i];
                    603:                                minissdpdpath = "";     /* Disable usage of minissdpd */
                    604:                        }
                    605:                        else if(argv[i][1] == 'z')
                    606:                        {
                    607:                                char junk;
                    608:                                if(sscanf(argv[++i], "%d%c", &localport, &junk)!=1 ||
                    609:                                        localport<0 || localport>65535 ||
                    610:                                   (localport >1 && localport < 1024))
                    611:                                {
                    612:                                        fprintf(stderr, "Invalid localport '%s'\n", argv[i]);
                    613:                                        localport = UPNP_LOCAL_PORT_ANY;
                    614:                                        break;
                    615:                                }
                    616:                        }
                    617:                        else if(argv[i][1] == 'p')
                    618:                                minissdpdpath = argv[++i];
                    619:                        else if(argv[i][1] == '6')
                    620:                                ipv6 = 1;
                    621:                        else if(argv[i][1] == 'e')
                    622:                                description = argv[++i];
                    623:                        else if(argv[i][1] == 't')
                    624:                                ttl = (unsigned char)atoi(argv[++i]);
                    625:                        else if(argv[i][1] == 'i')
                    626:                                ignore = 1;
                    627:                        else
                    628:                        {
                    629:                                command = argv[i][1];
                    630:                                i++;
                    631:                                commandargv = argv + i;
                    632:                                commandargc = argc - i;
                    633:                                break;
                    634:                        }
                    635:                }
                    636:                else
                    637:                {
                    638:                        fprintf(stderr, "option '%s' invalid\n", argv[i]);
                    639:                }
                    640:        }
                    641: 
                    642:        if(!command
                    643:           || (command == 'a' && commandargc<4)
                    644:           || (command == 'd' && argc<2)
                    645:           || (command == 'r' && argc<2)
                    646:           || (command == 'A' && commandargc<6)
                    647:           || (command == 'U' && commandargc<2)
                    648:           || (command == 'D' && commandargc<1))
                    649:        {
                    650:                fprintf(stderr, "Usage :\t%s [options] -a ip port external_port protocol [duration] [remote host]\n\t\tAdd port redirection\n", argv[0]);
                    651:                fprintf(stderr, "       \t%s [options] -d external_port protocol [remote host]\n\t\tDelete port redirection\n", argv[0]);
                    652:                fprintf(stderr, "       \t%s [options] -s\n\t\tGet Connection status\n", argv[0]);
                    653:                fprintf(stderr, "       \t%s [options] -l\n\t\tList redirections\n", argv[0]);
                    654:                fprintf(stderr, "       \t%s [options] -L\n\t\tList redirections (using GetListOfPortMappings (for IGD:2 only)\n", argv[0]);
                    655:                fprintf(stderr, "       \t%s [options] -n ip port external_port protocol [duration] [remote host]\n\t\tAdd (any) port redirection allowing IGD to use alternative external_port (for IGD:2 only)\n", argv[0]);
                    656:                fprintf(stderr, "       \t%s [options] -N external_port_start external_port_end protocol [manage]\n\t\tDelete range of port redirections (for IGD:2 only)\n", argv[0]);
                    657:                fprintf(stderr, "       \t%s [options] -r port1 [external_port1] protocol1 [port2 [external_port2] protocol2] [...]\n\t\tAdd all redirections to the current host\n", argv[0]);
                    658:                fprintf(stderr, "       \t%s [options] -A remote_ip remote_port internal_ip internal_port protocol lease_time\n\t\tAdd Pinhole (for IGD:2 only)\n", argv[0]);
                    659:                fprintf(stderr, "       \t%s [options] -U uniqueID new_lease_time\n\t\tUpdate Pinhole (for IGD:2 only)\n", argv[0]);
                    660:                fprintf(stderr, "       \t%s [options] -C uniqueID\n\t\tCheck if Pinhole is Working (for IGD:2 only)\n", argv[0]);
                    661:                fprintf(stderr, "       \t%s [options] -K uniqueID\n\t\tGet Number of packets going through the rule (for IGD:2 only)\n", argv[0]);
                    662:                fprintf(stderr, "       \t%s [options] -D uniqueID\n\t\tDelete Pinhole (for IGD:2 only)\n", argv[0]);
                    663:                fprintf(stderr, "       \t%s [options] -S\n\t\tGet Firewall status (for IGD:2 only)\n", argv[0]);
                    664:                fprintf(stderr, "       \t%s [options] -G remote_ip remote_port internal_ip internal_port protocol\n\t\tGet Outbound Pinhole Timeout (for IGD:2 only)\n", argv[0]);
                    665:                fprintf(stderr, "       \t%s [options] -P\n\t\tGet Presentation url\n", argv[0]);
                    666:                fprintf(stderr, "\nprotocol is UDP or TCP\n");
                    667:                fprintf(stderr, "@ can be used in option -a, -n, -A and -G to represent local LAN address.\n");
                    668:                fprintf(stderr, "Options:\n");
                    669:                fprintf(stderr, "  -e description : set description for port mapping.\n");
                    670:                fprintf(stderr, "  -6 : use ip v6 instead of ip v4.\n");
                    671:                fprintf(stderr, "  -u url : bypass discovery process by providing the XML root description url.\n");
                    672:                fprintf(stderr, "  -m address/interface : provide ip address (ip v4) or interface name (ip v4 or v6) to use for sending SSDP multicast packets.\n");
                    673:                fprintf(stderr, "  -z localport : SSDP packets local (source) port (1024-65535).\n");
                    674:                fprintf(stderr, "  -p path : use this path for MiniSSDPd socket.\n");
                    675:                fprintf(stderr, "  -t ttl : set multicast TTL. Default value is 2.\n");
                    676:                fprintf(stderr, "  -i : ignore errors and try to use also disconnected IGD or non-IGD device.\n");
                    677:                return 1;
                    678:        }
                    679: 
                    680:        if( rootdescurl
                    681:          || (devlist = upnpDiscover(2000, multicastif, minissdpdpath,
                    682:                                     localport, ipv6, ttl, &error)))
                    683:        {
                    684:                struct UPNPDev * device;
                    685:                struct UPNPUrls urls;
                    686:                struct IGDdatas data;
                    687:                if(devlist)
                    688:                {
                    689:                        printf("List of UPNP devices found on the network :\n");
                    690:                        for(device = devlist; device; device = device->pNext)
                    691:                        {
                    692:                                printf(" desc: %s\n st: %s\n\n",
                    693:                                           device->descURL, device->st);
                    694:                        }
                    695:                }
                    696:                else if(!rootdescurl)
                    697:                {
                    698:                        printf("upnpDiscover() error code=%d\n", error);
                    699:                }
                    700:                i = 1;
                    701:                if( (rootdescurl && UPNP_GetIGDFromUrl(rootdescurl, &urls, &data, lanaddr, sizeof(lanaddr)))
                    702:                  || (i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr))))
                    703:                {
                    704:                        switch(i) {
                    705:                        case 1:
                    706:                                printf("Found valid IGD : %s\n", urls.controlURL);
                    707:                                break;
                    708:                        case 2:
                    709:                                printf("Found a (not connected?) IGD : %s\n", urls.controlURL);
                    710:                                if (ignore) printf("Trying to continue anyway\n");
                    711:                                break;
                    712:                        case 3:
                    713:                                printf("UPnP device found. Is it an IGD ? : %s\n", urls.controlURL);
                    714:                                if (ignore) printf("Trying to continue anyway\n");
                    715:                                break;
                    716:                        default:
                    717:                                printf("Found device (igd ?) : %s\n", urls.controlURL);
                    718:                                if (ignore) printf("Trying to continue anyway\n");
                    719:                        }
                    720:                        if(i==1 || ignore) {
                    721: 
                    722:                        printf("Local LAN ip address : %s\n", lanaddr);
                    723:                        #if 0
                    724:                        printf("getting \"%s\"\n", urls.ipcondescURL);
                    725:                        descXML = miniwget(urls.ipcondescURL, &descXMLsize);
                    726:                        if(descXML)
                    727:                        {
                    728:                                /*fwrite(descXML, 1, descXMLsize, stdout);*/
                    729:                                free(descXML); descXML = NULL;
                    730:                        }
                    731:                        #endif
                    732: 
                    733:                        /* replace '@' with the local LAN ip address */
                    734:                        if ((command == 'a' || command == 'n') && 0 == strcmp(commandargv[0], "@"))
                    735:                                commandargv[0] = lanaddr;
                    736:                        else if ((command == 'A' || command == 'G') && 0 == strcmp(commandargv[2], "@"))
                    737:                                commandargv[2] = lanaddr;
                    738: 
                    739:                        switch(command)
                    740:                        {
                    741:                        case 'l':
                    742:                                DisplayInfos(&urls, &data);
                    743:                                ListRedirections(&urls, &data);
                    744:                                break;
                    745:                        case 'L':
                    746:                                NewListRedirections(&urls, &data);
                    747:                                break;
                    748:                        case 'a':
                    749:                                if (SetRedirectAndTest(&urls, &data,
                    750:                                                   commandargv[0], commandargv[1],
                    751:                                                   commandargv[2], commandargv[3],
                    752:                                                   (commandargc > 4) && is_int(commandargv[4]) ? commandargv[4] : "0",
                    753:                                                   (commandargc > 4) && !is_int(commandargv[4]) ? commandargv[4] : (commandargc > 5) ? commandargv[5] : NULL,
                    754:                                                   description, 0) < 0)
                    755:                                        retcode = 2;
                    756:                                break;
                    757:                        case 'd':
                    758:                                if (RemoveRedirect(&urls, &data, commandargv[0], commandargv[1],
                    759:                                               commandargc > 2 ? commandargv[2] : NULL) < 0)
                    760:                                        retcode = 2;
                    761:                                break;
                    762:                        case 'n':       /* aNy */
                    763:                                if (SetRedirectAndTest(&urls, &data,
                    764:                                                   commandargv[0], commandargv[1],
                    765:                                                   commandargv[2], commandargv[3],
                    766:                                                   (commandargc > 4) && is_int(commandargv[4]) ? commandargv[4] : "0",
                    767:                                                   (commandargc > 4) && !is_int(commandargv[4]) ? commandargv[4] : (commandargc > 5) ? commandargv[5] : NULL,
                    768:                                                   description, 1) < 0)
                    769:                                        retcode = 2;
                    770:                                break;
                    771:                        case 'N':
                    772:                                if (commandargc < 3)
                    773:                                        fprintf(stderr, "too few arguments\n");
                    774: 
                    775:                                if (RemoveRedirectRange(&urls, &data, commandargv[0], commandargv[1], commandargv[2],
                    776:                                                    commandargc > 3 ? commandargv[3] : NULL) < 0)
                    777:                                        retcode = 2;
                    778:                                break;
                    779:                        case 's':
                    780:                                GetConnectionStatus(&urls, &data);
                    781:                                break;
                    782:                        case 'r':
                    783:                                i = 0;
                    784:                                while(i<commandargc)
                    785:                                {
                    786:                                        if(!is_int(commandargv[i])) {
                    787:                                                /* 1st parameter not an integer : error */
                    788:                                                fprintf(stderr, "command -r : %s is not an port number\n", commandargv[i]);
                    789:                                                retcode = 1;
                    790:                                                break;
                    791:                                        } else if(is_int(commandargv[i+1])){
                    792:                                                /* 2nd parameter is an integer : <port> <external_port> <protocol> */
                    793:                                                if (SetRedirectAndTest(&urls, &data,
                    794:                                                                   lanaddr, commandargv[i],
                    795:                                                                   commandargv[i+1], commandargv[i+2], "0", NULL,
                    796:                                                                   description, 0) < 0)
                    797:                                                        retcode = 2;
                    798:                                                i+=3;   /* 3 parameters parsed */
                    799:                                        } else {
                    800:                                                /* 2nd parameter not an integer : <port> <protocol> */
                    801:                                                if (SetRedirectAndTest(&urls, &data,
                    802:                                                                   lanaddr, commandargv[i],
                    803:                                                                   commandargv[i], commandargv[i+1], "0", NULL,
                    804:                                                                   description, 0) < 0)
                    805:                                                        retcode = 2;
                    806:                                                i+=2;   /* 2 parameters parsed */
                    807:                                        }
                    808:                                }
                    809:                                break;
                    810:                        case 'A':
                    811:                                SetPinholeAndTest(&urls, &data,
                    812:                                                  commandargv[0], commandargv[1],
                    813:                                                  commandargv[2], commandargv[3],
                    814:                                                  commandargv[4], commandargv[5]);
                    815:                                break;
                    816:                        case 'U':
                    817:                                GetPinholeAndUpdate(&urls, &data,
                    818:                                                   commandargv[0], commandargv[1]);
                    819:                                break;
                    820:                        case 'C':
                    821:                                for(i=0; i<commandargc; i++)
                    822:                                {
                    823:                                        CheckPinhole(&urls, &data, commandargv[i]);
                    824:                                }
                    825:                                break;
                    826:                        case 'K':
                    827:                                for(i=0; i<commandargc; i++)
                    828:                                {
                    829:                                        GetPinholePackets(&urls, &data, commandargv[i]);
                    830:                                }
                    831:                                break;
                    832:                        case 'D':
                    833:                                for(i=0; i<commandargc; i++)
                    834:                                {
                    835:                                        RemovePinhole(&urls, &data, commandargv[i]);
                    836:                                }
                    837:                                break;
                    838:                        case 'S':
                    839:                                GetFirewallStatus(&urls, &data);
                    840:                                break;
                    841:                        case 'G':
                    842:                                GetPinholeOutboundTimeout(&urls, &data,
                    843:                                                        commandargv[0], commandargv[1],
                    844:                                                        commandargv[2], commandargv[3],
                    845:                                                        commandargv[4]);
                    846:                                break;
                    847:                        case 'P':
                    848:                                printf("Presentation URL found:\n");
                    849:                                printf("            %s\n", data.presentationurl);
                    850:                                break;
                    851:                        default:
                    852:                                fprintf(stderr, "Unknown switch -%c\n", command);
                    853:                                retcode = 1;
                    854:                        }
                    855: 
                    856:                        } else {
                    857:                                fprintf(stderr, "No valid UPNP Internet Gateway Device found.\n");
                    858:                                retcode = 1;
                    859:                        }
                    860:                        FreeUPNPUrls(&urls);
                    861:                }
                    862:                else
                    863:                {
                    864:                        fprintf(stderr, "No valid UPNP Internet Gateway Device found.\n");
                    865:                        retcode = 1;
                    866:                }
                    867:                freeUPNPDevlist(devlist); devlist = 0;
                    868:        }
                    869:        else
                    870:        {
                    871:                fprintf(stderr, "No IGD UPnP Device found on the network !\n");
                    872:                retcode = 1;
                    873:        }
                    874: #ifdef _WIN32
                    875:        nResult = WSACleanup();
                    876:        if(nResult != NO_ERROR) {
                    877:                fprintf(stderr, "WSACleanup() failed.\n");
                    878:        }
                    879: #endif /* _WIN32 */
                    880:        return retcode;
                    881: }
                    882: 

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