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;
79 sdp_session_t *session ;
83 * IO buffer used for buffering data in transit (to wireless or to stdout).
88 * How many bytes of data are stored in 'buf' for transmission right now?
89 * Data always starts at offset 0 and extends to 'size'.
94 * How many bytes that were stored in 'buf' did we already write to the
95 * destination? Always smaller than 'size'.
100 * Buffered data; twice the maximum allowed message size as we add some
103 char buf[MAXLINE * 2];
108 * Buffer for data read from stdin to be transmitted to the bluetooth device
110 static struct SendBuffer write_pout;
113 * Buffer for data read from the bluetooth device to be transmitted to stdout.
115 static struct SendBuffer write_std;
118 /* *********** specialized version of server_mst.c begins here ********** */
119 /* ****** this is the same version as the one used in gnunet-helper-transport-wlan.c ****** */
122 * To what multiple do we align messages? 8 byte should suffice for everyone
125 #define ALIGN_FACTOR 8
128 * Smallest supported message.
130 #define MIN_BUFFER_SIZE sizeof (struct GNUNET_MessageHeader)
134 * Functions with this signature are called whenever a
135 * complete message is received by the tokenizer.
138 * @param message the actual message
140 typedef void (*MessageTokenizerCallback) (void *cls,
142 GNUNET_MessageHeader *
146 * Handle to a message stream tokenizer.
148 struct MessageStreamTokenizer
152 * Function to call on completed messages.
154 MessageTokenizerCallback cb;
162 * Size of the buffer (starting at 'hdr').
167 * How many bytes in buffer have we already processed?
172 * How many bytes in buffer are valid right now?
177 * Beginning of the buffer. Typed like this to force alignment.
179 struct GNUNET_MessageHeader *hdr;
185 * Create a message stream tokenizer.
187 * @param cb function to call on completed messages
188 * @param cb_cls closure for cb
189 * @return handle to tokenizer
191 static struct MessageStreamTokenizer *
192 mst_create (MessageTokenizerCallback cb,
195 struct MessageStreamTokenizer *ret;
197 ret = malloc (sizeof (struct MessageStreamTokenizer));
200 fprintf (stderr, "Failed to allocate buffer for tokenizer\n");
203 ret->hdr = malloc (MIN_BUFFER_SIZE);
204 if (NULL == ret->hdr)
206 fprintf (stderr, "Failed to allocate buffer for alignment\n");
209 ret->curr_buf = MIN_BUFFER_SIZE;
211 ret->cb_cls = cb_cls;
217 * Add incoming data to the receive buffer and call the
218 * callback for all complete messages.
220 * @param mst tokenizer to use
221 * @param buf input data to add
222 * @param size number of bytes in buf
223 * @return GNUNET_OK if we are done processing (need more data)
224 * GNUNET_SYSERR if the data stream is corrupt
227 mst_receive (struct MessageStreamTokenizer *mst,
228 const char *buf, size_t size)
230 const struct GNUNET_MessageHeader *hdr;
235 unsigned long offset;
239 ibuf = (char *) mst->hdr;
243 if ((mst->curr_buf - mst->off < sizeof (struct GNUNET_MessageHeader)) ||
244 (0 != (mst->off % ALIGN_FACTOR)))
246 /* need to align or need more space */
247 mst->pos -= mst->off;
248 memmove (ibuf, &ibuf[mst->off], mst->pos);
251 if (mst->pos - mst->off < sizeof (struct GNUNET_MessageHeader))
254 GNUNET_MIN (sizeof (struct GNUNET_MessageHeader) -
255 (mst->pos - mst->off), size);
256 memcpy (&ibuf[mst->pos], buf, delta);
261 if (mst->pos - mst->off < sizeof (struct GNUNET_MessageHeader))
265 hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off];
266 want = ntohs (hdr->size);
267 if (want < sizeof (struct GNUNET_MessageHeader))
270 "Received invalid message from stdin\n");
273 if (mst->curr_buf - mst->off < want)
275 /* need more space */
276 mst->pos -= mst->off;
277 memmove (ibuf, &ibuf[mst->off], mst->pos);
280 if (want > mst->curr_buf)
282 mst->hdr = realloc (mst->hdr, want);
283 if (NULL == mst->hdr)
285 fprintf (stderr, "Failed to allocate buffer for alignment\n");
288 ibuf = (char *) mst->hdr;
289 mst->curr_buf = want;
291 hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off];
292 if (mst->pos - mst->off < want)
294 delta = GNUNET_MIN (want - (mst->pos - mst->off), size);
295 memcpy (&ibuf[mst->pos], buf, delta);
300 if (mst->pos - mst->off < want)
304 mst->cb (mst->cb_cls, hdr);
306 if (mst->off == mst->pos)
308 /* reset to beginning of buffer, it's free right now! */
315 if (size < sizeof (struct GNUNET_MessageHeader))
317 offset = (unsigned long) buf;
318 need_align = (0 != offset % ALIGN_FACTOR) ? GNUNET_YES : GNUNET_NO;
319 if (GNUNET_NO == need_align)
321 /* can try to do zero-copy and process directly from original buffer */
322 hdr = (const struct GNUNET_MessageHeader *) buf;
323 want = ntohs (hdr->size);
324 if (want < sizeof (struct GNUNET_MessageHeader))
327 "Received invalid message from stdin\n");
331 break; /* or not, buffer incomplete, so copy to private buffer... */
332 mst->cb (mst->cb_cls, hdr);
338 /* need to copy to private buffer to align;
339 * yes, we go a bit more spagetti than usual here */
345 if (size + mst->pos > mst->curr_buf)
347 mst->hdr = realloc (mst->hdr, size + mst->pos);
348 if (NULL == mst->hdr)
350 fprintf (stderr, "Failed to allocate buffer for alignment\n");
353 ibuf = (char *) mst->hdr;
354 mst->curr_buf = size + mst->pos;
356 if (mst->pos + size > mst->curr_buf)
359 "Assertion failed\n");
362 memcpy (&ibuf[mst->pos], buf, size);
370 * Destroys a tokenizer.
372 * @param mst tokenizer to destroy
375 mst_destroy (struct MessageStreamTokenizer *mst)
381 /* ***************** end of server_mst.c clone ***************** **/
384 /* ****** same crc version as the one used in gnunet-helper-transport-wlan.c ****** */
387 * Calculate crc32, the start of the calculation
389 * @param buf buffer to calc the crc
390 * @param len len of the buffer
394 calc_crc_osdep (const unsigned char *buf, size_t len)
396 static const unsigned long int crc_tbl_osdep[256] = {
397 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
398 0xE963A535, 0x9E6495A3,
399 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
400 0xE7B82D07, 0x90BF1D91,
401 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB,
402 0xF4D4B551, 0x83D385C7,
403 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
404 0xFA0F3D63, 0x8D080DF5,
405 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447,
406 0xD20D85FD, 0xA50AB56B,
407 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75,
408 0xDCD60DCF, 0xABD13D59,
409 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
410 0xCFBA9599, 0xB8BDA50F,
411 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11,
412 0xC1611DAB, 0xB6662D3D,
413 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F,
414 0x9FBFE4A5, 0xE8B8D433,
415 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
416 0x91646C97, 0xE6635C01,
417 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B,
418 0x8208F4C1, 0xF50FC457,
419 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49,
420 0x8CD37CF3, 0xFBD44C65,
421 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
422 0xA4D1C46D, 0xD3D6F4FB,
423 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5,
424 0xAA0A4C5F, 0xDD0D7CC9,
425 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3,
426 0xB966D409, 0xCE61E49F,
427 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
428 0xB7BD5C3B, 0xC0BA6CAD,
429 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF,
430 0x04DB2615, 0x73DC1683,
431 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D,
432 0x0A00AE27, 0x7D079EB1,
433 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
434 0x196C3671, 0x6E6B06E7,
435 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9,
436 0x17B7BE43, 0x60B08ED5,
437 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767,
438 0x3FB506DD, 0x48B2364B,
439 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
440 0x316E8EEF, 0x4669BE79,
441 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703,
442 0x220216B9, 0x5505262F,
443 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31,
444 0x2CD99E8B, 0x5BDEAE1D,
445 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
446 0x72076785, 0x05005713,
447 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D,
448 0x7CDCEFB7, 0x0BDBDF21,
449 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B,
450 0x6FB077E1, 0x18B74777,
451 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
452 0x616BFFD3, 0x166CCF45,
453 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7,
454 0x4969474D, 0x3E6E77DB,
455 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5,
456 0x47B2CF7F, 0x30B5FFE9,
457 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
458 0x54DE5729, 0x23D967BF,
459 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1,
460 0x5A05DF1B, 0x2D02EF8D
463 unsigned long crc = 0xFFFFFFFF;
465 for (; len > 0; len--, buf++)
466 crc = crc_tbl_osdep[(crc ^ *buf) & 0xFF] ^ (crc >> 8);
472 * Calculate and check crc of the bluetooth packet
474 * @param buf buffer of the packet, with len + 4 bytes of data,
475 * the last 4 bytes being the checksum
476 * @param len length of the payload in data
477 * @return 0 on success (checksum matches), 1 on error
480 check_crc_buf_osdep (const unsigned char *buf, size_t len)
484 crc = calc_crc_osdep (buf, len);
486 if (((crc) & 0xFF) == buf[0] && ((crc >> 8) & 0xFF) == buf[1] &&
487 ((crc >> 16) & 0xFF) == buf[2] && ((crc >> 24) & 0xFF) == buf[3])
494 /* ************** end of crc version ***************** */
500 * Function for assigning a port number
501 * @param socket the socket used to bind
502 * @param addr pointer to the rfcomm address
503 * @return 0 on success
506 bind_socket (int socket, struct sockaddr_rc *addr)
510 /* Bind every possible port (from 0 to 30) and stop when bind doesn't fail */
511 //FIXME : it should start from port 1, but on my computer it doesn't work :)
512 for (port = 3; port <= 30; port++)
514 addr->rc_channel = port;
515 status = bind (socket, (struct sockaddr *) addr, sizeof (struct sockaddr_rc));
525 * Function used for creating the service record and registering it.
526 * @param dev pointer to the device struct
527 * @param channel the rfcomm channel
528 * @return 0 on success
531 register_service (struct HardwareInfos *dev, int rc_channel)
535 * 2. set the service ID, class, profile information
536 * 3. make the service record publicly nrowsable
537 * 4. register the RFCOMM channel
538 * 5. set the name, provider and description
539 * 6. register the service record to the local SDP server
543 //FIXME: probably this is not the best idea. I should find a different uuid
544 uint8_t svc_uuid_int[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
545 dev->pl_mac.mac[5], dev->pl_mac.mac[4], dev->pl_mac.mac[3],
546 dev->pl_mac.mac[2], dev->pl_mac.mac[1], dev->pl_mac.mac[0]};
547 // const char *service_name = "GNUnet";
548 const char *service_dsc = "Bluetooth plugin services";
549 const char *service_prov = "GNUnet provider";
550 uuid_t root_uuid, rfcomm_uuid, l2cap_uuid, svc_uuid;
551 sdp_list_t *root_list = 0, *rfcomm_list = 0, *l2cap_list = 0,
552 *proto_list = 0, *access_proto_list = 0, *svc_list = 0;
553 sdp_record_t *record = 0;
554 sdp_data_t *channel = 0;
556 record = sdp_record_alloc();
558 /* Set the general service ID */
559 sdp_uuid128_create (&svc_uuid, &svc_uuid_int);
560 svc_list = sdp_list_append (0, &svc_uuid);
561 sdp_set_service_classes (record, svc_list);
562 sdp_set_service_id (record, svc_uuid);
564 /* Make the service record publicly browsable */
565 sdp_uuid16_create (&root_uuid, PUBLIC_BROWSE_GROUP);
566 root_list = sdp_list_append (0, &root_uuid);
567 sdp_set_browse_groups (record, root_list);
569 /* Register the RFCOMM channel */
570 sdp_uuid16_create (&rfcomm_uuid, RFCOMM_UUID);
571 channel = sdp_data_alloc (SDP_UINT8, &rc_channel);
572 rfcomm_list = sdp_list_append (0, &rfcomm_uuid);
573 sdp_list_append (rfcomm_list, channel);
574 proto_list = sdp_list_append (0, rfcomm_list);
576 /* Set L2CAP information FIXME: probably not needed */
577 // sdp_uuid16_create (&l2cap_uuid, L2CAP_UUID);
578 // l2cap_list = sdp_list_append (0, &l2cap_uuid);
579 //sdp_list_append (proto_list, l2cap_list);
581 /* Set protocol information */
582 access_proto_list = sdp_list_append (0, proto_list);
583 sdp_set_access_protos (record, access_proto_list);
585 /* Set the name, provider, and description */
586 sdp_set_info_attr (record, dev->iface, service_prov, service_dsc);
588 /* Connect to the local SDP server */
589 dev->session = sdp_connect (BDADDR_ANY, BDADDR_LOCAL, SDP_RETRY_IF_BUSY);
593 fprintf (stderr, "Failed to connect to the SDP server on interface `%.*s': %s\n",
594 IFNAMSIZ, dev->iface, strerror (errno));
599 /* Register the service record */
600 if (sdp_record_register (dev->session, record, 0) < 0)
602 fprintf (stderr, "Failed to register a service record on interface `%.*s': %s\n",
603 IFNAMSIZ, dev->iface, strerror (errno));
609 sdp_data_free (channel);
610 sdp_list_free (root_list, 0);
611 sdp_list_free (rfcomm_list, 0);
612 sdp_list_free (l2cap_list, 0);
613 sdp_list_free (proto_list, 0);
614 sdp_list_free (access_proto_list, 0);
615 sdp_list_free (svc_list, 0);
616 sdp_record_free (record);
622 * Function for searching and browsing for a service. This will return the
623 * port number on which the service is running.
624 * @param dev pointer to the device struct
625 * @param dest target address
629 get_channel(struct HardwareInfos *dev, bdaddr_t dest)
632 * 1. detect all nearby devices //FIXME : Connect directly to the device with the service
633 * 2. for each device:
634 * 2.1. connect to the SDP server running
635 * 2.2. get a list of service records with the specific UUID
636 * 2.3. for each service record get a list of the protocol sequences and get
639 uint8_t svc_uuid_int[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
640 dest.b[5], dest.b[4], dest.b[3],
641 dest.b[2], dest.b[1], dest.b[0]};
642 sdp_session_t *session = 0;
643 sdp_list_t *search_list = 0, *attrid_list = 0, *response_list = 0, *it = 0;
645 uint32_t range = 0x0000ffff;
646 uint8_t channel = -1;
648 /* Connect to the local SDP server */
649 session = sdp_connect (BDADDR_ANY, &dest, 0);
652 fprintf (stderr, "Failed to connect to the SDP server on interface `%.*s': %s\n",
653 IFNAMSIZ, dev->iface, strerror (errno));
658 sdp_uuid128_create (&svc_uuid, &svc_uuid_int);
659 search_list = sdp_list_append (0, &svc_uuid);
660 attrid_list = sdp_list_append (0, &range);
662 if (sdp_service_search_attr_req (session, search_list,
663 SDP_ATTR_REQ_RANGE, attrid_list, &response_list) == 0)
665 for (it = response_list; it; it = it->next)
667 sdp_record_t *record = (sdp_record_t*) it->data;
668 //TODO print some record informations to be sure everything is good
669 sdp_list_t *proto_list = 0;
670 if (sdp_get_access_protos (record, &proto_list) == 0)
672 channel = sdp_get_proto_port (proto_list, RFCOMM_UUID);
673 sdp_list_free (proto_list, 0);
675 sdp_record_free (record);
679 sdp_list_free (search_list, 0);
680 sdp_list_free (attrid_list, 0);
681 sdp_list_free (response_list, 0);
686 fprintf (stderr, "Failed to find the listening channel for interface `%.*s': %s\n",
687 IFNAMSIZ, dev->iface, strerror (errno));
693 * Read from the socket and put the result into the buffer for transmission to 'stdout'.
694 * @param sock file descriptor for reading
695 * @param buf buffer to read to; first bytes will be the 'struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame',
696 * followed by the actual payload
697 * @param buf_size size of the buffer
698 * @param ri where to write radiotap_rx info
699 * @return number of bytes written to 'buf'
702 read_from_the_socket (int sock,
703 unsigned char *buf, size_t buf_size,
704 struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *ri)
707 * 1. Read from the socket in a temporary buffer (check for errors)
708 * 2. Detect if the crc exists
709 * 3. Write the result to the buffer
711 unsigned char tmpbuf[buf_size];
714 struct sockaddr_rc rc_addr = { 0 };
716 count = read (sock, tmpbuf, buf_size);
723 fprintf (stderr, "Failed to read from the HCI socket: %s\n", strerror (errno));
727 /* Get the channel used */
728 memset (&rc_addr, 0, sizeof (rc_addr));
729 len = sizeof (rc_addr);
730 if (0 > getsockname (sock, (struct sockaddr *) &rc_addr, (socklen_t *) &len))
732 fprintf (stderr, "getsockname() call failed : %s\n", strerror (errno));
736 memset (ri, 0, sizeof (*ri));
737 ri->ri_channel = rc_addr.rc_channel;
739 /* detect CRC32 at the end */
740 if (0 == check_crc_buf_osdep (tmpbuf, count - sizeof (uint32_t)))
742 count -= sizeof(uint32_t);
745 memcpy (buf, tmpbuf, count);
751 * Open the bluetooth interface for reading/writing
753 * @param dev pointer to the device struct
754 * @return 0 on success
757 open_device (struct HardwareInfos *dev)
760 * 1. Open a HCI socket (if RFCOMM protocol is used. If not, the HCI socket is
761 * saved in dev->rfcomm).
762 * 2. Find the device id (request a list with all the devices and find the one
763 * with the dev->iface name)
764 * 3. If the interface is down try to get it up
765 * 4. Bind the RFCOMM socket to the interface using the bind_socket() method and register
767 * 5. For now use a hard coded port number(channel) value
768 * FIXME : if I use HCI sockets , should I enable RAW_SOCKET MODE?!?!?!
771 int i, dev_id = -1, fd_hci;
774 struct hci_dev_list_req list;
775 struct hci_dev_req dev[HCI_MAX_DEV];
776 } request; //used for detecting the local devices
777 struct sockaddr_rc rc_addr = { 0 }; //used for binding
779 fd_hci = socket (AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
783 fprintf (stderr, "Failed to create HCI socket: %s\n", strerror (errno));
787 memset (&request, 0, sizeof(request));
788 request.list.dev_num = HCI_MAX_DEV;
790 if (ioctl (fd_hci, HCIGETDEVLIST, (void *) &request) < 0)
792 fprintf (stderr, "ioctl(HCIGETDEVLIST) on interface `%.*s' failed: %s\n",
793 IFNAMSIZ, dev->iface, strerror (errno));
797 /* Search for a device with dev->iface name */
798 for (i = 0; i < request.list.dev_num; i++)
800 struct hci_dev_info dev_info;
802 memset (&dev_info, 0, sizeof(struct hci_dev_info));
803 dev_info.dev_id = request.dev[i].dev_id;
804 strncpy (dev_info.name, dev->iface, IFNAMSIZ);
806 if (ioctl (fd_hci, HCIGETDEVINFO, (void *) &dev_info))
808 fprintf (stderr, "ioctl(HCIGETDEVINFO) on interface `%.*s' failed: %s\n",
809 IFNAMSIZ, dev->iface, strerror (errno));
813 if (strcmp (dev_info.name, dev->iface) == 0)
815 char addr[19] = { 0 }; //the device MAC address
817 dev_id = dev_info.dev_id; //the device was found
819 ba2str (&dev_info.bdaddr, addr); //get the device's MAC address
821 * Copy the MAC address to the device structure
822 * FIXME: probably this is not the best solution
824 memcpy (&dev->pl_mac, &dev_info.bdaddr, sizeof (bdaddr_t));
826 /* Check if the interface is UP */
827 if (hci_test_bit (HCI_UP, (void *) &dev_info.flags) == 0)
829 /* Bring interface up */ //FIXME should I check if is HCI_RUNNING ?!?!??!
830 if (ioctl (fd_hci, HCIDEVUP, dev_info.dev_id))
832 fprintf (stderr, "ioctl(HCIDEVUP) on interface `%.*s' failed: %s\n",
833 IFNAMSIZ, dev->iface, strerror (errno));
838 /* Check if the device is discoverable */
839 if (hci_test_bit (HCI_PSCAN, (void *) &dev_info.flags) == 0 ||
840 hci_test_bit (HCI_ISCAN, (void *) &dev_info.flags) == 0)
842 /* Set interface Page Scan and Inqury Scan ON */
843 struct hci_dev_req dev_req;
845 memset (&dev_req, 0, sizeof (dev_req));
846 dev_req.dev_id = dev_info.dev_id;
847 dev_req.dev_opt = SCAN_PAGE | SCAN_INQUIRY;
849 if (ioctl (fd_hci, HCISETSCAN, (unsigned long) &dev_req))
851 fprintf (stderr, "ioctl(HCISETSCAN) on interface `%.*s' failed: %s\n",
852 IFNAMSIZ, dev->iface, strerror (errno));
858 //FIXME : Sniff mode!?!
859 //FIXME : RAW MODE?!?
866 /* Check if the interface was not found */
869 fprintf (stderr, "The interface %s was not found\n", dev->iface);
873 /* Close the hci socket */
874 (void) close(fd_hci);
878 /* Bind the rfcomm socket to the interface */
879 memset (&rc_addr, 0, sizeof (rc_addr));
880 rc_addr.rc_family = AF_BLUETOOTH;
881 rc_addr.rc_bdaddr = *BDADDR_ANY;
883 if (bind_socket (dev->fd_rfcomm, &rc_addr) != 0)
885 fprintf (stderr, "Failed to bind interface `%.*s': %s\n", IFNAMSIZ,
886 dev->iface, strerror (errno));
890 /* Register a SDP service */
891 if (register_service (dev, rc_addr.rc_channel) != 0)
893 fprintf (stderr, "Failed to register a service on interface `%.*s': %s\n", IFNAMSIZ,
894 dev->iface, strerror (errno));
898 /* Switch socket in listening mode */
899 if (listen (dev->fd_rfcomm, 5) == -1) //FIXME: probably we need a bigger number
901 fprintf (stderr, "Failed to listen on socket for interface `%.*s': %s\n", IFNAMSIZ,
902 dev->iface, strerror (errno));
912 * Set the header to sane values to make attacks more difficult
914 * @param taIeeeHeader pointer to the header of the packet
915 * @param dev pointer to the Hardware_Infos struct
917 **** copy from gnunet-helper-transport-wlan.c ****
920 mac_set (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *taIeeeHeader,
921 const struct HardwareInfos *dev)
923 taIeeeHeader->frame_control = htons (IEEE80211_FC0_TYPE_DATA);
924 taIeeeHeader->addr2 = dev->pl_mac;
925 taIeeeHeader->addr3 = mac_bssid_gnunet;
929 * Test if the given interface name really corresponds to a bluetooth
932 * @param iface name of the interface
933 * @return 0 on success, 1 on error
934 **** similar with the one from gnunet-helper-transport-wlan.c ****
937 test_bluetooth_interface (const char *iface)
943 ret = snprintf (strbuf, sizeof (strbuf),
944 "/sys/class/bluetooth/%s/subsystem",
946 if ((ret < 0) || (ret >= sizeof (strbuf)) || (0 != stat (strbuf, &sbuf)))
949 "Did not find 802.15.1 interface `%s'. Exiting.\n",
957 * Test incoming packets mac for being our own.
959 * @param taIeeeHeader buffer of the packet
960 * @param dev the Hardware_Infos struct
961 * @return 0 if mac belongs to us, 1 if mac is for another target
963 **** same as the one from gnunet-helper-transport-wlan.c ****
966 mac_test (const struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *taIeeeHeader,
967 const struct HardwareInfos *dev)
969 static struct GNUNET_TRANSPORT_WLAN_MacAddress all_zeros;
971 if ( (0 == memcmp (&taIeeeHeader->addr3, &all_zeros, MAC_ADDR_SIZE)) ||
972 (0 == memcmp (&taIeeeHeader->addr1, &all_zeros, MAC_ADDR_SIZE)) )
973 return 0; /* some drivers set no Macs, then assume it is all for us! */
975 if (0 != memcmp (&taIeeeHeader->addr3, &mac_bssid_gnunet, MAC_ADDR_SIZE))
976 return 1; /* not a GNUnet ad-hoc package */
977 if ( (0 == memcmp (&taIeeeHeader->addr1, &dev->pl_mac, MAC_ADDR_SIZE)) ||
978 (0 == memcmp (&taIeeeHeader->addr1, &bc_all_mac, MAC_ADDR_SIZE)) )
979 return 0; /* for us, or broadcast */
980 return 1; /* not for us */
985 * Process data from the stdin. Takes the message forces the sender MAC to be correct
986 * and puts it into our buffer for transmission to the kernel. (the other device).
988 * @param cls pointer to the device struct ('struct HardwareInfos*')
989 * @param hdr pointer to the start of the packet
991 **** same as the one from gnunet-helper-transport-wlan.c ****
994 stdin_send_hw (void *cls, const struct GNUNET_MessageHeader *hdr)
996 struct HardwareInfos *dev = cls;
997 const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *header;
998 struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *blueheader;
1001 sendsize = ntohs (hdr->size);
1003 sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage)) ||
1004 (GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER != ntohs (hdr->type)) )
1006 fprintf (stderr, "Received malformed message\n");
1009 sendsize -= (sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) -
1010 sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame));
1011 if (MAXLINE < sendsize)
1013 fprintf (stderr, "Packet too big for buffer\n");
1016 header = (const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) hdr;
1017 memcpy (&write_pout.buf, &header->frame, sendsize);
1018 blueheader = (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *) &write_pout.buf;
1020 /* payload contains MAC address, but we don't trust it, so we'll
1021 * overwrite it with OUR MAC address to prevent mischief */
1022 mac_set (blueheader, dev);
1023 write_pout.size = sendsize;
1028 * Main function of the helper. This code accesses a bluetooth interface
1029 * forwards traffic in both directions between the bluetooth interface and
1030 * stdin/stdout of this process. Error messages are written to stdout.
1032 * @param argc number of arguments, must be 2
1033 * @param argv arguments only argument is the name of the interface (i.e. 'hci0')
1034 * @return 0 on success (never happens, as we don't return unless aborted), 1 on error
1036 **** same as the one from gnunet-helper-transport-wlan.c ****
1039 main (int argc, char *argv[])
1041 struct HardwareInfos dev;
1042 char readbuf[MAXLINE];
1048 struct MessageStreamTokenizer *stdin_mst;
1052 /* Assert privs so we can modify the firewall rules! */
1054 #ifdef HAVE_SETRESUID
1055 if (0 != setresuid (uid, 0, 0))
1057 fprintf (stderr, "Failed to setresuid to root: %s\n", strerror (errno));
1061 if (0 != seteuid (0))
1063 fprintf (stderr, "Failed to seteuid back to root: %s\n", strerror (errno));
1068 /* Make use of SGID capabilities on POSIX */
1069 memset (&dev, 0, sizeof (dev));
1070 dev.fd_rfcomm = socket (AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
1071 raw_eno = errno; /* remember for later */
1073 /* Now that we've dropped root rights, we can do error checking */
1076 fprintf (stderr, "You must specify the name of the interface as the first \
1077 and only argument to this program.\n");
1078 if (-1 != dev.fd_rfcomm)
1079 (void) close (dev.fd_rfcomm);
1083 if (-1 == dev.fd_rfcomm)
1085 fprintf (stderr, "Failed to create a HCI socket: %s\n", strerror (raw_eno));
1088 if (dev.fd_rfcomm >= FD_SETSIZE)
1090 fprintf (stderr, "File descriptor too large for select (%d > %d)\n",
1091 dev.fd_rfcomm, FD_SETSIZE);
1092 (void) close (dev.fd_rfcomm);
1095 if (0 != test_bluetooth_interface (argv[1]))
1097 (void) close (dev.fd_rfcomm);
1100 strncpy (dev.iface, argv[1], IFNAMSIZ);
1101 if (0 != open_device (&dev))
1103 (void) close (dev.fd_rfcomm);
1109 uid_t uid = getuid ();
1110 #ifdef HAVE_SETRESUID
1111 if (0 != setresuid (uid, uid, uid))
1113 fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno));
1114 if (-1 != dev.fd_rfcomm)
1115 (void) close (dev.fd_rfcomm);
1119 if (0 != (setuid (uid) | seteuid (uid)))
1121 fprintf (stderr, "Failed to setuid: %s\n", strerror (errno));
1122 if (-1 != dev.fd_rfcomm)
1123 (void) close (dev.fd_rfcomm);
1130 /* Send MAC address of the bluetooth interface to STDOUT first */
1132 struct GNUNET_TRANSPORT_WLAN_HelperControlMessage macmsg;
1134 macmsg.hdr.size = htons (sizeof (macmsg));
1135 macmsg.hdr.type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL);
1136 memcpy (&macmsg.mac, &dev.pl_mac, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress));
1137 memcpy (write_std.buf, &macmsg, sizeof (macmsg));
1138 write_std.size = sizeof (macmsg);
1142 stdin_mst = mst_create (&stdin_send_hw, &dev);
1148 if ((0 == write_pout.size) && (1 == stdin_open))
1150 FD_SET (STDIN_FILENO, &rfds);
1151 maxfd = MAX (maxfd, STDIN_FILENO);
1153 if (0 == write_std.size)
1155 FD_SET (dev.fd_rfcomm, &rfds);
1156 maxfd = MAX (maxfd, dev.fd_rfcomm);
1159 if (0 < write_std.size)
1161 FD_SET (STDOUT_FILENO, &wfds);
1162 maxfd = MAX (maxfd, STDOUT_FILENO);
1164 if (0 < write_pout.size)
1166 int sendsocket, status;
1167 struct sockaddr_rc addr = { 0 };
1168 struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame frame;
1170 memset (dest, 0, sizeof (dest));
1172 sendsocket = socket (AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
1176 fprintf (stderr, "Failed to create a RFCOMM socket (sending stage): %s\n",
1181 /* Get the destination address */
1182 if (write_pout.pos == 0) //FIXME: if write_pout.pos != 0, I cannot get the destination address
1184 //FIXME : not sure if this is correct
1185 memset (&frame, 0, sizeof (frame));
1186 memcpy (&frame, write_pout.buf + sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)
1187 - sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame),
1188 sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame));
1189 memcpy (&addr.rc_bdaddr, &frame.addr1, sizeof (bdaddr_t));
1191 addr.rc_family = AF_BLUETOOTH;
1192 addr.rc_channel = get_channel (&dev, addr.rc_bdaddr);
1194 /*TODO: use a NON-BLOCKING socket
1195 * sock_flags = fcntl (sendsocket, F_GETFL, 0);
1196 * fcntl( sendsocket, F_SETFL, sock_flags | O_NONBLOCK);
1198 status = connect (sendsocket, (struct sockaddr *) &addr, sizeof (addr));
1199 if (0 != status && errno != EAGAIN)
1201 //fprintf (stderr, "connect error on %s\n", argv[1]);
1202 perror("Connect error");
1206 FD_SET (sendsocket, &wfds);
1207 maxfd = MAX (maxfd, sendsocket);
1210 int retval = select (maxfd + 1, &rfds, &wfds, NULL, NULL);
1211 if ((-1 == retval) && (EINTR == errno))
1215 fprintf (stderr, "select failed: %s\n", strerror (errno));
1220 for (i = 0; i <= maxfd; i++)
1222 if (FD_ISSET (i , &wfds))
1224 if (i == STDOUT_FILENO)
1227 write (STDOUT_FILENO, write_std.buf + write_std.pos,
1228 write_std.size - write_std.pos);
1231 fprintf (stderr, "Failed to write to STDOUT: %s\n", strerror (errno));
1234 write_std.pos += ret;
1235 if (write_std.pos == write_std.size)
1244 write (i, write_pout.buf + write_std.pos,
1245 write_pout.size - write_pout.pos);
1248 fprintf (stderr, "Failed to write to bluetooth device: %s\n",
1252 write_pout.pos += ret;
1253 if ((write_pout.pos != write_pout.size) && (0 != ret))
1255 /* we should not get partial sends with packet-oriented devices... */
1256 fprintf (stderr, "Write error, partial send: %u/%u\n",
1257 (unsigned int) write_pout.pos,
1258 (unsigned int) write_pout.size);
1261 if (write_pout.pos == write_pout.size)
1264 write_pout.size = 0;
1270 if (FD_ISSET (i, &rfds))
1272 if (i == STDIN_FILENO)
1275 read (i, readbuf, sizeof (readbuf));
1278 fprintf (stderr, "Read error from STDIN: %s\n", strerror (errno));
1283 /* stop reading... */
1286 mst_receive (stdin_mst, readbuf, ret);
1288 else if (i == dev.fd_rfcomm)
1291 struct sockaddr_rc addr = { 0 };
1292 unsigned int opt = sizeof (addr);
1294 newfd = accept (dev.fd_rfcomm, (struct sockaddr *) &addr, &opt);
1298 fprintf (stderr, "Failed to accept a connection on interface: %s\n",
1302 FD_SET (newfd, &rfds);
1303 maxfd = MAX (maxfd, newfd);
1309 struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *rrm;
1312 rrm = (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *) write_std.buf;
1314 read_from_the_socket (i, (unsigned char *) &rrm->frame,
1315 sizeof (write_std.buf)
1316 - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)
1317 + sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame),
1321 fprintf (stderr, "Read error from rfcomm socket: %s\n", strerror (errno));
1324 if ((0 < ret) && (0 == mac_test (&rrm->frame, &dev)))
1326 write_std.size = ret
1327 + sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)
1328 - sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame);
1329 rrm->header.size = htons (write_std.size);
1330 rrm->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA_FROM_HELPER);
1339 /* Error handling, try to clean up a bit at least */
1340 mst_destroy (stdin_mst);
1341 (void) close (dev.fd_rfcomm);
1343 return 1; /* we never exit 'normally' */