diff options
author | David Brodski <david@brodski.eu> | 2010-07-28 08:01:56 +0000 |
---|---|---|
committer | David Brodski <david@brodski.eu> | 2010-07-28 08:01:56 +0000 |
commit | d4a051f87d9d420ec474d0c15c27d94d8ebe264b (patch) | |
tree | dd2c4950e65657865d28c6e58fb440dcb6361d63 /src/transport/gnunet-transport-wlan-helper.c | |
parent | 2b2f0a8c002b5c0946cccbdd6bf0012e4f1ad8e2 (diff) | |
download | gnunet-d4a051f87d9d420ec474d0c15c27d94d8ebe264b.tar.gz gnunet-d4a051f87d9d420ec474d0c15c27d94d8ebe264b.zip |
First try of the wlan-helper
Diffstat (limited to 'src/transport/gnunet-transport-wlan-helper.c')
-rw-r--r-- | src/transport/gnunet-transport-wlan-helper.c | 665 |
1 files changed, 665 insertions, 0 deletions
diff --git a/src/transport/gnunet-transport-wlan-helper.c b/src/transport/gnunet-transport-wlan-helper.c new file mode 100644 index 000000000..6ae31a647 --- /dev/null +++ b/src/transport/gnunet-transport-wlan-helper.c | |||
@@ -0,0 +1,665 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2010 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file src/transport/gnunet-wlan.c | ||
23 | * @brief wlan layer two server; must run as root (SUID will do) | ||
24 | * This code will work under GNU/Linux only. | ||
25 | * @author David Brodski | ||
26 | * | ||
27 | * This program serves as the mediator between the wlan interface and | ||
28 | * gnunet | ||
29 | */ | ||
30 | |||
31 | #include "gnunet_wlan.h" | ||
32 | #include <pcap/pcap.h> | ||
33 | |||
34 | //#include "radiotap.h" | ||
35 | |||
36 | // broadcast mac | ||
37 | static const char macbc[] = "13223344"; | ||
38 | |||
39 | // mac of this node | ||
40 | char mac[] = "13223355"; | ||
41 | |||
42 | /* wifi bitrate to use in 500kHz units */ | ||
43 | |||
44 | static const u8 u8aRatesToUse[] = { | ||
45 | |||
46 | 54*2, | ||
47 | 48*2, | ||
48 | 36*2, | ||
49 | 24*2, | ||
50 | 18*2, | ||
51 | 12*2, | ||
52 | 9*2, | ||
53 | 11*2, | ||
54 | 11, // 5.5 | ||
55 | 2*2, | ||
56 | 1*2 | ||
57 | }; | ||
58 | |||
59 | /* Penumbra IEEE80211 header */ | ||
60 | static const u8 u8aIeeeHeader[] = { | ||
61 | 0x08, 0x01, 0x00, 0x00, | ||
62 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, | ||
63 | 0x13, 0x22, 0x33, 0x44, 0x55, 0x66, | ||
64 | 0x13, 0x22, 0x33, 0x44, 0x55, 0x66, | ||
65 | 0x10, 0x86, | ||
66 | }; | ||
67 | |||
68 | /* this is the template radiotap header we send packets out with */ | ||
69 | |||
70 | static const u8 u8aRadiotapHeader[] = { | ||
71 | |||
72 | 0x00, 0x00, // <-- radiotap version | ||
73 | 0x19, 0x00, // <- radiotap header length | ||
74 | 0x6f, 0x08, 0x00, 0x00, // <-- bitmap | ||
75 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // <-- timestamp | ||
76 | 0x00, // <-- flags (Offset +0x10) | ||
77 | 0x6c, // <-- rate (0ffset +0x11) | ||
78 | 0x71, 0x09, 0xc0, 0x00, // <-- channel | ||
79 | 0xde, // <-- antsignal | ||
80 | 0x00, // <-- antnoise | ||
81 | 0x01, // <-- antenna | ||
82 | |||
83 | }; | ||
84 | #define OFFSET_FLAGS 0x10 | ||
85 | #define OFFSET_RATE 0x11 | ||
86 | |||
87 | // this is where we store a summary of the | ||
88 | // information from the radiotap header | ||
89 | |||
90 | typedef struct { | ||
91 | int m_nChannel; | ||
92 | int m_nChannelFlags; | ||
93 | int m_nRate; | ||
94 | int m_nAntenna; | ||
95 | int m_nRadiotapFlags; | ||
96 | } __attribute__((packed)) PENUMBRA_RADIOTAP_DATA; | ||
97 | |||
98 | void | ||
99 | Dump(u8 * pu8, int nLength) | ||
100 | { | ||
101 | char sz[256], szBuf[512], szChar[17], *buf, fFirst = 1; | ||
102 | unsigned char baaLast[2][16]; | ||
103 | uint n, nPos = 0, nStart = 0, nLine = 0, nSameCount = 0; | ||
104 | |||
105 | buf = szBuf; | ||
106 | szChar[0] = '\0'; | ||
107 | |||
108 | for (n = 0; n < nLength; n++) { | ||
109 | baaLast[(nLine&1)^1][n&0xf] = pu8[n]; | ||
110 | if ((pu8[n] < 32) || (pu8[n] >= 0x7f)) | ||
111 | szChar[n&0xf] = '.'; | ||
112 | else | ||
113 | szChar[n&0xf] = pu8[n]; | ||
114 | szChar[(n&0xf)+1] = '\0'; | ||
115 | nPos += sprintf(&sz[nPos], "%02X ", | ||
116 | baaLast[(nLine&1)^1][n&0xf]); | ||
117 | if ((n&15) != 15) | ||
118 | continue; | ||
119 | if ((memcmp(baaLast[0], baaLast[1], 16) == 0) && (!fFirst)) { | ||
120 | nSameCount++; | ||
121 | } else { | ||
122 | if (nSameCount) | ||
123 | buf += sprintf(buf, "(repeated %d times)\n", | ||
124 | nSameCount); | ||
125 | buf += sprintf(buf, "%04x: %s %s\n", | ||
126 | nStart, sz, szChar); | ||
127 | nSameCount = 0; | ||
128 | printf("%s", szBuf); | ||
129 | buf = szBuf; | ||
130 | } | ||
131 | nPos = 0; nStart = n+1; nLine++; | ||
132 | fFirst = 0; sz[0] = '\0'; szChar[0] = '\0'; | ||
133 | } | ||
134 | if (nSameCount) | ||
135 | buf += sprintf(buf, "(repeated %d times)\n", nSameCount); | ||
136 | |||
137 | buf += sprintf(buf, "%04x: %s", nStart, sz); | ||
138 | if (n & 0xf) { | ||
139 | *buf++ = ' '; | ||
140 | while (n & 0xf) { | ||
141 | buf += sprintf(buf, " "); | ||
142 | n++; | ||
143 | } | ||
144 | } | ||
145 | buf += sprintf(buf, "%s\n", szChar); | ||
146 | printf("%s", szBuf); | ||
147 | } | ||
148 | |||
149 | |||
150 | void | ||
151 | usage(void) | ||
152 | { | ||
153 | printf( | ||
154 | "Usage: wlan-hwd [options] <interface>\n\nOptions\n" | ||
155 | "-f/--fcs Mark as having FCS (CRC) already\n" | ||
156 | " (pkt ends with 4 x sacrificial - chars)\n" | ||
157 | "Example:\n" | ||
158 | " echo -n mon0 > /sys/class/ieee80211/phy0/add_iface\n" | ||
159 | " iwconfig mon0 mode monitor\n" | ||
160 | " ifconfig mon0 up\n" | ||
161 | " wlan-hwd mon0 Spam down mon0 with\n" | ||
162 | " radiotap header first\n" | ||
163 | "\n"); | ||
164 | exit(1); | ||
165 | } | ||
166 | |||
167 | int flagHelp = 0, flagMarkWithFCS = 0; | ||
168 | int flagVerbose = 0; | ||
169 | |||
170 | |||
171 | /* | ||
172 | * Radiotap parser | ||
173 | * | ||
174 | * Copyright 2007 Andy Green <andy@warmcat.com> | ||
175 | */ | ||
176 | |||
177 | /** | ||
178 | * ieee80211_radiotap_iterator_init - radiotap parser iterator initialization | ||
179 | * @iterator: radiotap_iterator to initialize | ||
180 | * @radiotap_header: radiotap header to parse | ||
181 | * @max_length: total length we can parse into (eg, whole packet length) | ||
182 | * | ||
183 | * Returns: 0 or a negative error code if there is a problem. | ||
184 | * | ||
185 | * This function initializes an opaque iterator struct which can then | ||
186 | * be passed to ieee80211_radiotap_iterator_next() to visit every radiotap | ||
187 | * argument which is present in the header. It knows about extended | ||
188 | * present headers and handles them. | ||
189 | * | ||
190 | * How to use: | ||
191 | * call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator | ||
192 | * struct ieee80211_radiotap_iterator (no need to init the struct beforehand) | ||
193 | * checking for a good 0 return code. Then loop calling | ||
194 | * __ieee80211_radiotap_iterator_next()... it returns either 0, | ||
195 | * -ENOENT if there are no more args to parse, or -EINVAL if there is a problem. | ||
196 | * The iterator's @this_arg member points to the start of the argument | ||
197 | * associated with the current argument index that is present, which can be | ||
198 | * found in the iterator's @this_arg_index member. This arg index corresponds | ||
199 | * to the IEEE80211_RADIOTAP_... defines. | ||
200 | * | ||
201 | * Radiotap header length: | ||
202 | * You can find the CPU-endian total radiotap header length in | ||
203 | * iterator->max_length after executing ieee80211_radiotap_iterator_init() | ||
204 | * successfully. | ||
205 | * | ||
206 | * Example code: | ||
207 | * See Documentation/networking/radiotap-headers.txt | ||
208 | */ | ||
209 | |||
210 | int ieee80211_radiotap_iterator_init( | ||
211 | struct ieee80211_radiotap_iterator *iterator, | ||
212 | struct ieee80211_radiotap_header *radiotap_header, | ||
213 | int max_length) | ||
214 | { | ||
215 | /* Linux only supports version 0 radiotap format */ | ||
216 | if (radiotap_header->it_version) | ||
217 | return -EINVAL; | ||
218 | |||
219 | /* sanity check for allowed length and radiotap length field */ | ||
220 | if (max_length < le16_to_cpu(radiotap_header->it_len)) | ||
221 | return -EINVAL; | ||
222 | |||
223 | iterator->rtheader = radiotap_header; | ||
224 | iterator->max_length = le16_to_cpu(radiotap_header->it_len); | ||
225 | iterator->arg_index = 0; | ||
226 | iterator->bitmap_shifter = le32_to_cpu(radiotap_header->it_present); | ||
227 | iterator->arg = (u8 *)radiotap_header + sizeof(*radiotap_header); | ||
228 | iterator->this_arg = 0; | ||
229 | |||
230 | /* find payload start allowing for extended bitmap(s) */ | ||
231 | |||
232 | if (unlikely(iterator->bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT))) { | ||
233 | while (le32_to_cpu(*((u32 *)iterator->arg)) & | ||
234 | (1<<IEEE80211_RADIOTAP_EXT)) { | ||
235 | iterator->arg += sizeof(u32); | ||
236 | |||
237 | /* | ||
238 | * check for insanity where the present bitmaps | ||
239 | * keep claiming to extend up to or even beyond the | ||
240 | * stated radiotap header length | ||
241 | */ | ||
242 | |||
243 | if (((ulong)iterator->arg - | ||
244 | (ulong)iterator->rtheader) > iterator->max_length) | ||
245 | return -EINVAL; | ||
246 | } | ||
247 | |||
248 | iterator->arg += sizeof(u32); | ||
249 | |||
250 | /* | ||
251 | * no need to check again for blowing past stated radiotap | ||
252 | * header length, because ieee80211_radiotap_iterator_next | ||
253 | * checks it before it is dereferenced | ||
254 | */ | ||
255 | } | ||
256 | |||
257 | /* we are all initialized happily */ | ||
258 | |||
259 | return 0; | ||
260 | } | ||
261 | |||
262 | |||
263 | /** | ||
264 | * ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg | ||
265 | * @iterator: radiotap_iterator to move to next arg (if any) | ||
266 | * | ||
267 | * Returns: 0 if there is an argument to handle, | ||
268 | * -ENOENT if there are no more args or -EINVAL | ||
269 | * if there is something else wrong. | ||
270 | * | ||
271 | * This function provides the next radiotap arg index (IEEE80211_RADIOTAP_*) | ||
272 | * in @this_arg_index and sets @this_arg to point to the | ||
273 | * payload for the field. It takes care of alignment handling and extended | ||
274 | * present fields. @this_arg can be changed by the caller (eg, | ||
275 | * incremented to move inside a compound argument like | ||
276 | * IEEE80211_RADIOTAP_CHANNEL). The args pointed to are in | ||
277 | * little-endian format whatever the endianess of your CPU. | ||
278 | */ | ||
279 | |||
280 | int ieee80211_radiotap_iterator_next( | ||
281 | struct ieee80211_radiotap_iterator *iterator) | ||
282 | { | ||
283 | |||
284 | /* | ||
285 | * small length lookup table for all radiotap types we heard of | ||
286 | * starting from b0 in the bitmap, so we can walk the payload | ||
287 | * area of the radiotap header | ||
288 | * | ||
289 | * There is a requirement to pad args, so that args | ||
290 | * of a given length must begin at a boundary of that length | ||
291 | * -- but note that compound args are allowed (eg, 2 x u16 | ||
292 | * for IEEE80211_RADIOTAP_CHANNEL) so total arg length is not | ||
293 | * a reliable indicator of alignment requirement. | ||
294 | * | ||
295 | * upper nybble: content alignment for arg | ||
296 | * lower nybble: content length for arg | ||
297 | */ | ||
298 | |||
299 | static const u8 rt_sizes[] = { | ||
300 | [IEEE80211_RADIOTAP_TSFT] = 0x88, | ||
301 | [IEEE80211_RADIOTAP_FLAGS] = 0x11, | ||
302 | [IEEE80211_RADIOTAP_RATE] = 0x11, | ||
303 | [IEEE80211_RADIOTAP_CHANNEL] = 0x24, | ||
304 | [IEEE80211_RADIOTAP_FHSS] = 0x22, | ||
305 | [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = 0x11, | ||
306 | [IEEE80211_RADIOTAP_DBM_ANTNOISE] = 0x11, | ||
307 | [IEEE80211_RADIOTAP_LOCK_QUALITY] = 0x22, | ||
308 | [IEEE80211_RADIOTAP_TX_ATTENUATION] = 0x22, | ||
309 | [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = 0x22, | ||
310 | [IEEE80211_RADIOTAP_DBM_TX_POWER] = 0x11, | ||
311 | [IEEE80211_RADIOTAP_ANTENNA] = 0x11, | ||
312 | [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = 0x11, | ||
313 | [IEEE80211_RADIOTAP_DB_ANTNOISE] = 0x11 | ||
314 | /* | ||
315 | * add more here as they are defined in | ||
316 | * include/net/ieee80211_radiotap.h | ||
317 | */ | ||
318 | }; | ||
319 | |||
320 | /* | ||
321 | * for every radiotap entry we can at | ||
322 | * least skip (by knowing the length)... | ||
323 | */ | ||
324 | |||
325 | while (iterator->arg_index < sizeof(rt_sizes)) { | ||
326 | int hit = 0; | ||
327 | int pad; | ||
328 | |||
329 | if (!(iterator->bitmap_shifter & 1)) | ||
330 | goto next_entry; /* arg not present */ | ||
331 | |||
332 | /* | ||
333 | * arg is present, account for alignment padding | ||
334 | * 8-bit args can be at any alignment | ||
335 | * 16-bit args must start on 16-bit boundary | ||
336 | * 32-bit args must start on 32-bit boundary | ||
337 | * 64-bit args must start on 64-bit boundary | ||
338 | * | ||
339 | * note that total arg size can differ from alignment of | ||
340 | * elements inside arg, so we use upper nybble of length | ||
341 | * table to base alignment on | ||
342 | * | ||
343 | * also note: these alignments are ** relative to the | ||
344 | * start of the radiotap header **. There is no guarantee | ||
345 | * that the radiotap header itself is aligned on any | ||
346 | * kind of boundary. | ||
347 | */ | ||
348 | |||
349 | pad = (((ulong)iterator->arg) - | ||
350 | ((ulong)iterator->rtheader)) & | ||
351 | ((rt_sizes[iterator->arg_index] >> 4) - 1); | ||
352 | |||
353 | if (pad) | ||
354 | iterator->arg_index += | ||
355 | (rt_sizes[iterator->arg_index] >> 4) - pad; | ||
356 | |||
357 | /* | ||
358 | * this is what we will return to user, but we need to | ||
359 | * move on first so next call has something fresh to test | ||
360 | */ | ||
361 | iterator->this_arg_index = iterator->arg_index; | ||
362 | iterator->this_arg = iterator->arg; | ||
363 | hit = 1; | ||
364 | |||
365 | /* internally move on the size of this arg */ | ||
366 | iterator->arg += rt_sizes[iterator->arg_index] & 0x0f; | ||
367 | |||
368 | /* | ||
369 | * check for insanity where we are given a bitmap that | ||
370 | * claims to have more arg content than the length of the | ||
371 | * radiotap section. We will normally end up equalling this | ||
372 | * max_length on the last arg, never exceeding it. | ||
373 | */ | ||
374 | |||
375 | if (((ulong)iterator->arg - (ulong)iterator->rtheader) > | ||
376 | iterator->max_length) | ||
377 | return -EINVAL; | ||
378 | |||
379 | next_entry: | ||
380 | iterator->arg_index++; | ||
381 | if (unlikely((iterator->arg_index & 31) == 0)) { | ||
382 | /* completed current u32 bitmap */ | ||
383 | if (iterator->bitmap_shifter & 1) { | ||
384 | /* b31 was set, there is more */ | ||
385 | /* move to next u32 bitmap */ | ||
386 | iterator->bitmap_shifter = | ||
387 | le32_to_cpu(*iterator->next_bitmap); | ||
388 | iterator->next_bitmap++; | ||
389 | } else { | ||
390 | /* no more bitmaps: end */ | ||
391 | iterator->arg_index = sizeof(rt_sizes); | ||
392 | } | ||
393 | } else { /* just try the next bit */ | ||
394 | iterator->bitmap_shifter >>= 1; | ||
395 | } | ||
396 | |||
397 | /* if we found a valid arg earlier, return it now */ | ||
398 | if (hit) | ||
399 | return 0; | ||
400 | } | ||
401 | |||
402 | /* we don't know how to handle any more args, we're done */ | ||
403 | return -ENOENT; | ||
404 | } | ||
405 | |||
406 | |||
407 | |||
408 | int | ||
409 | main(int argc, char *argv[]) | ||
410 | { | ||
411 | u8 u8aSendBuffer[500]; | ||
412 | char szErrbuf[PCAP_ERRBUF_SIZE]; | ||
413 | int nCaptureHeaderLength = 0, n80211HeaderLength = 0, nLinkEncap = 0; | ||
414 | int nOrdinal = 0, r, nDelay = 100000; | ||
415 | int nRateIndex = 0, retval, bytes; | ||
416 | pcap_t *ppcap = NULL; | ||
417 | struct bpf_program bpfprogram; | ||
418 | char * szProgram = "", fBrokenSocket = 0; | ||
419 | u16 u16HeaderLen; | ||
420 | char szHostname[PATH_MAX]; | ||
421 | |||
422 | if (gethostname(szHostname, sizeof (szHostname) - 1)) { | ||
423 | perror("unable to get hostname"); | ||
424 | } | ||
425 | szHostname[sizeof (szHostname) - 1] = '\0'; | ||
426 | |||
427 | |||
428 | printf("Packetspammer (c)2007 Andy Green <andy@warmcat.com> GPL2\n"); | ||
429 | |||
430 | while (1) { | ||
431 | int nOptionIndex; | ||
432 | static const struct option optiona[] = { | ||
433 | { "delay", required_argument, NULL, 'd' }, | ||
434 | { "fcs", no_argument, &flagMarkWithFCS, 1 }, | ||
435 | { "help", no_argument, &flagHelp, 1 }, | ||
436 | { "verbose", no_argument, &flagVerbose, 1}, | ||
437 | { 0, 0, 0, 0 } | ||
438 | }; | ||
439 | int c = getopt_long(argc, argv, "d:hf", | ||
440 | optiona, &nOptionIndex); | ||
441 | |||
442 | if (c == -1) | ||
443 | break; | ||
444 | switch (c) { | ||
445 | case 0: // long option | ||
446 | break; | ||
447 | |||
448 | case 'h': // help | ||
449 | usage(); | ||
450 | |||
451 | case 'd': // delay | ||
452 | nDelay = atoi(optarg); | ||
453 | break; | ||
454 | |||
455 | case 'f': // mark as FCS attached | ||
456 | flagMarkWithFCS = 1; | ||
457 | break; | ||
458 | |||
459 | case 'v': //Verbose / readable output to cout | ||
460 | flagVerbose = 1; | ||
461 | break; | ||
462 | |||
463 | default: | ||
464 | printf("unknown switch %c\n", c); | ||
465 | usage(); | ||
466 | break; | ||
467 | } | ||
468 | } | ||
469 | |||
470 | if (optind >= argc) | ||
471 | usage(); | ||
472 | |||
473 | |||
474 | // open the interface in pcap | ||
475 | |||
476 | szErrbuf[0] = '\0'; | ||
477 | ppcap = pcap_open_live(argv[optind], 800, 1, 20, szErrbuf); | ||
478 | if (ppcap == NULL) { | ||
479 | printf("Unable to open interface %s in pcap: %s\n", | ||
480 | argv[optind], szErrbuf); | ||
481 | return (1); | ||
482 | } | ||
483 | |||
484 | //get mac from interface | ||
485 | |||
486 | /*int sock, j, k; | ||
487 | char mac[32]; | ||
488 | |||
489 | sock=socket(PF_INET, SOCK_STREAM, 0); | ||
490 | if (-1==sock) { | ||
491 | perror("can not open socket\n"); | ||
492 | return 1; | ||
493 | } | ||
494 | |||
495 | if (-1==ioctl(sock, SIOCGIFHWADDR, &ifr)) { | ||
496 | perror("ioctl(SIOCGIFHWADDR) "); | ||
497 | return 1; | ||
498 | } | ||
499 | for (j=0, k=0; j<6; j++) { | ||
500 | k+=snprintf(mac+k, sizeof(mac)-k-1, j ? ":%02X" : "%02X", | ||
501 | (int)(unsigned int)(unsigned char)ifr.ifr_hwaddr.sa_data[j]); | ||
502 | } | ||
503 | mac[sizeof(mac)-1]='\0'; | ||
504 | */ | ||
505 | |||
506 | //get header type | ||
507 | nLinkEncap = pcap_datalink(ppcap); | ||
508 | nCaptureHeaderLength = 0; | ||
509 | |||
510 | switch (nLinkEncap) { | ||
511 | |||
512 | case DLT_PRISM_HEADER: | ||
513 | printf("DLT_PRISM_HEADER Encap\n"); | ||
514 | nCaptureHeaderLength = 0x40; | ||
515 | n80211HeaderLength = 0x20; // ieee80211 comes after this | ||
516 | szProgram = "radio[0x4a:4]==0x13223344"; | ||
517 | break; | ||
518 | |||
519 | case DLT_IEEE802_11_RADIO: | ||
520 | printf("DLT_IEEE802_11_RADIO Encap\n"); | ||
521 | nCaptureHeaderLength = 0x40; | ||
522 | n80211HeaderLength = 0x18; // ieee80211 comes after this | ||
523 | szProgram = "ether[0x0a:4]==0x13223344"; | ||
524 | break; | ||
525 | |||
526 | default: | ||
527 | printf("!!! unknown encapsulation on %s !\n", argv[1]); | ||
528 | return (1); | ||
529 | |||
530 | } | ||
531 | |||
532 | if (pcap_compile(ppcap, &bpfprogram, szProgram, 1, 0) == -1) { | ||
533 | puts(szProgram); | ||
534 | puts(pcap_geterr(ppcap)); | ||
535 | return (1); | ||
536 | } else { | ||
537 | if (pcap_setfilter(ppcap, &bpfprogram) == -1) { | ||
538 | puts(szProgram); | ||
539 | puts(pcap_geterr(ppcap)); | ||
540 | } else { | ||
541 | printf("RX Filter applied\n"); | ||
542 | } | ||
543 | pcap_freecode(&bpfprogram); | ||
544 | } | ||
545 | |||
546 | pcap_setnonblock(ppcap, 1, szErrbuf); | ||
547 | |||
548 | printf(" (delay between packets %dus)\n", nDelay); | ||
549 | |||
550 | memset(u8aSendBuffer, 0, sizeof (u8aSendBuffer)); | ||
551 | |||
552 | while (!fBrokenSocket) { | ||
553 | u8 * pu8 = u8aSendBuffer; | ||
554 | struct pcap_pkthdr * ppcapPacketHeader = NULL; | ||
555 | struct ieee80211_radiotap_iterator rti; | ||
556 | PENUMBRA_RADIOTAP_DATA prd; | ||
557 | u8 * pu8Payload = u8aSendBuffer; | ||
558 | int n, nRate; | ||
559 | |||
560 | // receive | ||
561 | |||
562 | retval = pcap_next_ex(ppcap, &ppcapPacketHeader, | ||
563 | (const u_char**)&pu8Payload); | ||
564 | |||
565 | if (retval < 0) { | ||
566 | fBrokenSocket = 1; | ||
567 | continue; | ||
568 | } | ||
569 | |||
570 | if (retval != 1) | ||
571 | goto do_tx; | ||
572 | |||
573 | u16HeaderLen = (pu8Payload[2] + (pu8Payload[3] << 8)); | ||
574 | |||
575 | printf("rtap: "); | ||
576 | Dump(pu8Payload, u16HeaderLen); | ||
577 | |||
578 | if (ppcapPacketHeader->len < | ||
579 | (u16HeaderLen + n80211HeaderLength)) | ||
580 | continue; | ||
581 | |||
582 | bytes = ppcapPacketHeader->len - | ||
583 | (u16HeaderLen + n80211HeaderLength); | ||
584 | if (bytes < 0) | ||
585 | continue; | ||
586 | |||
587 | if (ieee80211_radiotap_iterator_init(&rti, | ||
588 | (struct ieee80211_radiotap_header *)pu8Payload, | ||
589 | bytes) < 0) | ||
590 | continue; | ||
591 | |||
592 | while ((n = ieee80211_radiotap_iterator_next(&rti)) == 0) { | ||
593 | |||
594 | switch (rti.this_arg_index) { | ||
595 | case IEEE80211_RADIOTAP_RATE: | ||
596 | prd.m_nRate = (*rti.this_arg); | ||
597 | break; | ||
598 | |||
599 | case IEEE80211_RADIOTAP_CHANNEL: | ||
600 | prd.m_nChannel = | ||
601 | le16_to_cpu(*((u16 *)rti.this_arg)); | ||
602 | prd.m_nChannelFlags = | ||
603 | le16_to_cpu(*((u16 *)(rti.this_arg + 2))); | ||
604 | break; | ||
605 | |||
606 | case IEEE80211_RADIOTAP_ANTENNA: | ||
607 | prd.m_nAntenna = (*rti.this_arg) + 1; | ||
608 | break; | ||
609 | |||
610 | case IEEE80211_RADIOTAP_FLAGS: | ||
611 | prd.m_nRadiotapFlags = *rti.this_arg; | ||
612 | break; | ||
613 | |||
614 | } | ||
615 | } | ||
616 | |||
617 | pu8Payload += u16HeaderLen + n80211HeaderLength; | ||
618 | |||
619 | if (prd.m_nRadiotapFlags & IEEE80211_RADIOTAP_F_FCS) | ||
620 | bytes -= 4; | ||
621 | |||
622 | printf("RX: Rate: %2d.%dMbps, Freq: %d.%dGHz, " | ||
623 | "Ant: %d, Flags: 0x%X\n", | ||
624 | prd.m_nRate / 2, 5 * (prd.m_nRate & 1), | ||
625 | prd.m_nChannel / 1000, | ||
626 | prd.m_nChannel - ((prd.m_nChannel / 1000) * 1000), | ||
627 | prd.m_nAntenna, | ||
628 | prd.m_nRadiotapFlags); | ||
629 | |||
630 | Dump(pu8Payload, bytes); | ||
631 | |||
632 | do_tx: | ||
633 | |||
634 | // transmit | ||
635 | |||
636 | memcpy(u8aSendBuffer, u8aRadiotapHeader, | ||
637 | sizeof (u8aRadiotapHeader)); | ||
638 | if (flagMarkWithFCS) | ||
639 | pu8[OFFSET_FLAGS] |= IEEE80211_RADIOTAP_F_FCS; | ||
640 | nRate = pu8[OFFSET_RATE] = u8aRatesToUse[nRateIndex++]; | ||
641 | if (nRateIndex >= sizeof (u8aRatesToUse)) | ||
642 | nRateIndex = 0; | ||
643 | pu8 += sizeof (u8aRadiotapHeader); | ||
644 | |||
645 | memcpy(pu8, u8aIeeeHeader, sizeof (u8aIeeeHeader)); | ||
646 | pu8 += sizeof (u8aIeeeHeader); | ||
647 | |||
648 | pu8 += sprintf((char *)pu8, | ||
649 | "Packetspammer %02d" | ||
650 | "broadcast packet" | ||
651 | "#%05d -- :-D --%s ----", | ||
652 | nRate/2, nOrdinal++, szHostname); | ||
653 | r = pcap_inject(ppcap, u8aSendBuffer, pu8 - u8aSendBuffer); | ||
654 | if (r != (pu8-u8aSendBuffer)) { | ||
655 | perror("Trouble injecting packet"); | ||
656 | return (1); | ||
657 | } | ||
658 | if (nDelay) | ||
659 | usleep(nDelay); | ||
660 | } | ||
661 | |||
662 | |||
663 | |||
664 | return (0); | ||
665 | } | ||