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 /* *********** specialized version of server_mst.c begins here ********** */
118 /* ****** this is the same version as the one used in gnunet-helper-transport-wlan.c ****** */
121 * To what multiple do we align messages? 8 byte should suffice for everyone
124 #define ALIGN_FACTOR 8
127 * Smallest supported message.
129 #define MIN_BUFFER_SIZE sizeof (struct GNUNET_MessageHeader)
133 * Functions with this signature are called whenever a
134 * complete message is received by the tokenizer.
137 * @param message the actual message
139 typedef void (*MessageTokenizerCallback) (void *cls,
141 GNUNET_MessageHeader *
145 * Handle to a message stream tokenizer.
147 struct MessageStreamTokenizer
151 * Function to call on completed messages.
153 MessageTokenizerCallback cb;
161 * Size of the buffer (starting at 'hdr').
166 * How many bytes in buffer have we already processed?
171 * How many bytes in buffer are valid right now?
176 * Beginning of the buffer. Typed like this to force alignment.
178 struct GNUNET_MessageHeader *hdr;
184 * Create a message stream tokenizer.
186 * @param cb function to call on completed messages
187 * @param cb_cls closure for cb
188 * @return handle to tokenizer
190 static struct MessageStreamTokenizer *
191 mst_create (MessageTokenizerCallback cb,
194 struct MessageStreamTokenizer *ret;
196 ret = malloc (sizeof (struct MessageStreamTokenizer));
199 fprintf (stderr, "Failed to allocate buffer for tokenizer\n");
202 ret->hdr = malloc (MIN_BUFFER_SIZE);
203 if (NULL == ret->hdr)
205 fprintf (stderr, "Failed to allocate buffer for alignment\n");
208 ret->curr_buf = MIN_BUFFER_SIZE;
210 ret->cb_cls = cb_cls;
216 * Add incoming data to the receive buffer and call the
217 * callback for all complete messages.
219 * @param mst tokenizer to use
220 * @param buf input data to add
221 * @param size number of bytes in buf
222 * @return GNUNET_OK if we are done processing (need more data)
223 * GNUNET_SYSERR if the data stream is corrupt
226 mst_receive (struct MessageStreamTokenizer *mst,
227 const char *buf, size_t size)
229 const struct GNUNET_MessageHeader *hdr;
234 unsigned long offset;
238 ibuf = (char *) mst->hdr;
242 if ((mst->curr_buf - mst->off < sizeof (struct GNUNET_MessageHeader)) ||
243 (0 != (mst->off % ALIGN_FACTOR)))
245 /* need to align or need more space */
246 mst->pos -= mst->off;
247 memmove (ibuf, &ibuf[mst->off], mst->pos);
250 if (mst->pos - mst->off < sizeof (struct GNUNET_MessageHeader))
253 GNUNET_MIN (sizeof (struct GNUNET_MessageHeader) -
254 (mst->pos - mst->off), size);
255 memcpy (&ibuf[mst->pos], buf, delta);
260 if (mst->pos - mst->off < sizeof (struct GNUNET_MessageHeader))
264 hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off];
265 want = ntohs (hdr->size);
266 if (want < sizeof (struct GNUNET_MessageHeader))
269 "Received invalid message from stdin\n");
272 if (mst->curr_buf - mst->off < want)
274 /* need more space */
275 mst->pos -= mst->off;
276 memmove (ibuf, &ibuf[mst->off], mst->pos);
279 if (want > mst->curr_buf)
281 mst->hdr = realloc (mst->hdr, want);
282 if (NULL == mst->hdr)
284 fprintf (stderr, "Failed to allocate buffer for alignment\n");
287 ibuf = (char *) mst->hdr;
288 mst->curr_buf = want;
290 hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off];
291 if (mst->pos - mst->off < want)
293 delta = GNUNET_MIN (want - (mst->pos - mst->off), size);
294 memcpy (&ibuf[mst->pos], buf, delta);
299 if (mst->pos - mst->off < want)
303 mst->cb (mst->cb_cls, hdr);
305 if (mst->off == mst->pos)
307 /* reset to beginning of buffer, it's free right now! */
314 if (size < sizeof (struct GNUNET_MessageHeader))
316 offset = (unsigned long) buf;
317 need_align = (0 != offset % ALIGN_FACTOR) ? GNUNET_YES : GNUNET_NO;
318 if (GNUNET_NO == need_align)
320 /* can try to do zero-copy and process directly from original buffer */
321 hdr = (const struct GNUNET_MessageHeader *) buf;
322 want = ntohs (hdr->size);
323 if (want < sizeof (struct GNUNET_MessageHeader))
326 "Received invalid message from stdin\n");
330 break; /* or not, buffer incomplete, so copy to private buffer... */
331 mst->cb (mst->cb_cls, hdr);
337 /* need to copy to private buffer to align;
338 * yes, we go a bit more spagetti than usual here */
344 if (size + mst->pos > mst->curr_buf)
346 mst->hdr = realloc (mst->hdr, size + mst->pos);
347 if (NULL == mst->hdr)
349 fprintf (stderr, "Failed to allocate buffer for alignment\n");
352 ibuf = (char *) mst->hdr;
353 mst->curr_buf = size + mst->pos;
355 if (mst->pos + size > mst->curr_buf)
358 "Assertion failed\n");
361 memcpy (&ibuf[mst->pos], buf, size);
369 * Destroys a tokenizer.
371 * @param mst tokenizer to destroy
374 mst_destroy (struct MessageStreamTokenizer *mst)
380 /* ***************** end of server_mst.c clone ***************** **/
383 /* ****** same crc version as the one used in gnunet-helper-transport-wlan.c ****** */
386 * Calculate crc32, the start of the calculation
388 * @param buf buffer to calc the crc
389 * @param len len of the buffer
393 calc_crc_osdep (const unsigned char *buf, size_t len)
395 static const unsigned long int crc_tbl_osdep[256] = {
396 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
397 0xE963A535, 0x9E6495A3,
398 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
399 0xE7B82D07, 0x90BF1D91,
400 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB,
401 0xF4D4B551, 0x83D385C7,
402 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
403 0xFA0F3D63, 0x8D080DF5,
404 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447,
405 0xD20D85FD, 0xA50AB56B,
406 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75,
407 0xDCD60DCF, 0xABD13D59,
408 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
409 0xCFBA9599, 0xB8BDA50F,
410 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11,
411 0xC1611DAB, 0xB6662D3D,
412 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F,
413 0x9FBFE4A5, 0xE8B8D433,
414 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
415 0x91646C97, 0xE6635C01,
416 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B,
417 0x8208F4C1, 0xF50FC457,
418 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49,
419 0x8CD37CF3, 0xFBD44C65,
420 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
421 0xA4D1C46D, 0xD3D6F4FB,
422 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5,
423 0xAA0A4C5F, 0xDD0D7CC9,
424 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3,
425 0xB966D409, 0xCE61E49F,
426 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
427 0xB7BD5C3B, 0xC0BA6CAD,
428 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF,
429 0x04DB2615, 0x73DC1683,
430 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D,
431 0x0A00AE27, 0x7D079EB1,
432 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
433 0x196C3671, 0x6E6B06E7,
434 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9,
435 0x17B7BE43, 0x60B08ED5,
436 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767,
437 0x3FB506DD, 0x48B2364B,
438 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
439 0x316E8EEF, 0x4669BE79,
440 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703,
441 0x220216B9, 0x5505262F,
442 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31,
443 0x2CD99E8B, 0x5BDEAE1D,
444 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
445 0x72076785, 0x05005713,
446 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D,
447 0x7CDCEFB7, 0x0BDBDF21,
448 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B,
449 0x6FB077E1, 0x18B74777,
450 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
451 0x616BFFD3, 0x166CCF45,
452 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7,
453 0x4969474D, 0x3E6E77DB,
454 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5,
455 0x47B2CF7F, 0x30B5FFE9,
456 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
457 0x54DE5729, 0x23D967BF,
458 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1,
459 0x5A05DF1B, 0x2D02EF8D
462 unsigned long crc = 0xFFFFFFFF;
464 for (; len > 0; len--, buf++)
465 crc = crc_tbl_osdep[(crc ^ *buf) & 0xFF] ^ (crc >> 8);
471 * Calculate and check crc of the bluetooth packet
473 * @param buf buffer of the packet, with len + 4 bytes of data,
474 * the last 4 bytes being the checksum
475 * @param len length of the payload in data
476 * @return 0 on success (checksum matches), 1 on error
479 check_crc_buf_osdep (const unsigned char *buf, size_t len)
483 crc = calc_crc_osdep (buf, len);
485 if (((crc) & 0xFF) == buf[0] && ((crc >> 8) & 0xFF) == buf[1] &&
486 ((crc >> 16) & 0xFF) == buf[2] && ((crc >> 24) & 0xFF) == buf[3])
493 /* ************** end of crc version ***************** */
499 * Function for assigning a port number
500 * @param socket the socket used to bind
501 * @param addr pointer to the rfcomm address
502 * @return 0 on success
505 bind_socket (int socket, struct sockaddr_rc *addr)
509 /* Bind every possible port (from 0 to 30) and stop when bind doesn't fail */
510 //FIXME : it should start from port 1, but on my computer it doesn't work :)
511 for (port = 3; port <= 30; port++)
513 addr->rc_channel = port;
514 status = bind (socket, (struct sockaddr *) addr, sizeof (struct sockaddr_rc));
524 * Function used for creating the service record and registering it.
525 * @param dev pointer to the device struct
526 * @param rc_channel the rfcomm channel
527 * @return 0 on success
530 register_service (struct HardwareInfos *dev, int rc_channel)
534 * 2. set the service ID, class, profile information
535 * 3. make the service record publicly nrowsable
536 * 4. register the RFCOMM channel
537 * 5. set the name, provider and description
538 * 6. register the service record to the local SDP server
542 //FIXME: probably this is not the best idea. I should find a different uuid
543 uint8_t svc_uuid_int[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
544 dev->pl_mac.mac[5], dev->pl_mac.mac[4], dev->pl_mac.mac[3],
545 dev->pl_mac.mac[2], dev->pl_mac.mac[1], dev->pl_mac.mac[0]};
546 // const char *service_name = "GNUnet";
547 const char *service_dsc = "Bluetooth plugin services";
548 const char *service_prov = "GNUnet provider";
549 uuid_t root_uuid, rfcomm_uuid, l2cap_uuid, svc_uuid;
550 sdp_list_t *root_list = 0, *rfcomm_list = 0, *l2cap_list = 0,
551 *proto_list = 0, *access_proto_list = 0, *svc_list = 0;
552 sdp_record_t *record = 0;
553 sdp_data_t *channel = 0;
555 record = sdp_record_alloc();
557 /* Set the general service ID */
558 sdp_uuid128_create (&svc_uuid, &svc_uuid_int);
559 svc_list = sdp_list_append (0, &svc_uuid);
560 sdp_set_service_classes (record, svc_list);
561 sdp_set_service_id (record, svc_uuid);
563 /* Make the service record publicly browsable */
564 sdp_uuid16_create (&root_uuid, PUBLIC_BROWSE_GROUP);
565 root_list = sdp_list_append (0, &root_uuid);
566 sdp_set_browse_groups (record, root_list);
568 /* Register the RFCOMM channel */
569 sdp_uuid16_create (&rfcomm_uuid, RFCOMM_UUID);
570 channel = sdp_data_alloc (SDP_UINT8, &rc_channel);
571 rfcomm_list = sdp_list_append (0, &rfcomm_uuid);
572 sdp_list_append (rfcomm_list, channel);
573 proto_list = sdp_list_append (0, rfcomm_list);
575 /* Set L2CAP information FIXME: probably not needed */
576 // sdp_uuid16_create (&l2cap_uuid, L2CAP_UUID);
577 // l2cap_list = sdp_list_append (0, &l2cap_uuid);
578 //sdp_list_append (proto_list, l2cap_list);
580 /* Set protocol information */
581 access_proto_list = sdp_list_append (0, proto_list);
582 sdp_set_access_protos (record, access_proto_list);
584 /* Set the name, provider, and description */
585 sdp_set_info_attr (record, dev->iface, service_prov, service_dsc);
587 /* Connect to the local SDP server */
588 dev->session = sdp_connect (BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
592 fprintf (stderr, "Failed to connect to the SDP server on interface `%.*s': %s\n",
593 IFNAMSIZ, dev->iface, strerror (errno));
598 /* Register the service record */
599 if (sdp_record_register (dev->session, record, 0) < 0)
601 fprintf (stderr, "Failed to register a service record on interface `%.*s': %s\n",
602 IFNAMSIZ, dev->iface, strerror (errno));
608 sdp_data_free (channel);
609 sdp_list_free (root_list, 0);
610 sdp_list_free (rfcomm_list, 0);
611 sdp_list_free (l2cap_list, 0);
612 sdp_list_free (proto_list, 0);
613 sdp_list_free (access_proto_list, 0);
614 sdp_list_free (svc_list, 0);
615 sdp_record_free (record);
621 * Function for searching and browsing for a service. This will return the
622 * port number on which the service is running.
623 * @param dev pointer to the device struct
624 * @param dest target address
628 get_channel(struct HardwareInfos *dev, bdaddr_t dest)
631 * 1. detect all nearby devices //FIXME : Connect directly to the device with the service
632 * 2. for each device:
633 * 2.1. connect to the SDP server running
634 * 2.2. get a list of service records with the specific UUID
635 * 2.3. for each service record get a list of the protocol sequences and get
638 uint8_t svc_uuid_int[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
639 dest.b[5], dest.b[4], dest.b[3],
640 dest.b[2], dest.b[1], dest.b[0]};
641 sdp_session_t *session = 0;
642 sdp_list_t *search_list = 0, *attrid_list = 0, *response_list = 0, *it = 0;
644 uint32_t range = 0x0000ffff;
645 uint8_t channel = -1;
647 /* Connect to the local SDP server */
648 session = sdp_connect (BDADDR_ANY, &dest, 0);
651 fprintf (stderr, "Failed to connect to the SDP server on interface `%.*s': %s\n",
652 IFNAMSIZ, dev->iface, strerror (errno));
657 sdp_uuid128_create (&svc_uuid, &svc_uuid_int);
658 search_list = sdp_list_append (0, &svc_uuid);
659 attrid_list = sdp_list_append (0, &range);
661 if (sdp_service_search_attr_req (session, search_list,
662 SDP_ATTR_REQ_RANGE, attrid_list, &response_list) == 0)
664 for (it = response_list; it; it = it->next)
666 sdp_record_t *record = (sdp_record_t*) it->data;
667 //TODO print some record informations to be sure everything is good
668 sdp_list_t *proto_list = 0;
669 if (sdp_get_access_protos (record, &proto_list) == 0)
671 channel = sdp_get_proto_port (proto_list, RFCOMM_UUID);
672 sdp_list_free (proto_list, 0);
674 sdp_record_free (record);
678 sdp_list_free (search_list, 0);
679 sdp_list_free (attrid_list, 0);
680 sdp_list_free (response_list, 0);
685 fprintf (stderr, "Failed to find the listening channel for interface `%.*s': %s\n",
686 IFNAMSIZ, dev->iface, strerror (errno));
692 * Read from the socket and put the result into the buffer for transmission to 'stdout'.
693 * @param sock file descriptor for reading
694 * @param buf buffer to read to; first bytes will be the 'struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame',
695 * followed by the actual payload
696 * @param buf_size size of the buffer
697 * @param ri where to write radiotap_rx info
698 * @return number of bytes written to 'buf'
701 read_from_the_socket (int sock,
702 unsigned char *buf, size_t buf_size,
703 struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *ri)
706 * 1. Read from the socket in a temporary buffer (check for errors)
707 * 2. Detect if the crc exists
708 * 3. Write the result to the buffer
710 unsigned char tmpbuf[buf_size];
713 struct sockaddr_rc rc_addr = { 0 };
715 count = read (sock, tmpbuf, buf_size);
722 fprintf (stderr, "Failed to read from the HCI socket: %s\n", strerror (errno));
726 /* Get the channel used */
727 memset (&rc_addr, 0, sizeof (rc_addr));
728 len = sizeof (rc_addr);
729 if (0 > getsockname (sock, (struct sockaddr *) &rc_addr, (socklen_t *) &len))
731 fprintf (stderr, "getsockname() call failed : %s\n", strerror (errno));
735 memset (ri, 0, sizeof (*ri));
736 ri->ri_channel = rc_addr.rc_channel;
738 /* detect CRC32 at the end */
739 if (0 == check_crc_buf_osdep (tmpbuf, count - sizeof (uint32_t)))
741 count -= sizeof(uint32_t);
744 memcpy (buf, tmpbuf, count);
750 * Open the bluetooth interface for reading/writing
752 * @param dev pointer to the device struct
753 * @return 0 on success
756 open_device (struct HardwareInfos *dev)
759 * 1. Open a HCI socket (if RFCOMM protocol is used. If not, the HCI socket is
760 * saved in dev->rfcomm).
761 * 2. Find the device id (request a list with all the devices and find the one
762 * with the dev->iface name)
763 * 3. If the interface is down try to get it up
764 * 4. Bind the RFCOMM socket to the interface using the bind_socket() method and register
766 * 5. For now use a hard coded port number(channel) value
767 * FIXME : if I use HCI sockets , should I enable RAW_SOCKET MODE?!?!?!
770 int i, dev_id = -1, fd_hci;
773 struct hci_dev_list_req list;
774 struct hci_dev_req dev[HCI_MAX_DEV];
775 } request; //used for detecting the local devices
776 struct sockaddr_rc rc_addr = { 0 }; //used for binding
778 fd_hci = socket (AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
782 fprintf (stderr, "Failed to create HCI socket: %s\n", strerror (errno));
786 memset (&request, 0, sizeof(request));
787 request.list.dev_num = HCI_MAX_DEV;
789 if (ioctl (fd_hci, HCIGETDEVLIST, (void *) &request) < 0)
791 fprintf (stderr, "ioctl(HCIGETDEVLIST) on interface `%.*s' failed: %s\n",
792 IFNAMSIZ, dev->iface, strerror (errno));
796 /* Search for a device with dev->iface name */
797 for (i = 0; i < request.list.dev_num; i++)
799 struct hci_dev_info dev_info;
801 memset (&dev_info, 0, sizeof(struct hci_dev_info));
802 dev_info.dev_id = request.dev[i].dev_id;
803 strncpy (dev_info.name, dev->iface, IFNAMSIZ);
805 if (ioctl (fd_hci, HCIGETDEVINFO, (void *) &dev_info))
807 fprintf (stderr, "ioctl(HCIGETDEVINFO) on interface `%.*s' failed: %s\n",
808 IFNAMSIZ, dev->iface, strerror (errno));
812 if (strcmp (dev_info.name, dev->iface) == 0)
814 char addr[19] = { 0 }; //the device MAC address
816 dev_id = dev_info.dev_id; //the device was found
818 ba2str (&dev_info.bdaddr, addr); //get the device's MAC address
820 * Copy the MAC address to the device structure
821 * FIXME: probably this is not the best solution
823 memcpy (&dev->pl_mac, &dev_info.bdaddr, sizeof (bdaddr_t));
825 /* Check if the interface is UP */
826 if (hci_test_bit (HCI_UP, (void *) &dev_info.flags) == 0)
828 /* Bring interface up */ //FIXME should I check if is HCI_RUNNING ?!?!??!
829 if (ioctl (fd_hci, HCIDEVUP, dev_info.dev_id))
831 fprintf (stderr, "ioctl(HCIDEVUP) on interface `%.*s' failed: %s\n",
832 IFNAMSIZ, dev->iface, strerror (errno));
837 /* Check if the device is discoverable */
838 if (hci_test_bit (HCI_PSCAN, (void *) &dev_info.flags) == 0 ||
839 hci_test_bit (HCI_ISCAN, (void *) &dev_info.flags) == 0)
841 /* Set interface Page Scan and Inqury Scan ON */
842 struct hci_dev_req dev_req;
844 memset (&dev_req, 0, sizeof (dev_req));
845 dev_req.dev_id = dev_info.dev_id;
846 dev_req.dev_opt = SCAN_PAGE | SCAN_INQUIRY;
848 if (ioctl (fd_hci, HCISETSCAN, (unsigned long) &dev_req))
850 fprintf (stderr, "ioctl(HCISETSCAN) on interface `%.*s' failed: %s\n",
851 IFNAMSIZ, dev->iface, strerror (errno));
857 //FIXME : Sniff mode!?!
858 //FIXME : RAW MODE?!?
865 /* Check if the interface was not found */
868 fprintf (stderr, "The interface %s was not found\n", dev->iface);
872 /* Close the hci socket */
873 (void) close(fd_hci);
877 /* Bind the rfcomm socket to the interface */
878 memset (&rc_addr, 0, sizeof (rc_addr));
879 rc_addr.rc_family = AF_BLUETOOTH;
880 rc_addr.rc_bdaddr = *BDADDR_ANY;
882 if (bind_socket (dev->fd_rfcomm, &rc_addr) != 0)
884 fprintf (stderr, "Failed to bind interface `%.*s': %s\n", IFNAMSIZ,
885 dev->iface, strerror (errno));
889 /* Register a SDP service */
890 if (register_service (dev, rc_addr.rc_channel) != 0)
892 fprintf (stderr, "Failed to register a service on interface `%.*s': %s\n", IFNAMSIZ,
893 dev->iface, strerror (errno));
897 /* Switch socket in listening mode */
898 if (listen (dev->fd_rfcomm, 5) == -1) //FIXME: probably we need a bigger number
900 fprintf (stderr, "Failed to listen on socket for interface `%.*s': %s\n", IFNAMSIZ,
901 dev->iface, strerror (errno));
911 * Set the header to sane values to make attacks more difficult
913 * @param taIeeeHeader pointer to the header of the packet
914 * @param dev pointer to the Hardware_Infos struct
916 **** copy from gnunet-helper-transport-wlan.c ****
919 mac_set (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *taIeeeHeader,
920 const struct HardwareInfos *dev)
922 taIeeeHeader->frame_control = htons (IEEE80211_FC0_TYPE_DATA);
923 taIeeeHeader->addr2 = dev->pl_mac;
924 taIeeeHeader->addr3 = mac_bssid_gnunet;
928 * Test if the given interface name really corresponds to a bluetooth
931 * @param iface name of the interface
932 * @return 0 on success, 1 on error
933 **** similar with the one from gnunet-helper-transport-wlan.c ****
936 test_bluetooth_interface (const char *iface)
942 ret = snprintf (strbuf, sizeof (strbuf),
943 "/sys/class/bluetooth/%s/subsystem",
945 if ((ret < 0) || (ret >= sizeof (strbuf)) || (0 != stat (strbuf, &sbuf)))
948 "Did not find 802.15.1 interface `%s'. Exiting.\n",
956 * Test incoming packets mac for being our own.
958 * @param taIeeeHeader buffer of the packet
959 * @param dev the Hardware_Infos struct
960 * @return 0 if mac belongs to us, 1 if mac is for another target
962 **** same as the one from gnunet-helper-transport-wlan.c ****
965 mac_test (const struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *taIeeeHeader,
966 const struct HardwareInfos *dev)
968 static struct GNUNET_TRANSPORT_WLAN_MacAddress all_zeros;
970 if ( (0 == memcmp (&taIeeeHeader->addr3, &all_zeros, MAC_ADDR_SIZE)) ||
971 (0 == memcmp (&taIeeeHeader->addr1, &all_zeros, MAC_ADDR_SIZE)) )
972 return 0; /* some drivers set no Macs, then assume it is all for us! */
974 if (0 != memcmp (&taIeeeHeader->addr3, &mac_bssid_gnunet, MAC_ADDR_SIZE))
975 return 1; /* not a GNUnet ad-hoc package */
976 if ( (0 == memcmp (&taIeeeHeader->addr1, &dev->pl_mac, MAC_ADDR_SIZE)) ||
977 (0 == memcmp (&taIeeeHeader->addr1, &bc_all_mac, MAC_ADDR_SIZE)) )
978 return 0; /* for us, or broadcast */
979 return 1; /* not for us */
984 * Process data from the stdin. Takes the message forces the sender MAC to be correct
985 * and puts it into our buffer for transmission to the kernel. (the other device).
987 * @param cls pointer to the device struct ('struct HardwareInfos*')
988 * @param hdr pointer to the start of the packet
990 **** same as the one from gnunet-helper-transport-wlan.c ****
993 stdin_send_hw (void *cls, const struct GNUNET_MessageHeader *hdr)
995 struct HardwareInfos *dev = cls;
996 const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *header;
997 struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *blueheader;
1000 sendsize = ntohs (hdr->size);
1002 sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage)) ||
1003 (GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER != ntohs (hdr->type)) )
1005 fprintf (stderr, "Received malformed message\n");
1008 sendsize -= (sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) -
1009 sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame));
1010 if (MAXLINE < sendsize)
1012 fprintf (stderr, "Packet too big for buffer\n");
1015 header = (const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) hdr;
1016 memcpy (&write_pout.buf, &header->frame, sendsize);
1017 blueheader = (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *) &write_pout.buf;
1019 /* payload contains MAC address, but we don't trust it, so we'll
1020 * overwrite it with OUR MAC address to prevent mischief */
1021 mac_set (blueheader, dev);
1022 memcpy (&blueheader->addr1, &header->frame.addr1,
1023 sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress)); //FIXME is this correct?
1024 write_pout.size = sendsize;
1029 * Main function of the helper. This code accesses a bluetooth interface
1030 * forwards traffic in both directions between the bluetooth interface and
1031 * stdin/stdout of this process. Error messages are written to stdout.
1033 * @param argc number of arguments, must be 2
1034 * @param argv arguments only argument is the name of the interface (i.e. 'hci0')
1035 * @return 0 on success (never happens, as we don't return unless aborted), 1 on error
1037 **** same as the one from gnunet-helper-transport-wlan.c ****
1040 main (int argc, char *argv[])
1042 struct HardwareInfos dev;
1043 char readbuf[MAXLINE];
1049 struct MessageStreamTokenizer *stdin_mst;
1052 int crt_rfds = 0, crt_wfds = 0, rfds_list[MAX_PORTS], wfds_list[MAX_PORTS];
1054 /* Assert privs so we can modify the firewall rules! */
1056 #ifdef HAVE_SETRESUID
1057 if (0 != setresuid (uid, 0, 0))
1059 fprintf (stderr, "Failed to setresuid to root: %s\n", strerror (errno));
1063 if (0 != seteuid (0))
1065 fprintf (stderr, "Failed to seteuid back to root: %s\n", strerror (errno));
1070 /* Make use of SGID capabilities on POSIX */
1071 memset (&dev, 0, sizeof (dev));
1072 dev.fd_rfcomm = socket (AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
1073 raw_eno = errno; /* remember for later */
1075 /* Now that we've dropped root rights, we can do error checking */
1078 fprintf (stderr, "You must specify the name of the interface as the first \
1079 and only argument to this program.\n");
1080 if (-1 != dev.fd_rfcomm)
1081 (void) close (dev.fd_rfcomm);
1085 if (-1 == dev.fd_rfcomm)
1087 fprintf (stderr, "Failed to create a HCI socket: %s\n", strerror (raw_eno));
1090 if (dev.fd_rfcomm >= FD_SETSIZE)
1092 fprintf (stderr, "File descriptor too large for select (%d > %d)\n",
1093 dev.fd_rfcomm, FD_SETSIZE);
1094 (void) close (dev.fd_rfcomm);
1097 if (0 != test_bluetooth_interface (argv[1]))
1099 (void) close (dev.fd_rfcomm);
1102 strncpy (dev.iface, argv[1], IFNAMSIZ);
1103 if (0 != open_device (&dev))
1105 (void) close (dev.fd_rfcomm);
1111 uid_t uid = getuid ();
1112 #ifdef HAVE_SETRESUID
1113 if (0 != setresuid (uid, uid, uid))
1115 fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno));
1116 if (-1 != dev.fd_rfcomm)
1117 (void) close (dev.fd_rfcomm);
1121 if (0 != (setuid (uid) | seteuid (uid)))
1123 fprintf (stderr, "Failed to setuid: %s\n", strerror (errno));
1124 if (-1 != dev.fd_rfcomm)
1125 (void) close (dev.fd_rfcomm);
1132 /* Send MAC address of the bluetooth interface to STDOUT first */
1134 struct GNUNET_TRANSPORT_WLAN_HelperControlMessage macmsg;
1136 macmsg.hdr.size = htons (sizeof (macmsg));
1137 macmsg.hdr.type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL);
1138 memcpy (&macmsg.mac, &dev.pl_mac, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress));
1139 memcpy (write_std.buf, &macmsg, sizeof (macmsg));
1140 write_std.size = sizeof (macmsg);
1144 stdin_mst = mst_create (&stdin_send_hw, &dev);
1150 if ((0 == write_pout.size) && (1 == stdin_open))
1152 FD_SET (STDIN_FILENO, &rfds);
1153 maxfd = MAX (maxfd, STDIN_FILENO);
1155 if (0 == write_std.size)
1157 FD_SET (dev.fd_rfcomm, &rfds);
1158 maxfd = MAX (maxfd, dev.fd_rfcomm);
1161 if (0 < write_std.size)
1163 FD_SET (STDOUT_FILENO, &wfds);
1164 maxfd = MAX (maxfd, STDOUT_FILENO);
1167 for (i = 0; i < crt_rfds; i++)
1169 FD_SET (rfds_list[i], &rfds);
1170 maxfd = MAX (maxfd, rfds_list[i]);
1173 for (i = 0; i < crt_wfds; i++)
1175 FD_SET (wfds_list[i], &wfds);
1176 maxfd = MAX (maxfd, wfds_list[i]);
1179 if (0 < write_pout.size)
1181 int sendsocket, status;
1182 struct sockaddr_rc addr = { 0 };
1183 struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *frame;
1185 memset (dest, 0, sizeof (dest));
1187 sendsocket = socket (AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
1191 fprintf (stderr, "Failed to create a RFCOMM socket (sending stage): %s\n",
1196 /* Get the destination address */
1197 //FIXME : not sure if this is correct
1198 frame = (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *) write_pout.buf;
1199 memcpy (&addr.rc_bdaddr, &frame->addr1, sizeof (bdaddr_t));
1201 addr.rc_family = AF_BLUETOOTH;
1202 addr.rc_channel = get_channel (&dev, addr.rc_bdaddr);
1204 /*TODO: use a NON-BLOCKING socket
1205 * sock_flags = fcntl (sendsocket, F_GETFL, 0);
1206 * fcntl( sendsocket, F_SETFL, sock_flags | O_NONBLOCK);
1208 status = connect (sendsocket, (struct sockaddr *) &addr, sizeof (addr));
1209 if (0 != status && errno != EAGAIN)
1211 //fprintf (stderr, "connect error on %s\n", argv[1]);
1212 perror("Connect error");
1216 FD_SET (sendsocket, &wfds);
1217 maxfd = MAX (maxfd, sendsocket);
1219 if (crt_wfds < MAX_PORTS)
1220 wfds_list[crt_wfds++] = sendsocket; //add the socket to the list
1223 fprintf (stderr, "The limit for the write file descriptors list was \
1229 int retval = select (maxfd + 1, &rfds, &wfds, NULL, NULL);
1230 if ((-1 == retval) && (EINTR == errno))
1234 fprintf (stderr, "select failed: %s\n", strerror (errno));
1239 for (i = 0; i <= maxfd; i++)
1241 if (FD_ISSET (i , &wfds))
1243 if (i == STDOUT_FILENO)
1246 write (STDOUT_FILENO, write_std.buf + write_std.pos,
1247 write_std.size - write_std.pos);
1250 fprintf (stderr, "Failed to write to STDOUT: %s\n", strerror (errno));
1253 write_std.pos += ret;
1254 if (write_std.pos == write_std.size)
1263 write (i, write_pout.buf + write_std.pos,
1264 write_pout.size - write_pout.pos);
1267 fprintf (stderr, "Failed to write to bluetooth device: %s\n",
1271 write_pout.pos += ret;
1272 if ((write_pout.pos != write_pout.size) && (0 != ret))
1274 /* we should not get partial sends with packet-oriented devices... */
1275 fprintf (stderr, "Write error, partial send: %u/%u\n",
1276 (unsigned int) write_pout.pos,
1277 (unsigned int) write_pout.size);
1280 if (write_pout.pos == write_pout.size)
1283 write_pout.size = 0;
1289 if (FD_ISSET (i, &rfds))
1291 if (i == STDIN_FILENO)
1294 read (i, readbuf, sizeof (readbuf));
1297 fprintf (stderr, "Read error from STDIN: %s\n", strerror (errno));
1302 /* stop reading... */
1305 mst_receive (stdin_mst, readbuf, ret);
1307 else if (i == dev.fd_rfcomm)
1310 struct sockaddr_rc addr = { 0 };
1311 unsigned int opt = sizeof (addr);
1313 readsocket = accept (dev.fd_rfcomm, (struct sockaddr *) &addr, &opt);
1315 if (readsocket == -1)
1317 fprintf (stderr, "Failed to accept a connection on interface: %s\n",
1321 FD_SET (readsocket, &rfds);
1322 maxfd = MAX (maxfd, readsocket);
1324 if (crt_rfds < MAX_PORTS)
1325 rfds_list[crt_rfds++] = readsocket;
1328 fprintf (stderr, "The limit for the read file descriptors list was \
1337 struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *rrm;
1340 rrm = (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *) write_std.buf;
1342 read_from_the_socket (i, (unsigned char *) &rrm->frame,
1343 sizeof (write_std.buf)
1344 - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)
1345 + sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame),
1349 fprintf (stderr, "Read error from rfcomm socket: %s\n", strerror (errno));
1352 if ((0 < ret) && (0 == mac_test (&rrm->frame, &dev)))
1354 write_std.size = ret
1355 + sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)
1356 - sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame);
1357 rrm->header.size = htons (write_std.size);
1358 rrm->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA_FROM_HELPER);
1364 /* Error handling, try to clean up a bit at least */
1365 mst_destroy (stdin_mst);
1366 sdp_close (dev.session);
1368 (void) close (dev.fd_rfcomm);
1369 for (i = 0; i < crt_rfds; i++)
1370 (void) close (rfds_list[i]);
1372 for (i = 0; i < crt_wfds; i++)
1373 (void) close (wfds_list[i]);
1375 return 1; /* we never exit 'normally' */
1379 * 1. check if the rate from get_wlan_header (plugin_transport_bluetooth.c) is correct