upnpc.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. /* $Id: upnpc.c,v 1.72 2010/05/29 09:21:12 nanard Exp $ */
  2. /* Project : miniupnp
  3. * Author : Thomas Bernard
  4. * Copyright (c) 2005-2010 Thomas Bernard
  5. * This software is subject to the conditions detailed in the
  6. * LICENCE file provided in this distribution. */
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <time.h>
  11. #ifdef WIN32
  12. #include <winsock2.h>
  13. #define snprintf _snprintf
  14. #endif
  15. #include "miniwget.h"
  16. #include "miniupnpc.h"
  17. #include "upnpcommands.h"
  18. #include "upnperrors.h"
  19. /* protofix() checks if protocol is "UDP" or "TCP"
  20. * returns NULL if not */
  21. const char * protofix(const char * proto)
  22. {
  23. static const char proto_tcp[4] = { 'T', 'C', 'P', 0};
  24. static const char proto_udp[4] = { 'U', 'D', 'P', 0};
  25. int i, b;
  26. for(i=0, b=1; i<4; i++)
  27. b = b && ( (proto[i] == proto_tcp[i])
  28. || (proto[i] == (proto_tcp[i] | 32)) );
  29. if(b)
  30. return proto_tcp;
  31. for(i=0, b=1; i<4; i++)
  32. b = b && ( (proto[i] == proto_udp[i])
  33. || (proto[i] == (proto_udp[i] | 32)) );
  34. if(b)
  35. return proto_udp;
  36. return 0;
  37. }
  38. static void DisplayInfos(struct UPNPUrls * urls,
  39. struct IGDdatas * data)
  40. {
  41. char externalIPAddress[16];
  42. char connectionType[64];
  43. char status[64];
  44. char lastconnerr[64];
  45. unsigned int uptime;
  46. unsigned int brUp, brDown;
  47. time_t timenow, timestarted;
  48. int r;
  49. UPNP_GetConnectionTypeInfo(urls->controlURL,
  50. data->first.servicetype,
  51. connectionType);
  52. if(connectionType[0])
  53. printf("Connection Type : %s\n", connectionType);
  54. else
  55. printf("GetConnectionTypeInfo failed.\n");
  56. UPNP_GetStatusInfo(urls->controlURL, data->first.servicetype,
  57. status, &uptime, lastconnerr);
  58. printf("Status : %s, uptime=%us, LastConnectionError : %s\n",
  59. status, uptime, lastconnerr);
  60. timenow = time(NULL);
  61. timestarted = timenow - uptime;
  62. printf(" Time started : %s", ctime(&timestarted));
  63. UPNP_GetLinkLayerMaxBitRates(urls->controlURL_CIF, data->CIF.servicetype,
  64. &brDown, &brUp);
  65. printf("MaxBitRateDown : %u bps MaxBitRateUp %u bps\n", brDown, brUp);
  66. r = UPNP_GetExternalIPAddress(urls->controlURL,
  67. data->first.servicetype,
  68. externalIPAddress);
  69. if(r != UPNPCOMMAND_SUCCESS)
  70. printf("GetExternalIPAddress() returned %d\n", r);
  71. if(externalIPAddress[0])
  72. printf("ExternalIPAddress = %s\n", externalIPAddress);
  73. else
  74. printf("GetExternalIPAddress failed.\n");
  75. }
  76. static void GetConnectionStatus(struct UPNPUrls * urls,
  77. struct IGDdatas * data)
  78. {
  79. unsigned int bytessent, bytesreceived, packetsreceived, packetssent;
  80. DisplayInfos(urls, data);
  81. bytessent = UPNP_GetTotalBytesSent(urls->controlURL_CIF, data->CIF.servicetype);
  82. bytesreceived = UPNP_GetTotalBytesReceived(urls->controlURL_CIF, data->CIF.servicetype);
  83. packetssent = UPNP_GetTotalPacketsSent(urls->controlURL_CIF, data->CIF.servicetype);
  84. packetsreceived = UPNP_GetTotalPacketsReceived(urls->controlURL_CIF, data->CIF.servicetype);
  85. printf("Bytes: Sent: %8u\tRecv: %8u\n", bytessent, bytesreceived);
  86. printf("Packets: Sent: %8u\tRecv: %8u\n", packetssent, packetsreceived);
  87. }
  88. static void ListRedirections(struct UPNPUrls * urls,
  89. struct IGDdatas * data)
  90. {
  91. int r;
  92. int i = 0;
  93. char index[6];
  94. char intClient[16];
  95. char intPort[6];
  96. char extPort[6];
  97. char protocol[4];
  98. char desc[80];
  99. char enabled[6];
  100. char rHost[64];
  101. char duration[16];
  102. /*unsigned int num=0;
  103. UPNP_GetPortMappingNumberOfEntries(urls->controlURL, data->servicetype, &num);
  104. printf("PortMappingNumberOfEntries : %u\n", num);*/
  105. do {
  106. snprintf(index, 6, "%d", i);
  107. rHost[0] = '\0'; enabled[0] = '\0';
  108. duration[0] = '\0'; desc[0] = '\0';
  109. extPort[0] = '\0'; intPort[0] = '\0'; intClient[0] = '\0';
  110. r = UPNP_GetGenericPortMappingEntry(urls->controlURL,
  111. data->first.servicetype,
  112. index,
  113. extPort, intClient, intPort,
  114. protocol, desc, enabled,
  115. rHost, duration);
  116. if(r==0)
  117. /*
  118. printf("%02d - %s %s->%s:%s\tenabled=%s leaseDuration=%s\n"
  119. " desc='%s' rHost='%s'\n",
  120. i, protocol, extPort, intClient, intPort,
  121. enabled, duration,
  122. desc, rHost);
  123. */
  124. printf("%2d %s %5s->%s:%-5s '%s' '%s'\n",
  125. i, protocol, extPort, intClient, intPort,
  126. desc, rHost);
  127. else
  128. printf("GetGenericPortMappingEntry() returned %d (%s)\n",
  129. r, strupnperror(r));
  130. i++;
  131. } while(r==0);
  132. }
  133. /* Test function
  134. * 1 - get connection type
  135. * 2 - get extenal ip address
  136. * 3 - Add port mapping
  137. * 4 - get this port mapping from the IGD */
  138. static void SetRedirectAndTest(struct UPNPUrls * urls,
  139. struct IGDdatas * data,
  140. const char * iaddr,
  141. const char * iport,
  142. const char * eport,
  143. const char * proto)
  144. {
  145. char externalIPAddress[16];
  146. char intClient[16];
  147. char intPort[6];
  148. int r;
  149. if(!iaddr || !iport || !eport || !proto)
  150. {
  151. fprintf(stderr, "Wrong arguments\n");
  152. return;
  153. }
  154. proto = protofix(proto);
  155. if(!proto)
  156. {
  157. fprintf(stderr, "invalid protocol\n");
  158. return;
  159. }
  160. UPNP_GetExternalIPAddress(urls->controlURL,
  161. data->first.servicetype,
  162. externalIPAddress);
  163. if(externalIPAddress[0])
  164. printf("ExternalIPAddress = %s\n", externalIPAddress);
  165. else
  166. printf("GetExternalIPAddress failed.\n");
  167. r = UPNP_AddPortMapping(urls->controlURL, data->first.servicetype,
  168. eport, iport, iaddr, 0, proto, 0);
  169. if(r!=UPNPCOMMAND_SUCCESS)
  170. printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n",
  171. eport, iport, iaddr, r, strupnperror(r));
  172. r = UPNP_GetSpecificPortMappingEntry(urls->controlURL,
  173. data->first.servicetype,
  174. eport, proto,
  175. intClient, intPort);
  176. if(r!=UPNPCOMMAND_SUCCESS)
  177. printf("GetSpecificPortMappingEntry() failed with code %d (%s)\n",
  178. r, strupnperror(r));
  179. if(intClient[0]) {
  180. printf("InternalIP:Port = %s:%s\n", intClient, intPort);
  181. printf("external %s:%s %s is redirected to internal %s:%s\n",
  182. externalIPAddress, eport, proto, intClient, intPort);
  183. }
  184. }
  185. static void
  186. RemoveRedirect(struct UPNPUrls * urls,
  187. struct IGDdatas * data,
  188. const char * eport,
  189. const char * proto)
  190. {
  191. int r;
  192. if(!proto || !eport)
  193. {
  194. fprintf(stderr, "invalid arguments\n");
  195. return;
  196. }
  197. proto = protofix(proto);
  198. if(!proto)
  199. {
  200. fprintf(stderr, "protocol invalid\n");
  201. return;
  202. }
  203. r = UPNP_DeletePortMapping(urls->controlURL, data->first.servicetype, eport, proto, 0);
  204. printf("UPNP_DeletePortMapping() returned : %d\n", r);
  205. }
  206. /* sample upnp client program */
  207. int main(int argc, char ** argv)
  208. {
  209. char command = 0;
  210. char ** commandargv = 0;
  211. int commandargc = 0;
  212. struct UPNPDev * devlist = 0;
  213. char lanaddr[64]; /* my ip address on the LAN */
  214. int i;
  215. const char * rootdescurl = 0;
  216. const char * multicastif = 0;
  217. const char * minissdpdpath = 0;
  218. int retcode = 0;
  219. #ifdef WIN32
  220. WSADATA wsaData;
  221. int nResult = WSAStartup(MAKEWORD(2,2), &wsaData);
  222. if(nResult != NO_ERROR)
  223. {
  224. fprintf(stderr, "WSAStartup() failed.\n");
  225. return -1;
  226. }
  227. #endif
  228. printf("upnpc : miniupnpc library test client. (c) 2006-2010 Thomas Bernard\n");
  229. printf("Go to http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/\n"
  230. "for more information.\n");
  231. /* command line processing */
  232. for(i=1; i<argc; i++)
  233. {
  234. if(argv[i][0] == '-')
  235. {
  236. if(argv[i][1] == 'u')
  237. rootdescurl = argv[++i];
  238. else if(argv[i][1] == 'm')
  239. multicastif = argv[++i];
  240. else if(argv[i][1] == 'p')
  241. minissdpdpath = argv[++i];
  242. else
  243. {
  244. command = argv[i][1];
  245. i++;
  246. commandargv = argv + i;
  247. commandargc = argc - i;
  248. break;
  249. }
  250. }
  251. else
  252. {
  253. fprintf(stderr, "option '%s' invalid\n", argv[i]);
  254. }
  255. }
  256. if(!command || (command == 'a' && commandargc<4)
  257. || (command == 'd' && argc<2)
  258. || (command == 'r' && argc<2))
  259. {
  260. fprintf(stderr, "Usage :\t%s [options] -a ip port external_port protocol\n\t\tAdd port redirection\n", argv[0]);
  261. fprintf(stderr, " \t%s [options] -d external_port protocol [port2 protocol2] [...]\n\t\tDelete port redirection\n", argv[0]);
  262. fprintf(stderr, " \t%s [options] -s\n\t\tGet Connection status\n", argv[0]);
  263. fprintf(stderr, " \t%s [options] -l\n\t\tList redirections\n", argv[0]);
  264. fprintf(stderr, " \t%s [options] -r port1 protocol1 [port2 protocol2] [...]\n\t\tAdd all redirections to the current host\n", argv[0]);
  265. fprintf(stderr, "\nprotocol is UDP or TCP\n");
  266. fprintf(stderr, "Options:\n");
  267. fprintf(stderr, " -u url : bypass discovery process by providing the XML root description url.\n");
  268. fprintf(stderr, " -m address : provide ip address of the interface to use for sending SSDP multicast packets.\n");
  269. fprintf(stderr, " -p path : use this path for MiniSSDPd socket.\n");
  270. return 1;
  271. }
  272. if( rootdescurl
  273. || (devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0)))
  274. {
  275. struct UPNPDev * device;
  276. struct UPNPUrls urls;
  277. struct IGDdatas data;
  278. if(devlist)
  279. {
  280. printf("List of UPNP devices found on the network :\n");
  281. for(device = devlist; device; device = device->pNext)
  282. {
  283. printf(" desc: %s\n st: %s\n\n",
  284. device->descURL, device->st);
  285. }
  286. }
  287. i = 1;
  288. if( (rootdescurl && UPNP_GetIGDFromUrl(rootdescurl, &urls, &data, lanaddr, sizeof(lanaddr)))
  289. || (i = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr))))
  290. {
  291. switch(i) {
  292. case 1:
  293. printf("Found valid IGD : %s\n", urls.controlURL);
  294. break;
  295. case 2:
  296. printf("Found a (not connected?) IGD : %s\n", urls.controlURL);
  297. printf("Trying to continue anyway\n");
  298. break;
  299. case 3:
  300. printf("UPnP device found. Is it an IGD ? : %s\n", urls.controlURL);
  301. printf("Trying to continue anyway\n");
  302. break;
  303. default:
  304. printf("Found device (igd ?) : %s\n", urls.controlURL);
  305. printf("Trying to continue anyway\n");
  306. }
  307. printf("Local LAN ip address : %s\n", lanaddr);
  308. #if 0
  309. printf("getting \"%s\"\n", urls.ipcondescURL);
  310. descXML = miniwget(urls.ipcondescURL, &descXMLsize);
  311. if(descXML)
  312. {
  313. /*fwrite(descXML, 1, descXMLsize, stdout);*/
  314. free(descXML); descXML = NULL;
  315. }
  316. #endif
  317. switch(command)
  318. {
  319. case 'l':
  320. DisplayInfos(&urls, &data);
  321. ListRedirections(&urls, &data);
  322. break;
  323. case 'a':
  324. SetRedirectAndTest(&urls, &data,
  325. commandargv[0], commandargv[1],
  326. commandargv[2], commandargv[3]);
  327. break;
  328. case 'd':
  329. for(i=0; i<commandargc; i+=2)
  330. {
  331. RemoveRedirect(&urls, &data, commandargv[i], commandargv[i+1]);
  332. }
  333. break;
  334. case 's':
  335. GetConnectionStatus(&urls, &data);
  336. break;
  337. case 'r':
  338. for(i=0; i<commandargc; i+=2)
  339. {
  340. /*printf("port %s protocol %s\n", argv[i], argv[i+1]);*/
  341. SetRedirectAndTest(&urls, &data,
  342. lanaddr, commandargv[i],
  343. commandargv[i], commandargv[i+1]);
  344. }
  345. break;
  346. default:
  347. fprintf(stderr, "Unknown switch -%c\n", command);
  348. retcode = 1;
  349. }
  350. FreeUPNPUrls(&urls);
  351. }
  352. else
  353. {
  354. fprintf(stderr, "No valid UPNP Internet Gateway Device found.\n");
  355. retcode = 1;
  356. }
  357. freeUPNPDevlist(devlist); devlist = 0;
  358. }
  359. else
  360. {
  361. fprintf(stderr, "No IGD UPnP Device found on the network !\n");
  362. retcode = 1;
  363. }
  364. return retcode;
  365. }
粤ICP备19079148号