PageRenderTime 169ms CodeModel.GetById 60ms app.highlight 78ms RepoModel.GetById 23ms app.codeStats 0ms

/thirdparty/libportfwd/third-party/miniupnpc-1.6/upnpc.c

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