123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514 |
- /*
- This file is part of GNUnet.
- Copyright (C) 2010, 2012 GNUnet e.V.
- GNUnet is free software: you can redistribute it and/or modify it
- under the terms of the GNU Affero General Public License as published
- by the Free Software Foundation, either version 3 of the License,
- or (at your option) any later version.
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Affero General Public License for more details.
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
- SPDX-License-Identifier: AGPL3.0-or-later
- */
- /**
- * @file transport/gnunet-helper-transport-wlan-dummy.c
- * @brief helper for the testcases for plugin_transport_wlan.c
- * @author David Brodski
- */
- #include "platform.h"
- #include "gnunet_protocols.h"
- #include "gnunet_util_lib.h"
- #include "plugin_transport_wlan.h"
- /**
- * Name of the fifo to use for IPC with the other dummy process.
- */
- #define FIFO_FILE1 "/tmp/test-transport/api-wlan-p1/WLAN_FIFO_in"
- /**
- * Name of the fifo to use for IPC with the other dummy process.
- */
- #define FIFO_FILE2 "/tmp/test-transport/api-wlan-p1/WLAN_FIFO_out"
- /**
- * Maximum size of a message allowed in either direction
- * (used for our receive and sent buffers).
- */
- #define MAXLINE 4096
- /**
- * IO buffer used for buffering data in transit.
- */
- struct SendBuffer
- {
- /**
- * How many bytes that were stored in 'buf' did we already write to the
- * destination? Always smaller than 'size'.
- */
- size_t pos;
- /**
- * How many bytes of data are stored in 'buf' for transmission right now?
- * Data always starts at offset 0 and extends to 'size'.
- */
- size_t size;
- /**
- * Buffered data; twice the maximum allowed message size as we add some
- * headers.
- */
- char buf[MAXLINE * 2];
- };
- /**
- * Flag set to 1 if we are to terminate, otherwise 0.
- */
- static int closeprog;
- /**
- * We're being killed, clean up.
- *
- * @param sig killing signal
- */
- static void
- sigfunc (int sig)
- {
- closeprog = 1;
- (void) unlink (FIFO_FILE1);
- (void) unlink (FIFO_FILE2);
- }
- /**
- * Create control message for plugin
- *
- * @param buffer pointer to buffer for the message
- * @param mac pointer to the mac address
- * @return number of bytes written
- */
- static int
- send_mac_to_plugin (char *buffer, struct GNUNET_TRANSPORT_WLAN_MacAddress *mac)
- {
- struct GNUNET_TRANSPORT_WLAN_HelperControlMessage macmsg;
- GNUNET_memcpy (&macmsg.mac,
- (char *) mac,
- sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress));
- macmsg.hdr.size = htons (sizeof (struct GNUNET_TRANSPORT_WLAN_HelperControlMessage));
- macmsg.hdr.type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL);
- GNUNET_memcpy (buffer,
- &macmsg,
- sizeof (struct GNUNET_TRANSPORT_WLAN_HelperControlMessage));
- return sizeof (struct GNUNET_TRANSPORT_WLAN_HelperControlMessage);
- }
- /**
- * We got a message from the FIFO, check it, convert the message
- * type to the output forward and copy it to the buffer for stdout.
- *
- * @param cls the 'struct SendBuffer' to copy the converted message to
- * @param hdr inbound message from the FIFO
- * @return #GNUNET_OK on success,
- * #GNUNET_NO to stop further processing (no error)
- * #GNUNET_SYSERR to stop further processing with error
- */
- static int
- stdin_send (void *cls,
- const struct GNUNET_MessageHeader *hdr)
- {
- struct SendBuffer *write_pout = cls;
- const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *in;
- size_t payload_size;
- struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage newheader;
- uint16_t sendsize;
- sendsize = ntohs (hdr->size);
- in = (const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) hdr;
- if ( (GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER != ntohs (hdr->type)) ||
- (sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) > sendsize) )
- {
- FPRINTF (stderr, "%s", "Received malformed message\n");
- exit (1);
- }
- payload_size = sendsize - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage);
- if ((payload_size + sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage) + write_pout->size) > MAXLINE * 2)
- {
- FPRINTF (stderr, "%s", "Packet too big for buffer\n");
- exit (1);
- }
- memset (&newheader, 0, sizeof (newheader));
- newheader.header.size = htons (payload_size + sizeof (newheader));
- newheader.header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA_FROM_HELPER);
- newheader.frame = in->frame;
- GNUNET_memcpy (write_pout->buf + write_pout->size,
- &newheader,
- sizeof (newheader));
- write_pout->size += sizeof (newheader);
- GNUNET_memcpy (write_pout->buf + write_pout->size,
- &in[1],
- payload_size);
- write_pout->size += payload_size;
- return GNUNET_OK;
- }
- /**
- * We read a full message from stdin. Copy it to our send buffer.
- *
- * @param cls the 'struct SendBuffer' to copy to
- * @param hdr the message we received to copy to the buffer
- * @return #GNUNET_OK on success,
- * #GNUNET_NO to stop further processing (no error)
- * #GNUNET_SYSERR to stop further processing with error
- */
- static int
- file_in_send (void *cls,
- const struct GNUNET_MessageHeader *hdr)
- {
- struct SendBuffer *write_std = cls;
- uint16_t sendsize;
- sendsize = ntohs (hdr->size);
- if ((sendsize + write_std->size) > MAXLINE * 2)
- {
- FPRINTF (stderr, "%s", "Packet too big for buffer\n");
- exit (1);
- }
- GNUNET_memcpy (write_std->buf + write_std->size, hdr, sendsize);
- write_std->size += sendsize;
- return GNUNET_OK;
- }
- /**
- * Main function of a program that pretends to be a WLAN card.
- *
- * @param argc should be 2
- * @param argv either '1' or '2', depending on which of the two cards this dummy is to emulate
- * @return 1 on error, 0 if terminated normally via signal
- */
- int
- main (int argc, char *argv[])
- {
- struct stat st;
- int erg;
- FILE *fpin = NULL;
- FILE *fpout = NULL;
- int fdpin;
- int fdpout;
- char readbuf[MAXLINE];
- int readsize;
- struct SendBuffer write_std;
- struct SendBuffer write_pout;
- int ret;
- int maxfd;
- fd_set rfds;
- fd_set wfds;
- struct timeval tv;
- int retval;
- struct GNUNET_MessageStreamTokenizer *stdin_mst = NULL;
- struct GNUNET_MessageStreamTokenizer *file_in_mst = NULL;
- struct GNUNET_TRANSPORT_WLAN_MacAddress macaddr;
- int first;
- if ( (2 != argc) ||
- ((0 != strcmp (argv[1], "1")) && (0 != strcmp (argv[1], "2"))) )
- {
- FPRINTF (stderr,
- "%s",
- "This program must be started with the operating mode (1 or 2) as the only argument.\n");
- return 1;
- }
- /* make the fifos if needed */
- umask (0);
- if ( (GNUNET_OK != GNUNET_DISK_directory_create_for_file (FIFO_FILE1)) ||
- (GNUNET_OK != GNUNET_DISK_directory_create_for_file (FIFO_FILE2)) )
- {
- FPRINTF (stderr,
- "Failed to create directory for file `%s'\n",
- FIFO_FILE1);
- return 1;
- }
- if (0 == strcmp (argv[1], "1") )
- {
- if (0 != stat (FIFO_FILE1, &st))
- {
- erg = mkfifo (FIFO_FILE1, 0666);
- if ( (0 != erg) && (EEXIST != errno) )
- FPRINTF (stderr, "Error in mkfifo(%s): %s\n", FIFO_FILE1,
- strerror (errno));
- }
- }
- else
- {
- if (0 != stat (FIFO_FILE2, &st))
- {
- GNUNET_break (0 == (erg = mkfifo (FIFO_FILE2, 0666)));
- if ( (0 != erg) && (EEXIST != errno) )
- FPRINTF (stderr,
- "Error in mkfifo(%s): %s\n",
- FIFO_FILE2,
- strerror (errno));
- }
- }
- if (0 == strcmp (argv[1], "1"))
- {
- first = 1;
- fpin = fopen (FIFO_FILE1, "r");
- if (NULL == fpin)
- {
- FPRINTF (stderr,
- "fopen of read FIFO_FILE1 failed: %s\n",
- STRERROR (errno));
- goto end;
- }
- if (NULL == (fpout = fopen (FIFO_FILE2, "w")))
- {
- GNUNET_break (0 == mkfifo (FIFO_FILE2, 0666));
- fpout = fopen (FIFO_FILE2, "w");
- }
- if (NULL == fpout)
- {
- FPRINTF (stderr,
- "fopen of write FIFO_FILE2 failed: %s\n",
- STRERROR (errno));
- goto end;
- }
- }
- else
- {
- first = 0;
- if (NULL == (fpout = fopen (FIFO_FILE1, "w")))
- {
- GNUNET_break (0 == mkfifo (FIFO_FILE1, 0666));
- fpout = fopen (FIFO_FILE1, "w");
- }
- if (NULL == fpout)
- {
- FPRINTF (stderr,
- "fopen of write FIFO_FILE1 failed: %s\n",
- STRERROR (errno));
- goto end;
- }
- fpin = fopen (FIFO_FILE2, "r");
- if (NULL == fpin)
- {
- FPRINTF (stderr,
- "fopen of read FIFO_FILE2 failed: %s\n",
- STRERROR (errno));
- goto end;
- }
- }
- fdpin = fileno (fpin);
- GNUNET_assert (fpin >= 0);
- if (fdpin >= FD_SETSIZE)
- {
- FPRINTF (stderr,
- "File fdpin number too large (%d > %u)\n",
- fdpin,
- (unsigned int) FD_SETSIZE);
- goto end;
- }
- fdpout = fileno (fpout);
- GNUNET_assert (fdpout >= 0);
- if (fdpout >= FD_SETSIZE)
- {
- FPRINTF (stderr,
- "File fdpout number too large (%d > %u)\n",
- fdpout,
- (unsigned int) FD_SETSIZE);
- goto end;
- }
- signal (SIGINT, &sigfunc);
- signal (SIGTERM, &sigfunc);
- signal (GNUNET_TERM_SIG, &sigfunc);
- write_std.size = 0;
- write_std.pos = 0;
- write_pout.size = 0;
- write_pout.pos = 0;
- stdin_mst = GNUNET_MST_create (&stdin_send, &write_pout);
- file_in_mst = GNUNET_MST_create (&file_in_send, &write_std);
- /* Send 'random' mac address */
- macaddr.mac[0] = 0x13;
- macaddr.mac[1] = 0x22;
- macaddr.mac[2] = 0x33;
- macaddr.mac[3] = 0x44;
- macaddr.mac[4] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_STRONG, 256);
- macaddr.mac[5] = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE, 256);
- write_std.size = send_mac_to_plugin (write_std.buf, &macaddr);
- while (0 == closeprog)
- {
- maxfd = -1;
- tv.tv_sec = 5;
- tv.tv_usec = 0;
- FD_ZERO (&rfds);
- FD_ZERO (&wfds);
- /* if output queue is empty, read */
- if (0 == write_pout.size)
- {
- FD_SET (STDIN_FILENO, &rfds);
- maxfd = MAX (STDIN_FILENO, maxfd);
- }
- if (0 == write_std.size)
- {
- FD_SET (fdpin, &rfds);
- maxfd = MAX (fdpin, maxfd);
- }
- /* if there is something to write, try to write */
- if (0 < write_std.size)
- {
- FD_SET (STDOUT_FILENO, &wfds);
- maxfd = MAX (maxfd, STDOUT_FILENO);
- }
- if (0 < write_pout.size)
- {
- FD_SET (fdpout, &wfds);
- maxfd = MAX (maxfd, fdpout);
- }
- retval = select (maxfd + 1, &rfds, &wfds, NULL, &tv);
- if ((-1 == retval) && (EINTR == errno))
- continue;
- if (0 > retval)
- {
- FPRINTF (stderr, "select failed: %s\n", STRERROR (errno));
- closeprog = 1;
- break;
- }
- if (FD_ISSET (STDOUT_FILENO, &wfds))
- {
- ret =
- write (STDOUT_FILENO, write_std.buf + write_std.pos,
- write_std.size - write_std.pos);
- if (0 > ret)
- {
- closeprog = 1;
- FPRINTF (stderr, "Write ERROR to STDOUT_FILENO: %s\n",
- STRERROR (errno));
- break;
- }
- else
- {
- write_std.pos += ret;
- /* check if finished writing */
- if (write_std.pos == write_std.size)
- {
- write_std.pos = 0;
- write_std.size = 0;
- }
- }
- }
- if (FD_ISSET (fdpout, &wfds))
- {
- ret =
- write (fdpout, write_pout.buf + write_pout.pos,
- write_pout.size - write_pout.pos);
- if (0 > ret)
- {
- closeprog = 1;
- FPRINTF (stderr, "Write ERROR to fdpout failed: %s\n", STRERROR (errno));
- }
- else
- {
- write_pout.pos += ret;
- /* check if finished writing */
- if (write_pout.pos == write_pout.size)
- {
- write_pout.pos = 0;
- write_pout.size = 0;
- }
- }
- }
- if (FD_ISSET (STDIN_FILENO, &rfds))
- {
- readsize = read (STDIN_FILENO, readbuf, sizeof (readbuf));
- if (0 > readsize)
- {
- closeprog = 1;
- FPRINTF (stderr, "Error reading from STDIN_FILENO: %s\n",
- STRERROR (errno));
- }
- else if (0 < readsize)
- {
- GNUNET_MST_from_buffer (stdin_mst,
- readbuf, readsize,
- GNUNET_NO, GNUNET_NO);
- }
- else
- {
- /* eof */
- closeprog = 1;
- }
- }
- if (FD_ISSET (fdpin, &rfds))
- {
- readsize = read (fdpin, readbuf, sizeof (readbuf));
- if (0 > readsize)
- {
- closeprog = 1;
- FPRINTF (stderr, "Error reading from fdpin: %s\n", STRERROR (errno));
- break;
- }
- else if (0 < readsize)
- {
- GNUNET_MST_from_buffer (file_in_mst,
- readbuf, readsize,
- GNUNET_NO, GNUNET_NO);
- }
- else
- {
- /* eof */
- closeprog = 1;
- }
- }
- }
- end:
- /* clean up */
- if (NULL != stdin_mst)
- GNUNET_MST_destroy (stdin_mst);
- if (NULL != file_in_mst)
- GNUNET_MST_destroy (file_in_mst);
- if (NULL != fpout)
- fclose (fpout);
- if (NULL != fpin)
- fclose (fpin);
- if (1 == first)
- {
- (void) unlink (FIFO_FILE1);
- (void) unlink (FIFO_FILE2);
- }
- return 0;
- }
|