2 This file is part of GNUnet.
3 (C) 2010, 2011, 2012 Christian Grothoff (and other contributing authors)
4 Copyright (c) 2007, 2008, Andy Green <andy@warmcat.com>
5 Copyright (C) 2009 Thomas d'Otreppe
7 GNUnet is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published
9 by the Free Software Foundation; either version 3, or (at your
10 option) any later version.
12 GNUnet is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNUnet; see the file COPYING. If not, write to the
19 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.
22 #include "gnunet_config.h"
24 #include <bluetooth/bluetooth.h>
25 #include <bluetooth/hci.h>
26 #include <bluetooth/hci_lib.h>
27 #include <bluetooth/rfcomm.h>
28 #include <bluetooth/sdp.h>
29 #include <bluetooth/sdp_lib.h>
34 #include <sys/ioctl.h>
35 #include <sys/param.h>
36 #include <sys/socket.h>
38 #include <sys/types.h>
41 #include "gnunet_protocols.h"
42 #include "plugin_transport_wlan.h"
44 #define HARD_CODED_PORT_NUMBER 10
45 #define HARD_CODED_PORT_NUMBER2 10
48 * Maximum size of a message allowed in either direction
49 * (used for our receive and sent buffers).
55 * struct for storing the information of the hardware. There is only
62 * file descriptor for the rfcomm socket
67 * Name of the interface, not necessarily 0-terminated (!).
72 * MAC address of our own bluetooth interface.
74 struct GNUNET_TRANSPORT_WLAN_MacAddress pl_mac;
78 * IO buffer used for buffering data in transit (to wireless or to stdout).
83 * How many bytes of data are stored in 'buf' for transmission right now?
84 * Data always starts at offset 0 and extends to 'size'.
89 * How many bytes that were stored in 'buf' did we already write to the
90 * destination? Always smaller than 'size'.
95 * Buffered data; twice the maximum allowed message size as we add some
98 char buf[MAXLINE * 2];
103 * Buffer for data read from stdin to be transmitted to the bluetooth device
105 static struct SendBuffer write_pout;
108 * Buffer for data read from the bluetooth device to be transmitted to stdout.
110 static struct SendBuffer write_std;
113 /* *********** specialized version of server_mst.c begins here ********** */
114 /* ****** this is the same version as the one used in gnunet-helper-transport-wlan.c ****** */
117 * To what multiple do we align messages? 8 byte should suffice for everyone
120 #define ALIGN_FACTOR 8
123 * Smallest supported message.
125 #define MIN_BUFFER_SIZE sizeof (struct GNUNET_MessageHeader)
129 * Functions with this signature are called whenever a
130 * complete message is received by the tokenizer.
133 * @param message the actual message
135 typedef void (*MessageTokenizerCallback) (void *cls,
137 GNUNET_MessageHeader *
141 * Handle to a message stream tokenizer.
143 struct MessageStreamTokenizer
147 * Function to call on completed messages.
149 MessageTokenizerCallback cb;
157 * Size of the buffer (starting at 'hdr').
162 * How many bytes in buffer have we already processed?
167 * How many bytes in buffer are valid right now?
172 * Beginning of the buffer. Typed like this to force alignment.
174 struct GNUNET_MessageHeader *hdr;
180 * Create a message stream tokenizer.
182 * @param cb function to call on completed messages
183 * @param cb_cls closure for cb
184 * @return handle to tokenizer
186 static struct MessageStreamTokenizer *
187 mst_create (MessageTokenizerCallback cb,
190 struct MessageStreamTokenizer *ret;
192 ret = malloc (sizeof (struct MessageStreamTokenizer));
195 fprintf (stderr, "Failed to allocate buffer for tokenizer\n");
198 ret->hdr = malloc (MIN_BUFFER_SIZE);
199 if (NULL == ret->hdr)
201 fprintf (stderr, "Failed to allocate buffer for alignment\n");
204 ret->curr_buf = MIN_BUFFER_SIZE;
206 ret->cb_cls = cb_cls;
212 * Add incoming data to the receive buffer and call the
213 * callback for all complete messages.
215 * @param mst tokenizer to use
216 * @param buf input data to add
217 * @param size number of bytes in buf
218 * @return GNUNET_OK if we are done processing (need more data)
219 * GNUNET_SYSERR if the data stream is corrupt
222 mst_receive (struct MessageStreamTokenizer *mst,
223 const char *buf, size_t size)
225 const struct GNUNET_MessageHeader *hdr;
230 unsigned long offset;
234 ibuf = (char *) mst->hdr;
238 if ((mst->curr_buf - mst->off < sizeof (struct GNUNET_MessageHeader)) ||
239 (0 != (mst->off % ALIGN_FACTOR)))
241 /* need to align or need more space */
242 mst->pos -= mst->off;
243 memmove (ibuf, &ibuf[mst->off], mst->pos);
246 if (mst->pos - mst->off < sizeof (struct GNUNET_MessageHeader))
249 GNUNET_MIN (sizeof (struct GNUNET_MessageHeader) -
250 (mst->pos - mst->off), size);
251 memcpy (&ibuf[mst->pos], buf, delta);
256 if (mst->pos - mst->off < sizeof (struct GNUNET_MessageHeader))
260 hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off];
261 want = ntohs (hdr->size);
262 if (want < sizeof (struct GNUNET_MessageHeader))
265 "Received invalid message from stdin\n");
268 if (mst->curr_buf - mst->off < want)
270 /* need more space */
271 mst->pos -= mst->off;
272 memmove (ibuf, &ibuf[mst->off], mst->pos);
275 if (want > mst->curr_buf)
277 mst->hdr = realloc (mst->hdr, want);
278 if (NULL == mst->hdr)
280 fprintf (stderr, "Failed to allocate buffer for alignment\n");
283 ibuf = (char *) mst->hdr;
284 mst->curr_buf = want;
286 hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off];
287 if (mst->pos - mst->off < want)
289 delta = GNUNET_MIN (want - (mst->pos - mst->off), size);
290 memcpy (&ibuf[mst->pos], buf, delta);
295 if (mst->pos - mst->off < want)
299 mst->cb (mst->cb_cls, hdr);
301 if (mst->off == mst->pos)
303 /* reset to beginning of buffer, it's free right now! */
310 if (size < sizeof (struct GNUNET_MessageHeader))
312 offset = (unsigned long) buf;
313 need_align = (0 != offset % ALIGN_FACTOR) ? GNUNET_YES : GNUNET_NO;
314 if (GNUNET_NO == need_align)
316 /* can try to do zero-copy and process directly from original buffer */
317 hdr = (const struct GNUNET_MessageHeader *) buf;
318 want = ntohs (hdr->size);
319 if (want < sizeof (struct GNUNET_MessageHeader))
322 "Received invalid message from stdin\n");
326 break; /* or not, buffer incomplete, so copy to private buffer... */
327 mst->cb (mst->cb_cls, hdr);
333 /* need to copy to private buffer to align;
334 * yes, we go a bit more spagetti than usual here */
340 if (size + mst->pos > mst->curr_buf)
342 mst->hdr = realloc (mst->hdr, size + mst->pos);
343 if (NULL == mst->hdr)
345 fprintf (stderr, "Failed to allocate buffer for alignment\n");
348 ibuf = (char *) mst->hdr;
349 mst->curr_buf = size + mst->pos;
351 if (mst->pos + size > mst->curr_buf)
354 "Assertion failed\n");
357 memcpy (&ibuf[mst->pos], buf, size);
365 * Destroys a tokenizer.
367 * @param mst tokenizer to destroy
370 mst_destroy (struct MessageStreamTokenizer *mst)
376 /* ***************** end of server_mst.c clone ***************** **/
379 /* ****** same crc version as the one used in gnunet-helper-transport-wlan.c ****** */
382 * Calculate crc32, the start of the calculation
384 * @param buf buffer to calc the crc
385 * @param len len of the buffer
389 calc_crc_osdep (const unsigned char *buf, size_t len)
391 static const unsigned long int crc_tbl_osdep[256] = {
392 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
393 0xE963A535, 0x9E6495A3,
394 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
395 0xE7B82D07, 0x90BF1D91,
396 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB,
397 0xF4D4B551, 0x83D385C7,
398 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
399 0xFA0F3D63, 0x8D080DF5,
400 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447,
401 0xD20D85FD, 0xA50AB56B,
402 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75,
403 0xDCD60DCF, 0xABD13D59,
404 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
405 0xCFBA9599, 0xB8BDA50F,
406 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11,
407 0xC1611DAB, 0xB6662D3D,
408 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F,
409 0x9FBFE4A5, 0xE8B8D433,
410 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
411 0x91646C97, 0xE6635C01,
412 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B,
413 0x8208F4C1, 0xF50FC457,
414 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49,
415 0x8CD37CF3, 0xFBD44C65,
416 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
417 0xA4D1C46D, 0xD3D6F4FB,
418 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5,
419 0xAA0A4C5F, 0xDD0D7CC9,
420 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3,
421 0xB966D409, 0xCE61E49F,
422 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
423 0xB7BD5C3B, 0xC0BA6CAD,
424 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF,
425 0x04DB2615, 0x73DC1683,
426 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D,
427 0x0A00AE27, 0x7D079EB1,
428 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
429 0x196C3671, 0x6E6B06E7,
430 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9,
431 0x17B7BE43, 0x60B08ED5,
432 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767,
433 0x3FB506DD, 0x48B2364B,
434 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
435 0x316E8EEF, 0x4669BE79,
436 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703,
437 0x220216B9, 0x5505262F,
438 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31,
439 0x2CD99E8B, 0x5BDEAE1D,
440 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
441 0x72076785, 0x05005713,
442 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D,
443 0x7CDCEFB7, 0x0BDBDF21,
444 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B,
445 0x6FB077E1, 0x18B74777,
446 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
447 0x616BFFD3, 0x166CCF45,
448 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7,
449 0x4969474D, 0x3E6E77DB,
450 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5,
451 0x47B2CF7F, 0x30B5FFE9,
452 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
453 0x54DE5729, 0x23D967BF,
454 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1,
455 0x5A05DF1B, 0x2D02EF8D
458 unsigned long crc = 0xFFFFFFFF;
460 for (; len > 0; len--, buf++)
461 crc = crc_tbl_osdep[(crc ^ *buf) & 0xFF] ^ (crc >> 8);
467 * Calculate and check crc of the bluetooth packet
469 * @param buf buffer of the packet, with len + 4 bytes of data,
470 * the last 4 bytes being the checksum
471 * @param len length of the payload in data
472 * @return 0 on success (checksum matches), 1 on error
475 check_crc_buf_osdep (const unsigned char *buf, size_t len)
479 crc = calc_crc_osdep (buf, len);
481 if (((crc) & 0xFF) == buf[0] && ((crc >> 8) & 0xFF) == buf[1] &&
482 ((crc >> 16) & 0xFF) == buf[2] && ((crc >> 24) & 0xFF) == buf[3])
489 /* ************** end of crc version ***************** */
495 * Function for assigning a port number
496 * @return 0 on success
499 bind_socket (int *socket)
502 struct sockaddr_rc src = { 0 };
504 src.rc_family = AF_BLUETOOTH;
505 src.rc_bdaddr = *BDADDR_ANY;
507 /* Bind every possible port (from 0 to 30) and stop when bind doesn't fail */
508 for (port = 1; port <= 30; port++)
510 src.rc_channel = port;
511 status = bind(*socket, (struct sockaddr *)&src, sizeof(src));
522 * Function used for creating the service record and registering it.
524 static sdp_session_t*
525 register_service (void)
529 * 2. set the service ID, class, profile information
530 * 3. make the service record publicly nrowsable
531 * 4. register the RFCOMM channel
532 * 5. set the name, provider and description
533 * 6. register the service record to the local SDP server
537 //TODO: For now I will use a hard coded port number but in the end I will implement the SDP protocol
544 * Function for searching and browsing for a service. This will return the
545 * port number on which the service is running.
549 searching_service (void)
552 * 1. detect all nearby devices
553 * 2. for each device:
554 * 2.1. connect to the SDP server running
555 * 2.2. get a list of service records with the specific UUID
556 * 2.3. for each service record get a list of the protocol sequences and get
564 * Read from the socket and put the result into the buffer for transmission to 'stdout'.
565 * @param sock file descriptor for reading
566 * @param buf buffer to read to; first bytes will be the 'struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame',
567 * followed by the actual payload
568 * @param buf_size size of the buffer
569 * @param ri where to write radiotap_rx info
570 * @return number of bytes written to 'buf'
573 read_from_the_socket (int sock,
574 unsigned char *buf, size_t buf_size,
575 struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *ri)
578 * 1. Read from the socket in a temporary buffer (check for errors)
579 * 2. Detect if the crc exists
580 * 3. Write the result to the buffer
582 unsigned char tmpbuf[buf_size];
585 struct sockaddr_rc rc_addr = { 0 };
587 //count = recv (dev->fd_rfcomm, tmpbuf, buf_size, 0); //FIXME if I use RFCOMM
589 count = read (sock, tmpbuf, buf_size);
596 fprintf (stderr, "Failed to read from the HCI socket: %s\n", strerror (errno));
600 /* Get the channel used */
601 memset (&rc_addr, 0, sizeof (rc_addr));
602 len = sizeof (rc_addr);
603 if (0 > getsockname (sock, (struct sockaddr *) &rc_addr, (socklen_t *) &len))
605 fprintf (stderr, "getsockname() call failed : %s\n", strerror (errno));
609 memset (ri, 0, sizeof (*ri));
610 ri->ri_channel = rc_addr.rc_channel;
612 /* detect CRC32 at the end */
613 if (0 == check_crc_buf_osdep (tmpbuf, count - sizeof (uint32_t)))
615 count -= sizeof(uint32_t);
618 memcpy (buf, tmpbuf, count);
624 * Open the bluetooth interface for reading/writing
626 * @param dev pointer to the device struct
627 * @return 0 on success
630 open_device (struct HardwareInfos *dev)
633 * 1. Open a HCI socket (if RFCOMM protocol is used. If not, the HCI socket is
634 * saved in dev->fd_hci.
635 * 2. Find the device id (request a list with all the devices and find the one
636 * with the dev->iface name)
637 * 3. If the interface is down try to get it up
638 * 4. TODO: Bind the RFCOMM socket to the interface using the bind_socket() method and register
640 * 5. For now use a hard coded port number(channel) value
641 * FIXME : if I use HCI sockets , should I enable RAW_SOCKET MODE?!?!?!
644 int i, dev_id = -1, fd_hci;
647 struct hci_dev_list_req list;
648 struct hci_dev_req dev[HCI_MAX_DEV];
649 } request; //used for detecting the local devices
650 struct sockaddr_rc rc_addr = { 0 }; //used for binding
652 fd_hci = socket (AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
656 fprintf (stderr, "Failed to create HCI socket: %s\n", strerror (errno));
660 memset (&request, 0, sizeof(request));
661 request.list.dev_num = HCI_MAX_DEV;
663 if (ioctl (fd_hci, HCIGETDEVLIST, (void *) &request) < 0)
665 fprintf (stderr, "ioctl(HCIGETDEVLIST) on interface `%.*s' failed: %s\n",
666 IFNAMSIZ, dev->iface, strerror (errno));
670 /* Search for a device with dev->iface name */
671 for (i = 0; i < request.list.dev_num; i++)
673 struct hci_dev_info dev_info;
675 memset (&dev_info, 0, sizeof(struct hci_dev_info));
676 dev_info.dev_id = request.dev[i].dev_id;
677 strncpy (dev_info.name, dev->iface, IFNAMSIZ);
679 if (ioctl (fd_hci, HCIGETDEVINFO, (void *) &dev_info))
681 fprintf (stderr, "ioctl(HCIGETDEVINFO) on interface `%.*s' failed: %s\n",
682 IFNAMSIZ, dev->iface, strerror (errno));
686 if (strcmp (dev_info.name, dev->iface) == 0)
688 char addr[19] = { 0 }; //the device MAC address
690 dev_id = dev_info.dev_id; //the device was found
692 ba2str (&dev_info.bdaddr, addr); //get the device's MAC address
693 //TODO : copy the MAC address to the device structure
694 memcpy (&dev->pl_mac, &dev_info.bdaddr, sizeof (bdaddr_t));
696 /* Check if the interface is UP */
697 if (hci_test_bit (HCI_UP, (void *) &dev_info.flags) == 0)
699 /* Bring interface up */ //FIXME should I check if is HCI_RUNNING ?!?!??!
700 if (ioctl (fd_hci, HCIDEVUP, dev_info.dev_id))
702 fprintf (stderr, "ioctl(HCIDEVUP) on interface `%.*s' failed: %s\n",
703 IFNAMSIZ, dev->iface, strerror (errno));
708 /* Check if the device is discoverable */
709 if (hci_test_bit (HCI_PSCAN, (void *) &dev_info.flags) == 0 ||
710 hci_test_bit (HCI_ISCAN, (void *) &dev_info.flags) == 0)
712 /* Set interface Page Scan and Inqury Scan ON */
713 struct hci_dev_req dev_req;
715 memset (&dev_req, 0, sizeof (dev_req));
716 dev_req.dev_id = dev_info.dev_id;
717 dev_req.dev_opt = SCAN_PAGE | SCAN_INQUIRY;
719 if (ioctl (fd_hci, HCISETSCAN, (unsigned long) &dev_req))
721 fprintf (stderr, "ioctl(HCISETSCAN) on interface `%.*s' failed: %s\n",
722 IFNAMSIZ, dev->iface, strerror (errno));
728 //FIXME : Sniff mode!?!
729 //FIXME : RAW MODE?!?
736 /* Check if the interface was not found */
739 fprintf (stderr, "The interface %s was not found\n", dev->iface);
743 /* Close the hci socket */
744 (void) close(fd_hci);
748 /* Bind the rfcomm socket to the interface */
749 memset (&rc_addr, 0, sizeof (rc_addr));
750 rc_addr.rc_family = AF_BLUETOOTH;
751 rc_addr.rc_bdaddr = *BDADDR_ANY;
752 rc_addr.rc_channel = (uint8_t) HARD_CODED_PORT_NUMBER;
754 if (bind (dev->fd_rfcomm, (struct sockaddr *) &rc_addr, sizeof (rc_addr) != 0))
756 fprintf (stderr, "Failed to bind interface `%.*s': %s\n", IFNAMSIZ,
757 dev->iface, strerror (errno));
762 memset (&hci_addr, 0, sizeof (hci_addr));
763 hci_addr.hci_family = AF_BLUETOOTH;
764 hci_addr.hci_dev = dev_id;
767 * FIXME hci_addr.hci_channel = HARD_CODED_PORT_NUMBER
768 * For linux kernel >= 2.6.7 the kernel automatically chooses an available port
769 * number. (getsockname() function can be used for finding out what port the kernel
773 if (-1 == bind (dev->fd_hci, (struct sockaddr *) &hci_addr, sizeof (hci_addr)))
775 fprintf (stderr, "Failed to bind interface `%.*s': %s\n", IFNAMSIZ,
776 dev->iface, strerror (errno));
781 if (listen (dev->fd_rfcomm, 5) == -1)
783 fprintf (stderr, "Failed to listen on socket for interface `%.*s': %s\n", IFNAMSIZ,
784 dev->iface, strerror (errno));
794 * Set the header to sane values to make attacks more difficult
796 * @param taIeeeHeader pointer to the header of the packet
797 * @param dev pointer to the Hardware_Infos struct
799 **** copy from gnunet-helper-transport-wlan.c ****
802 mac_set (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *taIeeeHeader,
803 const struct HardwareInfos *dev)
805 taIeeeHeader->frame_control = htons (IEEE80211_FC0_TYPE_DATA);
806 taIeeeHeader->addr2 = dev->pl_mac;
807 taIeeeHeader->addr3 = mac_bssid_gnunet;
811 * Test if the given interface name really corresponds to a bluetooth
814 * @param iface name of the interface
815 * @return 0 on success, 1 on error
816 **** similar with the one from gnunet-helper-transport-wlan.c ****
819 test_bluetooth_interface (const char *iface)
825 ret = snprintf (strbuf, sizeof (strbuf),
826 "/sys/class/bluetooth/%s/subsystem",
828 if ((ret < 0) || (ret >= sizeof (strbuf)) || (0 != stat (strbuf, &sbuf)))
831 "Did not find 802.15.1 interface `%s'. Exiting.\n",
839 * Test incoming packets mac for being our own.
841 * @param taIeeeHeader buffer of the packet
842 * @param dev the Hardware_Infos struct
843 * @return 0 if mac belongs to us, 1 if mac is for another target
845 **** same as the one from gnunet-helper-transport-wlan.c ****
848 mac_test (const struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *taIeeeHeader,
849 const struct HardwareInfos *dev)
851 static struct GNUNET_TRANSPORT_WLAN_MacAddress all_zeros;
853 if ( (0 == memcmp (&taIeeeHeader->addr3, &all_zeros, MAC_ADDR_SIZE)) ||
854 (0 == memcmp (&taIeeeHeader->addr1, &all_zeros, MAC_ADDR_SIZE)) )
855 return 0; /* some drivers set no Macs, then assume it is all for us! */
857 if (0 != memcmp (&taIeeeHeader->addr3, &mac_bssid_gnunet, MAC_ADDR_SIZE))
858 return 1; /* not a GNUnet ad-hoc package */
859 if ( (0 == memcmp (&taIeeeHeader->addr1, &dev->pl_mac, MAC_ADDR_SIZE)) ||
860 (0 == memcmp (&taIeeeHeader->addr1, &bc_all_mac, MAC_ADDR_SIZE)) )
861 return 0; /* for us, or broadcast */
862 return 1; /* not for us */
867 * Process data from the stdin. Takes the message forces the sender MAC to be correct
868 * and puts it into our buffer for transmission to the kernel. (the other device).
870 * @param cls pointer to the device struct ('struct HardwareInfos*')
871 * @param hdr pointer to the start of the packet
873 **** same as the one from gnunet-helper-transport-wlan.c ****
876 stdin_send_hw (void *cls, const struct GNUNET_MessageHeader *hdr)
878 struct HardwareInfos *dev = cls;
879 const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *header;
880 struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *blueheader;
883 sendsize = ntohs (hdr->size);
885 sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage)) ||
886 (GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER != ntohs (hdr->type)) )
888 fprintf (stderr, "Received malformed message\n");
891 sendsize -= (sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) - sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame));
892 if (MAXLINE < sendsize)
894 fprintf (stderr, "Packet too big for buffer\n");
897 header = (const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) hdr;
898 memcpy (&write_pout.buf, &header->frame, sendsize);
899 blueheader = (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *) &write_pout.buf;
901 /* payload contains MAC address, but we don't trust it, so we'll
902 * overwrite it with OUR MAC address to prevent mischief */
903 mac_set (blueheader, dev);
904 write_pout.size = sendsize;
909 * Main function of the helper. This code accesses a bluetooth interface
910 * forwards traffic in both directions between the bluetooth interface and
911 * stdin/stdout of this
912 * process. Error messages are written to stdout.
914 * @param argc number of arguments, must be 2
915 * @param argv arguments only argument is the name of the interface (i.e. 'mon0')
916 * @return 0 on success (never happens, as we don't return unless aborted), 1 on error
918 **** same as the one from gnunet-helper-transport-wlan.c ****
921 main (int argc, char *argv[])
923 struct HardwareInfos dev;
924 char readbuf[MAXLINE];
930 struct MessageStreamTokenizer *stdin_mst;
934 /* assert privs so we can modify the firewall rules! */
936 #ifdef HAVE_SETRESUID
937 if (0 != setresuid (uid, 0, 0))
939 fprintf (stderr, "Failed to setresuid to root: %s\n", strerror (errno));
943 if (0 != seteuid (0))
945 fprintf (stderr, "Failed to seteuid back to root: %s\n", strerror (errno));
950 /* make use of SGID capabilities on POSIX */
951 memset (&dev, 0, sizeof (dev));
952 dev.fd_rfcomm = socket (AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
953 //FIXME : using RFCOMM protocol : dev.fd_rfcomm = socket (AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
954 raw_eno = errno; /* remember for later */
956 /* now that we've dropped root rights, we can do error checking */
960 "You must specify the name of the interface as the first and only argument to this program.\n");
961 if (-1 != dev.fd_rfcomm)
962 (void) close (dev.fd_rfcomm);
966 if (-1 == dev.fd_rfcomm)
968 fprintf (stderr, "Failed to create a HCI socket: %s\n", strerror (raw_eno));
971 if (dev.fd_rfcomm >= FD_SETSIZE)
973 fprintf (stderr, "File descriptor too large for select (%d > %d)\n",
974 dev.fd_rfcomm, FD_SETSIZE);
975 (void) close (dev.fd_rfcomm);
978 if (0 != test_bluetooth_interface (argv[1]))
980 (void) close (dev.fd_rfcomm);
983 strncpy (dev.iface, argv[1], IFNAMSIZ);
984 if (0 != open_device (&dev))
986 (void) close (dev.fd_rfcomm);
992 uid_t uid = getuid ();
993 #ifdef HAVE_SETRESUID
994 if (0 != setresuid (uid, uid, uid))
996 fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno));
997 if (-1 != dev.fd_rfcomm)
998 (void) close (dev.fd_rfcomm);
1002 if (0 != (setuid (uid) | seteuid (uid)))
1004 fprintf (stderr, "Failed to setuid: %s\n", strerror (errno));
1005 if (-1 != dev.fd_rfcomm)
1006 (void) close (dev.fd_rfcomm);
1013 /* send MAC address of the bluetooth interface to STDOUT first */
1015 struct GNUNET_TRANSPORT_WLAN_HelperControlMessage macmsg;
1017 macmsg.hdr.size = htons (sizeof (macmsg));
1018 macmsg.hdr.type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL);
1019 memcpy (&macmsg.mac, &dev.pl_mac, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress));
1020 memcpy (write_std.buf, &macmsg, sizeof (macmsg));
1021 write_std.size = sizeof (macmsg);
1024 stdin_mst = mst_create (&stdin_send_hw, &dev);
1030 if ((0 == write_pout.size) && (1 == stdin_open))
1032 FD_SET (STDIN_FILENO, &rfds);
1033 maxfd = MAX (maxfd, STDIN_FILENO);
1035 if (0 == write_std.size)
1037 FD_SET (dev.fd_rfcomm, &rfds);
1038 maxfd = MAX (maxfd, dev.fd_rfcomm);
1041 if (0 < write_std.size)
1043 FD_SET (STDOUT_FILENO, &wfds);
1044 maxfd = MAX (maxfd, STDOUT_FILENO);
1046 if (0 < write_pout.size)
1048 int sendsocket, status;
1049 struct sockaddr_rc addr = { 0 };
1051 memset (dest, 0, sizeof (dest));
1053 sendsocket = socket (AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
1057 fprintf (stderr, "Failed to create a RFCOMM socket (sending stage): %s\n",
1062 addr.rc_family = AF_BLUETOOTH;
1063 addr.rc_channel = HARD_CODED_PORT_NUMBER2; //TODO: dinamically binding
1064 str2ba(dest, &addr.rc_bdaddr); //TODO: get the destination address from the message
1066 /*TODO: use a NON-BLOCKING socket
1067 * sock_flags = fcntl (sendsocket, F_GETFL, 0);
1068 * fcntl( sendsocket, F_SETFL, sock_flags | O_NONBLOCK);
1070 status = connect (sendsocket, (struct sockaddr *) &addr, sizeof (addr));
1071 if (0 != status && errno != EAGAIN)
1073 //fprintf (stderr, "connect error on %s\n", argv[1]);
1074 perror("Connect error");
1078 FD_SET (sendsocket, &wfds);
1079 maxfd = MAX (maxfd, sendsocket);
1082 int retval = select (maxfd + 1, &rfds, &wfds, NULL, NULL);
1083 if ((-1 == retval) && (EINTR == errno))
1087 fprintf (stderr, "select failed: %s\n", strerror (errno));
1092 for (i = 0; i <= maxfd; i++)
1094 if (FD_ISSET (i , &wfds))
1096 if (i == STDOUT_FILENO)
1099 write (STDOUT_FILENO, write_std.buf + write_std.pos,
1100 write_std.size - write_std.pos);
1103 fprintf (stderr, "Failed to write to STDOUT: %s\n", strerror (errno));
1106 write_std.pos += ret;
1107 if (write_std.pos == write_std.size)
1116 write (i, write_pout.buf + write_std.pos,
1117 write_pout.size - write_pout.pos);
1120 fprintf (stderr, "Failed to write to bluetooth device: %s\n",
1124 write_pout.pos += ret;
1125 if ((write_pout.pos != write_pout.size) && (0 != ret))
1127 /* we should not get partial sends with packet-oriented devices... */
1128 fprintf (stderr, "Write error, partial send: %u/%u\n",
1129 (unsigned int) write_pout.pos,
1130 (unsigned int) write_pout.size);
1133 if (write_pout.pos == write_pout.size)
1136 write_pout.size = 0;
1142 if (FD_ISSET (i, &rfds))
1144 if (i == STDIN_FILENO)
1147 read (i, readbuf, sizeof (readbuf));
1150 fprintf (stderr, "Read error from STDIN: %s\n", strerror (errno));
1155 /* stop reading... */
1158 mst_receive (stdin_mst, readbuf, ret);
1160 else if (i == dev.fd_rfcomm)
1163 struct sockaddr_rc addr = { 0 };
1164 unsigned int opt = sizeof (addr);
1166 newfd = accept (dev.fd_rfcomm, (struct sockaddr *) &addr, &opt);
1170 fprintf (stderr, "Failed to accept a connection on interface: %s\n",
1174 FD_SET (newfd, &rfds);
1175 maxfd = MAX (maxfd, newfd);
1181 struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *rrm;
1184 rrm = (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *) write_std.buf;
1186 read_from_the_socket (i, (unsigned char *) &rrm->frame,
1187 sizeof (write_std.buf)
1188 - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)
1189 + sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame),
1193 fprintf (stderr, "Read error from rfcomm socket: %s\n", strerror (errno));
1196 if ((0 < ret) && (0 == mac_test (&rrm->frame, &dev)))
1198 write_std.size = ret
1199 + sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)
1200 - sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame);
1201 rrm->header.size = htons (write_std.size);
1202 rrm->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA_FROM_HELPER);
1208 /* Error handling, try to clean up a bit at least */
1209 mst_destroy (stdin_mst);
1210 (void) close (dev.fd_rfcomm);
1212 return 1; /* we never exit 'normally' */