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(×tarted));
! 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>