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"
47 * Maximum size of a message allowed in either direction
48 * (used for our receive and sent buffers).
54 * struct for storing the information of the hardware. There is only
61 * file descriptor for the rfcomm socket
66 * Name of the interface, not necessarily 0-terminated (!).
71 * MAC address of our own bluetooth interface.
73 struct GNUNET_TRANSPORT_WLAN_MacAddress pl_mac;
78 sdp_session_t *session ;
82 * IO buffer used for buffering data in transit (to wireless or to stdout).
87 * How many bytes of data are stored in 'buf' for transmission right now?
88 * Data always starts at offset 0 and extends to 'size'.
93 * How many bytes that were stored in 'buf' did we already write to the
94 * destination? Always smaller than 'size'.
99 * Buffered data; twice the maximum allowed message size as we add some
102 char buf[MAXLINE * 2];
107 * Buffer for data read from stdin to be transmitted to the bluetooth device
109 static struct SendBuffer write_pout;
112 * Buffer for data read from the bluetooth device to be transmitted to stdout.
114 static struct SendBuffer write_std;
117 static struct GNUNET_TRANSPORT_WLAN_MacAddress broadcast = {{255, 255, 255, 255, 255, 255}};
119 /* *********** specialized version of server_mst.c begins here ********** */
120 /* ****** this is the same version as the one used in gnunet-helper-transport-wlan.c ****** */
123 * To what multiple do we align messages? 8 byte should suffice for everyone
126 #define ALIGN_FACTOR 8
129 * Smallest supported message.
131 #define MIN_BUFFER_SIZE sizeof (struct GNUNET_MessageHeader)
135 * Functions with this signature are called whenever a
136 * complete message is received by the tokenizer.
139 * @param message the actual message
141 typedef void (*MessageTokenizerCallback) (void *cls,
143 GNUNET_MessageHeader *
147 * Handle to a message stream tokenizer.
149 struct MessageStreamTokenizer
153 * Function to call on completed messages.
155 MessageTokenizerCallback cb;
163 * Size of the buffer (starting at 'hdr').
168 * How many bytes in buffer have we already processed?
173 * How many bytes in buffer are valid right now?
178 * Beginning of the buffer. Typed like this to force alignment.
180 struct GNUNET_MessageHeader *hdr;
186 * Create a message stream tokenizer.
188 * @param cb function to call on completed messages
189 * @param cb_cls closure for cb
190 * @return handle to tokenizer
192 static struct MessageStreamTokenizer *
193 mst_create (MessageTokenizerCallback cb,
196 struct MessageStreamTokenizer *ret;
198 ret = malloc (sizeof (struct MessageStreamTokenizer));
201 fprintf (stderr, "Failed to allocate buffer for tokenizer\n");
204 ret->hdr = malloc (MIN_BUFFER_SIZE);
205 if (NULL == ret->hdr)
207 fprintf (stderr, "Failed to allocate buffer for alignment\n");
210 ret->curr_buf = MIN_BUFFER_SIZE;
212 ret->cb_cls = cb_cls;
220 * Add incoming data to the receive buffer and call the
221 * callback for all complete messages.
223 * @param mst tokenizer to use
224 * @param buf input data to add
225 * @param size number of bytes in buf
226 * @return GNUNET_OK if we are done processing (need more data)
227 * GNUNET_SYSERR if the data stream is corrupt
230 mst_receive (struct MessageStreamTokenizer *mst,
231 const char *buf, size_t size)
233 const struct GNUNET_MessageHeader *hdr;
238 unsigned long offset;
242 ibuf = (char *) mst->hdr;
247 if ((mst->curr_buf - mst->off < sizeof (struct GNUNET_MessageHeader)) ||
248 (0 != (mst->off % ALIGN_FACTOR)))
250 /* need to align or need more space */
251 mst->pos -= mst->off;
252 memmove (ibuf, &ibuf[mst->off], mst->pos);
255 if (mst->pos - mst->off < sizeof (struct GNUNET_MessageHeader))
258 GNUNET_MIN (sizeof (struct GNUNET_MessageHeader) -
259 (mst->pos - mst->off), size);
260 memcpy (&ibuf[mst->pos], buf, delta);
265 if (mst->pos - mst->off < sizeof (struct GNUNET_MessageHeader))
269 hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off];
270 want = ntohs (hdr->size);
271 if (want < sizeof (struct GNUNET_MessageHeader))
274 "Received invalid message from stdin\n");
277 if (mst->curr_buf - mst->off < want)
279 /* need more space */
280 mst->pos -= mst->off;
281 memmove (ibuf, &ibuf[mst->off], mst->pos);
284 if (want > mst->curr_buf)
286 mst->hdr = realloc (mst->hdr, want);
287 if (NULL == mst->hdr)
289 fprintf (stderr, "Failed to allocate buffer for alignment\n");
292 ibuf = (char *) mst->hdr;
293 mst->curr_buf = want;
295 hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off];
296 if (mst->pos - mst->off < want)
298 delta = GNUNET_MIN (want - (mst->pos - mst->off), size);
299 memcpy (&ibuf[mst->pos], buf, delta);
304 if (mst->pos - mst->off < want)
308 mst->cb (mst->cb_cls, hdr);
310 if (mst->off == mst->pos)
312 /* reset to beginning of buffer, it's free right now! */
320 if (size < sizeof (struct GNUNET_MessageHeader))
322 offset = (unsigned long) buf;
323 need_align = (0 != offset % ALIGN_FACTOR) ? GNUNET_YES : GNUNET_NO;
324 if (GNUNET_NO == need_align)
326 /* can try to do zero-copy and process directly from original buffer */
327 hdr = (const struct GNUNET_MessageHeader *) buf;
328 want = ntohs (hdr->size);
329 if (want < sizeof (struct GNUNET_MessageHeader))
332 "Received invalid message from stdin\n");
336 break; /* or not, buffer incomplete, so copy to private buffer... */
337 mst->cb (mst->cb_cls, hdr);
343 /* need to copy to private buffer to align;
344 * yes, we go a bit more spagetti than usual here */
350 if (size + mst->pos > mst->curr_buf)
352 mst->hdr = realloc (mst->hdr, size + mst->pos);
353 if (NULL == mst->hdr)
355 fprintf (stderr, "Failed to allocate buffer for alignment\n");
358 ibuf = (char *) mst->hdr;
359 mst->curr_buf = size + mst->pos;
361 if (mst->pos + size > mst->curr_buf)
364 "Assertion failed\n");
367 memcpy (&ibuf[mst->pos], buf, size);
376 * Destroys a tokenizer.
378 * @param mst tokenizer to destroy
381 mst_destroy (struct MessageStreamTokenizer *mst)
387 /* ***************** end of server_mst.c clone ***************** **/
390 /* ****** same crc version as the one used in gnunet-helper-transport-wlan.c ****** */
393 * Calculate crc32, the start of the calculation
395 * @param buf buffer to calc the crc
396 * @param len len of the buffer
400 calc_crc_osdep (const unsigned char *buf, size_t len)
402 static const unsigned long int crc_tbl_osdep[256] = {
403 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
404 0xE963A535, 0x9E6495A3,
405 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
406 0xE7B82D07, 0x90BF1D91,
407 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB,
408 0xF4D4B551, 0x83D385C7,
409 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
410 0xFA0F3D63, 0x8D080DF5,
411 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447,
412 0xD20D85FD, 0xA50AB56B,
413 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75,
414 0xDCD60DCF, 0xABD13D59,
415 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
416 0xCFBA9599, 0xB8BDA50F,
417 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11,
418 0xC1611DAB, 0xB6662D3D,
419 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F,
420 0x9FBFE4A5, 0xE8B8D433,
421 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
422 0x91646C97, 0xE6635C01,
423 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B,
424 0x8208F4C1, 0xF50FC457,
425 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49,
426 0x8CD37CF3, 0xFBD44C65,
427 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
428 0xA4D1C46D, 0xD3D6F4FB,
429 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5,
430 0xAA0A4C5F, 0xDD0D7CC9,
431 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3,
432 0xB966D409, 0xCE61E49F,
433 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
434 0xB7BD5C3B, 0xC0BA6CAD,
435 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF,
436 0x04DB2615, 0x73DC1683,
437 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D,
438 0x0A00AE27, 0x7D079EB1,
439 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
440 0x196C3671, 0x6E6B06E7,
441 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9,
442 0x17B7BE43, 0x60B08ED5,
443 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767,
444 0x3FB506DD, 0x48B2364B,
445 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
446 0x316E8EEF, 0x4669BE79,
447 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703,
448 0x220216B9, 0x5505262F,
449 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31,
450 0x2CD99E8B, 0x5BDEAE1D,
451 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
452 0x72076785, 0x05005713,
453 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D,
454 0x7CDCEFB7, 0x0BDBDF21,
455 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B,
456 0x6FB077E1, 0x18B74777,
457 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
458 0x616BFFD3, 0x166CCF45,
459 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7,
460 0x4969474D, 0x3E6E77DB,
461 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5,
462 0x47B2CF7F, 0x30B5FFE9,
463 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
464 0x54DE5729, 0x23D967BF,
465 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1,
466 0x5A05DF1B, 0x2D02EF8D
469 unsigned long crc = 0xFFFFFFFF;
471 for (; len > 0; len--, buf++)
472 crc = crc_tbl_osdep[(crc ^ *buf) & 0xFF] ^ (crc >> 8);
478 * Calculate and check crc of the bluetooth packet
480 * @param buf buffer of the packet, with len + 4 bytes of data,
481 * the last 4 bytes being the checksum
482 * @param len length of the payload in data
483 * @return 0 on success (checksum matches), 1 on error
486 check_crc_buf_osdep (const unsigned char *buf, size_t len)
490 crc = calc_crc_osdep (buf, len);
492 if (((crc) & 0xFF) == buf[0] && ((crc >> 8) & 0xFF) == buf[1] &&
493 ((crc >> 16) & 0xFF) == buf[2] && ((crc >> 24) & 0xFF) == buf[3])
500 /* ************** end of crc version ***************** */
506 * Function for assigning a port number
507 * @param socket the socket used to bind
508 * @param addr pointer to the rfcomm address
509 * @return 0 on success
512 bind_socket (int socket, struct sockaddr_rc *addr)
516 /* Bind every possible port (from 0 to 30) and stop when bind doesn't fail */
517 //FIXME : it should start from port 1, but on my computer it doesn't work :)
518 for (port = 3; port <= 30; port++)
520 addr->rc_channel = port;
521 status = bind (socket, (struct sockaddr *) addr, sizeof (struct sockaddr_rc));
531 * Function used for creating the service record and registering it.
532 * @param dev pointer to the device struct
533 * @param rc_channel the rfcomm channel
534 * @return 0 on success
537 register_service (struct HardwareInfos *dev, int rc_channel)
541 * 2. set the service ID, class, profile information
542 * 3. make the service record publicly browsable
543 * 4. register the RFCOMM channel
544 * 5. set the name, provider and description
545 * 6. register the service record to the local SDP server
549 //FIXME: probably this is not the best idea. I should find a different uuid
550 uint8_t svc_uuid_int[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
551 dev->pl_mac.mac[5], dev->pl_mac.mac[4], dev->pl_mac.mac[3],
552 dev->pl_mac.mac[2], dev->pl_mac.mac[1], dev->pl_mac.mac[0]};
553 // const char *service_name = "GNUnet";
554 const char *service_dsc = "Bluetooth plugin services";
555 const char *service_prov = "GNUnet provider";
556 uuid_t root_uuid, rfcomm_uuid, l2cap_uuid, svc_uuid;
557 sdp_list_t *root_list = 0, *rfcomm_list = 0, *l2cap_list = 0,
558 *proto_list = 0, *access_proto_list = 0, *svc_list = 0;
559 sdp_record_t *record = 0;
560 sdp_data_t *channel = 0;
562 record = sdp_record_alloc();
564 /* Set the general service ID */
565 sdp_uuid128_create (&svc_uuid, &svc_uuid_int);
566 svc_list = sdp_list_append (0, &svc_uuid);
567 sdp_set_service_classes (record, svc_list);
568 sdp_set_service_id (record, svc_uuid);
570 /* Make the service record publicly browsable */
571 sdp_uuid16_create (&root_uuid, PUBLIC_BROWSE_GROUP);
572 root_list = sdp_list_append (0, &root_uuid);
573 sdp_set_browse_groups (record, root_list);
575 /* Register the RFCOMM channel */
576 sdp_uuid16_create (&rfcomm_uuid, RFCOMM_UUID);
577 channel = sdp_data_alloc (SDP_UINT8, &rc_channel);
578 rfcomm_list = sdp_list_append (0, &rfcomm_uuid);
579 sdp_list_append (rfcomm_list, channel);
580 proto_list = sdp_list_append (0, rfcomm_list);
582 /* Set L2CAP information FIXME: probably not needed */
583 // sdp_uuid16_create (&l2cap_uuid, L2CAP_UUID);
584 // l2cap_list = sdp_list_append (0, &l2cap_uuid);
585 //sdp_list_append (proto_list, l2cap_list);
587 /* Set protocol information */
588 access_proto_list = sdp_list_append (0, proto_list);
589 sdp_set_access_protos (record, access_proto_list);
591 /* Set the name, provider, and description */
592 sdp_set_info_attr (record, dev->iface, service_prov, service_dsc);
594 /* Connect to the local SDP server */
595 dev->session = sdp_connect (BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
599 fprintf (stderr, "Failed to connect to the SDP server on interface `%.*s': %s\n",
600 IFNAMSIZ, dev->iface, strerror (errno));
605 /* Register the service record */
606 if (sdp_record_register (dev->session, record, 0) < 0)
608 fprintf (stderr, "Failed to register a service record on interface `%.*s': %s\n",
609 IFNAMSIZ, dev->iface, strerror (errno));
615 sdp_data_free (channel);
616 sdp_list_free (root_list, 0);
617 sdp_list_free (rfcomm_list, 0);
618 sdp_list_free (l2cap_list, 0);
619 sdp_list_free (proto_list, 0);
620 sdp_list_free (access_proto_list, 0);
621 sdp_list_free (svc_list, 0);
622 sdp_record_free (record);
628 * Function for searching and browsing for a service. This will return the
629 * port number on which the service is running.
630 * @param dev pointer to the device struct
631 * @param dest target address
635 get_channel(struct HardwareInfos *dev, bdaddr_t dest)
638 * 1. detect all nearby devices //FIXME : Connect directly to the device with the service
639 * 2. for each device:
640 * 2.1. connect to the SDP server running
641 * 2.2. get a list of service records with the specific UUID
642 * 2.3. for each service record get a list of the protocol sequences and get
645 uint8_t svc_uuid_int[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
646 dest.b[5], dest.b[4], dest.b[3],
647 dest.b[2], dest.b[1], dest.b[0]};
648 sdp_session_t *session = 0;
649 sdp_list_t *search_list = 0, *attrid_list = 0, *response_list = 0, *it = 0;
651 uint32_t range = 0x0000ffff;
652 uint8_t channel = -1;
654 /* Connect to the local SDP server */
655 session = sdp_connect (BDADDR_ANY, &dest, 0);
658 fprintf (stderr, "Failed to connect to the SDP server on interface `%.*s': %s\n",
659 IFNAMSIZ, dev->iface, strerror (errno));
664 sdp_uuid128_create (&svc_uuid, &svc_uuid_int);
665 search_list = sdp_list_append (0, &svc_uuid);
666 attrid_list = sdp_list_append (0, &range);
668 if (sdp_service_search_attr_req (session, search_list,
669 SDP_ATTR_REQ_RANGE, attrid_list, &response_list) == 0)
671 for (it = response_list; it; it = it->next)
673 sdp_record_t *record = (sdp_record_t*) it->data;
674 //TODO print some record informations to be sure everything is good
675 sdp_list_t *proto_list = 0;
676 if (sdp_get_access_protos (record, &proto_list) == 0)
678 channel = sdp_get_proto_port (proto_list, RFCOMM_UUID);
679 sdp_list_free (proto_list, 0);
681 sdp_record_free (record);
685 sdp_list_free (search_list, 0);
686 sdp_list_free (attrid_list, 0);
687 sdp_list_free (response_list, 0);
692 fprintf (stderr, "Failed to find the listening channel for interface `%.*s': %s\n",
693 IFNAMSIZ, dev->iface, strerror (errno));
699 * Read from the socket and put the result into the buffer for transmission to 'stdout'.
700 * @param sock file descriptor for reading
701 * @param buf buffer to read to; first bytes will be the 'struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame',
702 * followed by the actual payload
703 * @param buf_size size of the buffer
704 * @param ri where to write radiotap_rx info
705 * @return number of bytes written to 'buf'
708 read_from_the_socket (int sock,
709 unsigned char *buf, size_t buf_size,
710 struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *ri)
713 * 1. Read from the socket in a temporary buffer (check for errors)
714 * 2. Detect if the crc exists
715 * 3. Write the result to the buffer
717 unsigned char tmpbuf[buf_size];
720 struct sockaddr_rc rc_addr = { 0 };
722 count = read (sock, tmpbuf, buf_size);
729 fprintf (stderr, "Failed to read from the HCI socket: %s\n", strerror (errno));
733 /* Get the channel used */
734 memset (&rc_addr, 0, sizeof (rc_addr));
735 len = sizeof (rc_addr);
736 if (0 > getsockname (sock, (struct sockaddr *) &rc_addr, (socklen_t *) &len))
738 fprintf (stderr, "getsockname() call failed : %s\n", strerror (errno));
742 memset (ri, 0, sizeof (*ri));
743 ri->ri_channel = rc_addr.rc_channel;
745 /* detect CRC32 at the end */
746 if (0 == check_crc_buf_osdep (tmpbuf, count - sizeof (uint32_t)))
748 count -= sizeof(uint32_t);
751 memcpy (buf, tmpbuf, count);
757 * Open the bluetooth interface for reading/writing
759 * @param dev pointer to the device struct
760 * @return 0 on success
763 open_device (struct HardwareInfos *dev)
766 * 1. Open a HCI socket (if RFCOMM protocol is used. If not, the HCI socket is
767 * saved in dev->rfcomm).
768 * 2. Find the device id (request a list with all the devices and find the one
769 * with the dev->iface name)
770 * 3. If the interface is down try to get it up
771 * 4. Bind the RFCOMM socket to the interface using the bind_socket() method and register
773 * 5. For now use a hard coded port number(channel) value
774 * FIXME : if I use HCI sockets , should I enable RAW_SOCKET MODE?!?!?!
777 int i, dev_id = -1, fd_hci;
780 struct hci_dev_list_req list;
781 struct hci_dev_req dev[HCI_MAX_DEV];
782 } request; //used for detecting the local devices
783 struct sockaddr_rc rc_addr = { 0 }; //used for binding
785 fd_hci = socket (AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
789 fprintf (stderr, "Failed to create HCI socket: %s\n", strerror (errno));
793 memset (&request, 0, sizeof(request));
794 request.list.dev_num = HCI_MAX_DEV;
796 if (ioctl (fd_hci, HCIGETDEVLIST, (void *) &request) < 0)
798 fprintf (stderr, "ioctl(HCIGETDEVLIST) on interface `%.*s' failed: %s\n",
799 IFNAMSIZ, dev->iface, strerror (errno));
803 /* Search for a device with dev->iface name */
804 for (i = 0; i < request.list.dev_num; i++)
806 struct hci_dev_info dev_info;
808 memset (&dev_info, 0, sizeof(struct hci_dev_info));
809 dev_info.dev_id = request.dev[i].dev_id;
810 strncpy (dev_info.name, dev->iface, IFNAMSIZ);
812 if (ioctl (fd_hci, HCIGETDEVINFO, (void *) &dev_info))
814 fprintf (stderr, "ioctl(HCIGETDEVINFO) on interface `%.*s' failed: %s\n",
815 IFNAMSIZ, dev->iface, strerror (errno));
819 if (strcmp (dev_info.name, dev->iface) == 0)
821 //char addr[19] = { 0 }; //the device MAC address
823 dev_id = dev_info.dev_id; //the device was found
825 // ba2str (&dev_info.bdaddr, addr); //get the device's MAC address
827 * Copy the MAC address to the device structure
828 * FIXME: probably this is not the best solution
830 memcpy (&dev->pl_mac, &dev_info.bdaddr, sizeof (bdaddr_t));
832 /* Check if the interface is UP */
833 if (hci_test_bit (HCI_UP, (void *) &dev_info.flags) == 0)
835 /* Bring interface up */ //FIXME should I check if is HCI_RUNNING ?!?!??!
836 if (ioctl (fd_hci, HCIDEVUP, dev_info.dev_id))
838 fprintf (stderr, "ioctl(HCIDEVUP) on interface `%.*s' failed: %s\n",
839 IFNAMSIZ, dev->iface, strerror (errno));
844 /* Check if the device is discoverable */
845 if (hci_test_bit (HCI_PSCAN, (void *) &dev_info.flags) == 0 ||
846 hci_test_bit (HCI_ISCAN, (void *) &dev_info.flags) == 0)
848 /* Set interface Page Scan and Inqury Scan ON */
849 struct hci_dev_req dev_req;
851 memset (&dev_req, 0, sizeof (dev_req));
852 dev_req.dev_id = dev_info.dev_id;
853 dev_req.dev_opt = SCAN_PAGE | SCAN_INQUIRY;
855 if (ioctl (fd_hci, HCISETSCAN, (unsigned long) &dev_req))
857 fprintf (stderr, "ioctl(HCISETSCAN) on interface `%.*s' failed: %s\n",
858 IFNAMSIZ, dev->iface, strerror (errno));
864 //FIXME : Sniff mode!?!
865 //FIXME : RAW MODE?!?
872 /* Check if the interface was not found */
875 fprintf (stderr, "The interface %s was not found\n", dev->iface);
879 /* Close the hci socket */
880 (void) close(fd_hci);
884 /* Bind the rfcomm socket to the interface */
885 memset (&rc_addr, 0, sizeof (rc_addr));
886 rc_addr.rc_family = AF_BLUETOOTH;
887 rc_addr.rc_bdaddr = *BDADDR_ANY;
889 if (bind_socket (dev->fd_rfcomm, &rc_addr) != 0)
891 fprintf (stderr, "Failed to bind interface `%.*s': %s\n", IFNAMSIZ,
892 dev->iface, strerror (errno));
896 /* Register a SDP service */
897 if (register_service (dev, rc_addr.rc_channel) != 0)
899 fprintf (stderr, "Failed to register a service on interface `%.*s': %s\n", IFNAMSIZ,
900 dev->iface, strerror (errno));
904 /* Switch socket in listening mode */
905 if (listen (dev->fd_rfcomm, 5) == -1) //FIXME: probably we need a bigger number
907 fprintf (stderr, "Failed to listen on socket for interface `%.*s': %s\n", IFNAMSIZ,
908 dev->iface, strerror (errno));
918 * Set the header to sane values to make attacks more difficult
920 * @param taIeeeHeader pointer to the header of the packet
921 * @param dev pointer to the Hardware_Infos struct
923 **** copy from gnunet-helper-transport-wlan.c ****
926 mac_set (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *taIeeeHeader,
927 const struct HardwareInfos *dev)
929 taIeeeHeader->frame_control = htons (IEEE80211_FC0_TYPE_DATA);
930 taIeeeHeader->addr2 = dev->pl_mac;
931 taIeeeHeader->addr3 = mac_bssid_gnunet;
935 * Test if the given interface name really corresponds to a bluetooth
938 * @param iface name of the interface
939 * @return 0 on success, 1 on error
940 **** similar with the one from gnunet-helper-transport-wlan.c ****
943 test_bluetooth_interface (const char *iface)
949 ret = snprintf (strbuf, sizeof (strbuf),
950 "/sys/class/bluetooth/%s/subsystem",
952 if ((ret < 0) || (ret >= sizeof (strbuf)) || (0 != stat (strbuf, &sbuf)))
955 "Did not find 802.15.1 interface `%s'. Exiting.\n",
963 * Test incoming packets mac for being our own.
965 * @param taIeeeHeader buffer of the packet
966 * @param dev the Hardware_Infos struct
967 * @return 0 if mac belongs to us, 1 if mac is for another target
969 **** same as the one from gnunet-helper-transport-wlan.c ****
972 mac_test (const struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *taIeeeHeader,
973 const struct HardwareInfos *dev)
975 static struct GNUNET_TRANSPORT_WLAN_MacAddress all_zeros;
977 if ( (0 == memcmp (&taIeeeHeader->addr3, &all_zeros, MAC_ADDR_SIZE)) ||
978 (0 == memcmp (&taIeeeHeader->addr1, &all_zeros, MAC_ADDR_SIZE)) )
979 return 0; /* some drivers set no Macs, then assume it is all for us! */
981 if (0 != memcmp (&taIeeeHeader->addr3, &mac_bssid_gnunet, MAC_ADDR_SIZE))
982 return 1; /* not a GNUnet ad-hoc package */
983 if ( (0 == memcmp (&taIeeeHeader->addr1, &dev->pl_mac, MAC_ADDR_SIZE)) ||
984 (0 == memcmp (&taIeeeHeader->addr1, &bc_all_mac, MAC_ADDR_SIZE)) )
985 return 0; /* for us, or broadcast */
986 return 1; /* not for us */
991 * Process data from the stdin. Takes the message forces the sender MAC to be correct
992 * and puts it into our buffer for transmission to the kernel. (the other device).
994 * @param cls pointer to the device struct ('struct HardwareInfos*')
995 * @param hdr pointer to the start of the packet
997 **** same as the one from gnunet-helper-transport-wlan.c ****
1000 stdin_send_hw (void *cls, const struct GNUNET_MessageHeader *hdr)
1002 struct HardwareInfos *dev = cls;
1003 const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *header;
1004 struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *blueheader;
1007 sendsize = ntohs (hdr->size);
1009 sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage)) ||
1010 (GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER != ntohs (hdr->type)) )
1012 fprintf (stderr, "Received malformed message\n");
1015 sendsize -= (sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) -
1016 sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame));
1017 if (MAXLINE < sendsize)
1019 fprintf (stderr, "Packet too big for buffer\n");
1022 header = (const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) hdr;
1023 memcpy (&write_pout.buf, &header->frame, sendsize);
1024 blueheader = (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *) &write_pout.buf;
1026 /* payload contains MAC address, but we don't trust it, so we'll
1027 * overwrite it with OUR MAC address to prevent mischief */
1028 mac_set (blueheader, dev);
1029 memcpy (&blueheader->addr1, &header->frame.addr1,
1030 sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)); //FIXME is this correct?
1031 write_pout.size = sendsize;
1037 * Broadcast a HELLO message for peer discovery
1042 // Use a hard coded port number to send hello messages to all the neighbours
1045 * Main function of the helper. This code accesses a bluetooth interface
1046 * forwards traffic in both directions between the bluetooth interface and
1047 * stdin/stdout of this process. Error messages are written to stdout.
1049 * @param argc number of arguments, must be 2
1050 * @param argv arguments only argument is the name of the interface (i.e. 'hci0')
1051 * @return 0 on success (never happens, as we don't return unless aborted), 1 on error
1053 **** same as the one from gnunet-helper-transport-wlan.c ****
1056 main (int argc, char *argv[])
1058 struct HardwareInfos dev;
1059 char readbuf[MAXLINE];
1064 struct MessageStreamTokenizer *stdin_mst;
1067 int crt_rfds = 0, crt_wfds = 0, rfds_list[MAX_PORTS], wfds_list[MAX_PORTS];
1069 /* Assert privs so we can modify the firewall rules! */
1071 #ifdef HAVE_SETRESUID
1072 if (0 != setresuid (uid, 0, 0))
1074 fprintf (stderr, "Failed to setresuid to root: %s\n", strerror (errno));
1078 if (0 != seteuid (0))
1080 fprintf (stderr, "Failed to seteuid back to root: %s\n", strerror (errno));
1085 /* Make use of SGID capabilities on POSIX */
1086 memset (&dev, 0, sizeof (dev));
1087 dev.fd_rfcomm = socket (AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
1088 raw_eno = errno; /* remember for later */
1090 /* Now that we've dropped root rights, we can do error checking */
1093 fprintf (stderr, "You must specify the name of the interface as the first \
1094 and only argument to this program.\n");
1095 if (-1 != dev.fd_rfcomm)
1096 (void) close (dev.fd_rfcomm);
1100 if (-1 == dev.fd_rfcomm)
1102 fprintf (stderr, "Failed to create a HCI socket: %s\n", strerror (raw_eno));
1105 if (dev.fd_rfcomm >= FD_SETSIZE)
1107 fprintf (stderr, "File descriptor too large for select (%d > %d)\n",
1108 dev.fd_rfcomm, FD_SETSIZE);
1109 (void) close (dev.fd_rfcomm);
1112 if (0 != test_bluetooth_interface (argv[1]))
1114 (void) close (dev.fd_rfcomm);
1117 strncpy (dev.iface, argv[1], IFNAMSIZ);
1118 if (0 != open_device (&dev))
1120 (void) close (dev.fd_rfcomm);
1126 uid_t uid = getuid ();
1127 #ifdef HAVE_SETRESUID
1128 if (0 != setresuid (uid, uid, uid))
1130 fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno));
1131 if (-1 != dev.fd_rfcomm)
1132 (void) close (dev.fd_rfcomm);
1136 if (0 != (setuid (uid) | seteuid (uid)))
1138 fprintf (stderr, "Failed to setuid: %s\n", strerror (errno));
1139 if (-1 != dev.fd_rfcomm)
1140 (void) close (dev.fd_rfcomm);
1146 /* Send MAC address of the bluetooth interface to STDOUT first */
1148 struct GNUNET_TRANSPORT_WLAN_HelperControlMessage macmsg;
1150 macmsg.hdr.size = htons (sizeof (macmsg));
1151 macmsg.hdr.type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL);
1152 memcpy (&macmsg.mac, &dev.pl_mac, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress));
1153 memcpy (write_std.buf, &macmsg, sizeof (macmsg));
1154 write_std.size = sizeof (macmsg);
1158 stdin_mst = mst_create (&stdin_send_hw, &dev);
1161 fprintf (stderr, "Check if the program exits\n");
1166 if ((0 == write_pout.size) && (1 == stdin_open))
1168 // fprintf(stderr, "LOG : %s adds STDIN to rfds\n", dev.iface); //FIXME: debugging message
1169 FD_SET (STDIN_FILENO, &rfds);
1170 maxfd = MAX (maxfd, STDIN_FILENO);
1172 if (0 == write_std.size)
1174 // fprintf(stderr, "LOG : %s adds fd_rfcomm to rfds\n", dev.iface); //FIXME: debugging message
1175 FD_SET (dev.fd_rfcomm, &rfds);
1176 maxfd = MAX (maxfd, dev.fd_rfcomm);
1179 if (0 < write_std.size)
1181 // fprintf(stderr, "LOG : %s adds STDOUT to wfds\n", dev.iface); //FIXME: debugging message
1182 FD_SET (STDOUT_FILENO, &wfds);
1183 maxfd = MAX (maxfd, STDOUT_FILENO);
1186 for (i = 0; i < crt_rfds; i++)
1188 // fprintf(stderr, "LOG : %s adds extra fds to rfds\n", dev.iface); //FIXME: debugging message
1189 FD_SET (rfds_list[i], &rfds);
1190 maxfd = MAX (maxfd, rfds_list[i]);
1193 for (i = 0; i < crt_wfds; i++)
1195 // fprintf(stderr, "LOG : %s adds extra fds to wfds\n", dev.iface); //FIXME: debugging message
1196 FD_SET (wfds_list[i], &wfds);
1197 maxfd = MAX (maxfd, wfds_list[i]);
1200 if (0 < write_pout.size)
1202 struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *frame;
1204 /* Get the destination address */
1205 //FIXME : not sure if this is correct
1206 frame = (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *) write_pout.buf;
1208 if (memcmp (&frame->addr1, &dev.pl_mac,
1209 sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)) == 0)
1211 // fprintf (stderr, "LOG : %s has a message for him:)\n", dev.iface); //FIXME: debugging message
1212 memset (&write_pout, 0, sizeof (write_pout)); // clear the buffer
1214 else if (memcmp (&frame->addr1, &broadcast,
1215 sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)) == 0)
1217 // fprintf (stderr, "LOG : %s has a broadcast message\n", dev.iface); //FIXME: debugging message
1218 memset (&write_pout, 0, sizeof (write_pout)); //FIXME for now just clear the buffer
1224 int sendsocket, status;
1225 struct sockaddr_rc addr = { 0 };
1227 fprintf (stderr, "LOG : %s has a new message for %.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", dev.iface,
1228 frame->addr1.mac[5], frame->addr1.mac[4], frame->addr1.mac[3],
1229 frame->addr1.mac[2], frame->addr1.mac[1], frame->addr1.mac[0]); //FIXME: debugging message
1231 memcpy (&addr.rc_bdaddr, &frame->addr1, sizeof (bdaddr_t));
1233 sendsocket = socket (AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
1237 fprintf (stderr, "Failed to create a RFCOMM socket (sending stage): %s\n",
1243 addr.rc_family = AF_BLUETOOTH;
1244 addr.rc_channel = get_channel (&dev, addr.rc_bdaddr);
1246 /*TODO: use a NON-BLOCKING socket
1247 * sock_flags = fcntl (sendsocket, F_GETFL, 0);
1248 * fcntl( sendsocket, F_SETFL, sock_flags | O_NONBLOCK);
1250 status = connect (sendsocket, (struct sockaddr *) &addr, sizeof (addr));
1251 if (0 != status && errno != EAGAIN)
1253 fprintf (stderr, "%s failed to connect : %s\n", dev.iface, strerror (errno));
1257 FD_SET (sendsocket, &wfds);
1258 maxfd = MAX (maxfd, sendsocket);
1260 if (crt_wfds < MAX_PORTS)
1261 wfds_list[crt_wfds++] = sendsocket; //add the socket to the list
1264 fprintf (stderr, "The limit for the write file descriptors list was \
1270 //fprintf (stderr, "inainte de select\n");
1273 int retval = select (maxfd + 1, &rfds, &wfds, NULL, NULL);
1274 if ((-1 == retval) && (EINTR == errno))
1278 fprintf (stderr, "select failed: %s\n", strerror (errno));
1282 // fprintf (stderr, "dupa select\n");
1283 for (i = 0; i <= maxfd; i++) //FIXME it should be incremented
1285 if (FD_ISSET (i , &wfds))
1287 if (i == STDOUT_FILENO)
1290 write (STDOUT_FILENO, write_std.buf + write_std.pos,
1291 write_std.size - write_std.pos);
1294 fprintf (stderr, "Failed to write to STDOUT: %s\n", strerror (errno));
1297 write_std.pos += ret;
1298 if (write_std.pos == write_std.size)
1303 // fprintf(stderr, "LOG : %s sends a message to STDOUT\n", dev.iface); //FIXME: debugging message
1308 write (i, write_pout.buf + write_std.pos,
1309 write_pout.size - write_pout.pos);
1312 fprintf (stderr, "Failed to write to bluetooth device: %s\n",
1316 write_pout.pos += ret;
1317 if ((write_pout.pos != write_pout.size) && (0 != ret))
1319 /* we should not get partial sends with packet-oriented devices... */
1320 fprintf (stderr, "Write error, partial send: %u/%u\n",
1321 (unsigned int) write_pout.pos,
1322 (unsigned int) write_pout.size);
1325 if (write_pout.pos == write_pout.size)
1328 write_pout.size = 0;
1331 // fprintf(stderr, "LOG : %s sends a message to a DEVICE\n", dev.iface); //FIXME: debugging message
1336 if (FD_ISSET (i, &rfds))
1338 if (i == STDIN_FILENO)
1341 read (i, readbuf, sizeof (readbuf));
1344 fprintf (stderr, "Read error from STDIN: %s\n", strerror (errno));
1349 /* stop reading... */
1352 // fprintf(stderr, "LOG : %s receives a message from STDIN\n", dev.iface); //FIXME: debugging message
1353 mst_receive (stdin_mst, readbuf, ret);
1355 else if (i == dev.fd_rfcomm)
1358 struct sockaddr_rc addr = { 0 };
1359 unsigned int opt = sizeof (addr);
1361 readsocket = accept (dev.fd_rfcomm, (struct sockaddr *) &addr, &opt);
1362 fprintf(stderr, "LOG : %s accepts a message\n", dev.iface); //FIXME: debugging message
1363 if (readsocket == -1)
1365 fprintf (stderr, "Failed to accept a connection on interface: %s\n",
1369 FD_SET (readsocket, &rfds);
1370 maxfd = MAX (maxfd, readsocket);
1372 if (crt_rfds < MAX_PORTS)
1373 rfds_list[crt_rfds++] = readsocket;
1376 fprintf (stderr, "The limit for the read file descriptors list was \
1385 struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *rrm;
1388 rrm = (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *) write_std.buf;
1390 read_from_the_socket (i, (unsigned char *) &rrm->frame,
1391 sizeof (write_std.buf)
1392 - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)
1393 + sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame),
1395 fprintf (stderr, "LOG: %s reads something from the socket\n", dev.iface);//FIXME : debugging message
1398 fprintf (stderr, "Read error from rfcomm socket: %s\n", strerror (errno));
1401 if ((0 < ret) && (0 == mac_test (&rrm->frame, &dev)))
1403 write_std.size = ret
1404 + sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)
1405 - sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame);
1406 rrm->header.size = htons (write_std.size);
1407 rrm->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA_FROM_HELPER);
1416 /* Error handling, try to clean up a bit at least */
1417 mst_destroy (stdin_mst);
1419 sdp_close (dev.session);
1420 (void) close (dev.fd_rfcomm);
1421 for (i = 0; i < crt_rfds; i++)
1422 (void) close (rfds_list[i]);
1424 for (i = 0; i < crt_wfds; i++)
1425 (void) close (wfds_list[i]);
1427 return 1; /* we never exit 'normally' */
1431 * 1. check if the rate from get_wlan_header (plugin_transport_bluetooth.c) is correct