2 * QEMU WLAN access point emulation
4 * Copyright (c) 2008 Clemens Kolbitsch
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 * 2008-February-24 Clemens Kolbitsch :
26 * New implementation based on ne2000.c
30 #include "qemu/osdep.h"
32 #if defined(CONFIG_WIN32)
33 #warning("not compiled for Windows host")
42 #include <sys/socket.h>
46 #include <netinet/in.h>
50 #include "hw/atheros_wlan.h"
51 #include "hw/atheros_wlan_crc32.h"
52 #include "hw/atheros_wlan_packet.h"
54 #define FRAME_INSERT(_8bit_data) buf[i++] = _8bit_data
57 static int insertCRC(mac80211_frame
*frame
, uint32_t frame_length
)
60 unsigned char *fcs
= (unsigned char *)frame
;
62 crc
= crc32_ccitt(fcs
, frame_length
);
63 memcpy(&fcs
[frame_length
], &crc
, 4);
65 return frame_length
+ 4;
69 void Atheros_WLAN_init_frame(Atheros_WLANState
*s
, mac80211_frame
*frame
)
75 frame
->sequence_control
.sequence_number
= s
->inject_sequence_number
++;
76 memcpy(frame
->source_address
, s
->ap_macaddr
, 6);
77 memcpy(frame
->bssid_address
, s
->ap_macaddr
, 6);
79 frame
->frame_length
= insertCRC(frame
, frame
->frame_length
);
83 mac80211_frame
*Atheros_WLAN_create_beacon_frame(void)
87 mac80211_frame
*frame
;
89 frame
= (mac80211_frame
*)malloc(sizeof(mac80211_frame
));
94 frame
->next_frame
= NULL
;
95 frame
->frame_control
.protocol_version
= 0;
96 frame
->frame_control
.type
= IEEE80211_TYPE_MGT
;
97 frame
->frame_control
.sub_type
= IEEE80211_TYPE_MGT_SUBTYPE_BEACON
;
98 frame
->frame_control
.flags
= 0;
99 frame
->duration_id
= 0;
100 frame
->sequence_control
.fragment_number
= 0;
102 for (i
= 0; i
< 6; frame
->destination_address
[i
] = 0xff, i
++) {
106 buf
= (unsigned char *)frame
->data_and_fcs
;
109 * Fixed params... typical AP params (12 byte)
114 * - Capability Information
129 FRAME_INSERT(IEEE80211_BEACON_PARAM_SSID
);
130 FRAME_INSERT(4); /* length */
131 FRAME_INSERT('Q'); /* SSID */
132 FRAME_INSERT('L'); /* SSID */
133 FRAME_INSERT('a'); /* SSID */
134 FRAME_INSERT('n'); /* SSID */
136 FRAME_INSERT(IEEE80211_BEACON_PARAM_RATES
);
137 FRAME_INSERT(8); /* length */
147 FRAME_INSERT(IEEE80211_BEACON_PARAM_CHANNEL
);
148 FRAME_INSERT(1); /* length */
151 frame
->frame_length
= IEEE80211_HEADER_SIZE
+ i
;
155 mac80211_frame
*Atheros_WLAN_create_probe_response(void)
159 mac80211_frame
*frame
;
161 frame
= (mac80211_frame
*)malloc(sizeof(mac80211_frame
));
166 frame
->next_frame
= NULL
;
167 frame
->frame_control
.protocol_version
= 0;
168 frame
->frame_control
.type
= IEEE80211_TYPE_MGT
;
169 frame
->frame_control
.sub_type
= IEEE80211_TYPE_MGT_SUBTYPE_PROBE_RESP
;
170 frame
->frame_control
.flags
= 0;
171 frame
->duration_id
= 314;
172 frame
->sequence_control
.fragment_number
= 0;
175 buf
= (unsigned char *)frame
->data_and_fcs
;
178 * Fixed params... typical AP params (12 byte)
183 * - Capability Information
198 FRAME_INSERT(IEEE80211_BEACON_PARAM_SSID
);
199 FRAME_INSERT(4); /* length */
200 FRAME_INSERT('Q'); /* SSID */
201 FRAME_INSERT('L'); /* SSID */
202 FRAME_INSERT('a'); /* SSID */
203 FRAME_INSERT('n'); /* SSID */
205 FRAME_INSERT(IEEE80211_BEACON_PARAM_RATES
);
206 FRAME_INSERT(8); /* length */
216 FRAME_INSERT(IEEE80211_BEACON_PARAM_CHANNEL
);
217 FRAME_INSERT(1); /* length */
220 frame
->frame_length
= IEEE80211_HEADER_SIZE
+ i
;
224 mac80211_frame
*Atheros_WLAN_create_authentication(void)
228 mac80211_frame
*frame
;
230 frame
= (mac80211_frame
*)malloc(sizeof(mac80211_frame
));
235 frame
->next_frame
= NULL
;
236 frame
->frame_control
.protocol_version
= 0;
237 frame
->frame_control
.type
= IEEE80211_TYPE_MGT
;
238 frame
->frame_control
.sub_type
= IEEE80211_TYPE_MGT_SUBTYPE_AUTHENTICATION
;
239 frame
->frame_control
.flags
= 0;
240 frame
->duration_id
= 314;
241 frame
->sequence_control
.fragment_number
= 0;
244 buf
= (unsigned char *)frame
->data_and_fcs
;
247 * Fixed params... typical AP params (6 byte)
250 * - Authentication Algorithm (here: Open System)
251 * - Authentication SEQ
252 * - Status code (successful 0x0)
261 FRAME_INSERT(IEEE80211_BEACON_PARAM_SSID
);
262 FRAME_INSERT(4); /* length */
263 FRAME_INSERT('Q'); /* SSID */
264 FRAME_INSERT('L'); /* SSID */
265 FRAME_INSERT('a'); /* SSID */
266 FRAME_INSERT('n'); /* SSID */
268 frame
->frame_length
= IEEE80211_HEADER_SIZE
+ i
;
272 mac80211_frame
*Atheros_WLAN_create_deauthentication(void)
276 mac80211_frame
*frame
;
278 frame
= (mac80211_frame
*)malloc(sizeof(mac80211_frame
));
283 frame
->next_frame
= NULL
;
284 frame
->frame_control
.protocol_version
= 0;
285 frame
->frame_control
.type
= IEEE80211_TYPE_MGT
;
286 frame
->frame_control
.sub_type
= IEEE80211_TYPE_MGT_SUBTYPE_DEAUTHENTICATION
;
287 frame
->frame_control
.flags
= 0;
288 frame
->duration_id
= 314;
289 frame
->sequence_control
.fragment_number
= 0;
292 buf
= (unsigned char *)frame
->data_and_fcs
;
295 * Insert reason code:
296 * "Deauthentication because sending STA is leaving"
301 frame
->frame_length
= IEEE80211_HEADER_SIZE
+ i
;
305 mac80211_frame
*Atheros_WLAN_create_association_response(void)
309 mac80211_frame
*frame
;
311 frame
= (mac80211_frame
*)malloc(sizeof(mac80211_frame
));
316 frame
->next_frame
= NULL
;
317 frame
->frame_control
.protocol_version
= 0;
318 frame
->frame_control
.type
= IEEE80211_TYPE_MGT
;
319 frame
->frame_control
.sub_type
= IEEE80211_TYPE_MGT_SUBTYPE_ASSOCIATION_RESP
;
320 frame
->frame_control
.flags
= 0;
322 frame
->duration_id
= 314;
324 frame
->sequence_control
.fragment_number
= 0;
327 buf
= (unsigned char *)frame
->data_and_fcs
;
330 * Fixed params... typical AP params (6 byte)
333 * - Capability Information
334 * - Status code (successful 0x0)
344 FRAME_INSERT(IEEE80211_BEACON_PARAM_SSID
);
345 FRAME_INSERT(4); /* length */
346 FRAME_INSERT('Q'); /* SSID */
347 FRAME_INSERT('L'); /* SSID */
348 FRAME_INSERT('a'); /* SSID */
349 FRAME_INSERT('n'); /* SSID */
351 FRAME_INSERT(IEEE80211_BEACON_PARAM_RATES
);
352 FRAME_INSERT(8); /* length */
362 FRAME_INSERT(IEEE80211_BEACON_PARAM_EXTENDED_RATES
);
363 FRAME_INSERT(4); /* length */
369 frame
->frame_length
= IEEE80211_HEADER_SIZE
+ i
;
373 mac80211_frame
*Atheros_WLAN_create_disassociation(void)
377 mac80211_frame
*frame
;
379 frame
= (mac80211_frame
*)malloc(sizeof(mac80211_frame
));
384 frame
->next_frame
= NULL
;
385 frame
->frame_control
.protocol_version
= 0;
386 frame
->frame_control
.type
= IEEE80211_TYPE_MGT
;
387 frame
->frame_control
.sub_type
= IEEE80211_TYPE_MGT_SUBTYPE_DISASSOCIATION
;
388 frame
->frame_control
.flags
= 0;
389 frame
->duration_id
= 314;
390 frame
->sequence_control
.fragment_number
= 0;
393 buf
= (unsigned char *)frame
->data_and_fcs
;
396 * Insert reason code:
397 * "Disassociation because sending STA is leaving"
402 frame
->frame_length
= IEEE80211_HEADER_SIZE
+ i
;
406 mac80211_frame
*Atheros_WLAN_create_data_packet(Atheros_WLANState
*s
,
407 const uint8_t *buf
, int size
)
409 mac80211_frame
*frame
;
411 frame
= (mac80211_frame
*)malloc(sizeof(mac80211_frame
));
416 frame
->next_frame
= NULL
;
417 frame
->frame_control
.protocol_version
= 0;
418 frame
->frame_control
.type
= IEEE80211_TYPE_DATA
;
419 frame
->frame_control
.sub_type
= IEEE80211_TYPE_DATA_SUBTYPE_DATA
;
420 frame
->frame_control
.flags
= 0x2; /* from station back to station via AP */
421 frame
->duration_id
= 44;
422 frame
->sequence_control
.fragment_number
= 0;
424 /* send message to wlan-device */
425 memcpy(frame
->destination_address
, s
->macaddr
, 6);
427 size
-= 12; /* remove old 803.2 header */
428 size
+= 6; /* add new 803.11 header */
429 if (size
> sizeof(frame
->data_and_fcs
)) {
430 /* sanitize memcpy */
431 size
= sizeof(frame
->data_and_fcs
);
435 frame
->data_and_fcs
[0] = 0xaa;
436 frame
->data_and_fcs
[1] = 0xaa;
437 frame
->data_and_fcs
[2] = 0x03;
438 frame
->data_and_fcs
[3] = 0x00;
439 frame
->data_and_fcs
[4] = 0x00;
440 frame
->data_and_fcs
[5] = 0x00;
442 memcpy(&frame
->data_and_fcs
[6], &buf
[12], size
);
443 frame
->frame_length
= IEEE80211_HEADER_SIZE
+ size
;
448 int Atheros_WLAN_dumpFrame(mac80211_frame
*frame
, int frame_len
, char *filename
)
452 unsigned char buf
[56];
453 unsigned int frame_total_length
= frame_len
+ 16;
454 unsigned char *l
= (unsigned char *)&frame_total_length
;
456 /* Wireshark header */
490 /* total frame length */
491 for (j
= 0; j
< 4; buf
[i
++] = l
[j
++]) {
493 /* captured frame length */
494 for (j
= 0; j
< 4; buf
[i
++] = l
[j
++]) {
497 /* Radiotap header */
516 fp
= fopen(filename
, "w");
519 if (fwrite(buf
, 1, sizeof(buf
), fp
) != sizeof(buf
)) {
522 if (fwrite(frame
, 1, frame_len
, fp
) != frame_len
) {
531 #endif /* CONFIG_WIN32 */