aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorClaudiu Olteanu <claudiu@140774ce-b5e7-0310-ab8b-a85725594a96>2013-07-07 13:43:59 +0000
committerClaudiu Olteanu <claudiu@140774ce-b5e7-0310-ab8b-a85725594a96>2013-07-07 13:43:59 +0000
commite1fa8e431de13b5fe11ecd24ca2d4394d440ce54 (patch)
treee0670739e38f5f9c8b0e01f2c25e9456d0e306a1 /src
parentbfc8ee022023e46b17839aa8eb71e6588abdb73f (diff)
downloadgnunet-e1fa8e431de13b5fe11ecd24ca2d4394d440ce54.tar.gz
gnunet-e1fa8e431de13b5fe11ecd24ca2d4394d440ce54.zip
Adding a helper file for bluetooth plugin : gnunet-helper-transport-bluetooth.c
Diffstat (limited to 'src')
-rw-r--r--src/transport/gnunet-helper-transport-bluetooth.c1217
1 files changed, 1217 insertions, 0 deletions
diff --git a/src/transport/gnunet-helper-transport-bluetooth.c b/src/transport/gnunet-helper-transport-bluetooth.c
new file mode 100644
index 000000000..418cc9dec
--- /dev/null
+++ b/src/transport/gnunet-helper-transport-bluetooth.c
@@ -0,0 +1,1217 @@
1/*
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
6
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.
11
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.
16
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.
21*/
22#include "gnunet_config.h"
23
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>
30#include <errno.h>
31#include <linux/if.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <sys/ioctl.h>
35#include <sys/param.h>
36#include <sys/socket.h>
37#include <sys/stat.h>
38#include <sys/types.h>
39#include <unistd.h>
40
41#include "gnunet_protocols.h"
42#include "plugin_transport_wlan.h"
43
44#define HARD_CODED_PORT_NUMBER 10
45#define HARD_CODED_PORT_NUMBER2 10
46
47/**
48 * Maximum size of a message allowed in either direction
49 * (used for our receive and sent buffers).
50 */
51#define MAXLINE 4096
52
53
54/**
55 * struct for storing the information of the hardware. There is only
56 * one of these.
57 */
58struct HardwareInfos
59{
60
61 /**
62 * file descriptor for the rfcomm socket
63 */
64 int fd_rfcomm;
65
66 /**
67 * Name of the interface, not necessarily 0-terminated (!).
68 */
69 char iface[IFNAMSIZ];
70
71 /**
72 * MAC address of our own bluetooth interface.
73 */
74 struct GNUNET_TRANSPORT_WLAN_MacAddress pl_mac;
75};
76
77/**
78 * IO buffer used for buffering data in transit (to wireless or to stdout).
79 */
80struct SendBuffer
81{
82 /**
83 * How many bytes of data are stored in 'buf' for transmission right now?
84 * Data always starts at offset 0 and extends to 'size'.
85 */
86 size_t size;
87
88 /**
89 * How many bytes that were stored in 'buf' did we already write to the
90 * destination? Always smaller than 'size'.
91 */
92 size_t pos;
93
94 /**
95 * Buffered data; twice the maximum allowed message size as we add some
96 * headers.
97 */
98 char buf[MAXLINE * 2];
99};
100
101
102/**
103 * Buffer for data read from stdin to be transmitted to the bluetooth device
104 */
105static struct SendBuffer write_pout;
106
107/**
108 * Buffer for data read from the bluetooth device to be transmitted to stdout.
109 */
110static struct SendBuffer write_std;
111
112
113/* *********** specialized version of server_mst.c begins here ********** */
114/* ****** this is the same version as the one used in gnunet-helper-transport-wlan.c ****** */
115
116/**
117 * To what multiple do we align messages? 8 byte should suffice for everyone
118 * for now.
119 */
120#define ALIGN_FACTOR 8
121
122/**
123 * Smallest supported message.
124 */
125#define MIN_BUFFER_SIZE sizeof (struct GNUNET_MessageHeader)
126
127
128/**
129 * Functions with this signature are called whenever a
130 * complete message is received by the tokenizer.
131 *
132 * @param cls closure
133 * @param message the actual message
134 */
135typedef void (*MessageTokenizerCallback) (void *cls,
136 const struct
137 GNUNET_MessageHeader *
138 message);
139
140/**
141 * Handle to a message stream tokenizer.
142 */
143struct MessageStreamTokenizer
144{
145
146 /**
147 * Function to call on completed messages.
148 */
149 MessageTokenizerCallback cb;
150
151 /**
152 * Closure for cb.
153 */
154 void *cb_cls;
155
156 /**
157 * Size of the buffer (starting at 'hdr').
158 */
159 size_t curr_buf;
160
161 /**
162 * How many bytes in buffer have we already processed?
163 */
164 size_t off;
165
166 /**
167 * How many bytes in buffer are valid right now?
168 */
169 size_t pos;
170
171 /**
172 * Beginning of the buffer. Typed like this to force alignment.
173 */
174 struct GNUNET_MessageHeader *hdr;
175
176};
177
178
179/**
180 * Create a message stream tokenizer.
181 *
182 * @param cb function to call on completed messages
183 * @param cb_cls closure for cb
184 * @return handle to tokenizer
185 */
186static struct MessageStreamTokenizer *
187mst_create (MessageTokenizerCallback cb,
188 void *cb_cls)
189{
190 struct MessageStreamTokenizer *ret;
191
192 ret = malloc (sizeof (struct MessageStreamTokenizer));
193 if (NULL == ret)
194 {
195 fprintf (stderr, "Failed to allocate buffer for tokenizer\n");
196 exit (1);
197 }
198 ret->hdr = malloc (MIN_BUFFER_SIZE);
199 if (NULL == ret->hdr)
200 {
201 fprintf (stderr, "Failed to allocate buffer for alignment\n");
202 exit (1);
203 }
204 ret->curr_buf = MIN_BUFFER_SIZE;
205 ret->cb = cb;
206 ret->cb_cls = cb_cls;
207 return ret;
208}
209
210
211/**
212 * Add incoming data to the receive buffer and call the
213 * callback for all complete messages.
214 *
215 * @param mst tokenizer to use
216 * @param buf input data to add
217 * @param size number of bytes in buf
218 * @return GNUNET_OK if we are done processing (need more data)
219 * GNUNET_SYSERR if the data stream is corrupt
220 */
221static int
222mst_receive (struct MessageStreamTokenizer *mst,
223 const char *buf, size_t size)
224{
225 const struct GNUNET_MessageHeader *hdr;
226 size_t delta;
227 uint16_t want;
228 char *ibuf;
229 int need_align;
230 unsigned long offset;
231 int ret;
232
233 ret = GNUNET_OK;
234 ibuf = (char *) mst->hdr;
235 while (mst->pos > 0)
236 {
237do_align:
238 if ((mst->curr_buf - mst->off < sizeof (struct GNUNET_MessageHeader)) ||
239 (0 != (mst->off % ALIGN_FACTOR)))
240 {
241 /* need to align or need more space */
242 mst->pos -= mst->off;
243 memmove (ibuf, &ibuf[mst->off], mst->pos);
244 mst->off = 0;
245 }
246 if (mst->pos - mst->off < sizeof (struct GNUNET_MessageHeader))
247 {
248 delta =
249 GNUNET_MIN (sizeof (struct GNUNET_MessageHeader) -
250 (mst->pos - mst->off), size);
251 memcpy (&ibuf[mst->pos], buf, delta);
252 mst->pos += delta;
253 buf += delta;
254 size -= delta;
255 }
256 if (mst->pos - mst->off < sizeof (struct GNUNET_MessageHeader))
257 {
258 return GNUNET_OK;
259 }
260 hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off];
261 want = ntohs (hdr->size);
262 if (want < sizeof (struct GNUNET_MessageHeader))
263 {
264 fprintf (stderr,
265 "Received invalid message from stdin\n");
266 exit (1);
267 }
268 if (mst->curr_buf - mst->off < want)
269 {
270 /* need more space */
271 mst->pos -= mst->off;
272 memmove (ibuf, &ibuf[mst->off], mst->pos);
273 mst->off = 0;
274 }
275 if (want > mst->curr_buf)
276 {
277 mst->hdr = realloc (mst->hdr, want);
278 if (NULL == mst->hdr)
279 {
280 fprintf (stderr, "Failed to allocate buffer for alignment\n");
281 exit (1);
282 }
283 ibuf = (char *) mst->hdr;
284 mst->curr_buf = want;
285 }
286 hdr = (const struct GNUNET_MessageHeader *) &ibuf[mst->off];
287 if (mst->pos - mst->off < want)
288 {
289 delta = GNUNET_MIN (want - (mst->pos - mst->off), size);
290 memcpy (&ibuf[mst->pos], buf, delta);
291 mst->pos += delta;
292 buf += delta;
293 size -= delta;
294 }
295 if (mst->pos - mst->off < want)
296 {
297 return GNUNET_OK;
298 }
299 mst->cb (mst->cb_cls, hdr);
300 mst->off += want;
301 if (mst->off == mst->pos)
302 {
303 /* reset to beginning of buffer, it's free right now! */
304 mst->off = 0;
305 mst->pos = 0;
306 }
307 }
308 while (size > 0)
309 {
310 if (size < sizeof (struct GNUNET_MessageHeader))
311 break;
312 offset = (unsigned long) buf;
313 need_align = (0 != offset % ALIGN_FACTOR) ? GNUNET_YES : GNUNET_NO;
314 if (GNUNET_NO == need_align)
315 {
316 /* can try to do zero-copy and process directly from original buffer */
317 hdr = (const struct GNUNET_MessageHeader *) buf;
318 want = ntohs (hdr->size);
319 if (want < sizeof (struct GNUNET_MessageHeader))
320 {
321 fprintf (stderr,
322 "Received invalid message from stdin\n");
323 exit (1);
324 }
325 if (size < want)
326 break; /* or not, buffer incomplete, so copy to private buffer... */
327 mst->cb (mst->cb_cls, hdr);
328 buf += want;
329 size -= want;
330 }
331 else
332 {
333 /* need to copy to private buffer to align;
334 * yes, we go a bit more spagetti than usual here */
335 goto do_align;
336 }
337 }
338 if (size > 0)
339 {
340 if (size + mst->pos > mst->curr_buf)
341 {
342 mst->hdr = realloc (mst->hdr, size + mst->pos);
343 if (NULL == mst->hdr)
344 {
345 fprintf (stderr, "Failed to allocate buffer for alignment\n");
346 exit (1);
347 }
348 ibuf = (char *) mst->hdr;
349 mst->curr_buf = size + mst->pos;
350 }
351 if (mst->pos + size > mst->curr_buf)
352 {
353 fprintf (stderr,
354 "Assertion failed\n");
355 exit (1);
356 }
357 memcpy (&ibuf[mst->pos], buf, size);
358 mst->pos += size;
359 }
360 return ret;
361}
362
363
364/**
365 * Destroys a tokenizer.
366 *
367 * @param mst tokenizer to destroy
368 */
369static void
370mst_destroy (struct MessageStreamTokenizer *mst)
371{
372 free (mst->hdr);
373 free (mst);
374}
375
376/* ***************** end of server_mst.c clone ***************** **/
377
378
379/* ****** same crc version as the one used in gnunet-helper-transport-wlan.c ****** */
380
381/**
382 * Calculate crc32, the start of the calculation
383 *
384 * @param buf buffer to calc the crc
385 * @param len len of the buffer
386 * @return crc sum
387 */
388static unsigned long
389calc_crc_osdep (const unsigned char *buf, size_t len)
390{
391 static const unsigned long int crc_tbl_osdep[256] = {
392 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
393 0xE963A535, 0x9E6495A3,
394 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
395 0xE7B82D07, 0x90BF1D91,
396 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB,
397 0xF4D4B551, 0x83D385C7,
398 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
399 0xFA0F3D63, 0x8D080DF5,
400 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447,
401 0xD20D85FD, 0xA50AB56B,
402 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75,
403 0xDCD60DCF, 0xABD13D59,
404 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
405 0xCFBA9599, 0xB8BDA50F,
406 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11,
407 0xC1611DAB, 0xB6662D3D,
408 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F,
409 0x9FBFE4A5, 0xE8B8D433,
410 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
411 0x91646C97, 0xE6635C01,
412 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B,
413 0x8208F4C1, 0xF50FC457,
414 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49,
415 0x8CD37CF3, 0xFBD44C65,
416 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
417 0xA4D1C46D, 0xD3D6F4FB,
418 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5,
419 0xAA0A4C5F, 0xDD0D7CC9,
420 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3,
421 0xB966D409, 0xCE61E49F,
422 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
423 0xB7BD5C3B, 0xC0BA6CAD,
424 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF,
425 0x04DB2615, 0x73DC1683,
426 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D,
427 0x0A00AE27, 0x7D079EB1,
428 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
429 0x196C3671, 0x6E6B06E7,
430 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9,
431 0x17B7BE43, 0x60B08ED5,
432 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767,
433 0x3FB506DD, 0x48B2364B,
434 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
435 0x316E8EEF, 0x4669BE79,
436 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703,
437 0x220216B9, 0x5505262F,
438 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31,
439 0x2CD99E8B, 0x5BDEAE1D,
440 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
441 0x72076785, 0x05005713,
442 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D,
443 0x7CDCEFB7, 0x0BDBDF21,
444 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B,
445 0x6FB077E1, 0x18B74777,
446 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
447 0x616BFFD3, 0x166CCF45,
448 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7,
449 0x4969474D, 0x3E6E77DB,
450 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5,
451 0x47B2CF7F, 0x30B5FFE9,
452 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
453 0x54DE5729, 0x23D967BF,
454 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1,
455 0x5A05DF1B, 0x2D02EF8D
456 };
457
458 unsigned long crc = 0xFFFFFFFF;
459
460 for (; len > 0; len--, buf++)
461 crc = crc_tbl_osdep[(crc ^ *buf) & 0xFF] ^ (crc >> 8);
462 return (~crc);
463}
464
465
466/**
467 * Calculate and check crc of the bluetooth packet
468 *
469 * @param buf buffer of the packet, with len + 4 bytes of data,
470 * the last 4 bytes being the checksum
471 * @param len length of the payload in data
472 * @return 0 on success (checksum matches), 1 on error
473 */
474static int
475check_crc_buf_osdep (const unsigned char *buf, size_t len)
476{
477 unsigned long crc;
478
479 crc = calc_crc_osdep (buf, len);
480 buf += len;
481 if (((crc) & 0xFF) == buf[0] && ((crc >> 8) & 0xFF) == buf[1] &&
482 ((crc >> 16) & 0xFF) == buf[2] && ((crc >> 24) & 0xFF) == buf[3])
483 return 0;
484 return 1;
485}
486
487
488
489/* ************** end of crc version ***************** */
490
491
492
493
494/**
495 * Function for assigning a port number
496 * @return 0 on success
497 */
498static int
499bind_socket (int *socket)
500{
501 int port, status;
502 struct sockaddr_rc src = { 0 };
503
504 src.rc_family = AF_BLUETOOTH;
505 src.rc_bdaddr = *BDADDR_ANY;
506
507 /* Bind every possible port (from 0 to 30) and stop when bind doesn't fail */
508 for (port = 1; port <= 30; port++)
509 {
510 src.rc_channel = port;
511 status = bind(*socket, (struct sockaddr *)&src, sizeof(src));
512 if (status == 0)
513 return 0;
514 }
515
516 return -1;
517}
518
519
520//TODO
521/**
522 * Function used for creating the service record and registering it.
523 */
524static sdp_session_t*
525register_service (void)
526{
527 /**
528 * 1. initializations
529 * 2. set the service ID, class, profile information
530 * 3. make the service record publicly nrowsable
531 * 4. register the RFCOMM channel
532 * 5. set the name, provider and description
533 * 6. register the service record to the local SDP server
534 * 7. cleanup
535 */
536
537 //TODO: For now I will use a hard coded port number but in the end I will implement the SDP protocol
538
539 return NULL;
540}
541
542//TODO
543/**
544 * Function for searching and browsing for a service. This will return the
545 * port number on which the service is running.
546 */
547
548static int
549searching_service (void)
550{
551 /**
552 * 1. detect all nearby devices
553 * 2. for each device:
554 * 2.1. connect to the SDP server running
555 * 2.2. get a list of service records with the specific UUID
556 * 2.3. for each service record get a list of the protocol sequences and get
557 * the port number
558 */
559
560 return 0;
561}
562
563/**
564 * Read from the socket and put the result into the buffer for transmission to 'stdout'.
565 * @param sock file descriptor for reading
566 * @param buf buffer to read to; first bytes will be the 'struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame',
567 * followed by the actual payload
568 * @param buf_size size of the buffer
569 * @param ri where to write radiotap_rx info
570 * @return number of bytes written to 'buf'
571 */
572static ssize_t
573read_from_the_socket (int sock,
574 unsigned char *buf, size_t buf_size,
575 struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *ri)
576{
577 /**
578 * 1. Read from the socket in a temporary buffer (check for errors)
579 * 2. Detect if the crc exists
580 * 3. Write the result to the buffer
581 */
582 unsigned char tmpbuf[buf_size];
583 ssize_t count;
584 int len;
585 struct sockaddr_rc rc_addr = { 0 };
586
587 //count = recv (dev->fd_rfcomm, tmpbuf, buf_size, 0); //FIXME if I use RFCOMM
588
589 count = read (sock, tmpbuf, buf_size);
590
591 if (0 > count)
592 {
593 if (EAGAIN == errno)
594 return 0;
595
596 fprintf (stderr, "Failed to read from the HCI socket: %s\n", strerror (errno));
597 return -1;
598 }
599
600 /* Get the channel used */
601 memset (&rc_addr, 0, sizeof (rc_addr));
602 len = sizeof (rc_addr);
603 if (0 > getsockname (sock, (struct sockaddr *) &rc_addr, (socklen_t *) &len))
604 {
605 fprintf (stderr, "getsockname() call failed : %s\n", strerror (errno));
606 return -1;
607 }
608
609 memset (ri, 0, sizeof (*ri));
610 ri->ri_channel = rc_addr.rc_channel;
611
612 /* detect CRC32 at the end */
613 if (0 == check_crc_buf_osdep (tmpbuf, count - sizeof (uint32_t)))
614 {
615 count -= sizeof(uint32_t);
616 }
617
618 memcpy (buf, tmpbuf, count);
619
620 return count;
621}
622
623/**
624 * Open the bluetooth interface for reading/writing
625 *
626 * @param dev pointer to the device struct
627 * @return 0 on success
628 */
629static int
630open_device (struct HardwareInfos *dev)
631{
632 /**
633 * 1. Open a HCI socket (if RFCOMM protocol is used. If not, the HCI socket is
634 * saved in dev->fd_hci.
635 * 2. Find the device id (request a list with all the devices and find the one
636 * with the dev->iface name)
637 * 3. If the interface is down try to get it up
638 * 4. TODO: Bind the RFCOMM socket to the interface using the bind_socket() method and register
639 * a SDP service
640 * 5. For now use a hard coded port number(channel) value
641 * FIXME : if I use HCI sockets , should I enable RAW_SOCKET MODE?!?!?!
642 */
643
644 int i, dev_id = -1, fd_hci;
645 struct
646 {
647 struct hci_dev_list_req list;
648 struct hci_dev_req dev[HCI_MAX_DEV];
649 } request; //used for detecting the local devices
650 struct sockaddr_rc rc_addr = { 0 }; //used for binding
651
652 fd_hci = socket (AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
653
654 if (fd_hci < 0)
655 {
656 fprintf (stderr, "Failed to create HCI socket: %s\n", strerror (errno));
657 return -1;
658 }
659
660 memset (&request, 0, sizeof(request));
661 request.list.dev_num = HCI_MAX_DEV;
662
663 if (ioctl (fd_hci, HCIGETDEVLIST, (void *) &request) < 0)
664 {
665 fprintf (stderr, "ioctl(HCIGETDEVLIST) on interface `%.*s' failed: %s\n",
666 IFNAMSIZ, dev->iface, strerror (errno));
667 return 1;
668 }
669
670 /* Search for a device with dev->iface name */
671 for (i = 0; i < request.list.dev_num; i++)
672 {
673 struct hci_dev_info dev_info;
674
675 memset (&dev_info, 0, sizeof(struct hci_dev_info));
676 dev_info.dev_id = request.dev[i].dev_id;
677 strncpy (dev_info.name, dev->iface, IFNAMSIZ);
678
679 if (ioctl (fd_hci, HCIGETDEVINFO, (void *) &dev_info))
680 {
681 fprintf (stderr, "ioctl(HCIGETDEVINFO) on interface `%.*s' failed: %s\n",
682 IFNAMSIZ, dev->iface, strerror (errno));
683 return 1;
684 }
685
686 if (strcmp (dev_info.name, dev->iface) == 0)
687 {
688 char addr[19] = { 0 }; //the device MAC address
689
690 dev_id = dev_info.dev_id; //the device was found
691
692 ba2str (&dev_info.bdaddr, addr); //get the device's MAC address
693 //TODO : copy the MAC address to the device structure
694 memcpy (&dev->pl_mac, &dev_info.bdaddr, sizeof (bdaddr_t));
695
696 /* Check if the interface is UP */
697 if (hci_test_bit (HCI_UP, (void *) &dev_info.flags) == 0)
698 {
699 /* Bring interface up */ //FIXME should I check if is HCI_RUNNING ?!?!??!
700 if (ioctl (fd_hci, HCIDEVUP, dev_info.dev_id))
701 {
702 fprintf (stderr, "ioctl(HCIDEVUP) on interface `%.*s' failed: %s\n",
703 IFNAMSIZ, dev->iface, strerror (errno));
704 return 1;
705 }
706 }
707
708 /* Check if the device is discoverable */
709 if (hci_test_bit (HCI_PSCAN, (void *) &dev_info.flags) == 0 ||
710 hci_test_bit (HCI_ISCAN, (void *) &dev_info.flags) == 0)
711 {
712 /* Set interface Page Scan and Inqury Scan ON */
713 struct hci_dev_req dev_req;
714
715 memset (&dev_req, 0, sizeof (dev_req));
716 dev_req.dev_id = dev_info.dev_id;
717 dev_req.dev_opt = SCAN_PAGE | SCAN_INQUIRY;
718
719 if (ioctl (fd_hci, HCISETSCAN, (unsigned long) &dev_req))
720 {
721 fprintf (stderr, "ioctl(HCISETSCAN) on interface `%.*s' failed: %s\n",
722 IFNAMSIZ, dev->iface, strerror (errno));
723 return 1;
724 }
725
726 }
727
728 //FIXME : Sniff mode!?!
729 //FIXME : RAW MODE?!?
730
731 break;
732 }
733
734 }
735
736 /* Check if the interface was not found */
737 if (dev_id == -1)
738 {
739 fprintf (stderr, "The interface %s was not found\n", dev->iface);
740 return 1;
741 }
742
743 /* Close the hci socket */
744 (void) close(fd_hci);
745
746
747
748 /* Bind the rfcomm socket to the interface */
749 memset (&rc_addr, 0, sizeof (rc_addr));
750 rc_addr.rc_family = AF_BLUETOOTH;
751 rc_addr.rc_bdaddr = *BDADDR_ANY;
752 rc_addr.rc_channel = (uint8_t) HARD_CODED_PORT_NUMBER;
753
754 if (bind (dev->fd_rfcomm, (struct sockaddr *) &rc_addr, sizeof (rc_addr) != 0))
755 {
756 fprintf (stderr, "Failed to bind interface `%.*s': %s\n", IFNAMSIZ,
757 dev->iface, strerror (errno));
758 return 1;
759 }
760
761 /*
762 memset (&hci_addr, 0, sizeof (hci_addr));
763 hci_addr.hci_family = AF_BLUETOOTH;
764 hci_addr.hci_dev = dev_id;
765 */
766 /**
767 * FIXME hci_addr.hci_channel = HARD_CODED_PORT_NUMBER
768 * For linux kernel >= 2.6.7 the kernel automatically chooses an available port
769 * number. (getsockname() function can be used for finding out what port the kernel
770 * chose).
771 */
772 /*
773 if (-1 == bind (dev->fd_hci, (struct sockaddr *) &hci_addr, sizeof (hci_addr)))
774 {
775 fprintf (stderr, "Failed to bind interface `%.*s': %s\n", IFNAMSIZ,
776 dev->iface, strerror (errno));
777 return 1;
778 }
779 */
780
781 if (listen (dev->fd_rfcomm, 5) == -1)
782 {
783 fprintf (stderr, "Failed to listen on socket for interface `%.*s': %s\n", IFNAMSIZ,
784 dev->iface, strerror (errno));
785 return 3;
786 }
787
788
789 return 0;
790}
791
792
793/**
794 * Set the header to sane values to make attacks more difficult
795 *
796 * @param taIeeeHeader pointer to the header of the packet
797 * @param dev pointer to the Hardware_Infos struct
798 *
799 **** copy from gnunet-helper-transport-wlan.c ****
800 */
801static void
802mac_set (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *taIeeeHeader,
803 const struct HardwareInfos *dev)
804{
805 taIeeeHeader->frame_control = htons (IEEE80211_FC0_TYPE_DATA);
806 taIeeeHeader->addr2 = dev->pl_mac;
807 taIeeeHeader->addr3 = mac_bssid_gnunet;
808}
809
810/**
811 * Test if the given interface name really corresponds to a bluetooth
812 * device.
813 *
814 * @param iface name of the interface
815 * @return 0 on success, 1 on error
816 **** similar with the one from gnunet-helper-transport-wlan.c ****
817 */
818static int
819test_bluetooth_interface (const char *iface)
820{
821 char strbuf[512];
822 struct stat sbuf;
823 int ret;
824
825 ret = snprintf (strbuf, sizeof (strbuf),
826 "/sys/class/bluetooth/%s/subsystem",
827 iface);
828 if ((ret < 0) || (ret >= sizeof (strbuf)) || (0 != stat (strbuf, &sbuf)))
829 {
830 fprintf (stderr,
831 "Did not find 802.15.1 interface `%s'. Exiting.\n",
832 iface);
833 exit (1);
834 }
835 return 0;
836}
837
838/**
839 * Test incoming packets mac for being our own.
840 *
841 * @param taIeeeHeader buffer of the packet
842 * @param dev the Hardware_Infos struct
843 * @return 0 if mac belongs to us, 1 if mac is for another target
844 *
845 **** same as the one from gnunet-helper-transport-wlan.c ****
846 */
847static int
848mac_test (const struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *taIeeeHeader,
849 const struct HardwareInfos *dev)
850{
851 static struct GNUNET_TRANSPORT_WLAN_MacAddress all_zeros;
852
853 if ( (0 == memcmp (&taIeeeHeader->addr3, &all_zeros, MAC_ADDR_SIZE)) ||
854 (0 == memcmp (&taIeeeHeader->addr1, &all_zeros, MAC_ADDR_SIZE)) )
855 return 0; /* some drivers set no Macs, then assume it is all for us! */
856
857 if (0 != memcmp (&taIeeeHeader->addr3, &mac_bssid_gnunet, MAC_ADDR_SIZE))
858 return 1; /* not a GNUnet ad-hoc package */
859 if ( (0 == memcmp (&taIeeeHeader->addr1, &dev->pl_mac, MAC_ADDR_SIZE)) ||
860 (0 == memcmp (&taIeeeHeader->addr1, &bc_all_mac, MAC_ADDR_SIZE)) )
861 return 0; /* for us, or broadcast */
862 return 1; /* not for us */
863}
864
865
866/**
867 * Process data from the stdin. Takes the message forces the sender MAC to be correct
868 * and puts it into our buffer for transmission to the kernel. (the other device).
869 *
870 * @param cls pointer to the device struct ('struct HardwareInfos*')
871 * @param hdr pointer to the start of the packet
872 *
873 **** same as the one from gnunet-helper-transport-wlan.c ****
874 */
875static void
876stdin_send_hw (void *cls, const struct GNUNET_MessageHeader *hdr)
877{
878 struct HardwareInfos *dev = cls;
879 const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *header;
880 struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *blueheader;
881 size_t sendsize;
882
883 sendsize = ntohs (hdr->size);
884 if ( (sendsize <
885 sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage)) ||
886 (GNUNET_MESSAGE_TYPE_WLAN_DATA_TO_HELPER != ntohs (hdr->type)) )
887 {
888 fprintf (stderr, "Received malformed message\n");
889 exit (1);
890 }
891 sendsize -= (sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage) - sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame));
892 if (MAXLINE < sendsize)
893 {
894 fprintf (stderr, "Packet too big for buffer\n");
895 exit (1);
896 }
897 header = (const struct GNUNET_TRANSPORT_WLAN_RadiotapSendMessage *) hdr;
898 memcpy (&write_pout.buf, &header->frame, sendsize);
899 blueheader = (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame *) &write_pout.buf;
900
901 /* payload contains MAC address, but we don't trust it, so we'll
902 * overwrite it with OUR MAC address to prevent mischief */
903 mac_set (blueheader, dev);
904 write_pout.size = sendsize;
905}
906
907
908/**
909 * Main function of the helper. This code accesses a bluetooth interface
910 * forwards traffic in both directions between the bluetooth interface and
911 * stdin/stdout of this
912 * process. Error messages are written to stdout.
913 *
914 * @param argc number of arguments, must be 2
915 * @param argv arguments only argument is the name of the interface (i.e. 'mon0')
916 * @return 0 on success (never happens, as we don't return unless aborted), 1 on error
917 *
918 **** same as the one from gnunet-helper-transport-wlan.c ****
919 */
920int
921main (int argc, char *argv[])
922{
923 struct HardwareInfos dev;
924 char readbuf[MAXLINE];
925 char dest[18];
926 int maxfd;
927 fd_set rfds;
928 fd_set wfds;
929 int stdin_open;
930 struct MessageStreamTokenizer *stdin_mst;
931 int raw_eno, i;
932 uid_t uid;
933
934 /* assert privs so we can modify the firewall rules! */
935 uid = getuid ();
936#ifdef HAVE_SETRESUID
937 if (0 != setresuid (uid, 0, 0))
938 {
939 fprintf (stderr, "Failed to setresuid to root: %s\n", strerror (errno));
940 return 254;
941 }
942#else
943 if (0 != seteuid (0))
944 {
945 fprintf (stderr, "Failed to seteuid back to root: %s\n", strerror (errno));
946 return 254;
947 }
948#endif
949
950 /* make use of SGID capabilities on POSIX */
951 memset (&dev, 0, sizeof (dev));
952 dev.fd_rfcomm = socket (AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
953 //FIXME : using RFCOMM protocol : dev.fd_rfcomm = socket (AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
954 raw_eno = errno; /* remember for later */
955
956 /* now that we've dropped root rights, we can do error checking */
957 if (2 != argc)
958 {
959 fprintf (stderr,
960 "You must specify the name of the interface as the first and only argument to this program.\n");
961 if (-1 != dev.fd_rfcomm)
962 (void) close (dev.fd_rfcomm);
963 return 1;
964 }
965
966 if (-1 == dev.fd_rfcomm)
967 {
968 fprintf (stderr, "Failed to create a HCI socket: %s\n", strerror (raw_eno));
969 return 1;
970 }
971 if (dev.fd_rfcomm >= FD_SETSIZE)
972 {
973 fprintf (stderr, "File descriptor too large for select (%d > %d)\n",
974 dev.fd_rfcomm, FD_SETSIZE);
975 (void) close (dev.fd_rfcomm);
976 return 1;
977 }
978 if (0 != test_bluetooth_interface (argv[1]))
979 {
980 (void) close (dev.fd_rfcomm);
981 return 1;
982 }
983 strncpy (dev.iface, argv[1], IFNAMSIZ);
984 if (0 != open_device (&dev))
985 {
986 (void) close (dev.fd_rfcomm);
987 return 1;
988 }
989
990 /* drop privs */
991 {
992 uid_t uid = getuid ();
993#ifdef HAVE_SETRESUID
994 if (0 != setresuid (uid, uid, uid))
995 {
996 fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno));
997 if (-1 != dev.fd_rfcomm)
998 (void) close (dev.fd_rfcomm);
999 return 1;
1000 }
1001#else
1002 if (0 != (setuid (uid) | seteuid (uid)))
1003 {
1004 fprintf (stderr, "Failed to setuid: %s\n", strerror (errno));
1005 if (-1 != dev.fd_rfcomm)
1006 (void) close (dev.fd_rfcomm);
1007 return 1;
1008 }
1009#endif
1010 }
1011
1012
1013 /* send MAC address of the bluetooth interface to STDOUT first */
1014 {
1015 struct GNUNET_TRANSPORT_WLAN_HelperControlMessage macmsg;
1016
1017 macmsg.hdr.size = htons (sizeof (macmsg));
1018 macmsg.hdr.type = htons (GNUNET_MESSAGE_TYPE_WLAN_HELPER_CONTROL);
1019 memcpy (&macmsg.mac, &dev.pl_mac, sizeof (struct GNUNET_TRANSPORT_WLAN_MacAddress));
1020 memcpy (write_std.buf, &macmsg, sizeof (macmsg));
1021 write_std.size = sizeof (macmsg);
1022 }
1023
1024 stdin_mst = mst_create (&stdin_send_hw, &dev);
1025 stdin_open = 1;
1026 while (1)
1027 {
1028 maxfd = -1;
1029 FD_ZERO (&rfds);
1030 if ((0 == write_pout.size) && (1 == stdin_open))
1031 {
1032 FD_SET (STDIN_FILENO, &rfds);
1033 maxfd = MAX (maxfd, STDIN_FILENO);
1034 }
1035 if (0 == write_std.size)
1036 {
1037 FD_SET (dev.fd_rfcomm, &rfds);
1038 maxfd = MAX (maxfd, dev.fd_rfcomm);
1039 }
1040 FD_ZERO (&wfds);
1041 if (0 < write_std.size)
1042 {
1043 FD_SET (STDOUT_FILENO, &wfds);
1044 maxfd = MAX (maxfd, STDOUT_FILENO);
1045 }
1046 if (0 < write_pout.size)
1047 {
1048 int sendsocket, status;
1049 struct sockaddr_rc addr = { 0 };
1050
1051 memset (dest, 0, sizeof (dest));
1052
1053 sendsocket = socket (AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
1054
1055 if (sendsocket < 0)
1056 {
1057 fprintf (stderr, "Failed to create a RFCOMM socket (sending stage): %s\n",
1058 strerror (errno));
1059 return -1;
1060 }
1061
1062 addr.rc_family = AF_BLUETOOTH;
1063 addr.rc_channel = HARD_CODED_PORT_NUMBER2; //TODO: dinamically binding
1064 str2ba(dest, &addr.rc_bdaddr); //TODO: get the destination address from the message
1065
1066 /*TODO: use a NON-BLOCKING socket
1067 * sock_flags = fcntl (sendsocket, F_GETFL, 0);
1068 * fcntl( sendsocket, F_SETFL, sock_flags | O_NONBLOCK);
1069 */
1070 status = connect (sendsocket, (struct sockaddr *) &addr, sizeof (addr));
1071 if (0 != status && errno != EAGAIN)
1072 {
1073 //fprintf (stderr, "connect error on %s\n", argv[1]);
1074 perror("Connect error");
1075 return -1;
1076 }
1077
1078 FD_SET (sendsocket, &wfds);
1079 maxfd = MAX (maxfd, sendsocket);
1080 }
1081 {
1082 int retval = select (maxfd + 1, &rfds, &wfds, NULL, NULL);
1083 if ((-1 == retval) && (EINTR == errno))
1084 continue;
1085 if (0 > retval)
1086 {
1087 fprintf (stderr, "select failed: %s\n", strerror (errno));
1088 break;
1089 }
1090 }
1091
1092 for (i = 0; i <= maxfd; i++)
1093 {
1094 if (FD_ISSET (i , &wfds))
1095 {
1096 if (i == STDOUT_FILENO)
1097 {
1098 ssize_t ret =
1099 write (STDOUT_FILENO, write_std.buf + write_std.pos,
1100 write_std.size - write_std.pos);
1101 if (0 > ret)
1102 {
1103 fprintf (stderr, "Failed to write to STDOUT: %s\n", strerror (errno));
1104 break;
1105 }
1106 write_std.pos += ret;
1107 if (write_std.pos == write_std.size)
1108 {
1109 write_std.pos = 0;
1110 write_std.size = 0;
1111 }
1112 }
1113 else
1114 {
1115 ssize_t ret =
1116 write (i, write_pout.buf + write_std.pos,
1117 write_pout.size - write_pout.pos);
1118 if (0 > ret)
1119 {
1120 fprintf (stderr, "Failed to write to bluetooth device: %s\n",
1121 strerror (errno));
1122 break;
1123 }
1124 write_pout.pos += ret;
1125 if ((write_pout.pos != write_pout.size) && (0 != ret))
1126 {
1127 /* we should not get partial sends with packet-oriented devices... */
1128 fprintf (stderr, "Write error, partial send: %u/%u\n",
1129 (unsigned int) write_pout.pos,
1130 (unsigned int) write_pout.size);
1131 break;
1132 }
1133 if (write_pout.pos == write_pout.size)
1134 {
1135 write_pout.pos = 0;
1136 write_pout.size = 0;
1137 (void) close (i);
1138 }
1139 }
1140 }
1141
1142 if (FD_ISSET (i, &rfds))
1143 {
1144 if (i == STDIN_FILENO)
1145 {
1146 ssize_t ret =
1147 read (i, readbuf, sizeof (readbuf));
1148 if (0 > ret)
1149 {
1150 fprintf (stderr, "Read error from STDIN: %s\n", strerror (errno));
1151 break;
1152 }
1153 if (0 == ret)
1154 {
1155 /* stop reading... */
1156 stdin_open = 0;
1157 }
1158 mst_receive (stdin_mst, readbuf, ret);
1159 }
1160 else if (i == dev.fd_rfcomm)
1161 {
1162 int newfd;
1163 struct sockaddr_rc addr = { 0 };
1164 unsigned int opt = sizeof (addr);
1165
1166 newfd = accept (dev.fd_rfcomm, (struct sockaddr *) &addr, &opt);
1167
1168 if (newfd == -1)
1169 {
1170 fprintf (stderr, "Failed to accept a connection on interface: %s\n",
1171 strerror (errno));
1172 return -1;
1173 } else {
1174 FD_SET (newfd, &rfds);
1175 maxfd = MAX (maxfd, newfd);
1176 }
1177
1178 }
1179 else
1180 {
1181 struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *rrm;
1182 ssize_t ret;
1183
1184 rrm = (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage *) write_std.buf;
1185 ret =
1186 read_from_the_socket (i, (unsigned char *) &rrm->frame,
1187 sizeof (write_std.buf)
1188 - sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)
1189 + sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame),
1190 rrm);
1191 if (0 > ret)
1192 {
1193 fprintf (stderr, "Read error from rfcomm socket: %s\n", strerror (errno));
1194 break;
1195 }
1196 if ((0 < ret) && (0 == mac_test (&rrm->frame, &dev)))
1197 {
1198 write_std.size = ret
1199 + sizeof (struct GNUNET_TRANSPORT_WLAN_RadiotapReceiveMessage)
1200 - sizeof (struct GNUNET_TRANSPORT_WLAN_Ieee80211Frame);
1201 rrm->header.size = htons (write_std.size);
1202 rrm->header.type = htons (GNUNET_MESSAGE_TYPE_WLAN_DATA_FROM_HELPER);
1203 }
1204 }
1205 }
1206 }
1207 }
1208 /* Error handling, try to clean up a bit at least */
1209 mst_destroy (stdin_mst);
1210 (void) close (dev.fd_rfcomm);
1211
1212 return 1; /* we never exit 'normally' */
1213
1214}
1215
1216
1217