gnunet-helper-transport-wlan-dummy.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. /*
  2. This file is part of GNUnet.
  3. (C) 2010, 2012 Christian Grothoff (and other contributing authors)
  4. GNUnet is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published
  6. by the Free Software Foundation; either version 3, or (at your
  7. option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNUnet; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  15. Boston, MA 02111-1307, USA.
  16. */
  17. /**
  18. * @file transport/gnunet-helper-transport-wlan-dummy.c
  19. * @brief helper for the testcases for plugin_transport_wlan.c
  20. * @author David Brodski
  21. */
  22. #include "platform.h"
  23. #include "gnunet_protocols.h"
  24. #include "gnunet_util_lib.h"
  25. #include "plugin_transport_wlan.h"
  26. /**
  27. * Name of the fifo to use for IPC with the other dummy process.
  28. */
  29. #define FIFO_FILE1 "/tmp/test-transport/api-wlan-p1/WLAN_FIFO_in"
  30. /**
  31. * Name of the fifo to use for IPC with the other dummy process.
  32. */
  33. #define FIFO_FILE2 "/tmp/test-transport/api-wlan-p1/WLAN_FIFO_out"
  34. /**
  35. * Maximum size of a message allowed in either direction
  36. * (used for our receive and sent buffers).
  37. */
  38. #define MAXLINE 4096
  39. /**
  40. * IO buffer used for buffering data in transit.
  41. */
  42. struct SendBuffer
  43. {
  44. /**
  45. * How many bytes that were stored in 'buf' did we already write to the
  46. * destination? Always smaller than 'size'.
  47. */
  48. size_t pos;
  49. /**
  50. * How many bytes of data are stored in 'buf' for transmission right now?
  51. * Data always starts at offset 0 and extends to 'size'.
  52. */
  53. size_t size;
  54. /**
  55. * Buffered data; twice the maximum allowed message size as we add some
  56. * headers.
  57. */
  58. char buf[MAXLINE * 2];
  59. };
  60. /**
  61. * Flag set to 1 if we are to terminate, otherwise 0.
  62. */
  63. static int closeprog;
  64. /**
  65. * We're being killed, clean up.
  66. *
  67. * @param sig killing signal
  68. */
  69. static void
  70. sigfunc (int sig)
  71. {
  72. closeprog = 1;
  73. (void) unlink (FIFO_FILE1);
  74. (void) unlink (FIFO_FILE2);
  75. }
  76. /**
  77. * Create control message for plugin
  78. *
  79. * @param buffer pointer to buffer for the message
  80. * @param mac pointer to the mac address
  81. * @return number of bytes written
  82. */
  83. static int
  84. send_mac_to_plugin (char *buffer, struct GNUNET_TRANSPORT_WLAN_MacAddress *mac)
  85. {
  86. struct GNUNET_TRANSPORT_WLAN_HelperControlMessage macmsg;
  87. memcpy (&macmsg.mac, (char *) mac, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress));
  88. macmsg.hdr.size = htons (sizeof (struct GNUNET_TRANSPORT_WLAN_HelperControlMessage));
  89. macmsg.hdr.type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL);
  90. memcpy (buffer, &macmsg, sizeof (struct GNUNET_TRANSPORT_WLAN_HelperControlMessage));
  91. return sizeof (struct GNUNET_TRANSPORT_WLAN_HelperControlMessage);
  92. }
  93. /**
  94. * We got a message from the FIFO, check it, convert the message
  95. * type to the output forward and copy it to the buffer for stdout.
  96. *
  97. * @param cls the 'struct SendBuffer' to copy the converted message to
  98. * @param client unused
  99. * @param hdr inbound message from the FIFO
  100. */
  101. static int
  102. stdin_send (void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
  103. {
  104. struct SendBuffer *write_pout = cls;
  105. const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *in;
  106. size_t payload_size;
  107. struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage newheader;
  108. uint16_t sendsize;
  109. sendsize = ntohs (hdr->size);
  110. in = (const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) hdr;
  111. if ( (GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER != ntohs (hdr->type)) ||
  112. (sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) > sendsize) )
  113. {
  114. FPRINTF (stderr, "%s", "Received malformed message\n");
  115. exit (1);
  116. }
  117. payload_size = sendsize - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage);
  118. if ((payload_size + sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage) + write_pout->size) > MAXLINE * 2)
  119. {
  120. FPRINTF (stderr, "%s", "Packet too big for buffer\n");
  121. exit (1);
  122. }
  123. memset (&newheader, 0, sizeof (newheader));
  124. newheader.header.size = htons (payload_size + sizeof (newheader));
  125. newheader.header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA_FROM_HELPER);
  126. newheader.frame = in->frame;
  127. memcpy (write_pout->buf + write_pout->size,
  128. &newheader,
  129. sizeof (newheader));
  130. write_pout->size += sizeof (newheader);
  131. memcpy (write_pout->buf + write_pout->size,
  132. &in[1],
  133. payload_size);
  134. write_pout->size += payload_size;
  135. return GNUNET_OK;
  136. }
  137. /**
  138. * We read a full message from stdin. Copy it to our send buffer.
  139. *
  140. * @param cls the 'struct SendBuffer' to copy to
  141. * @param client unused
  142. * @param hdr the message we received to copy to the buffer
  143. */
  144. static int
  145. file_in_send (void *cls, void *client, const struct GNUNET_MessageHeader *hdr)
  146. {
  147. struct SendBuffer *write_std = cls;
  148. uint16_t sendsize;
  149. sendsize = ntohs (hdr->size);
  150. if ((sendsize + write_std->size) > MAXLINE * 2)
  151. {
  152. FPRINTF (stderr, "%s", "Packet too big for buffer\n");
  153. exit (1);
  154. }
  155. memcpy (write_std->buf + write_std->size, hdr, sendsize);
  156. write_std->size += sendsize;
  157. return GNUNET_OK;
  158. }
  159. /**
  160. * Main function of a program that pretends to be a WLAN card.
  161. *
  162. * @param argc should be 2
  163. * @param argv either '1' or '2', depending on which of the two cards this dummy is to emulate
  164. * @return 1 on error, 0 if terminated normally via signal
  165. */
  166. int
  167. main (int argc, char *argv[])
  168. {
  169. struct stat st;
  170. int erg;
  171. FILE *fpin = NULL;
  172. FILE *fpout = NULL;
  173. int fdpin;
  174. int fdpout;
  175. char readbuf[MAXLINE];
  176. int readsize;
  177. struct SendBuffer write_std;
  178. struct SendBuffer write_pout;
  179. int ret;
  180. int maxfd;
  181. fd_set rfds;
  182. fd_set wfds;
  183. struct timeval tv;
  184. int retval;
  185. struct GNUNET_SERVER_MessageStreamTokenizer *stdin_mst = NULL;
  186. struct GNUNET_SERVER_MessageStreamTokenizer *file_in_mst = NULL;
  187. struct GNUNET_TRANSPORT_WLAN_MacAddress macaddr;
  188. int first;
  189. if ( (2 != argc) ||
  190. ((0 != strcmp (argv[1], "1")) && (0 != strcmp (argv[1], "2"))) )
  191. {
  192. FPRINTF (stderr,
  193. "%s",
  194. "This program must be started with the operating mode (1 or 2) as the only argument.\n");
  195. return 1;
  196. }
  197. /* make the fifos if needed */
  198. umask (0);
  199. if ( (GNUNET_OK != GNUNET_DISK_directory_create_for_file (FIFO_FILE1)) ||
  200. (GNUNET_OK != GNUNET_DISK_directory_create_for_file (FIFO_FILE2)) )
  201. {
  202. FPRINTF (stderr, "Failed to create directory for file `%s'\n", FIFO_FILE1);
  203. return 1;
  204. }
  205. if (0 == strcmp (argv[1], "1") )
  206. {
  207. if (0 != stat (FIFO_FILE1, &st))
  208. {
  209. erg = mkfifo (FIFO_FILE1, 0666);
  210. if ( (0 != erg) && (EEXIST != errno) )
  211. FPRINTF (stderr, "Error in mkfifo(%s): %s\n", FIFO_FILE1,
  212. strerror (errno));
  213. }
  214. }
  215. else
  216. {
  217. if (0 != stat (FIFO_FILE2, &st))
  218. {
  219. GNUNET_break (0 == (erg = mkfifo (FIFO_FILE2, 0666)));
  220. if ( (0 != erg) && (EEXIST != errno) )
  221. FPRINTF (stderr, "Error in mkfifo(%s): %s\n", FIFO_FILE2,
  222. strerror (errno));
  223. }
  224. }
  225. if (0 == strcmp (argv[1], "1"))
  226. {
  227. first = 1;
  228. fpin = fopen (FIFO_FILE1, "r");
  229. if (NULL == fpin)
  230. {
  231. FPRINTF (stderr, "fopen of read FIFO_FILE1 failed: %s\n", STRERROR (errno));
  232. goto end;
  233. }
  234. if (NULL == (fpout = fopen (FIFO_FILE2, "w")))
  235. {
  236. GNUNET_break (0 == mkfifo (FIFO_FILE2, 0666));
  237. fpout = fopen (FIFO_FILE2, "w");
  238. }
  239. if (NULL == fpout)
  240. {
  241. FPRINTF (stderr, "fopen of write FIFO_FILE2 failed: %s\n", STRERROR (errno));
  242. goto end;
  243. }
  244. }
  245. else
  246. {
  247. first = 0;
  248. if (NULL == (fpout = fopen (FIFO_FILE1, "w")))
  249. {
  250. GNUNET_break (0 == mkfifo (FIFO_FILE1, 0666));
  251. fpout = fopen (FIFO_FILE1, "w");
  252. }
  253. if (NULL == fpout)
  254. {
  255. FPRINTF (stderr, "fopen of write FIFO_FILE1 failed: %s\n", STRERROR (errno));
  256. goto end;
  257. }
  258. fpin = fopen (FIFO_FILE2, "r");
  259. if (NULL == fpin)
  260. {
  261. FPRINTF (stderr, "fopen of read FIFO_FILE2 failed: %s\n", STRERROR (errno));
  262. goto end;
  263. }
  264. }
  265. fdpin = fileno (fpin);
  266. GNUNET_assert (fpin >= 0);
  267. if (fdpin >= FD_SETSIZE)
  268. {
  269. FPRINTF (stderr, "File fdpin number too large (%d > %u)\n", fdpin,
  270. (unsigned int) FD_SETSIZE);
  271. goto end;
  272. }
  273. fdpout = fileno (fpout);
  274. GNUNET_assert (fdpout >= 0);
  275. if (fdpout >= FD_SETSIZE)
  276. {
  277. FPRINTF (stderr, "File fdpout number too large (%d > %u)\n", fdpout,
  278. (unsigned int) FD_SETSIZE);
  279. goto end;
  280. }
  281. signal (SIGINT, &sigfunc);
  282. signal (SIGTERM, &sigfunc);
  283. signal (GNUNET_TERM_SIG, &sigfunc);
  284. write_std.size = 0;
  285. write_std.pos = 0;
  286. write_pout.size = 0;
  287. write_pout.pos = 0;
  288. stdin_mst = GNUNET_SERVER_mst_create (&stdin_send, &write_pout);
  289. file_in_mst = GNUNET_SERVER_mst_create (&file_in_send, &write_std);
  290. /* Send 'random' mac address */
  291. macaddr.mac[0] = 0x13;
  292. macaddr.mac[1] = 0x22;
  293. macaddr.mac[2] = 0x33;
  294. macaddr.mac[3] = 0x44;
  295. macaddr.mac[4] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 256);
  296. macaddr.mac[5] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, 256);
  297. write_std.size = send_mac_to_plugin (write_std.buf, &macaddr);
  298. while (0 == closeprog)
  299. {
  300. maxfd = -1;
  301. tv.tv_sec = 5;
  302. tv.tv_usec = 0;
  303. FD_ZERO (&rfds);
  304. FD_ZERO (&wfds);
  305. /* if output queue is empty, read */
  306. if (0 == write_pout.size)
  307. {
  308. FD_SET (STDIN_FILENO, &rfds);
  309. maxfd = MAX (STDIN_FILENO, maxfd);
  310. }
  311. if (0 == write_std.size)
  312. {
  313. FD_SET (fdpin, &rfds);
  314. maxfd = MAX (fdpin, maxfd);
  315. }
  316. /* if there is something to write, try to write */
  317. if (0 < write_std.size)
  318. {
  319. FD_SET (STDOUT_FILENO, &wfds);
  320. maxfd = MAX (maxfd, STDOUT_FILENO);
  321. }
  322. if (0 < write_pout.size)
  323. {
  324. FD_SET (fdpout, &wfds);
  325. maxfd = MAX (maxfd, fdpout);
  326. }
  327. retval = select (maxfd + 1, &rfds, &wfds, NULL, &tv);
  328. if ((-1 == retval) && (EINTR == errno))
  329. continue;
  330. if (0 > retval)
  331. {
  332. FPRINTF (stderr, "select failed: %s\n", STRERROR (errno));
  333. closeprog = 1;
  334. break;
  335. }
  336. if (FD_ISSET (STDOUT_FILENO, &wfds))
  337. {
  338. ret =
  339. write (STDOUT_FILENO, write_std.buf + write_std.pos,
  340. write_std.size - write_std.pos);
  341. if (0 > ret)
  342. {
  343. closeprog = 1;
  344. FPRINTF (stderr, "Write ERROR to STDOUT_FILENO: %s\n",
  345. STRERROR (errno));
  346. break;
  347. }
  348. else
  349. {
  350. write_std.pos += ret;
  351. /* check if finished writing */
  352. if (write_std.pos == write_std.size)
  353. {
  354. write_std.pos = 0;
  355. write_std.size = 0;
  356. }
  357. }
  358. }
  359. if (FD_ISSET (fdpout, &wfds))
  360. {
  361. ret =
  362. write (fdpout, write_pout.buf + write_pout.pos,
  363. write_pout.size - write_pout.pos);
  364. if (0 > ret)
  365. {
  366. closeprog = 1;
  367. FPRINTF (stderr, "Write ERROR to fdpout failed: %s\n", STRERROR (errno));
  368. }
  369. else
  370. {
  371. write_pout.pos += ret;
  372. /* check if finished writing */
  373. if (write_pout.pos == write_pout.size)
  374. {
  375. write_pout.pos = 0;
  376. write_pout.size = 0;
  377. }
  378. }
  379. }
  380. if (FD_ISSET (STDIN_FILENO, &rfds))
  381. {
  382. readsize = read (STDIN_FILENO, readbuf, sizeof (readbuf));
  383. if (0 > readsize)
  384. {
  385. closeprog = 1;
  386. FPRINTF (stderr, "Error reading from STDIN_FILENO: %s\n",
  387. STRERROR (errno));
  388. }
  389. else if (0 < readsize)
  390. {
  391. GNUNET_SERVER_mst_receive (stdin_mst, NULL, readbuf, readsize,
  392. GNUNET_NO, GNUNET_NO);
  393. }
  394. else
  395. {
  396. /* eof */
  397. closeprog = 1;
  398. }
  399. }
  400. if (FD_ISSET (fdpin, &rfds))
  401. {
  402. readsize = read (fdpin, readbuf, sizeof (readbuf));
  403. if (0 > readsize)
  404. {
  405. closeprog = 1;
  406. FPRINTF (stderr, "Error reading from fdpin: %s\n", STRERROR (errno));
  407. break;
  408. }
  409. else if (0 < readsize)
  410. {
  411. GNUNET_SERVER_mst_receive (file_in_mst, NULL, readbuf, readsize,
  412. GNUNET_NO, GNUNET_NO);
  413. }
  414. else
  415. {
  416. /* eof */
  417. closeprog = 1;
  418. }
  419. }
  420. }
  421. end:
  422. /* clean up */
  423. if (NULL != stdin_mst)
  424. GNUNET_SERVER_mst_destroy (stdin_mst);
  425. if (NULL != file_in_mst)
  426. GNUNET_SERVER_mst_destroy (file_in_mst);
  427. if (NULL != fpout)
  428. fclose (fpout);
  429. if (NULL != fpin)
  430. fclose (fpin);
  431. if (1 == first)
  432. {
  433. (void) unlink (FIFO_FILE1);
  434. (void) unlink (FIFO_FILE2);
  435. }
  436. return 0;
  437. }