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

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