Annotation of embedaddon/miniupnpc/src/upnpc.c, revision 1.1

1.1     ! misho       1: /* $Id: upnpc.c,v 1.134 2023/06/11 23:23:10 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:                                       "1",
        !           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:                                       "1",
        !           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:        /* CheckPinholeWorking is an Optional Action, error 602 should be
        !           469:         * returned if it is not implemented */
        !           470:        r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &isWorking);
        !           471:        if(r==UPNPCOMMAND_SUCCESS)
        !           472:                printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No");
        !           473:        else
        !           474:                printf("CheckPinholeWorking(%s) failed with code %d (%s)\n", uniqueID, r, strupnperror(r));
        !           475:        /* 702 FirewallDisabled Firewall is disabled and this action is disabled
        !           476:         * 703 InboundPinholeNotAllowed Creation of inbound pinholes by UPnP CPs
        !           477:         *                              are not allowed and this action is disabled
        !           478:         * 704 NoSuchEntry There is no pinhole with the specified UniqueID.
        !           479:         * 709 NoTrafficReceived No traffic corresponding to this pinhole has
        !           480:         *                       been received by the gateway. */
        !           481:        if(isWorking || (r!=702 && r!=703 && r!=704))
        !           482:        {
        !           483:                r = UPNP_UpdatePinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, lease_time);
        !           484:                printf("UpdatePinhole: Pinhole ID = %s with Lease Time: %s\n", uniqueID, lease_time);
        !           485:                if(r!=UPNPCOMMAND_SUCCESS)
        !           486:                        printf("UpdatePinhole: ID (%s) failed with code %d (%s)\n", uniqueID, r, strupnperror(r));
        !           487:        }
        !           488: }
        !           489: 
        !           490: /* Test function
        !           491:  * Get pinhole timeout
        !           492:  */
        !           493: static void GetPinholeOutboundTimeout(struct UPNPUrls * urls, struct IGDdatas * data,
        !           494:                                        const char * remoteaddr, const char * eport,
        !           495:                                        const char * intaddr, const char * iport,
        !           496:                                        const char * proto)
        !           497: {
        !           498:        int timeout = 0;
        !           499:        int r;
        !           500: 
        !           501:        if(!intaddr || !remoteaddr || !iport || !eport || !proto)
        !           502:        {
        !           503:                fprintf(stderr, "Wrong arguments\n");
        !           504:                return;
        !           505:        }
        !           506: 
        !           507:        r = UPNP_GetOutboundPinholeTimeout(urls->controlURL_6FC, data->IPv6FC.servicetype, remoteaddr, eport, intaddr, iport, proto, &timeout);
        !           508:        if(r!=UPNPCOMMAND_SUCCESS)
        !           509:                printf("GetOutboundPinholeTimeout([%s]:%s -> [%s]:%s) failed with code %d (%s)\n",
        !           510:                       intaddr, iport, remoteaddr, eport, r, strupnperror(r));
        !           511:        else
        !           512:                printf("GetOutboundPinholeTimeout: ([%s]:%s -> [%s]:%s) / Timeout = %d\n", intaddr, iport, remoteaddr, eport, timeout);
        !           513: }
        !           514: 
        !           515: static void
        !           516: GetPinholePackets(struct UPNPUrls * urls,
        !           517:                struct IGDdatas * data, const char * uniqueID)
        !           518: {
        !           519:        int r, pinholePackets = 0;
        !           520:        if(!uniqueID)
        !           521:        {
        !           522:                fprintf(stderr, "invalid arguments\n");
        !           523:                return;
        !           524:        }
        !           525:        r = UPNP_GetPinholePackets(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &pinholePackets);
        !           526:        if(r!=UPNPCOMMAND_SUCCESS)
        !           527:                printf("GetPinholePackets() failed with code %d (%s)\n", r, strupnperror(r));
        !           528:        else
        !           529:                printf("GetPinholePackets: Pinhole ID = %s / PinholePackets = %d\n", uniqueID, pinholePackets);
        !           530: }
        !           531: 
        !           532: static void
        !           533: CheckPinhole(struct UPNPUrls * urls,
        !           534:                struct IGDdatas * data, const char * uniqueID)
        !           535: {
        !           536:        int r, isWorking = 0;
        !           537:        if(!uniqueID)
        !           538:        {
        !           539:                fprintf(stderr, "invalid arguments\n");
        !           540:                return;
        !           541:        }
        !           542:        r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &isWorking);
        !           543:        if(r!=UPNPCOMMAND_SUCCESS)
        !           544:                printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r));
        !           545:        else
        !           546:                printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No");
        !           547: }
        !           548: 
        !           549: static void
        !           550: RemovePinhole(struct UPNPUrls * urls,
        !           551:                struct IGDdatas * data, const char * uniqueID)
        !           552: {
        !           553:        int r;
        !           554:        if(!uniqueID)
        !           555:        {
        !           556:                fprintf(stderr, "invalid arguments\n");
        !           557:                return;
        !           558:        }
        !           559:        r = UPNP_DeletePinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID);
        !           560:        printf("UPNP_DeletePinhole() returned : %d\n", r);
        !           561: }
        !           562: 
        !           563: 
        !           564: /* sample upnp client program */
        !           565: int main(int argc, char ** argv)
        !           566: {
        !           567:        char command = 0;
        !           568:        char ** commandargv = 0;
        !           569:        int commandargc = 0;
        !           570:        struct UPNPDev * devlist = 0;
        !           571:        char lanaddr[64] = "unset";     /* my ip address on the LAN */
        !           572:        int i;
        !           573:        const char * rootdescurl = 0;
        !           574:        const char * multicastif = 0;
        !           575:        const char * minissdpdpath = 0;
        !           576:        int localport = UPNP_LOCAL_PORT_ANY;
        !           577:        int retcode = 0;
        !           578:        int error = 0;
        !           579:        int ipv6 = 0;
        !           580:        int ignore = 0;
        !           581:        unsigned char ttl = 2;  /* defaulting to 2 */
        !           582:        const char * description = 0;
        !           583: 
        !           584: #ifdef _WIN32
        !           585:        WSADATA wsaData;
        !           586:        int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
        !           587:        if(nResult != NO_ERROR)
        !           588:        {
        !           589:                fprintf(stderr, "WSAStartup() failed.\n");
        !           590:                return -1;
        !           591:        }
        !           592: #endif
        !           593:     printf("upnpc : miniupnpc library test client, version %s.\n", MINIUPNPC_VERSION_STRING);
        !           594:        printf(" (c) 2005-2023 Thomas Bernard.\n");
        !           595:     printf("Go to http://miniupnp.free.fr/ or https://miniupnp.tuxfamily.org/\n"
        !           596:               "for more information.\n");
        !           597:        /* command line processing */
        !           598:        for(i=1; i<argc; i++)
        !           599:        {
        !           600:                if(0 == strcmp(argv[i], "--help") || 0 == strcmp(argv[i], "-h"))
        !           601:                {
        !           602:                        command = 0;
        !           603:                        break;
        !           604:                }
        !           605:                if(argv[i][0] == '-')
        !           606:                {
        !           607:                        if(argv[i][1] == 'u')
        !           608:                                rootdescurl = argv[++i];
        !           609:                        else if(argv[i][1] == 'm')
        !           610:                        {
        !           611:                                multicastif = argv[++i];
        !           612:                                minissdpdpath = "";     /* Disable usage of minissdpd */
        !           613:                        }
        !           614:                        else if(argv[i][1] == 'z')
        !           615:                        {
        !           616:                                char junk;
        !           617:                                if(sscanf(argv[++i], "%d%c", &localport, &junk)!=1 ||
        !           618:                                        localport<0 || localport>65535 ||
        !           619:                                   (localport >1 && localport < 1024))
        !           620:                                {
        !           621:                                        fprintf(stderr, "Invalid localport '%s'\n", argv[i]);
        !           622:                                        localport = UPNP_LOCAL_PORT_ANY;
        !           623:                                        break;
        !           624:                                }
        !           625:                        }
        !           626:                        else if(argv[i][1] == 'p')
        !           627:                                minissdpdpath = argv[++i];
        !           628:                        else if(argv[i][1] == '6')
        !           629:                                ipv6 = 1;
        !           630:                        else if(argv[i][1] == 'e')
        !           631:                                description = argv[++i];
        !           632:                        else if(argv[i][1] == 't')
        !           633:                                ttl = (unsigned char)atoi(argv[++i]);
        !           634:                        else if(argv[i][1] == 'i')
        !           635:                                ignore = 1;
        !           636:                        else
        !           637:                        {
        !           638:                                command = argv[i][1];
        !           639:                                i++;
        !           640:                                commandargv = argv + i;
        !           641:                                commandargc = argc - i;
        !           642:                                break;
        !           643:                        }
        !           644:                }
        !           645:                else
        !           646:                {
        !           647:                        fprintf(stderr, "option '%s' invalid\n", argv[i]);
        !           648:                }
        !           649:        }
        !           650: 
        !           651:        if(!command
        !           652:           || (command == 'a' && commandargc<4)
        !           653:           || (command == 'd' && argc<2)
        !           654:           || (command == 'r' && argc<2)
        !           655:           || (command == 'A' && commandargc<6)
        !           656:           || (command == 'U' && commandargc<2)
        !           657:           || (command == 'D' && commandargc<1))
        !           658:        {
        !           659:                fprintf(stderr, "Usage :\t%s [options] -a ip port external_port protocol [duration] [remote host]\n\t\tAdd port redirection\n", argv[0]);
        !           660:                fprintf(stderr, "       \t%s [options] -d external_port protocol [remote host]\n\t\tDelete port redirection\n", argv[0]);
        !           661:                fprintf(stderr, "       \t%s [options] -s\n\t\tGet Connection status\n", argv[0]);
        !           662:                fprintf(stderr, "       \t%s [options] -l\n\t\tList redirections\n", argv[0]);
        !           663:                fprintf(stderr, "       \t%s [options] -L\n\t\tList redirections (using GetListOfPortMappings (for IGD:2 only)\n", argv[0]);
        !           664:                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]);
        !           665:                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]);
        !           666:                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]);
        !           667:                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]);
        !           668:                fprintf(stderr, "       \t%s [options] -U uniqueID new_lease_time\n\t\tUpdate Pinhole (for IGD:2 only)\n", argv[0]);
        !           669:                fprintf(stderr, "       \t%s [options] -C uniqueID\n\t\tCheck if Pinhole is Working (for IGD:2 only)\n", argv[0]);
        !           670:                fprintf(stderr, "       \t%s [options] -K uniqueID\n\t\tGet Number of packets going through the rule (for IGD:2 only)\n", argv[0]);
        !           671:                fprintf(stderr, "       \t%s [options] -D uniqueID\n\t\tDelete Pinhole (for IGD:2 only)\n", argv[0]);
        !           672:                fprintf(stderr, "       \t%s [options] -S\n\t\tGet Firewall status (for IGD:2 only)\n", argv[0]);
        !           673:                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]);
        !           674:                fprintf(stderr, "       \t%s [options] -P\n\t\tGet Presentation url\n", argv[0]);
        !           675:                fprintf(stderr, "\nprotocol is UDP or TCP\n");
        !           676:                fprintf(stderr, "@ can be used in option -a, -n, -A and -G to represent local LAN address.\n");
        !           677:                fprintf(stderr, "Options:\n");
        !           678:                fprintf(stderr, "  -e description : set description for port mapping.\n");
        !           679:                fprintf(stderr, "  -6 : use ip v6 instead of ip v4.\n");
        !           680:                fprintf(stderr, "  -u url : bypass discovery process by providing the XML root description url.\n");
        !           681:                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");
        !           682:                fprintf(stderr, "  -z localport : SSDP packets local (source) port (1024-65535).\n");
        !           683:                fprintf(stderr, "  -p path : use this path for MiniSSDPd socket.\n");
        !           684:                fprintf(stderr, "  -t ttl : set multicast TTL. Default value is 2.\n");
        !           685:                fprintf(stderr, "  -i : ignore errors and try to use also disconnected IGD or non-IGD device.\n");
        !           686:                return 1;
        !           687:        }
        !           688: 
        !           689:        if( rootdescurl
        !           690:          || (devlist = upnpDiscover(2000, multicastif, minissdpdpath,
        !           691:                                     localport, ipv6, ttl, &error)))
        !           692:        {
        !           693:                struct UPNPDev * device;
        !           694:                struct UPNPUrls urls;
        !           695:                struct IGDdatas data;
        !           696:                if(devlist)
        !           697:                {
        !           698:                        printf("List of UPNP devices found on the network :\n");
        !           699:                        for(device = devlist; device; device = device->pNext)
        !           700:                        {
        !           701:                                printf(" desc: %s\n st: %s\n\n",
        !           702:                                           device->descURL, device->st);
        !           703:                        }
        !           704:                }
        !           705:                else if(!rootdescurl)
        !           706:                {
        !           707:                        printf("upnpDiscover() error code=%d\n", error);
        !           708:                }
        !           709:                i = 1;
        !           710:                if( (rootdescurl && UPNP_GetIGDFromUrl(rootdescurl, &urls, &data, lanaddr, sizeof(lanaddr)))
        !           711:                  || (i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr))))
        !           712:                {
        !           713:                        switch(i) {
        !           714:                        case 1:
        !           715:                                printf("Found valid IGD : %s\n", urls.controlURL);
        !           716:                                break;
        !           717:                        case 2:
        !           718:                                printf("Found a (not connected?) IGD : %s\n", urls.controlURL);
        !           719:                                if (ignore) printf("Trying to continue anyway\n");
        !           720:                                break;
        !           721:                        case 3:
        !           722:                                printf("UPnP device found. Is it an IGD ? : %s\n", urls.controlURL);
        !           723:                                if (ignore) printf("Trying to continue anyway\n");
        !           724:                                break;
        !           725:                        default:
        !           726:                                printf("Found device (igd ?) : %s\n", urls.controlURL);
        !           727:                                if (ignore) printf("Trying to continue anyway\n");
        !           728:                        }
        !           729:                        if(i==1 || ignore) {
        !           730: 
        !           731:                        printf("Local LAN ip address : %s\n", lanaddr);
        !           732:                        #if 0
        !           733:                        printf("getting \"%s\"\n", urls.ipcondescURL);
        !           734:                        descXML = miniwget(urls.ipcondescURL, &descXMLsize);
        !           735:                        if(descXML)
        !           736:                        {
        !           737:                                /*fwrite(descXML, 1, descXMLsize, stdout);*/
        !           738:                                free(descXML); descXML = NULL;
        !           739:                        }
        !           740:                        #endif
        !           741: 
        !           742:                        /* replace '@' with the local LAN ip address */
        !           743:                        if ((command == 'a' || command == 'n') && 0 == strcmp(commandargv[0], "@"))
        !           744:                                commandargv[0] = lanaddr;
        !           745:                        else if ((command == 'A' || command == 'G') && 0 == strcmp(commandargv[2], "@"))
        !           746:                                commandargv[2] = lanaddr;
        !           747: 
        !           748:                        switch(command)
        !           749:                        {
        !           750:                        case 'l':
        !           751:                                DisplayInfos(&urls, &data);
        !           752:                                ListRedirections(&urls, &data);
        !           753:                                break;
        !           754:                        case 'L':
        !           755:                                NewListRedirections(&urls, &data);
        !           756:                                break;
        !           757:                        case 'a':
        !           758:                                if (SetRedirectAndTest(&urls, &data,
        !           759:                                                   commandargv[0], commandargv[1],
        !           760:                                                   commandargv[2], commandargv[3],
        !           761:                                                   (commandargc > 4) && is_int(commandargv[4]) ? commandargv[4] : "0",
        !           762:                                                   (commandargc > 4) && !is_int(commandargv[4]) ? commandargv[4] : (commandargc > 5) ? commandargv[5] : NULL,
        !           763:                                                   description, 0) < 0)
        !           764:                                        retcode = 2;
        !           765:                                break;
        !           766:                        case 'd':
        !           767:                                if (RemoveRedirect(&urls, &data, commandargv[0], commandargv[1],
        !           768:                                               commandargc > 2 ? commandargv[2] : NULL) < 0)
        !           769:                                        retcode = 2;
        !           770:                                break;
        !           771:                        case 'n':       /* aNy */
        !           772:                                if (SetRedirectAndTest(&urls, &data,
        !           773:                                                   commandargv[0], commandargv[1],
        !           774:                                                   commandargv[2], commandargv[3],
        !           775:                                                   (commandargc > 4) && is_int(commandargv[4]) ? commandargv[4] : "0",
        !           776:                                                   (commandargc > 4) && !is_int(commandargv[4]) ? commandargv[4] : (commandargc > 5) ? commandargv[5] : NULL,
        !           777:                                                   description, 1) < 0)
        !           778:                                        retcode = 2;
        !           779:                                break;
        !           780:                        case 'N':
        !           781:                                if (commandargc < 3)
        !           782:                                        fprintf(stderr, "too few arguments\n");
        !           783: 
        !           784:                                if (RemoveRedirectRange(&urls, &data, commandargv[0], commandargv[1], commandargv[2],
        !           785:                                                    commandargc > 3 ? commandargv[3] : NULL) < 0)
        !           786:                                        retcode = 2;
        !           787:                                break;
        !           788:                        case 's':
        !           789:                                GetConnectionStatus(&urls, &data);
        !           790:                                break;
        !           791:                        case 'r':
        !           792:                                i = 0;
        !           793:                                while(i<commandargc)
        !           794:                                {
        !           795:                                        if(!is_int(commandargv[i])) {
        !           796:                                                /* 1st parameter not an integer : error */
        !           797:                                                fprintf(stderr, "command -r : %s is not an port number\n", commandargv[i]);
        !           798:                                                retcode = 1;
        !           799:                                                break;
        !           800:                                        } else if(is_int(commandargv[i+1])){
        !           801:                                                /* 2nd parameter is an integer : <port> <external_port> <protocol> */
        !           802:                                                if (SetRedirectAndTest(&urls, &data,
        !           803:                                                                   lanaddr, commandargv[i],
        !           804:                                                                   commandargv[i+1], commandargv[i+2], "0", NULL,
        !           805:                                                                   description, 0) < 0)
        !           806:                                                        retcode = 2;
        !           807:                                                i+=3;   /* 3 parameters parsed */
        !           808:                                        } else {
        !           809:                                                /* 2nd parameter not an integer : <port> <protocol> */
        !           810:                                                if (SetRedirectAndTest(&urls, &data,
        !           811:                                                                   lanaddr, commandargv[i],
        !           812:                                                                   commandargv[i], commandargv[i+1], "0", NULL,
        !           813:                                                                   description, 0) < 0)
        !           814:                                                        retcode = 2;
        !           815:                                                i+=2;   /* 2 parameters parsed */
        !           816:                                        }
        !           817:                                }
        !           818:                                break;
        !           819:                        case 'A':
        !           820:                                SetPinholeAndTest(&urls, &data,
        !           821:                                                  commandargv[0], commandargv[1],
        !           822:                                                  commandargv[2], commandargv[3],
        !           823:                                                  commandargv[4], commandargv[5]);
        !           824:                                break;
        !           825:                        case 'U':
        !           826:                                GetPinholeAndUpdate(&urls, &data,
        !           827:                                                   commandargv[0], commandargv[1]);
        !           828:                                break;
        !           829:                        case 'C':
        !           830:                                for(i=0; i<commandargc; i++)
        !           831:                                {
        !           832:                                        CheckPinhole(&urls, &data, commandargv[i]);
        !           833:                                }
        !           834:                                break;
        !           835:                        case 'K':
        !           836:                                for(i=0; i<commandargc; i++)
        !           837:                                {
        !           838:                                        GetPinholePackets(&urls, &data, commandargv[i]);
        !           839:                                }
        !           840:                                break;
        !           841:                        case 'D':
        !           842:                                for(i=0; i<commandargc; i++)
        !           843:                                {
        !           844:                                        RemovePinhole(&urls, &data, commandargv[i]);
        !           845:                                }
        !           846:                                break;
        !           847:                        case 'S':
        !           848:                                GetFirewallStatus(&urls, &data);
        !           849:                                break;
        !           850:                        case 'G':
        !           851:                                GetPinholeOutboundTimeout(&urls, &data,
        !           852:                                                        commandargv[0], commandargv[1],
        !           853:                                                        commandargv[2], commandargv[3],
        !           854:                                                        commandargv[4]);
        !           855:                                break;
        !           856:                        case 'P':
        !           857:                                printf("Presentation URL found:\n");
        !           858:                                printf("            %s\n", data.presentationurl);
        !           859:                                break;
        !           860:                        default:
        !           861:                                fprintf(stderr, "Unknown switch -%c\n", command);
        !           862:                                retcode = 1;
        !           863:                        }
        !           864: 
        !           865:                        } else {
        !           866:                                fprintf(stderr, "No valid UPNP Internet Gateway Device found.\n");
        !           867:                                retcode = 1;
        !           868:                        }
        !           869:                        FreeUPNPUrls(&urls);
        !           870:                }
        !           871:                else
        !           872:                {
        !           873:                        fprintf(stderr, "No valid UPNP Internet Gateway Device found.\n");
        !           874:                        retcode = 1;
        !           875:                }
        !           876:                freeUPNPDevlist(devlist); devlist = 0;
        !           877:        }
        !           878:        else
        !           879:        {
        !           880:                fprintf(stderr, "No IGD UPnP Device found on the network !\n");
        !           881:                retcode = 1;
        !           882:        }
        !           883: #ifdef _WIN32
        !           884:        nResult = WSACleanup();
        !           885:        if(nResult != NO_ERROR) {
        !           886:                fprintf(stderr, "WSACleanup() failed.\n");
        !           887:        }
        !           888: #endif /* _WIN32 */
        !           889:        return retcode;
        !           890: }
        !           891: 

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