UserBridge.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. /*
  2. * Copyright (c) 2005 - 2006
  3. * CACE Technologies, Davis, CA
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without
  7. * modification, are permitted provided that the following conditions
  8. * are met:
  9. *
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * 3. Neither the name of CACE Technologies nor the names of its
  16. * contributors may be used to endorse or promote products derived from
  17. * this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. *
  31. */
  32. /*
  33. * This simple program implements a user-level bridge.
  34. * It opens two adapters specified by the user and starts two threads.
  35. * The first thread receives packets from adapter 1 and sends them down to
  36. * adapter 2. The second thread does the same, but in the opposite
  37. * direction.
  38. */
  39. #include <signal.h>
  40. #include <pcap.h>
  41. #include <tchar.h>
  42. BOOL LoadNpcapDlls()
  43. {
  44. _TCHAR npcap_dir[512];
  45. UINT len;
  46. len = GetSystemDirectory(npcap_dir, 480);
  47. if (!len) {
  48. fprintf(stderr, "Error in GetSystemDirectory: %x", GetLastError());
  49. return FALSE;
  50. }
  51. _tcscat_s(npcap_dir, 512, _T("\\Npcap"));
  52. if (SetDllDirectory(npcap_dir) == 0) {
  53. fprintf(stderr, "Error in SetDllDirectory: %x", GetLastError());
  54. return FALSE;
  55. }
  56. return TRUE;
  57. }
  58. /* Storage data structure used to pass parameters to the threads */
  59. typedef struct _in_out_adapters
  60. {
  61. unsigned int state; /* Some simple state information */
  62. pcap_t *input_adapter;
  63. pcap_t *output_adapter;
  64. }in_out_adapters;
  65. /* Prototypes */
  66. DWORD WINAPI CaptureAndForwardThread(LPVOID lpParameter);
  67. void ctrlc_handler(int sig);
  68. /* This prevents the two threads to mess-up when they do printfs */
  69. CRITICAL_SECTION print_cs;
  70. /* Thread handlers. Global because we wait on the threads from the CTRL+C handler */
  71. HANDLE threads[2];
  72. /* This global variable tells the forwarder threads they must terminate */
  73. volatile int kill_forwaders = 0;
  74. /*******************************************************************/
  75. int main()
  76. {
  77. pcap_if_t *alldevs;
  78. pcap_if_t *d;
  79. int inum1, inum2;
  80. int i=0;
  81. pcap_t *adhandle1, *adhandle2;
  82. char errbuf[PCAP_ERRBUF_SIZE];
  83. u_int netmask1, netmask2;
  84. char packet_filter[256];
  85. struct bpf_program fcode;
  86. in_out_adapters couple0, couple1;
  87. /* Load Npcap and its functions. */
  88. if (!LoadNpcapDlls())
  89. {
  90. fprintf(stderr, "Couldn't load Npcap\n");
  91. exit(1);
  92. }
  93. /*
  94. * Retrieve the device list
  95. */
  96. if (pcap_findalldevs_ex(PCAP_SRC_IF_STRING, NULL, &alldevs, errbuf) == -1)
  97. {
  98. fprintf(stderr,"Error in pcap_findalldevs: %s\n", errbuf);
  99. exit(1);
  100. }
  101. /* Print the list */
  102. for(d=alldevs; d; d=d->next)
  103. {
  104. printf("%d. ", ++i);
  105. if (d->description)
  106. printf("%s\n", d->description);
  107. else
  108. printf("<unknown adapter>\n");
  109. }
  110. if(i==0)
  111. {
  112. printf("\nNo interfaces found! Make sure Npcap is installed.\n");
  113. return -1;
  114. }
  115. /*
  116. * Get input from the user
  117. */
  118. /* Get the filter*/
  119. printf("\nSpecify filter (hit return for no filter):");
  120. fgets(packet_filter, sizeof(packet_filter), stdin);
  121. /* Get the first interface number*/
  122. printf("\nEnter the number of the first interface to use (1-%d):",i);
  123. scanf_s("%d", &inum1);
  124. if(inum1 < 1 || inum1 > i)
  125. {
  126. printf("\nInterface number out of range.\n");
  127. /* Free the device list */
  128. pcap_freealldevs(alldevs);
  129. return -1;
  130. }
  131. /* Get the second interface number*/
  132. printf("Enter the number of the first interface to use (1-%d):",i);
  133. scanf_s("%d", &inum2);
  134. if(inum2 < 1 || inum2 > i)
  135. {
  136. printf("\nInterface number out of range.\n");
  137. /* Free the device list */
  138. pcap_freealldevs(alldevs);
  139. return -1;
  140. }
  141. if(inum1 == inum2 )
  142. {
  143. printf("\nCannot bridge packets on the same interface.\n");
  144. /* Free the device list */
  145. pcap_freealldevs(alldevs);
  146. return -1;
  147. }
  148. /*
  149. * Open the specified couple of adapters
  150. */
  151. /* Jump to the first selected adapter */
  152. for(d = alldevs, i = 0; i< inum1 - 1 ;d = d->next, i++);
  153. /*
  154. * Open the first adapter.
  155. * *NOTICE* the flags we are using, they are important for the behavior of the prgram:
  156. * - PCAP_OPENFLAG_PROMISCUOUS: tells the adapter to go in promiscuous mode.
  157. * This means that we are capturing all the traffic, not only the one to or from
  158. * this machine.
  159. * - PCAP_OPENFLAG_NOCAPTURE_LOCAL: prevents the adapter from capturing again the packets
  160. * transmitted by itself. This avoids annoying loops.
  161. * - PCAP_OPENFLAG_MAX_RESPONSIVENESS: configures the adapter to provide minimum latency,
  162. * at the cost of higher CPU usage.
  163. */
  164. if((adhandle1 = pcap_open(d->name, // name of the device
  165. 65536, // portion of the packet to capture.
  166. // 65536 grants that the whole packet will be captured on every link layer.
  167. PCAP_OPENFLAG_PROMISCUOUS | // flags. We specify that we don't want to capture loopback packets, and that the driver should deliver us the packets as fast as possible
  168. PCAP_OPENFLAG_NOCAPTURE_LOCAL |
  169. PCAP_OPENFLAG_MAX_RESPONSIVENESS,
  170. 500, // read timeout
  171. NULL, // remote authentication
  172. errbuf // error buffer
  173. )) == NULL)
  174. {
  175. fprintf(stderr,"\nUnable to open the adapter. %s is not supported by Npcap\n", d->description);
  176. /* Free the device list */
  177. pcap_freealldevs(alldevs);
  178. return -1;
  179. }
  180. if(d->addresses != NULL)
  181. {
  182. /* Retrieve the mask of the first address of the interface */
  183. netmask1 = ((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
  184. }
  185. else
  186. {
  187. /* If the interface is without addresses we suppose to be in a C class network */
  188. netmask1 = 0xffffff;
  189. }
  190. /* Jump to the second selected adapter */
  191. for(d = alldevs, i = 0; i< inum2 - 1 ;d = d->next, i++);
  192. /* Open the second adapter */
  193. if((adhandle2 = pcap_open(d->name, // name of the device
  194. 65536, // portion of the packet to capture.
  195. // 65536 grants that the whole packet will be captured on every link layer.
  196. PCAP_OPENFLAG_PROMISCUOUS | // flags. We specify that we don't want to capture loopback packets, and that the driver should deliver us the packets as fast as possible
  197. PCAP_OPENFLAG_NOCAPTURE_LOCAL |
  198. PCAP_OPENFLAG_MAX_RESPONSIVENESS,
  199. 500, // read timeout
  200. NULL, // remote authentication
  201. errbuf // error buffer
  202. )) == NULL)
  203. {
  204. fprintf(stderr,"\nUnable to open the adapter. %s is not supported by Npcap\n", d->description);
  205. /* Free the device list */
  206. pcap_freealldevs(alldevs);
  207. return -1;
  208. }
  209. if(d->addresses != NULL)
  210. {
  211. /* Retrieve the mask of the first address of the interface */
  212. netmask2 = ((struct sockaddr_in *)(d->addresses->netmask))->sin_addr.S_un.S_addr;
  213. }
  214. else
  215. {
  216. /* If the interface is without addresses we suppose to be in a C class network */
  217. netmask2 = 0xffffff;
  218. }
  219. /*
  220. * Compile and set the filters
  221. */
  222. /* compile the filter for the first adapter */
  223. if (pcap_compile(adhandle1, &fcode, packet_filter, 1, netmask1) <0 )
  224. {
  225. fprintf(stderr,"\nUnable to compile the packet filter. Check the syntax.\n");
  226. /* Close the adapters */
  227. pcap_close(adhandle1);
  228. pcap_close(adhandle2);
  229. /* Free the device list */
  230. pcap_freealldevs(alldevs);
  231. return -1;
  232. }
  233. /* set the filter for the first adapter*/
  234. if (pcap_setfilter(adhandle1, &fcode)<0)
  235. {
  236. fprintf(stderr,"\nError setting the filter.\n");
  237. /* Close the adapters */
  238. pcap_close(adhandle1);
  239. pcap_close(adhandle2);
  240. /* Free the device list */
  241. pcap_freealldevs(alldevs);
  242. return -1;
  243. }
  244. /* compile the filter for the second adapter */
  245. if (pcap_compile(adhandle2, &fcode, packet_filter, 1, netmask2) <0 )
  246. {
  247. fprintf(stderr,"\nUnable to compile the packet filter. Check the syntax.\n");
  248. /* Close the adapters */
  249. pcap_close(adhandle1);
  250. pcap_close(adhandle2);
  251. /* Free the device list */
  252. pcap_freealldevs(alldevs);
  253. return -1;
  254. }
  255. /* set the filter for the second adapter*/
  256. if (pcap_setfilter(adhandle2, &fcode)<0)
  257. {
  258. fprintf(stderr,"\nError setting the filter.\n");
  259. /* Close the adapters */
  260. pcap_close(adhandle1);
  261. pcap_close(adhandle2);
  262. /* Free the device list */
  263. pcap_freealldevs(alldevs);
  264. return -1;
  265. }
  266. /* At this point, we don't need the device list any more. Free it */
  267. pcap_freealldevs(alldevs);
  268. /*
  269. * Start the threads that will forward the packets
  270. */
  271. /* Initialize the critical section that will be used by the threads for console output */
  272. InitializeCriticalSection(&print_cs);
  273. /* Init input parameters of the threads */
  274. couple0.state = 0;
  275. couple0.input_adapter = adhandle1;
  276. couple0.output_adapter = adhandle2;
  277. couple1.state = 1;
  278. couple1.input_adapter = adhandle2;
  279. couple1.output_adapter = adhandle1;
  280. /* Start first thread */
  281. if((threads[0] = CreateThread(
  282. NULL,
  283. 0,
  284. CaptureAndForwardThread,
  285. &couple0,
  286. 0,
  287. NULL)) == NULL)
  288. {
  289. fprintf(stderr, "error creating the first forward thread");
  290. /* Close the adapters */
  291. pcap_close(adhandle1);
  292. pcap_close(adhandle2);
  293. /* Free the device list */
  294. pcap_freealldevs(alldevs);
  295. return -1;
  296. }
  297. /* Start second thread */
  298. if((threads[1] = CreateThread(
  299. NULL,
  300. 0,
  301. CaptureAndForwardThread,
  302. &couple1,
  303. 0,
  304. NULL)) == NULL)
  305. {
  306. fprintf(stderr, "error creating the second forward thread");
  307. /* Kill the first thread. Not very gentle at all...*/
  308. TerminateThread(threads[0], 0);
  309. /* Close the adapters */
  310. pcap_close(adhandle1);
  311. pcap_close(adhandle2);
  312. /* Free the device list */
  313. pcap_freealldevs(alldevs);
  314. return -1;
  315. }
  316. /*
  317. * Install a CTRL+C handler that will do the cleanups on exit
  318. */
  319. signal(SIGINT, ctrlc_handler);
  320. /*
  321. * Done!
  322. * Wait for the Greek calends...
  323. */
  324. printf("\nStart bridging the two adapters...\n", d->description);
  325. Sleep(INFINITE);
  326. return 0;
  327. }
  328. /*******************************************************************
  329. * Forwarding thread.
  330. * Gets the packets from the input adapter and sends them to the output one.
  331. *******************************************************************/
  332. DWORD WINAPI CaptureAndForwardThread(LPVOID lpParameter)
  333. {
  334. struct pcap_pkthdr *header;
  335. const u_char *pkt_data;
  336. int res = 0;
  337. in_out_adapters* ad_couple = lpParameter;
  338. unsigned int n_fwd = 0;
  339. /*
  340. * Loop receiving packets from the first input adapter
  341. */
  342. while((!kill_forwaders) && (res = pcap_next_ex(ad_couple->input_adapter, &header, &pkt_data)) >= 0)
  343. {
  344. if(res != 0) /* Note: res=0 means "read timeout elapsed"*/
  345. {
  346. /*
  347. * Print something, just to show when we have activity.
  348. * BEWARE: acquiring a critical section and printing strings with printf
  349. * is something inefficient that you seriously want to avoid in your packet loop!
  350. * However, since this is a *sample program*, we privilege visual output to efficiency.
  351. */
  352. EnterCriticalSection(&print_cs);
  353. if(ad_couple->state == 0)
  354. printf(">> Len: %u\n", header->caplen);
  355. else
  356. printf("<< Len: %u\n", header->caplen);
  357. LeaveCriticalSection(&print_cs);
  358. /*
  359. * Send the just received packet to the output adaper
  360. */
  361. if(pcap_sendpacket(ad_couple->output_adapter, pkt_data, header->caplen) != 0)
  362. {
  363. EnterCriticalSection(&print_cs);
  364. printf("Error sending a %u bytes packets on interface %u: %s\n",
  365. header->caplen,
  366. ad_couple->state,
  367. pcap_geterr(ad_couple->output_adapter));
  368. LeaveCriticalSection(&print_cs);
  369. }
  370. else
  371. {
  372. n_fwd++;
  373. }
  374. }
  375. }
  376. /*
  377. * We're out of the main loop. Check the reason.
  378. */
  379. if(res < 0)
  380. {
  381. EnterCriticalSection(&print_cs);
  382. printf("Error capturing the packets: %s\n", pcap_geterr(ad_couple->input_adapter));
  383. fflush(stdout);
  384. LeaveCriticalSection(&print_cs);
  385. }
  386. else
  387. {
  388. EnterCriticalSection(&print_cs);
  389. printf("End of bridging on interface %u. Forwarded packets:%u\n",
  390. ad_couple->state,
  391. n_fwd);
  392. fflush(stdout);
  393. LeaveCriticalSection(&print_cs);
  394. }
  395. return 0;
  396. }
  397. /*******************************************************************
  398. * CTRL+C hanlder.
  399. * We order the threads to die and then we patiently wait for their
  400. * suicide.
  401. *******************************************************************/
  402. void ctrlc_handler(int sig)
  403. {
  404. /*
  405. * unused variable
  406. */
  407. (VOID)(sig);
  408. kill_forwaders = 1;
  409. WaitForMultipleObjects(2,
  410. threads,
  411. TRUE, /* Wait for all the handles */
  412. 5000); /* Timeout */
  413. exit(0);
  414. }