diff options
Diffstat (limited to 'src/transport/gnunet-helper-transport-bluetooth.c')
-rw-r--r-- | src/transport/gnunet-helper-transport-bluetooth.c | 1217 |
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 | */ | ||
58 | struct 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 | */ | ||
80 | struct 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 | */ | ||
105 | static struct SendBuffer write_pout; | ||
106 | |||
107 | /** | ||
108 | * Buffer for data read from the bluetooth device to be transmitted to stdout. | ||
109 | */ | ||
110 | static 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 | */ | ||
135 | typedef void (*MessageTokenizerCallback) (void *cls, | ||
136 | const struct | ||
137 | GNUNET_MessageHeader * | ||
138 | message); | ||
139 | |||
140 | /** | ||
141 | * Handle to a message stream tokenizer. | ||
142 | */ | ||
143 | struct 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 | */ | ||
186 | static struct MessageStreamTokenizer * | ||
187 | mst_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 | */ | ||
221 | static int | ||
222 | mst_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 | { | ||
237 | do_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 | */ | ||
369 | static void | ||
370 | mst_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 | */ | ||
388 | static unsigned long | ||
389 | calc_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 | */ | ||
474 | static int | ||
475 | check_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 | */ | ||
498 | static int | ||
499 | bind_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 | */ | ||
524 | static sdp_session_t* | ||
525 | register_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 | |||
548 | static int | ||
549 | searching_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 | */ | ||
572 | static ssize_t | ||
573 | read_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 | */ | ||
629 | static int | ||
630 | open_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 | */ | ||
801 | static void | ||
802 | mac_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 | */ | ||
818 | static int | ||
819 | test_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 | */ | ||
847 | static int | ||
848 | mac_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 | */ | ||
875 | static void | ||
876 | stdin_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 | */ | ||
920 | int | ||
921 | main (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 | |||