1 /* $Id: upnpc.c,v 1.99 2013/02/06 12:56:41 nanard Exp $ */
2 /* Project : miniupnp
3 * Author : Thomas Bernard
4 * Copyright (c) 2005-2013 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 #define snprintf _snprintf
15 #else
16 /* for IPPROTO_TCP / IPPROTO_UDP */
17 #include <netinet/in.h>
18 #endif
19 #include "miniwget.h"
20 #include "miniupnpc.h"
21 #include "upnpcommands.h"
22 #include "upnperrors.h"
23
24 /* protofix() checks if protocol is "UDP" or "TCP"
25 * returns NULL if not */
protofix(const char * proto)26 const char * protofix(const char * proto)
27 {
28 static const char proto_tcp[4] = { 'T', 'C', 'P', 0};
29 static const char proto_udp[4] = { 'U', 'D', 'P', 0};
30 int i, b;
31 for(i=0, b=1; i<4; i++)
32 b = b && ( (proto[i] == proto_tcp[i])
33 || (proto[i] == (proto_tcp[i] | 32)) );
34 if(b)
35 return proto_tcp;
36 for(i=0, b=1; i<4; i++)
37 b = b && ( (proto[i] == proto_udp[i])
38 || (proto[i] == (proto_udp[i] | 32)) );
39 if(b)
40 return proto_udp;
41 return 0;
42 }
43
DisplayInfos(struct UPNPUrls * urls,struct IGDdatas * data)44 static void DisplayInfos(struct UPNPUrls * urls,
45 struct IGDdatas * data)
46 {
47 char externalIPAddress[40];
48 char connectionType[64];
49 char status[64];
50 char lastconnerr[64];
51 unsigned int uptime;
52 unsigned int brUp, brDown;
53 time_t timenow, timestarted;
54 int r;
55 if(UPNP_GetConnectionTypeInfo(urls->controlURL,
56 data->first.servicetype,
57 connectionType) != UPNPCOMMAND_SUCCESS)
58 printf("GetConnectionTypeInfo failed.\n");
59 else
60 printf("Connection Type : %s\n", connectionType);
61 if(UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype,
62 status, &uptime, lastconnerr) != UPNPCOMMAND_SUCCESS)
63 printf("GetStatusInfo failed.\n");
64 else
65 printf("Status : %s, uptime=%us, LastConnectionError : %s\n",
66 status, uptime, lastconnerr);
67 timenow = time(NULL);
68 timestarted = timenow - uptime;
69 printf(" Time started : %s", ctime(×tarted));
70 if(UPNP_GetLinkLayerMaxBitRates(urls->controlURL_CIF, data->CIF.servicetype,
71 &brDown, &brUp) != UPNPCOMMAND_SUCCESS) {
72 printf("GetLinkLayerMaxBitRates failed.\n");
73 } else {
74 printf("MaxBitRateDown : %u bps", brDown);
75 if(brDown >= 1000000) {
76 printf(" (%u.%u Mbps)", brDown / 1000000, (brDown / 100000) % 10);
77 } else if(brDown >= 1000) {
78 printf(" (%u Kbps)", brDown / 1000);
79 }
80 printf(" MaxBitRateUp %u bps", brUp);
81 if(brUp >= 1000000) {
82 printf(" (%u.%u Mbps)", brUp / 1000000, (brUp / 100000) % 10);
83 } else if(brUp >= 1000) {
84 printf(" (%u Kbps)", brUp / 1000);
85 }
86 printf("\n");
87 }
88 r = UPNP_GetExternalIPAddress(urls->controlURL,
89 data->first.servicetype,
90 externalIPAddress);
91 if(r != UPNPCOMMAND_SUCCESS) {
92 printf("GetExternalIPAddress failed. (errorcode=%d)\n", r);
93 } else {
94 printf("ExternalIPAddress = %s\n", externalIPAddress);
95 }
96 }
97
GetConnectionStatus(struct UPNPUrls * urls,struct IGDdatas * data)98 static void GetConnectionStatus(struct UPNPUrls * urls,
99 struct IGDdatas * data)
100 {
101 unsigned int bytessent, bytesreceived, packetsreceived, packetssent;
102 DisplayInfos(urls, data);
103 bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, data->CIF.servicetype);
104 bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, data->CIF.servicetype);
105 packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, data->CIF.servicetype);
106 packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, data->CIF.servicetype);
107 printf("Bytes: Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived);
108 printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived);
109 }
110
ListRedirections(struct UPNPUrls * urls,struct IGDdatas * data)111 static void ListRedirections(struct UPNPUrls * urls,
112 struct IGDdatas * data)
113 {
114 int r;
115 int i = 0;
116 char index[6];
117 char intClient[40];
118 char intPort[6];
119 char extPort[6];
120 char protocol[4];
121 char desc[80];
122 char enabled[6];
123 char rHost[64];
124 char duration[16];
125 /*unsigned int num=0;
126 UPNP_GetPortMappingNumberOfEntries(urls->controlURL, data->servicetype, &num);
127 printf("PortMappingNumberOfEntries : %u\n", num);*/
128 printf(" i protocol exPort->inAddr:inPort description remoteHost leaseTime\n");
129 do {
130 snprintf(index, 6, "%d", i);
131 rHost[0] = '\0'; enabled[0] = '\0';
132 duration[0] = '\0'; desc[0] = '\0';
133 extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0';
134 r = UPNP_GetGenericPortMappingEntry(urls->controlURL,
135 data->first.servicetype,
136 index,
137 extPort, intClient, intPort,
138 protocol, desc, enabled,
139 rHost, duration);
140 if(r==0)
141 /*
142 printf("%02d - %s %s->%s:%s\tenabled=%s leaseDuration=%s\n"
143 " desc='%s' rHost='%s'\n",
144 i, protocol, extPort, intClient, intPort,
145 enabled, duration,
146 desc, rHost);
147 */
148 printf("%2d %s %5s->%s:%-5s '%s' '%s' %s\n",
149 i, protocol, extPort, intClient, intPort,
150 desc, rHost, duration);
151 else
152 printf("GetGenericPortMappingEntry() returned %d (%s)\n",
153 r, strupnperror(r));
154 i++;
155 } while(r==0);
156 }
157
NewListRedirections(struct UPNPUrls * urls,struct IGDdatas * data)158 static void NewListRedirections(struct UPNPUrls * urls,
159 struct IGDdatas * data)
160 {
161 int r;
162 int i = 0;
163 struct PortMappingParserData pdata;
164 struct PortMapping * pm;
165
166 memset(&pdata, 0, sizeof(struct PortMappingParserData));
167 r = UPNP_GetListOfPortMappings(urls->controlURL,
168 data->first.servicetype,
169 "0",
170 "65535",
171 "TCP",
172 "1000",
173 &pdata);
174 if(r == UPNPCOMMAND_SUCCESS)
175 {
176 printf(" i protocol exPort->inAddr:inPort description remoteHost leaseTime\n");
177 for(pm = pdata.head.lh_first; pm != NULL; pm = pm->entries.le_next)
178 {
179 printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n",
180 i, pm->protocol, pm->externalPort, pm->internalClient,
181 pm->internalPort,
182 pm->description, pm->remoteHost,
183 (unsigned)pm->leaseTime);
184 i++;
185 }
186 FreePortListing(&pdata);
187 }
188 else
189 {
190 printf("GetListOfPortMappings() returned %d (%s)\n",
191 r, strupnperror(r));
192 }
193 r = UPNP_GetListOfPortMappings(urls->controlURL,
194 data->first.servicetype,
195 "0",
196 "65535",
197 "UDP",
198 "1000",
199 &pdata);
200 if(r == UPNPCOMMAND_SUCCESS)
201 {
202 for(pm = pdata.head.lh_first; pm != NULL; pm = pm->entries.le_next)
203 {
204 printf("%2d %s %5hu->%s:%-5hu '%s' '%s' %u\n",
205 i, pm->protocol, pm->externalPort, pm->internalClient,
206 pm->internalPort,
207 pm->description, pm->remoteHost,
208 (unsigned)pm->leaseTime);
209 i++;
210 }
211 FreePortListing(&pdata);
212 }
213 else
214 {
215 printf("GetListOfPortMappings() returned %d (%s)\n",
216 r, strupnperror(r));
217 }
218 }
219
220 /* Test function
221 * 1 - get connection type
222 * 2 - get extenal ip address
223 * 3 - Add port mapping
224 * 4 - get this port mapping from the IGD */
SetRedirectAndTest(struct UPNPUrls * urls,struct IGDdatas * data,const char * iaddr,const char * iport,const char * eport,const char * proto,const char * leaseDuration,const char * description)225 static void SetRedirectAndTest(struct UPNPUrls * urls,
226 struct IGDdatas * data,
227 const char * iaddr,
228 const char * iport,
229 const char * eport,
230 const char * proto,
231 const char * leaseDuration,
232 const char * description)
233 {
234 char externalIPAddress[40];
235 char intClient[40];
236 char intPort[6];
237 char duration[16];
238 int r;
239
240 if(!iaddr || !iport || !eport || !proto)
241 {
242 fprintf(stderr, "Wrong arguments\n");
243 return;
244 }
245 proto = protofix(proto);
246 if(!proto)
247 {
248 fprintf(stderr, "invalid protocol\n");
249 return;
250 }
251
252 UPNP_GetExternalIPAddress(urls->controlURL,
253 data->first.servicetype,
254 externalIPAddress);
255 if(externalIPAddress[0])
256 printf("ExternalIPAddress = %s\n", externalIPAddress);
257 else
258 printf("GetExternalIPAddress failed.\n");
259
260 r = UPNP_AddPortMapping(urls->controlURL, data->first.servicetype,
261 eport, iport, iaddr, description,
262 proto, 0, leaseDuration);
263 if(r!=UPNPCOMMAND_SUCCESS)
264 printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
265 eport, iport, iaddr, r, strupnperror(r));
266
267 r = UPNP_GetSpecificPortMappingEntry(urls->controlURL,
268 data->first.servicetype,
269 eport, proto,
270 intClient, intPort, NULL/*desc*/,
271 NULL/*enabled*/, duration);
272 if(r!=UPNPCOMMAND_SUCCESS)
273 printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n",
274 r, strupnperror(r));
275
276 if(intClient[0]) {
277 printf("InternalIP:Port = %s:%s\n", intClient, intPort);
278 printf("external %s:%s %s is redirected to internal %s:%s (duration=%s)\n",
279 externalIPAddress, eport, proto, intClient, intPort, duration);
280 }
281 }
282
283 static void
RemoveRedirect(struct UPNPUrls * urls,struct IGDdatas * data,const char * eport,const char * proto)284 RemoveRedirect(struct UPNPUrls * urls,
285 struct IGDdatas * data,
286 const char * eport,
287 const char * proto)
288 {
289 int r;
290 if(!proto || !eport)
291 {
292 fprintf(stderr, "invalid arguments\n");
293 return;
294 }
295 proto = protofix(proto);
296 if(!proto)
297 {
298 fprintf(stderr, "protocol invalid\n");
299 return;
300 }
301 r = UPNP_DeletePortMapping(urls->controlURL, data->first.servicetype, eport, proto, 0);
302 printf("UPNP_DeletePortMapping() returned : %d\n", r);
303 }
304
305 /* IGD:2, functions for service WANIPv6FirewallControl:1 */
GetFirewallStatus(struct UPNPUrls * urls,struct IGDdatas * data)306 static void GetFirewallStatus(struct UPNPUrls * urls, struct IGDdatas * data)
307 {
308 unsigned int bytessent, bytesreceived, packetsreceived, packetssent;
309 int firewallEnabled = 0, inboundPinholeAllowed = 0;
310
311 UPNP_GetFirewallStatus(urls->controlURL_6FC, data->IPv6FC.servicetype, &firewallEnabled, &inboundPinholeAllowed);
312 printf("FirewallEnabled: %d & Inbound Pinhole Allowed: %d\n", firewallEnabled, inboundPinholeAllowed);
313 printf("GetFirewallStatus:\n Firewall Enabled: %s\n Inbound Pinhole Allowed: %s\n", (firewallEnabled)? "Yes":"No", (inboundPinholeAllowed)? "Yes":"No");
314
315 bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, data->CIF.servicetype);
316 bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, data->CIF.servicetype);
317 packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, data->CIF.servicetype);
318 packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, data->CIF.servicetype);
319 printf("Bytes: Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived);
320 printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived);
321 }
322
323 /* Test function
324 * 1 - Add pinhole
325 * 2 - Check if pinhole is working from the IGD side */
SetPinholeAndTest(struct UPNPUrls * urls,struct IGDdatas * data,const char * remoteaddr,const char * eport,const char * intaddr,const char * iport,const char * proto,const char * lease_time)326 static void SetPinholeAndTest(struct UPNPUrls * urls, struct IGDdatas * data,
327 const char * remoteaddr, const char * eport,
328 const char * intaddr, const char * iport,
329 const char * proto, const char * lease_time)
330 {
331 char uniqueID[8];
332 /*int isWorking = 0;*/
333 int r;
334 char proto_tmp[8];
335
336 if(!intaddr || !remoteaddr || !iport || !eport || !proto || !lease_time)
337 {
338 fprintf(stderr, "Wrong arguments\n");
339 return;
340 }
341 if(atoi(proto) == 0)
342 {
343 const char * protocol;
344 protocol = protofix(proto);
345 if(protocol && (strcmp("TCP", protocol) == 0))
346 {
347 snprintf(proto_tmp, sizeof(proto_tmp), "%d", IPPROTO_TCP);
348 proto = proto_tmp;
349 }
350 else if(protocol && (strcmp("UDP", protocol) == 0))
351 {
352 snprintf(proto_tmp, sizeof(proto_tmp), "%d", IPPROTO_UDP);
353 proto = proto_tmp;
354 }
355 else
356 {
357 fprintf(stderr, "invalid protocol\n");
358 return;
359 }
360 }
361 r = UPNP_AddPinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, remoteaddr, eport, intaddr, iport, proto, lease_time, uniqueID);
362 if(r!=UPNPCOMMAND_SUCCESS)
363 printf("AddPinhole([%s]:%s -> [%s]:%s) failed with code %d (%s)\n",
364 remoteaddr, eport, intaddr, iport, r, strupnperror(r));
365 else
366 {
367 printf("AddPinhole: ([%s]:%s -> [%s]:%s) / Pinhole ID = %s\n",
368 remoteaddr, eport, intaddr, iport, uniqueID);
369 /*r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->servicetype_6FC, uniqueID, &isWorking);
370 if(r!=UPNPCOMMAND_SUCCESS)
371 printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r));
372 printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No");*/
373 }
374 }
375
376 /* Test function
377 * 1 - Check if pinhole is working from the IGD side
378 * 2 - Update pinhole */
GetPinholeAndUpdate(struct UPNPUrls * urls,struct IGDdatas * data,const char * uniqueID,const char * lease_time)379 static void GetPinholeAndUpdate(struct UPNPUrls * urls, struct IGDdatas * data,
380 const char * uniqueID, const char * lease_time)
381 {
382 int isWorking = 0;
383 int r;
384
385 if(!uniqueID || !lease_time)
386 {
387 fprintf(stderr, "Wrong arguments\n");
388 return;
389 }
390 r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &isWorking);
391 printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No");
392 if(r!=UPNPCOMMAND_SUCCESS)
393 printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r));
394 if(isWorking || r==709)
395 {
396 r = UPNP_UpdatePinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, lease_time);
397 printf("UpdatePinhole: Pinhole ID = %s with Lease Time: %s\n", uniqueID, lease_time);
398 if(r!=UPNPCOMMAND_SUCCESS)
399 printf("UpdatePinhole: ID (%s) failed with code %d (%s)\n", uniqueID, r, strupnperror(r));
400 }
401 }
402
403 /* Test function
404 * Get pinhole timeout
405 */
GetPinholeOutboundTimeout(struct UPNPUrls * urls,struct IGDdatas * data,const char * remoteaddr,const char * eport,const char * intaddr,const char * iport,const char * proto)406 static void GetPinholeOutboundTimeout(struct UPNPUrls * urls, struct IGDdatas * data,
407 const char * remoteaddr, const char * eport,
408 const char * intaddr, const char * iport,
409 const char * proto)
410 {
411 int timeout = 0;
412 int r;
413
414 if(!intaddr || !remoteaddr || !iport || !eport || !proto)
415 {
416 fprintf(stderr, "Wrong arguments\n");
417 return;
418 }
419
420 r = UPNP_GetOutboundPinholeTimeout(urls->controlURL_6FC, data->IPv6FC.servicetype, remoteaddr, eport, intaddr, iport, proto, &timeout);
421 if(r!=UPNPCOMMAND_SUCCESS)
422 printf("GetOutboundPinholeTimeout([%s]:%s -> [%s]:%s) failed with code %d (%s)\n",
423 intaddr, iport, remoteaddr, eport, r, strupnperror(r));
424 else
425 printf("GetOutboundPinholeTimeout: ([%s]:%s -> [%s]:%s) / Timeout = %d\n", intaddr, iport, remoteaddr, eport, timeout);
426 }
427
428 static void
GetPinholePackets(struct UPNPUrls * urls,struct IGDdatas * data,const char * uniqueID)429 GetPinholePackets(struct UPNPUrls * urls,
430 struct IGDdatas * data, const char * uniqueID)
431 {
432 int r, pinholePackets = 0;
433 if(!uniqueID)
434 {
435 fprintf(stderr, "invalid arguments\n");
436 return;
437 }
438 r = UPNP_GetPinholePackets(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &pinholePackets);
439 if(r!=UPNPCOMMAND_SUCCESS)
440 printf("GetPinholePackets() failed with code %d (%s)\n", r, strupnperror(r));
441 else
442 printf("GetPinholePackets: Pinhole ID = %s / PinholePackets = %d\n", uniqueID, pinholePackets);
443 }
444
445 static void
CheckPinhole(struct UPNPUrls * urls,struct IGDdatas * data,const char * uniqueID)446 CheckPinhole(struct UPNPUrls * urls,
447 struct IGDdatas * data, const char * uniqueID)
448 {
449 int r, isWorking = 0;
450 if(!uniqueID)
451 {
452 fprintf(stderr, "invalid arguments\n");
453 return;
454 }
455 r = UPNP_CheckPinholeWorking(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID, &isWorking);
456 if(r!=UPNPCOMMAND_SUCCESS)
457 printf("CheckPinholeWorking() failed with code %d (%s)\n", r, strupnperror(r));
458 else
459 printf("CheckPinholeWorking: Pinhole ID = %s / IsWorking = %s\n", uniqueID, (isWorking)? "Yes":"No");
460 }
461
462 static void
RemovePinhole(struct UPNPUrls * urls,struct IGDdatas * data,const char * uniqueID)463 RemovePinhole(struct UPNPUrls * urls,
464 struct IGDdatas * data, const char * uniqueID)
465 {
466 int r;
467 if(!uniqueID)
468 {
469 fprintf(stderr, "invalid arguments\n");
470 return;
471 }
472 r = UPNP_DeletePinhole(urls->controlURL_6FC, data->IPv6FC.servicetype, uniqueID);
473 printf("UPNP_DeletePinhole() returned : %d\n", r);
474 }
475
476
477 /* sample upnp client program */
main(int argc,char ** argv)478 int main(int argc, char ** argv)
479 {
480 char command = 0;
481 char ** commandargv = 0;
482 int commandargc = 0;
483 struct UPNPDev * devlist = 0;
484 char lanaddr[64]; /* my ip address on the LAN */
485 int i;
486 const char * rootdescurl = 0;
487 const char * multicastif = 0;
488 const char * minissdpdpath = 0;
489 int retcode = 0;
490 int error = 0;
491 int ipv6 = 0;
492 const char * description = 0;
493
494 #ifdef _WIN32
495 WSADATA wsaData;
496 int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
497 if(nResult != NO_ERROR)
498 {
499 fprintf(stderr, "WSAStartup() failed.\n");
500 return -1;
501 }
502 #endif
503 printf("upnpc : miniupnpc library test client. (c) 2005-2013 Thomas Bernard\n");
504 printf("Go to http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/\n"
505 "for more information.\n");
506 /* command line processing */
507 for(i=1; i<argc; i++)
508 {
509 if(argv[i][0] == '-')
510 {
511 if(argv[i][1] == 'u')
512 rootdescurl = argv[++i];
513 else if(argv[i][1] == 'm')
514 multicastif = argv[++i];
515 else if(argv[i][1] == 'p')
516 minissdpdpath = argv[++i];
517 else if(argv[i][1] == '6')
518 ipv6 = 1;
519 else if(argv[i][1] == 'e')
520 description = argv[++i];
521 else
522 {
523 command = argv[i][1];
524 i++;
525 commandargv = argv + i;
526 commandargc = argc - i;
527 break;
528 }
529 }
530 else
531 {
532 fprintf(stderr, "option '%s' invalid\n", argv[i]);
533 }
534 }
535
536 if(!command || (command == 'a' && commandargc<4)
537 || (command == 'd' && argc<2)
538 || (command == 'r' && argc<2)
539 || (command == 'A' && commandargc<6)
540 || (command == 'U' && commandargc<2)
541 || (command == 'D' && commandargc<1))
542 {
543 fprintf(stderr, "Usage :\t%s [options] -a ip port external_port protocol [duration]\n\t\tAdd port redirection\n", argv[0]);
544 fprintf(stderr, " \t%s [options] -d external_port protocol [port2 protocol2] [...]\n\t\tDelete port redirection\n", argv[0]);
545 fprintf(stderr, " \t%s [options] -s\n\t\tGet Connection status\n", argv[0]);
546 fprintf(stderr, " \t%s [options] -l\n\t\tList redirections\n", argv[0]);
547 fprintf(stderr, " \t%s [options] -L\n\t\tList redirections (using GetListOfPortMappings, IGD v2)\n", argv[0]);
548 fprintf(stderr, " \t%s [options] -r port1 protocol1 [port2 protocol2] [...]\n\t\tAdd all redirections to the current host\n", argv[0]);
549 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]);
550 fprintf(stderr, " \t%s [options] -U uniqueID new_lease_time\n\t\tUpdate Pinhole (for IGD:2 only)\n", argv[0]);
551 fprintf(stderr, " \t%s [options] -C uniqueID\n\t\tCheck if Pinhole is Working (for IGD:2 only)\n", argv[0]);
552 fprintf(stderr, " \t%s [options] -K uniqueID\n\t\tGet Number of packets going through the rule (for IGD:2 only)\n", argv[0]);
553 fprintf(stderr, " \t%s [options] -D uniqueID\n\t\tDelete Pinhole (for IGD:2 only)\n", argv[0]);
554 fprintf(stderr, " \t%s [options] -S\n\t\tGet Firewall status (for IGD:2 only)\n", argv[0]);
555 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]);
556 fprintf(stderr, " \t%s [options] -P\n\t\tGet Presentation url\n", argv[0]);
557 fprintf(stderr, "\nprotocol is UDP or TCP\n");
558 fprintf(stderr, "Options:\n");
559 fprintf(stderr, " -e description : set description for port mapping.\n");
560 fprintf(stderr, " -6 : use ip v6 instead of ip v4.\n");
561 fprintf(stderr, " -u url : bypass discovery process by providing the XML root description url.\n");
562 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");
563 fprintf(stderr, " -p path : use this path for MiniSSDPd socket.\n");
564 return 1;
565 }
566
567 if( rootdescurl
568 || (devlist = upnpDiscover(2000, multicastif, minissdpdpath,
569 0/*sameport*/, ipv6, &error)))
570 {
571 struct UPNPDev * device;
572 struct UPNPUrls urls;
573 struct IGDdatas data;
574 if(devlist)
575 {
576 printf("List of UPNP devices found on the network :\n");
577 for(device = devlist; device; device = device->pNext)
578 {
579 printf(" desc: %s\n st: %s\n\n",
580 device->descURL, device->st);
581 }
582 }
583 else
584 {
585 printf("upnpDiscover() error code=%d\n", error);
586 }
587 i = 1;
588 if( (rootdescurl && UPNP_GetIGDFromUrl(rootdescurl, &urls, &data, lanaddr, sizeof(lanaddr)))
589 || (i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr))))
590 {
591 switch(i) {
592 case 1:
593 printf("Found valid IGD : %s\n", urls.controlURL);
594 break;
595 case 2:
596 printf("Found a (not connected?) IGD : %s\n", urls.controlURL);
597 printf("Trying to continue anyway\n");
598 break;
599 case 3:
600 printf("UPnP device found. Is it an IGD ? : %s\n", urls.controlURL);
601 printf("Trying to continue anyway\n");
602 break;
603 default:
604 printf("Found device (igd ?) : %s\n", urls.controlURL);
605 printf("Trying to continue anyway\n");
606 }
607 printf("Local LAN ip address : %s\n", lanaddr);
608 #if 0
609 printf("getting \"%s\"\n", urls.ipcondescURL);
610 descXML = miniwget(urls.ipcondescURL, &descXMLsize);
611 if(descXML)
612 {
613 /*fwrite(descXML, 1, descXMLsize, stdout);*/
614 free(descXML); descXML = NULL;
615 }
616 #endif
617
618 switch(command)
619 {
620 case 'l':
621 DisplayInfos(&urls, &data);
622 ListRedirections(&urls, &data);
623 break;
624 case 'L':
625 NewListRedirections(&urls, &data);
626 break;
627 case 'a':
628 SetRedirectAndTest(&urls, &data,
629 commandargv[0], commandargv[1],
630 commandargv[2], commandargv[3],
631 (commandargc > 4)?commandargv[4]:"0",
632 description);
633 break;
634 case 'd':
635 for(i=0; i<commandargc; i+=2)
636 {
637 RemoveRedirect(&urls, &data, commandargv[i], commandargv[i+1]);
638 }
639 break;
640 case 's':
641 GetConnectionStatus(&urls, &data);
642 break;
643 case 'r':
644 for(i=0; i<commandargc; i+=2)
645 {
646 /*printf("port %s protocol %s\n", argv[i], argv[i+1]);*/
647 SetRedirectAndTest(&urls, &data,
648 lanaddr, commandargv[i],
649 commandargv[i], commandargv[i+1], "0",
650 description);
651 }
652 break;
653 case 'A':
654 SetPinholeAndTest(&urls, &data,
655 commandargv[0], commandargv[1],
656 commandargv[2], commandargv[3],
657 commandargv[4], commandargv[5]);
658 break;
659 case 'U':
660 GetPinholeAndUpdate(&urls, &data,
661 commandargv[0], commandargv[1]);
662 break;
663 case 'C':
664 for(i=0; i<commandargc; i++)
665 {
666 CheckPinhole(&urls, &data, commandargv[i]);
667 }
668 break;
669 case 'K':
670 for(i=0; i<commandargc; i++)
671 {
672 GetPinholePackets(&urls, &data, commandargv[i]);
673 }
674 break;
675 case 'D':
676 for(i=0; i<commandargc; i++)
677 {
678 RemovePinhole(&urls, &data, commandargv[i]);
679 }
680 break;
681 case 'S':
682 GetFirewallStatus(&urls, &data);
683 break;
684 case 'G':
685 GetPinholeOutboundTimeout(&urls, &data,
686 commandargv[0], commandargv[1],
687 commandargv[2], commandargv[3],
688 commandargv[4]);
689 break;
690 case 'P':
691 printf("Presentation URL found:\n");
692 printf(" %s\n", data.presentationurl);
693 break;
694 default:
695 fprintf(stderr, "Unknown switch -%c\n", command);
696 retcode = 1;
697 }
698
699 FreeUPNPUrls(&urls);
700 }
701 else
702 {
703 fprintf(stderr, "No valid UPNP Internet Gateway Device found.\n");
704 retcode = 1;
705 }
706 freeUPNPDevlist(devlist); devlist = 0;
707 }
708 else
709 {
710 fprintf(stderr, "No IGD UPnP Device found on the network !\n");
711 retcode = 1;
712 }
713 return retcode;
714 }
715
716