Annotation of embedaddon/miniupnpc/src/upnpc.c, revision 1.1.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>