Changeset 8a64320e in mainline for uspace/lib/ieee80211/src/ieee80211.c
- Timestamp:
- 2015-04-23T23:40:14Z (10 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- dcba819
- Parents:
- 09044cb
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/ieee80211/src/ieee80211.c
r09044cb r8a64320e 32 32 33 33 /** @file ieee80211.c 34 * 34 * 35 35 * IEEE 802.11 interface implementation. 36 36 */ … … 41 41 #include <macros.h> 42 42 #include <errno.h> 43 44 43 #include <ieee80211.h> 45 44 #include <ieee80211_impl.h> … … 48 47 #include <ops/ieee80211.h> 49 48 50 #define IEEE80211_DATA_RATES_SIZE 851 #define IEEE80211_EXT_DATA_RATES_SIZE 449 #define IEEE80211_DATA_RATES_SIZE 8 50 #define IEEE80211_EXT_DATA_RATES_SIZE 4 52 51 53 52 #define ATOMIC_GET(state) 54 53 55 54 /** Frame encapsulation used in IEEE 802.11. */ 56 static const uint8_t rfc1042_header[] = { 57 0x AA, 0xAA, 0x03, 0x00, 0x00, 0x0055 static const uint8_t rfc1042_header[] = { 56 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 58 57 }; 59 58 60 59 /** Broadcast MAC address. */ 61 60 static const uint8_t ieee80211_broadcast_mac_addr[] = { 62 0x FF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF61 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 63 62 }; 64 63 65 /** 66 * Check data frame. 67 * 64 /** Check data frame. 65 * 68 66 * @param frame_ctrl Frame control field in little endian (!). 69 * 67 * 70 68 * @return True if it is data frame, otherwise false. 69 * 71 70 */ 72 71 inline bool ieee80211_is_data_frame(uint16_t frame_ctrl) … … 74 73 frame_ctrl = uint16_t_le2host(frame_ctrl); 75 74 76 return (frame_ctrl & IEEE80211_FRAME_CTRL_FRAME_TYPE) 77 == IEEE80211_DATA_FRAME; 78 } 79 80 /** 81 * Check management frame. 82 * 75 return (frame_ctrl & IEEE80211_FRAME_CTRL_FRAME_TYPE) == 76 IEEE80211_DATA_FRAME; 77 } 78 79 /** Check management frame. 80 * 83 81 * @param frame_ctrl Frame control field in little endian (!). 84 * 82 * 85 83 * @return True if it is management frame, otherwise false. 84 * 86 85 */ 87 86 inline bool ieee80211_is_mgmt_frame(uint16_t frame_ctrl) … … 89 88 frame_ctrl = uint16_t_le2host(frame_ctrl); 90 89 91 return (frame_ctrl & IEEE80211_FRAME_CTRL_FRAME_TYPE) 92 == IEEE80211_MGMT_FRAME; 93 } 94 95 /** 96 * Check management beacon frame. 97 * 90 return (frame_ctrl & IEEE80211_FRAME_CTRL_FRAME_TYPE) == 91 IEEE80211_MGMT_FRAME; 92 } 93 94 /** Check management beacon frame. 95 * 98 96 * @param frame_ctrl Frame control field in little endian (!). 99 * 97 * 100 98 * @return True if it is beacon frame, otherwise false. 99 * 101 100 */ 102 101 inline bool ieee80211_is_beacon_frame(uint16_t frame_ctrl) … … 104 103 frame_ctrl = uint16_t_le2host(frame_ctrl); 105 104 106 return (frame_ctrl & IEEE80211_FRAME_CTRL_FRAME_SUBTYPE) 107 == IEEE80211_MGMT_BEACON_FRAME; 108 } 109 110 /** 111 * Check management probe response frame. 112 * 105 return (frame_ctrl & IEEE80211_FRAME_CTRL_FRAME_SUBTYPE) == 106 IEEE80211_MGMT_BEACON_FRAME; 107 } 108 109 /** Check management probe response frame. 110 * 113 111 * @param frame_ctrl Frame control field in little endian (!). 114 * 112 * 115 113 * @return True if it is probe resp frame, otherwise false. 114 * 116 115 */ 117 116 inline bool ieee80211_is_probe_response_frame(uint16_t frame_ctrl) … … 119 118 frame_ctrl = uint16_t_le2host(frame_ctrl); 120 119 121 return (frame_ctrl & IEEE80211_FRAME_CTRL_FRAME_SUBTYPE) 122 == IEEE80211_MGMT_PROBE_RESP_FRAME; 123 } 124 125 /** 126 * Check management authentication frame. 127 * 120 return (frame_ctrl & IEEE80211_FRAME_CTRL_FRAME_SUBTYPE) == 121 IEEE80211_MGMT_PROBE_RESP_FRAME; 122 } 123 124 /** Check management authentication frame. 125 * 128 126 * @param frame_ctrl Frame control field in little endian (!). 129 * 127 * 130 128 * @return True if it is auth frame, otherwise false. 129 * 131 130 */ 132 131 inline bool ieee80211_is_auth_frame(uint16_t frame_ctrl) … … 134 133 frame_ctrl = uint16_t_le2host(frame_ctrl); 135 134 136 return (frame_ctrl & IEEE80211_FRAME_CTRL_FRAME_SUBTYPE) 137 == IEEE80211_MGMT_AUTH_FRAME; 138 } 139 140 /** 141 * Check management association response frame. 142 * 135 return (frame_ctrl & IEEE80211_FRAME_CTRL_FRAME_SUBTYPE) == 136 IEEE80211_MGMT_AUTH_FRAME; 137 } 138 139 /** Check management association response frame. 140 * 143 141 * @param frame_ctrl Frame control field in little endian (!). 144 * 142 * 145 143 * @return True if it is assoc resp frame, otherwise false. 144 * 146 145 */ 147 146 inline bool ieee80211_is_assoc_response_frame(uint16_t frame_ctrl) … … 149 148 frame_ctrl = uint16_t_le2host(frame_ctrl); 150 149 151 return (frame_ctrl & IEEE80211_FRAME_CTRL_FRAME_SUBTYPE) 152 == IEEE80211_MGMT_ASSOC_RESP_FRAME; 153 } 154 155 /** 156 * Check data frame "to distribution system" direction. 157 * 150 return (frame_ctrl & IEEE80211_FRAME_CTRL_FRAME_SUBTYPE) == 151 IEEE80211_MGMT_ASSOC_RESP_FRAME; 152 } 153 154 /** Check data frame "to distribution system" direction. 155 * 158 156 * @param frame_ctrl Frame control field in little endian (!). 159 * 157 * 160 158 * @return True if it is TODS frame, otherwise false. 159 * 161 160 */ 162 161 inline bool ieee80211_is_tods_frame(uint16_t frame_ctrl) … … 167 166 } 168 167 169 /** 170 * Check data frame "from distribution system" direction. 171 * 168 /** Check data frame "from distribution system" direction. 169 * 172 170 * @param frame_ctrl Frame control field in little endian (!). 173 * 171 * 174 172 * @return True if it is FROMDS frame, otherwise false. 173 * 175 174 */ 176 175 inline bool ieee80211_is_fromds_frame(uint16_t frame_ctrl) … … 181 180 } 182 181 183 /** 184 * Check if it is data frame containing payload data. 185 * 182 /** Check if it is data frame containing payload data. 183 * 186 184 * @param frame_ctrl Frame control field in little endian (!). 187 * 185 * 188 186 * @return True if it has payload data, otherwise false. 187 * 189 188 */ 190 189 static inline bool ieee80211_has_data_frame(uint16_t frame_ctrl) … … 192 191 frame_ctrl = uint16_t_le2host(frame_ctrl); 193 192 194 return (frame_ctrl & (IEEE80211_FRAME_CTRL_FRAME_TYPE | 0x40)) 195 == IEEE80211_DATA_FRAME; 196 } 197 198 /** 199 * Check if it is encrypted frame. 200 * 193 return (frame_ctrl & (IEEE80211_FRAME_CTRL_FRAME_TYPE | 0x40)) == 194 IEEE80211_DATA_FRAME; 195 } 196 197 /** Check if it is encrypted frame. 198 * 201 199 * @param frame_ctrl Frame control field in little endian (!). 202 * 200 * 203 201 * @return True if the frame is encrypted, otherwise false. 202 * 204 203 */ 205 204 static inline bool ieee80211_is_encrypted_frame(uint16_t frame_ctrl) … … 210 209 } 211 210 212 /** 213 * Check if PAE packet is EAPOL-Key frame. 214 * 211 /** Check if PAE packet is EAPOL-Key frame. 212 * 215 213 * @param key_frame Pointer to start of EAPOL frame. 216 * 214 * 217 215 * @return True if it is EAPOL-Key frame, otherwise false. 218 */ 219 static inline bool ieee80211_is_eapol_key_frame(ieee80211_eapol_key_frame_t 220 *key_frame) 216 * 217 */ 218 static inline bool 219 ieee80211_is_eapol_key_frame(ieee80211_eapol_key_frame_t *key_frame) 221 220 { 222 221 return (key_frame->packet_type == IEEE80211_EAPOL_KEY); 223 222 } 224 223 225 226 /** 227 * Generate packet sequence number. 228 * 224 /** Generate packet sequence number. 225 * 229 226 * @param ieee80211_dev IEEE 802.11 device. 230 * 227 * 231 228 * @return True if it has payload data, otherwise false. 229 * 232 230 */ 233 231 static uint16_t ieee80211_get_sequence_number(ieee80211_dev_t *ieee80211_dev) … … 235 233 uint16_t ret_val = ieee80211_dev->sequence_number; 236 234 ieee80211_dev->sequence_number += (1 << 4); 235 237 236 return ret_val; 238 237 } 239 238 240 /** 241 * Get driver-specific structure for IEEE 802.11 device. 242 * 239 /** Get driver-specific structure for IEEE 802.11 device. 240 * 243 241 * @param ieee80211_dev IEEE 802.11 device. 244 * 242 * 245 243 * @return Driver-specific structure. 246 */ 247 void *ieee80211_get_specific(ieee80211_dev_t* ieee80211_dev) 244 * 245 */ 246 void *ieee80211_get_specific(ieee80211_dev_t *ieee80211_dev) 248 247 { 249 248 return ieee80211_dev->specific; 250 249 } 251 250 252 /** 253 * Set driver-specific structure for IEEE 802.11 device. 254 * 251 /** Set driver-specific structure for IEEE 802.11 device. 252 * 255 253 * @param ieee80211_dev IEEE 802.11 device. 256 * @param specific Driver-specific structure. 257 */ 258 void ieee80211_set_specific(ieee80211_dev_t* ieee80211_dev, 259 void *specific) 254 * @param specific Driver-specific structure. 255 * 256 */ 257 void ieee80211_set_specific(ieee80211_dev_t *ieee80211_dev, 258 void *specific) 260 259 { 261 260 ieee80211_dev->specific = specific; 262 261 } 263 262 264 /** 265 * Get related DDF device. 266 * 263 /** Get related DDF device. 264 * 267 265 * @param ieee80211_dev IEEE 802.11 device. 268 * 266 * 269 267 * @return DDF device. 270 */ 271 ddf_dev_t *ieee80211_get_ddf_dev(ieee80211_dev_t* ieee80211_dev) 268 * 269 */ 270 ddf_dev_t *ieee80211_get_ddf_dev(ieee80211_dev_t *ieee80211_dev) 272 271 { 273 272 return ieee80211_dev->ddf_dev; 274 273 } 275 274 276 /** 277 * Query current operating mode of IEEE 802.11 device. 278 * 275 /** Query current operating mode of IEEE 802.11 device. 276 * 279 277 * @param ieee80211_dev IEEE 802.11 device. 280 * 278 * 281 279 * @return Current IEEE 802.11 operating mode. 282 */ 283 ieee80211_operating_mode_t ieee80211_query_current_op_mode(ieee80211_dev_t* 284 ieee80211_dev) 280 * 281 */ 282 ieee80211_operating_mode_t 283 ieee80211_query_current_op_mode(ieee80211_dev_t *ieee80211_dev) 285 284 { 286 285 fibril_mutex_lock(&ieee80211_dev->gen_mutex); … … 291 290 } 292 291 293 /** 294 * Query current frequency of IEEE 802.11 device. 295 * 292 /** Query current frequency of IEEE 802.11 device. 293 * 296 294 * @param ieee80211_dev IEEE 802.11 device. 297 * 295 * 298 296 * @return Current device operating frequency. 299 */ 300 uint16_t ieee80211_query_current_freq(ieee80211_dev_t* ieee80211_dev) 297 * 298 */ 299 uint16_t ieee80211_query_current_freq(ieee80211_dev_t *ieee80211_dev) 301 300 { 302 301 fibril_mutex_lock(&ieee80211_dev->gen_mutex); … … 307 306 } 308 307 309 /** 310 * Query BSSID the device is connected to. 311 * 308 /** Query BSSID the device is connected to. 309 * 312 310 * Note: Expecting locked results_mutex. 313 * 311 * 314 312 * @param ieee80211_dev IEEE 802.11 device. 315 * @param bssid Pointer to structure where should be stored BSSID. 316 */ 317 void ieee80211_query_bssid(ieee80211_dev_t* ieee80211_dev, 318 nic_address_t *bssid) 313 * @param bssid Pointer to structure where should be stored BSSID. 314 * 315 */ 316 void ieee80211_query_bssid(ieee80211_dev_t *ieee80211_dev, 317 nic_address_t *bssid) 319 318 { 320 319 fibril_mutex_lock(&ieee80211_dev->gen_mutex); 321 320 322 if (bssid) {323 ieee80211_scan_result_link_t *res_link = 324 325 326 if (res_link) {327 memcpy(bssid, &res_link->scan_result.bssid, 328 321 if (bssid) { 322 ieee80211_scan_result_link_t *res_link = 323 ieee80211_dev->bssid_info.res_link; 324 325 if (res_link) { 326 memcpy(bssid, &res_link->scan_result.bssid, 327 sizeof(nic_address_t)); 329 328 } else { 330 329 nic_address_t broadcast_addr; 331 330 memcpy(broadcast_addr.address, 332 ieee80211_broadcast_mac_addr, 333 ETH_ADDR); 331 ieee80211_broadcast_mac_addr, ETH_ADDR); 334 332 memcpy(bssid, &broadcast_addr, sizeof(nic_address_t)); 335 333 } … … 339 337 } 340 338 341 /** 342 * Get AID of network we are connected to. 343 * 339 /** Get AID of network we are connected to. 340 * 344 341 * @param ieee80211_dev IEEE 802.11 device. 345 * 342 * 346 343 * @return AID. 347 */ 348 uint16_t ieee80211_get_aid(ieee80211_dev_t* ieee80211_dev) 344 * 345 */ 346 uint16_t ieee80211_get_aid(ieee80211_dev_t *ieee80211_dev) 349 347 { 350 348 fibril_mutex_lock(&ieee80211_dev->gen_mutex); … … 355 353 } 356 354 357 /** 358 * Get pairwise security suite used for HW encryption. 359 * 355 /** Get pairwise security suite used for HW encryption. 356 * 360 357 * @param ieee80211_dev IEEE 802.11 device. 361 * 358 * 362 359 * @return Security suite indicator. 363 */ 364 int ieee80211_get_pairwise_security(ieee80211_dev_t* ieee80211_dev) 360 * 361 */ 362 int ieee80211_get_pairwise_security(ieee80211_dev_t *ieee80211_dev) 365 363 { 366 364 fibril_mutex_lock(&ieee80211_dev->gen_mutex); 367 ieee80211_scan_result_link_t *auth_link = 368 365 ieee80211_scan_result_link_t *auth_link = 366 ieee80211_dev->bssid_info.res_link; 369 367 int suite = auth_link->scan_result.security.pair_alg; 370 368 fibril_mutex_unlock(&ieee80211_dev->gen_mutex); … … 373 371 } 374 372 375 /** 376 * Check if IEEE 802.11 device is connected to network. 377 * 373 /** Check if IEEE 802.11 device is connected to network. 374 * 378 375 * @param ieee80211_dev IEEE 802.11 device. 379 * 376 * 380 377 * @return True if device is connected to network, otherwise false. 381 */ 382 bool ieee80211_is_connected(ieee80211_dev_t* ieee80211_dev) 378 * 379 */ 380 bool ieee80211_is_connected(ieee80211_dev_t *ieee80211_dev) 383 381 { 384 382 fibril_mutex_lock(&ieee80211_dev->gen_mutex); 385 bool conn_state = 386 383 bool conn_state = 384 ieee80211_dev->current_auth_phase == IEEE80211_AUTH_CONNECTED; 387 385 fibril_mutex_unlock(&ieee80211_dev->gen_mutex); 386 388 387 return conn_state; 389 388 } 390 389 391 390 void ieee80211_set_auth_phase(ieee80211_dev_t *ieee80211_dev, 392 391 ieee80211_auth_phase_t auth_phase) 393 392 { 394 393 fibril_mutex_lock(&ieee80211_dev->gen_mutex); … … 397 396 } 398 397 399 ieee80211_auth_phase_t ieee80211_get_auth_phase(ieee80211_dev_t 400 *ieee80211_dev) 398 ieee80211_auth_phase_t ieee80211_get_auth_phase(ieee80211_dev_t *ieee80211_dev) 401 399 { 402 400 fibril_mutex_lock(&ieee80211_dev->gen_mutex); 403 401 ieee80211_auth_phase_t conn_state = ieee80211_dev->current_auth_phase; 404 402 fibril_mutex_unlock(&ieee80211_dev->gen_mutex); 403 405 404 return conn_state; 406 405 } … … 419 418 ieee80211_dev->pending_conn_req = false; 420 419 fibril_mutex_unlock(&ieee80211_dev->gen_mutex); 420 421 421 return conn_request; 422 422 } 423 423 424 /** 425 * Report current operating mode for IEEE 802.11 device. 426 * 424 /** Report current operating mode for IEEE 802.11 device. 425 * 427 426 * @param ieee80211_dev IEEE 802.11 device. 428 * @param op_mode Current IEEE 802.11 operating mode. 429 */ 430 void ieee80211_report_current_op_mode(ieee80211_dev_t* ieee80211_dev, 431 ieee80211_operating_mode_t op_mode) 427 * @param op_mode Current IEEE 802.11 operating mode. 428 * 429 */ 430 void ieee80211_report_current_op_mode(ieee80211_dev_t *ieee80211_dev, 431 ieee80211_operating_mode_t op_mode) 432 432 { 433 433 fibril_mutex_lock(&ieee80211_dev->gen_mutex); … … 436 436 } 437 437 438 /** 439 * Report current frequency for IEEE 802.11 device. 440 * 438 /** Report current frequency for IEEE 802.11 device. 439 * 441 440 * @param ieee80211_dev IEEE 802.11 device. 442 * @param freq Current device operating frequency. 443 */ 444 void ieee80211_report_current_freq(ieee80211_dev_t* ieee80211_dev, 445 uint16_t freq) 441 * @param freq Current device operating frequency. 442 * 443 */ 444 void ieee80211_report_current_freq(ieee80211_dev_t *ieee80211_dev, 445 uint16_t freq) 446 446 { 447 447 fibril_mutex_lock(&ieee80211_dev->gen_mutex); … … 450 450 } 451 451 452 /** 453 * Check if IEEE 802.11 device is ready (fully initialized). 454 * 452 /** Check if IEEE 802.11 device is ready (fully initialized). 453 * 455 454 * @param ieee80211_dev IEEE 802.11 device. 456 * 455 * 457 456 * @return True if device is ready to work, otherwise false. 458 */ 459 bool ieee80211_is_ready(ieee80211_dev_t* ieee80211_dev) 457 * 458 */ 459 bool ieee80211_is_ready(ieee80211_dev_t *ieee80211_dev) 460 460 { 461 461 fibril_mutex_lock(&ieee80211_dev->gen_mutex); … … 466 466 } 467 467 468 /** 469 * Set IEEE 802.11 device to ready state. 470 * 468 /** Set IEEE 802.11 device to ready state. 469 * 471 470 * @param ieee80211_dev IEEE 802.11 device. 472 * @param ready Ready state to be set. 473 */ 474 void ieee80211_set_ready(ieee80211_dev_t* ieee80211_dev, bool ready) 471 * @param ready Ready state to be set. 472 * 473 */ 474 void ieee80211_set_ready(ieee80211_dev_t *ieee80211_dev, bool ready) 475 475 { 476 476 fibril_mutex_lock(&ieee80211_dev->gen_mutex); … … 479 479 } 480 480 481 extern bool ieee80211_query_using_key(ieee80211_dev_t *ieee80211_dev)481 extern bool ieee80211_query_using_key(ieee80211_dev_t *ieee80211_dev) 482 482 { 483 483 fibril_mutex_lock(&ieee80211_dev->gen_mutex); … … 488 488 } 489 489 490 void ieee80211_setup_key_confirm(ieee80211_dev_t * ieee80211_dev,491 490 void ieee80211_setup_key_confirm(ieee80211_dev_t *ieee80211_dev, 491 bool using_key) 492 492 { 493 493 fibril_mutex_lock(&ieee80211_dev->gen_mutex); … … 502 502 ieee80211_dev_t *ieee80211_dev = (ieee80211_dev_t *) arg; 503 503 504 while (true) {504 while (true) { 505 505 ieee80211_dev->ops->scan(ieee80211_dev); 506 506 async_usleep(SCAN_PERIOD_USEC); … … 510 510 } 511 511 512 /** 513 * Implementation of NIC open callback for IEEE 802.11 devices. 514 * 512 /** Implementation of NIC open callback for IEEE 802.11 devices. 513 * 515 514 * @param fun NIC function. 516 * 515 * 517 516 * @return EOK if succeed, negative error code otherwise. 517 * 518 518 */ 519 519 static int ieee80211_open(ddf_fun_t *fun) … … 522 522 ieee80211_dev_t *ieee80211_dev = nic_get_specific(nic_data); 523 523 524 if (ieee80211_dev->started) {524 if (ieee80211_dev->started) 525 525 return EOK; 526 } else { 527 ieee80211_dev->started = true; 528 } 526 527 ieee80211_dev->started = true; 529 528 530 529 int rc = ieee80211_dev->ops->start(ieee80211_dev); 531 if (rc != EOK)530 if (rc != EOK) 532 531 return rc; 533 532 534 533 /* Add scanning fibril. */ 535 534 fid_t fibril = fibril_create(ieee80211_scan, ieee80211_dev); 536 if (fibril == 0) {535 if (fibril == 0) 537 536 return ENOMEM; 538 }537 539 538 fibril_add_ready(fibril); 540 539 … … 542 541 } 543 542 544 /** 545 * Send frame handler. 546 * 547 * @param nic Pointer to NIC device. 543 /** Send frame handler. 544 * 545 * @param nic Pointer to NIC device. 548 546 * @param data Data buffer. 549 547 * @param size Data buffer size. 548 * 550 549 */ 551 550 static void ieee80211_send_frame(nic_t *nic, void *data, size_t size) 552 551 { 553 ieee80211_dev_t *ieee80211_dev = (ieee80211_dev_t *) 554 555 556 ieee80211_auth_phase_t auth_phase = 557 558 if (auth_phase != IEEE80211_AUTH_ASSOCIATED &&559 auth_phase != IEEE80211_AUTH_CONNECTED) {552 ieee80211_dev_t *ieee80211_dev = (ieee80211_dev_t *) 553 nic_get_specific(nic); 554 555 ieee80211_auth_phase_t auth_phase = 556 ieee80211_get_auth_phase(ieee80211_dev); 557 if ((auth_phase != IEEE80211_AUTH_ASSOCIATED) && 558 (auth_phase != IEEE80211_AUTH_CONNECTED)) 560 559 return; 561 }562 560 563 561 ieee80211_scan_result_t *auth_data = 564 562 &ieee80211_dev->bssid_info.res_link->scan_result; 565 563 566 564 /* We drop part of IEEE 802.3 ethernet header. */ 567 565 size_t drop_bytes = sizeof(eth_header_t) - 2; 568 566 569 size_t complete_size = (size - drop_bytes) + 570 571 567 size_t complete_size = (size - drop_bytes) + 568 sizeof(ieee80211_data_header_t) + 569 ARRAY_SIZE(rfc1042_header); 572 570 573 571 /* Init crypto data. */ … … 579 577 580 578 // TODO: Distinguish used key (pair/group) by dest address ? 581 if (ieee80211_query_using_key(ieee80211_dev)) {579 if (ieee80211_query_using_key(ieee80211_dev)) { 582 580 int sec_suite = auth_data->security.pair_alg; 583 switch (sec_suite) {584 585 586 587 588 589 590 591 592 593 594 581 switch (sec_suite) { 582 case IEEE80211_SECURITY_SUITE_TKIP: 583 head_space = IEEE80211_TKIP_HEADER_LENGTH; 584 mic_space = MIC_LENGTH; 585 add_mic = true; 586 break; 587 case IEEE80211_SECURITY_SUITE_CCMP: 588 head_space = IEEE80211_CCMP_HEADER_LENGTH; 589 head_data[3] = 0x20; 590 break; 591 default: 592 break; 595 593 } 596 594 597 595 crypto = uint16_t_le2host(IEEE80211_FRAME_CTRL_PROTECTED); 598 596 } … … 601 599 602 600 void *complete_buffer = malloc(complete_size); 601 if (!complete_buffer) 602 return; 603 603 604 memset(complete_buffer, 0, complete_size); 604 605 605 if (head_space) {606 if (head_space) 606 607 memcpy(complete_buffer + sizeof(ieee80211_data_header_t), 607 head_data, head_space); 608 } 608 head_data, head_space); 609 609 610 610 memcpy(complete_buffer + sizeof(ieee80211_data_header_t) + head_space, 611 rfc1042_header, 612 ARRAY_SIZE(rfc1042_header)); 613 614 memcpy(complete_buffer + 615 sizeof(ieee80211_data_header_t) + 616 ARRAY_SIZE(rfc1042_header) + head_space, 617 data + drop_bytes, size - drop_bytes); 611 rfc1042_header, ARRAY_SIZE(rfc1042_header)); 612 613 memcpy(complete_buffer + sizeof(ieee80211_data_header_t) + 614 ARRAY_SIZE(rfc1042_header) + head_space, 615 data + drop_bytes, size - drop_bytes); 618 616 619 617 ieee80211_data_header_t *data_header = 620 621 data_header->frame_ctrl = 622 623 624 625 618 (ieee80211_data_header_t *) complete_buffer; 619 data_header->frame_ctrl = 620 uint16_t_le2host(IEEE80211_DATA_FRAME) | 621 uint16_t_le2host(IEEE80211_DATA_DATA_FRAME) | 622 uint16_t_le2host(IEEE80211_FRAME_CTRL_TODS) | 623 crypto; 626 624 data_header->seq_ctrl = ieee80211_get_sequence_number(ieee80211_dev); 627 625 628 626 /* BSSID, SA, DA. */ 629 memcpy(data_header->address1, auth_data->bssid.address, 627 memcpy(data_header->address1, auth_data->bssid.address, ETH_ADDR); 630 628 memcpy(data_header->address2, data + ETH_ADDR, ETH_ADDR); 631 629 memcpy(data_header->address3, data, ETH_ADDR); 632 630 633 if (add_mic) {631 if (add_mic) { 634 632 size_t size_wo_mic = complete_size - MIC_LENGTH; 635 633 uint8_t *tx_mic = ieee80211_dev->bssid_info.ptk + 636 TK_OFFSET + 637 IEEE80211_TKIP_TX_MIC_OFFSET; 634 TK_OFFSET + IEEE80211_TKIP_TX_MIC_OFFSET; 638 635 ieee80211_michael_mic(tx_mic, complete_buffer, size_wo_mic, 639 complete_buffer + size_wo_mic); 640 } 641 642 ieee80211_dev->ops->tx_handler(ieee80211_dev, 643 complete_buffer, 644 complete_size); 636 complete_buffer + size_wo_mic); 637 } 638 639 ieee80211_dev->ops->tx_handler(ieee80211_dev, 640 complete_buffer, complete_size); 645 641 646 642 free(complete_buffer); 647 643 } 648 644 649 /** 650 * Fill out IEEE 802.11 device functions implementations. 651 * 652 * @param ieee80211_dev IEEE 802.11 device. 653 * @param ieee80211_ops Callbacks implementation. 645 /** Fill out IEEE 802.11 device functions implementations. 646 * 647 * @param ieee80211_dev IEEE 802.11 device. 648 * @param ieee80211_ops Callbacks implementation. 654 649 * @param ieee80211_iface Interface functions implementation. 655 * @param nic_iface NIC interface functions implementation. 656 * @param nic_dev_ops NIC device functions implementation. 657 * 658 * @return EINVAL when missing pointer to ieee80211_ops or ieee80211_iface, 659 * otherwise EOK. 660 */ 661 static int ieee80211_implement(ieee80211_dev_t *ieee80211_dev, 662 ieee80211_ops_t *ieee80211_ops, ieee80211_iface_t *ieee80211_iface, 663 nic_iface_t *nic_iface, ddf_dev_ops_t *nic_dev_ops) 664 { 665 if(ieee80211_ops) { 666 if(!ieee80211_ops->start) 650 * @param nic_iface NIC interface functions implementation. 651 * @param nic_dev_ops NIC device functions implementation. 652 * 653 * @return EINVAL when missing pointer to ieee80211_ops 654 * or ieee80211_iface, otherwise EOK. 655 * 656 */ 657 static int ieee80211_implement(ieee80211_dev_t *ieee80211_dev, 658 ieee80211_ops_t *ieee80211_ops, ieee80211_iface_t *ieee80211_iface, 659 nic_iface_t *nic_iface, ddf_dev_ops_t *nic_dev_ops) 660 { 661 if (ieee80211_ops) { 662 if (!ieee80211_ops->start) 667 663 ieee80211_ops->start = ieee80211_start_impl; 668 669 if (!ieee80211_ops->tx_handler)664 665 if (!ieee80211_ops->tx_handler) 670 666 ieee80211_ops->tx_handler = ieee80211_tx_handler_impl; 671 672 if (!ieee80211_ops->set_freq)667 668 if (!ieee80211_ops->set_freq) 673 669 ieee80211_ops->set_freq = ieee80211_set_freq_impl; 674 670 675 if(!ieee80211_ops->bssid_change) 676 ieee80211_ops->bssid_change = 677 ieee80211_bssid_change_impl; 678 679 if(!ieee80211_ops->key_config) 671 if (!ieee80211_ops->bssid_change) 672 ieee80211_ops->bssid_change = ieee80211_bssid_change_impl; 673 674 if (!ieee80211_ops->key_config) 680 675 ieee80211_ops->key_config = ieee80211_key_config_impl; 681 676 682 if (!ieee80211_ops->scan)677 if (!ieee80211_ops->scan) 683 678 ieee80211_ops->scan = ieee80211_scan_impl; 684 } else {679 } else 685 680 return EINVAL; 686 }687 681 688 682 ieee80211_dev->ops = ieee80211_ops; 689 683 690 if (ieee80211_iface) {691 if (nic_dev_ops)684 if (ieee80211_iface) { 685 if (nic_dev_ops) 692 686 if (!nic_dev_ops->interfaces[IEEE80211_DEV_IFACE]) 693 nic_dev_ops->interfaces[IEEE80211_DEV_IFACE] = 694 695 696 if (!ieee80211_iface->get_scan_results)697 ieee80211_iface->get_scan_results = 698 699 700 if (!ieee80211_iface->connect)687 nic_dev_ops->interfaces[IEEE80211_DEV_IFACE] = 688 ieee80211_iface; 689 690 if (!ieee80211_iface->get_scan_results) 691 ieee80211_iface->get_scan_results = 692 ieee80211_get_scan_results_impl; 693 694 if (!ieee80211_iface->connect) 701 695 ieee80211_iface->connect = ieee80211_connect_impl; 702 696 703 if (!ieee80211_iface->disconnect)697 if (!ieee80211_iface->disconnect) 704 698 ieee80211_iface->disconnect = ieee80211_disconnect_impl; 705 } else {699 } else 706 700 return EINVAL; 707 } 708 709 if(nic_dev_ops) { 710 if(!nic_dev_ops->open) 701 702 if (nic_dev_ops) { 703 if (!nic_dev_ops->open) 711 704 nic_dev_ops->open = ieee80211_open; 712 } else {705 } else 713 706 return EINVAL; 714 }715 707 716 708 ieee80211_dev->iface = ieee80211_iface; … … 721 713 } 722 714 723 /** 724 * Allocate IEEE802.11 device structure. 725 * 715 /** Allocate IEEE802.11 device structure. 716 * 726 717 * @return Pointer to allocated IEEE802.11 device structure. 718 * 727 719 */ 728 720 ieee80211_dev_t *ieee80211_device_create() … … 731 723 } 732 724 733 /** 734 * Initialize an IEEE802.11 framework structure. 735 * 725 /** Initialize an IEEE802.11 framework structure. 726 * 736 727 * @param ieee80211_dev Device structure to initialize. 737 * @param ddf_dev Pointer to backing DDF device structure.738 * 728 * @param ddf_dev Pointer to backing DDF device structure. 729 * 739 730 * @return EOK if succeed, negative error code otherwise. 731 * 740 732 */ 741 733 int ieee80211_device_init(ieee80211_dev_t *ieee80211_dev, ddf_dev_t *ddf_dev) … … 748 740 ieee80211_dev->current_op_mode = IEEE80211_OPMODE_STATION; 749 741 ieee80211_dev->current_auth_phase = IEEE80211_AUTH_DISCONNECTED; 750 memcpy(ieee80211_dev->bssid_mask.address, ieee80211_broadcast_mac_addr, 751 ETH_ADDR); 742 743 memcpy(ieee80211_dev->bssid_mask.address, ieee80211_broadcast_mac_addr, 744 ETH_ADDR); 752 745 753 746 ieee80211_scan_result_list_init(&ieee80211_dev->ap_list); … … 759 752 /* Bind NIC to device */ 760 753 nic_t *nic = nic_create_and_bind(ddf_dev); 761 if (!nic) {754 if (!nic) 762 755 return ENOMEM; 763 }764 756 765 757 nic_set_specific(nic, ieee80211_dev); … … 768 760 } 769 761 770 /** 771 * IEEE802.11 WiFi framework initialization.772 * 773 * @param ieee80211_ dev Device structure to initialize.774 * @param ieee80211_ops Structure with implemented IEEE802.11device operations.775 * @param ieee80211_iface Structure with implemented IEEE802.11 interface776 * operations.777 * 762 /** IEEE802.11 WiFi framework initialization. 763 * 764 * @param ieee80211_dev Device structure to initialize. 765 * @param ieee80211_ops Structure with implemented IEEE802.11 766 * device operations. 767 * @param ieee80211_iface Structure with implemented IEEE802.11 768 * interface operations. 769 * 778 770 * @return EOK if succeed, negative error code otherwise. 779 */ 780 int ieee80211_init(ieee80211_dev_t *ieee80211_dev, 781 ieee80211_ops_t *ieee80211_ops, ieee80211_iface_t *ieee80211_iface, 782 nic_iface_t *ieee80211_nic_iface, ddf_dev_ops_t *ieee80211_nic_dev_ops) 783 { 784 int rc = ieee80211_implement(ieee80211_dev, 785 ieee80211_ops, ieee80211_iface, 786 ieee80211_nic_iface, ieee80211_nic_dev_ops); 787 if(rc != EOK) { 771 * 772 */ 773 int ieee80211_init(ieee80211_dev_t *ieee80211_dev, 774 ieee80211_ops_t *ieee80211_ops, ieee80211_iface_t *ieee80211_iface, 775 nic_iface_t *ieee80211_nic_iface, ddf_dev_ops_t *ieee80211_nic_dev_ops) 776 { 777 int rc = ieee80211_implement(ieee80211_dev, 778 ieee80211_ops, ieee80211_iface, 779 ieee80211_nic_iface, ieee80211_nic_dev_ops); 780 if (rc != EOK) 788 781 return rc; 789 }790 782 791 783 nic_t *nic = nic_get_from_ddf_dev(ieee80211_dev->ddf_dev); 792 784 793 /* *TODO: Set NIC handlers here. */785 /* TODO: Set NIC handlers here. */ 794 786 nic_set_send_frame_handler(nic, ieee80211_send_frame); 795 787 796 ddf_fun_t *fun = ddf_fun_create(ieee80211_dev->ddf_dev, fun_exposed, 797 798 if (fun == NULL) {788 ddf_fun_t *fun = ddf_fun_create(ieee80211_dev->ddf_dev, fun_exposed, 789 "port0"); 790 if (fun == NULL) 799 791 return EINVAL; 800 }801 792 802 793 nic_set_ddf_fun(nic, fun); … … 808 799 return rc; 809 800 } 801 810 802 rc = ddf_fun_add_to_category(fun, DEVICE_CATEGORY_NIC); 811 803 if (rc != EOK) { … … 813 805 return rc; 814 806 } 807 815 808 rc = ddf_fun_add_to_category(fun, DEVICE_CATEGORY_IEEE80211); 816 809 if (rc != EOK) { … … 822 815 } 823 816 824 /** 825 * Convert frequency value to channel number. 826 * 817 /** Convert frequency value to channel number. 818 * 827 819 * @param freq IEEE 802.11 operating frequency. 828 * 820 * 829 821 * @return Operating channel number. 822 * 830 823 */ 831 824 static uint8_t ieee80211_freq_to_channel(uint16_t freq) … … 835 828 836 829 static void ieee80211_prepare_ie_header(void **ie_header, 837 830 uint8_t id, uint8_t length, void *data) 838 831 { 839 832 ieee80211_ie_header_t *header = 840 833 (ieee80211_ie_header_t *) *ie_header; 841 834 842 835 header->element_id = id; … … 845 838 memcpy(*ie_header + sizeof(ieee80211_ie_header_t), data, length); 846 839 847 *ie_header = (void *) ((void *) header + 848 sizeof(ieee80211_ie_header_t) + length); 849 } 850 851 /** 852 * Probe request implementation. 853 * 840 *ie_header = (void *) ((void *) header + 841 sizeof(ieee80211_ie_header_t) + length); 842 } 843 844 /** Probe request implementation. 845 * 854 846 * @param ieee80211_dev Pointer to IEEE 802.11 device structure. 855 * @param ssid Probing SSID or NULL if broadcast.856 * 847 * @param ssid Probing SSID or NULL if broadcast. 848 * 857 849 * @return EOK if succeed, negative error code otherwise. 850 * 858 851 */ 859 852 int ieee80211_probe_request(ieee80211_dev_t *ieee80211_dev, char *ssid) … … 866 859 size_t channel_data_size = 1; 867 860 868 uint8_t channel = 869 ieee80211_freq_to_channel(ieee80211_dev->current_freq); 870 871 /* 4 headers - (ssid, rates, ext rates, current channel) and their data 872 * lengths. 861 uint8_t channel = 862 ieee80211_freq_to_channel(ieee80211_dev->current_freq); 863 864 /* 865 * 4 headers - (ssid, rates, ext rates, current channel) 866 * and their data lengths. 873 867 */ 874 size_t payload_size = 875 876 ssid_data_size +877 IEEE80211_DATA_RATES_SIZE + IEEE80211_EXT_DATA_RATES_SIZE +878 868 size_t payload_size = 869 sizeof(ieee80211_ie_header_t) * 4 + 870 ssid_data_size + 871 IEEE80211_DATA_RATES_SIZE + IEEE80211_EXT_DATA_RATES_SIZE + 872 channel_data_size; 879 873 880 874 size_t buffer_size = sizeof(ieee80211_mgmt_header_t) + payload_size; 881 875 void *buffer = malloc(buffer_size); 876 if (!buffer) 877 return ENOMEM; 878 882 879 memset(buffer, 0, buffer_size); 883 880 884 ieee80211_mgmt_header_t *mgmt_header = 885 (ieee80211_mgmt_header_t *) buffer; 886 887 mgmt_header->frame_ctrl = host2uint16_t_le( 888 IEEE80211_MGMT_FRAME | 889 IEEE80211_MGMT_PROBE_REQ_FRAME 890 ); 881 ieee80211_mgmt_header_t *mgmt_header = 882 (ieee80211_mgmt_header_t *) buffer; 883 884 mgmt_header->frame_ctrl = 885 host2uint16_t_le(IEEE80211_MGMT_FRAME | 886 IEEE80211_MGMT_PROBE_REQ_FRAME); 891 887 memcpy(mgmt_header->dest_addr, ieee80211_broadcast_mac_addr, ETH_ADDR); 892 888 memcpy(mgmt_header->src_addr, nic_address.address, ETH_ADDR); 893 889 memcpy(mgmt_header->bssid, ieee80211_broadcast_mac_addr, ETH_ADDR); 894 mgmt_header->seq_ctrl = 895 890 mgmt_header->seq_ctrl = 891 host2uint16_t_le(ieee80211_get_sequence_number(ieee80211_dev)); 896 892 897 893 /* Jump to payload. */ 898 894 void *it = (void *) buffer + sizeof(ieee80211_mgmt_header_t); 899 ieee80211_prepare_ie_header(&it, IEEE80211_SSID_IE, ssid_data_size, 900 (void *) ssid); 901 ieee80211_prepare_ie_header(&it, IEEE80211_RATES_IE, 902 IEEE80211_DATA_RATES_SIZE, 903 (void *) &ieee80211bg_data_rates); 904 ieee80211_prepare_ie_header(&it, IEEE80211_EXT_RATES_IE, 905 IEEE80211_EXT_DATA_RATES_SIZE, 906 (void *) &ieee80211bg_data_rates[IEEE80211_DATA_RATES_SIZE]); 907 ieee80211_prepare_ie_header(&it, IEEE80211_CHANNEL_IE, 908 channel_data_size, (void *) &channel); 895 ieee80211_prepare_ie_header(&it, IEEE80211_SSID_IE, ssid_data_size, 896 (void *) ssid); 897 ieee80211_prepare_ie_header(&it, IEEE80211_RATES_IE, 898 IEEE80211_DATA_RATES_SIZE, (void *) &ieee80211bg_data_rates); 899 ieee80211_prepare_ie_header(&it, IEEE80211_EXT_RATES_IE, 900 IEEE80211_EXT_DATA_RATES_SIZE, 901 (void *) &ieee80211bg_data_rates[IEEE80211_DATA_RATES_SIZE]); 902 ieee80211_prepare_ie_header(&it, IEEE80211_CHANNEL_IE, 903 channel_data_size, (void *) &channel); 909 904 910 905 ieee80211_dev->ops->tx_handler(ieee80211_dev, buffer, buffer_size); … … 915 910 } 916 911 917 /** 918 * IEEE 802.11 authentication implementation. 919 * 912 /** IEEE 802.11 authentication implementation. 913 * 920 914 * @param ieee80211_dev Pointer to IEEE 802.11 device structure. 921 * 915 * 922 916 * @return EOK if succeed, negative error code otherwise. 917 * 923 918 */ 924 919 int ieee80211_authenticate(ieee80211_dev_t *ieee80211_dev) … … 929 924 930 925 ieee80211_scan_result_t *auth_data = 931 932 933 size_t buffer_size = sizeof(ieee80211_mgmt_header_t) + 934 926 &ieee80211_dev->bssid_info.res_link->scan_result; 927 928 size_t buffer_size = sizeof(ieee80211_mgmt_header_t) + 929 sizeof(ieee80211_auth_body_t); 935 930 936 931 void *buffer = malloc(buffer_size); 932 if (!buffer) 933 return ENOMEM; 934 937 935 memset(buffer, 0, buffer_size); 938 936 939 ieee80211_mgmt_header_t *mgmt_header = 940 (ieee80211_mgmt_header_t *) buffer; 941 942 mgmt_header->frame_ctrl = host2uint16_t_le( 943 IEEE80211_MGMT_FRAME | 944 IEEE80211_MGMT_AUTH_FRAME 945 ); 937 ieee80211_mgmt_header_t *mgmt_header = 938 (ieee80211_mgmt_header_t *) buffer; 939 940 mgmt_header->frame_ctrl = 941 host2uint16_t_le(IEEE80211_MGMT_FRAME | 942 IEEE80211_MGMT_AUTH_FRAME); 946 943 memcpy(mgmt_header->dest_addr, auth_data->bssid.address, ETH_ADDR); 947 944 memcpy(mgmt_header->src_addr, nic_address.address, ETH_ADDR); … … 949 946 950 947 ieee80211_auth_body_t *auth_body = 951 (ieee80211_auth_body_t *)952 948 (ieee80211_auth_body_t *) 949 (buffer + sizeof(ieee80211_mgmt_header_t)); 953 950 auth_body->auth_alg = host2uint16_t_le(0); 954 951 auth_body->auth_trans_no = host2uint16_t_le(1); … … 961 958 } 962 959 963 /** 964 * IEEE 802.11 association implementation. 965 * 960 /** IEEE 802.11 association implementation. 961 * 966 962 * @param ieee80211_dev Pointer to IEEE 802.11 device structure. 967 * @param password Passphrase to be used in encrypted communication or NULL968 * for open networks.969 * 963 * @param password Passphrase to be used in encrypted communication 964 * or NULL for open networks. 965 * 970 966 * @return EOK if succeed, negative error code otherwise. 971 */ 972 int ieee80211_associate(ieee80211_dev_t *ieee80211_dev, char *password) 967 * 968 */ 969 int ieee80211_associate(ieee80211_dev_t *ieee80211_dev, char *password) 973 970 { 974 971 nic_t *nic = nic_get_from_ddf_dev(ieee80211_dev->ddf_dev); … … 977 974 978 975 ieee80211_scan_result_link_t *auth_link = 979 976 ieee80211_dev->bssid_info.res_link; 980 977 981 978 ieee80211_scan_result_t *auth_data = &auth_link->scan_result; … … 983 980 size_t ssid_data_size = str_size(auth_data->ssid); 984 981 985 size_t payload_size = 986 987 ssid_data_size +988 IEEE80211_DATA_RATES_SIZE +989 990 991 size_t buffer_size = 992 sizeof(ieee80211_mgmt_header_t) +993 994 995 996 if (auth_data->security.type == IEEE80211_SECURITY_WPA ||997 auth_data->security.type == IEEE80211_SECURITY_WPA2) {982 size_t payload_size = 983 sizeof(ieee80211_ie_header_t) * 3 + 984 ssid_data_size + 985 IEEE80211_DATA_RATES_SIZE + 986 IEEE80211_EXT_DATA_RATES_SIZE; 987 988 size_t buffer_size = 989 sizeof(ieee80211_mgmt_header_t) + 990 sizeof(ieee80211_assoc_req_body_t) + 991 payload_size; 992 993 if ((auth_data->security.type == IEEE80211_SECURITY_WPA) || 994 (auth_data->security.type == IEEE80211_SECURITY_WPA2)) 998 995 buffer_size += auth_link->auth_ie_len; 999 }1000 996 1001 997 void *buffer = malloc(buffer_size); 998 if (!buffer) 999 return ENOMEM; 1000 1002 1001 memset(buffer, 0, buffer_size); 1003 1002 1004 ieee80211_mgmt_header_t *mgmt_header = 1005 (ieee80211_mgmt_header_t *) buffer; 1006 1007 mgmt_header->frame_ctrl = host2uint16_t_le( 1008 IEEE80211_MGMT_FRAME | 1009 IEEE80211_MGMT_ASSOC_REQ_FRAME 1010 ); 1003 ieee80211_mgmt_header_t *mgmt_header = 1004 (ieee80211_mgmt_header_t *) buffer; 1005 1006 mgmt_header->frame_ctrl = 1007 host2uint16_t_le(IEEE80211_MGMT_FRAME | 1008 IEEE80211_MGMT_ASSOC_REQ_FRAME); 1011 1009 memcpy(mgmt_header->dest_addr, auth_data->bssid.address, ETH_ADDR); 1012 1010 memcpy(mgmt_header->src_addr, nic_address.address, ETH_ADDR); … … 1014 1012 1015 1013 ieee80211_assoc_req_body_t *assoc_body = 1016 (ieee80211_assoc_req_body_t *)1017 1014 (ieee80211_assoc_req_body_t *) 1015 (buffer + sizeof(ieee80211_mgmt_header_t)); 1018 1016 assoc_body->listen_interval = host2uint16_t_le(1); 1019 1017 1020 1018 /* Jump to payload. */ 1021 1019 void *it = buffer + sizeof(ieee80211_mgmt_header_t) + 1022 sizeof(ieee80211_assoc_req_body_t); 1023 ieee80211_prepare_ie_header(&it, IEEE80211_SSID_IE, 1024 ssid_data_size, (void *) auth_data->ssid); 1025 ieee80211_prepare_ie_header(&it, IEEE80211_RATES_IE, 1026 IEEE80211_DATA_RATES_SIZE, 1027 (void *) &ieee80211bg_data_rates); 1028 ieee80211_prepare_ie_header(&it, IEEE80211_EXT_RATES_IE, 1029 IEEE80211_EXT_DATA_RATES_SIZE, 1030 (void *) &ieee80211bg_data_rates[IEEE80211_DATA_RATES_SIZE]); 1031 1032 if(auth_data->security.type != IEEE80211_SECURITY_OPEN) { 1020 sizeof(ieee80211_assoc_req_body_t); 1021 ieee80211_prepare_ie_header(&it, IEEE80211_SSID_IE, 1022 ssid_data_size, (void *) auth_data->ssid); 1023 ieee80211_prepare_ie_header(&it, IEEE80211_RATES_IE, 1024 IEEE80211_DATA_RATES_SIZE, (void *) &ieee80211bg_data_rates); 1025 ieee80211_prepare_ie_header(&it, IEEE80211_EXT_RATES_IE, 1026 IEEE80211_EXT_DATA_RATES_SIZE, 1027 (void *) &ieee80211bg_data_rates[IEEE80211_DATA_RATES_SIZE]); 1028 1029 if (auth_data->security.type != IEEE80211_SECURITY_OPEN) 1033 1030 assoc_body->capability |= host2uint16_t_le(CAP_SECURITY); 1034 } 1035 1036 if(auth_data->security.type == IEEE80211_SECURITY_WPA || 1037 auth_data->security.type == IEEE80211_SECURITY_WPA2) { 1038 memcpy(it, auth_link->auth_ie, auth_link->auth_ie_len); 1039 } 1031 1032 if ((auth_data->security.type == IEEE80211_SECURITY_WPA) || 1033 (auth_data->security.type == IEEE80211_SECURITY_WPA2)) 1034 memcpy(it, auth_link->auth_ie, auth_link->auth_ie_len); 1040 1035 1041 1036 ieee80211_dev->ops->tx_handler(ieee80211_dev, buffer, buffer_size); 1042 1037 1043 /* 1044 * Save password to be used in eventual authentication handshake. 1038 /* 1039 * Save password to be used in eventual authentication handshake. 1045 1040 */ 1046 1041 memset(ieee80211_dev->bssid_info.password, 0, IEEE80211_MAX_PASSW_LEN); 1047 memcpy(ieee80211_dev->bssid_info.password, password, 1048 1042 memcpy(ieee80211_dev->bssid_info.password, password, 1043 str_size(password)); 1049 1044 1050 1045 free(buffer); … … 1053 1048 } 1054 1049 1055 /** 1056 * IEEE 802.11 deauthentication implementation. 1057 * 1050 /** IEEE 802.11 deauthentication implementation. 1051 * 1058 1052 * Note: Expecting locked results_mutex or scan_mutex. 1059 * 1053 * 1060 1054 * @param ieee80211_dev Pointer to IEEE 802.11 device structure. 1061 * 1055 * 1062 1056 * @return EOK if succeed, negative error code otherwise. 1057 * 1063 1058 */ 1064 1059 int ieee80211_deauthenticate(ieee80211_dev_t *ieee80211_dev) 1065 1060 { 1066 1061 ieee80211_scan_result_t *auth_data = 1067 1062 &ieee80211_dev->bssid_info.res_link->scan_result; 1068 1063 1069 1064 nic_t *nic = nic_get_from_ddf_dev(ieee80211_dev->ddf_dev); … … 1071 1066 nic_query_address(nic, &nic_address); 1072 1067 1073 size_t buffer_size = sizeof(ieee80211_mgmt_header_t) + 1074 sizeof(ieee80211_deauth_body_t); 1068 size_t buffer_size = sizeof(ieee80211_mgmt_header_t) + 1069 sizeof(ieee80211_deauth_body_t); 1070 1075 1071 void *buffer = malloc(buffer_size); 1072 if (!buffer) 1073 return ENOMEM; 1074 1076 1075 memset(buffer, 0, buffer_size); 1077 1076 1078 ieee80211_mgmt_header_t *mgmt_header = 1079 (ieee80211_mgmt_header_t *) buffer; 1080 1081 mgmt_header->frame_ctrl = host2uint16_t_le( 1082 IEEE80211_MGMT_FRAME | 1083 IEEE80211_MGMT_DEAUTH_FRAME 1084 ); 1077 ieee80211_mgmt_header_t *mgmt_header = 1078 (ieee80211_mgmt_header_t *) buffer; 1079 1080 mgmt_header->frame_ctrl = 1081 host2uint16_t_le(IEEE80211_MGMT_FRAME | 1082 IEEE80211_MGMT_DEAUTH_FRAME); 1085 1083 memcpy(mgmt_header->dest_addr, auth_data->bssid.address, ETH_ADDR); 1086 1084 memcpy(mgmt_header->src_addr, nic_address.address, ETH_ADDR); … … 1094 1092 ieee80211_dev->ops->bssid_change(ieee80211_dev, false); 1095 1093 1096 if (ieee80211_query_using_key(ieee80211_dev))1094 if (ieee80211_query_using_key(ieee80211_dev)) 1097 1095 ieee80211_dev->ops->key_config(ieee80211_dev, NULL, false); 1098 1096 … … 1103 1101 1104 1102 static void ieee80211_process_auth_info(ieee80211_scan_result_link_t *ap_data, 1105 1103 void *buffer) 1106 1104 { 1107 1105 uint8_t *it = (uint8_t *) buffer; 1108 1106 1109 1107 uint16_t *version = (uint16_t *) it; 1110 if (uint16_t_le2host(*version) != 0x1) {1108 if (uint16_t_le2host(*version) != 0x1) { 1111 1109 ap_data->scan_result.security.type = -1; 1112 1110 return; … … 1115 1113 it += sizeof(uint16_t); 1116 1114 1117 uint32_t group_cipher = *(it +3);1118 switch (group_cipher) {1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 } 1130 1131 it += 4 *sizeof(uint8_t);1115 uint32_t group_cipher = *(it + 3); 1116 switch (group_cipher) { 1117 case IEEE80211_AUTH_CIPHER_TKIP: 1118 ap_data->scan_result.security.group_alg = 1119 IEEE80211_SECURITY_SUITE_TKIP; 1120 break; 1121 case IEEE80211_AUTH_CIPHER_CCMP: 1122 ap_data->scan_result.security.group_alg = 1123 IEEE80211_SECURITY_SUITE_CCMP; 1124 break; 1125 default: 1126 ap_data->scan_result.security.group_alg = -1; 1127 } 1128 1129 it += 4 * sizeof(uint8_t); 1132 1130 1133 1131 uint16_t *pairwise_count = (uint16_t *) it; 1134 uint32_t pairwise_cipher = *(it +sizeof(uint16_t)+3);1135 switch (pairwise_cipher) {1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 } 1147 1148 it += 2 *sizeof(uint16_t) +1149 uint16_t_le2host(*pairwise_count)*sizeof(uint32_t);1150 1151 uint32_t auth_suite = *(it +3);1152 switch (auth_suite) {1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1132 uint32_t pairwise_cipher = *(it + sizeof(uint16_t) + 3); 1133 switch (pairwise_cipher) { 1134 case IEEE80211_AUTH_CIPHER_TKIP: 1135 ap_data->scan_result.security.pair_alg = 1136 IEEE80211_SECURITY_SUITE_TKIP; 1137 break; 1138 case IEEE80211_AUTH_CIPHER_CCMP: 1139 ap_data->scan_result.security.pair_alg = 1140 IEEE80211_SECURITY_SUITE_CCMP; 1141 break; 1142 default: 1143 ap_data->scan_result.security.pair_alg = -1; 1144 } 1145 1146 it += 2 * sizeof(uint16_t) + 1147 uint16_t_le2host(*pairwise_count) * sizeof(uint32_t); 1148 1149 uint32_t auth_suite = *(it + 3); 1150 switch (auth_suite) { 1151 case IEEE80211_AUTH_AKM_PSK: 1152 ap_data->scan_result.security.auth = 1153 IEEE80211_SECURITY_AUTH_PSK; 1154 break; 1155 case IEEE80211_AUTH_AKM_8021X: 1156 ap_data->scan_result.security.auth = 1157 IEEE80211_SECURITY_AUTH_8021X; 1158 break; 1159 default: 1160 ap_data->scan_result.security.auth = -1; 1163 1161 } 1164 1162 } 1165 1163 1166 1164 static void copy_auth_ie(ieee80211_ie_header_t *ie_header, 1167 1168 { 1169 ap_data->auth_ie_len = ie_header->length + 1170 1165 ieee80211_scan_result_link_t *ap_data, void *it) 1166 { 1167 ap_data->auth_ie_len = ie_header->length + 1168 sizeof(ieee80211_ie_header_t); 1171 1169 1172 1170 memcpy(ap_data->auth_ie, it, ap_data->auth_ie_len); … … 1174 1172 1175 1173 static uint8_t *ieee80211_process_ies(ieee80211_dev_t *ieee80211_dev, 1176 1174 ieee80211_scan_result_link_t *ap_data, void *buffer, size_t buffer_size) 1177 1175 { 1178 1176 void *it = buffer; 1179 while ((it + sizeof(ieee80211_ie_header_t)) < buffer + buffer_size) {1180 ieee80211_ie_header_t *ie_header = 1181 1177 while ((it + sizeof(ieee80211_ie_header_t)) < buffer + buffer_size) { 1178 ieee80211_ie_header_t *ie_header = 1179 (ieee80211_ie_header_t *) it; 1182 1180 uint8_t *channel; 1183 1181 uint32_t oui; 1184 switch(ie_header->element_id) { 1185 case IEEE80211_CHANNEL_IE: 1186 if(!ap_data) 1182 1183 switch (ie_header->element_id) { 1184 case IEEE80211_CHANNEL_IE: 1185 if (!ap_data) 1186 break; 1187 1188 channel = (uint8_t *) 1189 (it + sizeof(ieee80211_ie_header_t)); 1190 ap_data->scan_result.channel = *channel; 1191 break; 1192 case IEEE80211_RSN_IE: 1193 if (!ap_data) 1194 break; 1195 1196 ap_data->scan_result.security.type = 1197 IEEE80211_SECURITY_WPA2; 1198 ieee80211_process_auth_info(ap_data, 1199 it + sizeof(ieee80211_ie_header_t)); 1200 copy_auth_ie(ie_header, ap_data, it); 1201 break; 1202 case IEEE80211_VENDOR_IE: 1203 oui = uint32be_from_seq(it + 1204 sizeof(ieee80211_ie_header_t)); 1205 1206 if (oui == WPA_OUI) { 1207 if (!ap_data) 1187 1208 break; 1188 channel = (uint8_t *) 1189 (it + sizeof(ieee80211_ie_header_t)); 1190 ap_data->scan_result.channel = *channel; 1191 break; 1192 case IEEE80211_RSN_IE: 1193 if(!ap_data) 1209 1210 /* Prefering WPA2. */ 1211 if (ap_data->scan_result.security.type == 1212 IEEE80211_SECURITY_WPA2) 1194 1213 break; 1214 1195 1215 ap_data->scan_result.security.type = 1196 IEEE80211_SECURITY_WPA2; 1197 ieee80211_process_auth_info(ap_data, 1198 it + sizeof(ieee80211_ie_header_t)); 1216 IEEE80211_SECURITY_WPA; 1217 1218 ieee80211_process_auth_info(ap_data, 1219 it + sizeof(ieee80211_ie_header_t) + 1220 sizeof(uint32_t)); 1199 1221 copy_auth_ie(ie_header, ap_data, it); 1200 break; 1201 case IEEE80211_VENDOR_IE: 1202 oui = uint32be_from_seq(it + 1203 sizeof(ieee80211_ie_header_t)); 1204 if(oui == WPA_OUI) { 1205 if(!ap_data) 1206 break; 1207 /* Prefering WPA2. */ 1208 if(ap_data->scan_result.security.type == 1209 IEEE80211_SECURITY_WPA2) { 1210 break; 1211 } 1212 ap_data->scan_result.security.type = 1213 IEEE80211_SECURITY_WPA; 1214 ieee80211_process_auth_info(ap_data, 1215 it + 1216 sizeof(ieee80211_ie_header_t) + 1217 sizeof(uint32_t)); 1218 copy_auth_ie(ie_header, ap_data, it); 1219 } else if(oui == GTK_OUI) { 1220 return it + 1221 sizeof(ieee80211_ie_header_t) + 1222 sizeof(uint32_t); 1223 } 1222 } else if (oui == GTK_OUI) { 1223 return it + 1224 sizeof(ieee80211_ie_header_t) + 1225 sizeof(uint32_t); 1226 } 1224 1227 } 1228 1225 1229 it += sizeof(ieee80211_ie_header_t) + ie_header->length; 1226 1230 } … … 1229 1233 } 1230 1234 1231 /** 1232 * Process probe response and store results. 1233 * 1235 /** Process probe response and store results. 1236 * 1234 1237 * @param ieee80211_dev Pointer to IEEE 802.11 device structure. 1235 * @param mgmt_header Pointer to start of management frame header.1236 * 1238 * @param mgmt_header Pointer to start of management frame header. 1239 * 1237 1240 * @return EOK if succeed, negative error code otherwise. 1238 */ 1239 static int ieee80211_process_probe_response(ieee80211_dev_t *ieee80211_dev, 1240 ieee80211_mgmt_header_t *mgmt_header, size_t buffer_size) 1241 { 1242 ieee80211_beacon_start_t *beacon_body = (ieee80211_beacon_start_t *) 1243 ((void *)mgmt_header + sizeof(ieee80211_mgmt_header_t)); 1244 1245 ieee80211_ie_header_t *ssid_ie_header = (ieee80211_ie_header_t *) 1246 ((void *)beacon_body + sizeof(ieee80211_beacon_start_t)); 1241 * 1242 */ 1243 static int ieee80211_process_probe_response(ieee80211_dev_t *ieee80211_dev, 1244 ieee80211_mgmt_header_t *mgmt_header, size_t buffer_size) 1245 { 1246 ieee80211_beacon_start_t *beacon_body = (ieee80211_beacon_start_t *) 1247 ((void *) mgmt_header + sizeof(ieee80211_mgmt_header_t)); 1248 1249 ieee80211_ie_header_t *ssid_ie_header = (ieee80211_ie_header_t *) 1250 ((void *) beacon_body + sizeof(ieee80211_beacon_start_t)); 1247 1251 1248 1252 /* Not empty SSID. */ 1249 if (ssid_ie_header->length > 0) {1253 if (ssid_ie_header->length > 0) { 1250 1254 ieee80211_scan_result_list_t *result_list = 1251 1252 1253 uint8_t *ssid_start = (uint8_t *) ((void *) ssid_ie_header +1254 1255 &ieee80211_dev->ap_list; 1256 1257 uint8_t *ssid_start = (uint8_t *) ((void *) ssid_ie_header + 1258 sizeof(ieee80211_ie_header_t)); 1255 1259 char ssid[IEEE80211_MAX_SSID_LENGTH]; 1260 1256 1261 memcpy(ssid, ssid_start, ssid_ie_header->length); 1257 1262 ssid[ssid_ie_header->length] = '\0'; … … 1259 1264 /* Check whether SSID is already in results. */ 1260 1265 ieee80211_scan_result_list_foreach(*result_list, result) { 1261 if (!str_cmp(ssid, result->scan_result.ssid)) {1266 if (!str_cmp(ssid, result->scan_result.ssid)) { 1262 1267 result->last_beacon = time(NULL); 1263 1268 return EOK; … … 1266 1271 1267 1272 /* Results are full. */ 1268 if (result_list->size == IEEE80211_MAX_RESULTS_LENGTH - 1) {1273 if (result_list->size == IEEE80211_MAX_RESULTS_LENGTH - 1) 1269 1274 return EOK; 1270 } 1271 1272 ieee80211_scan_result_link_t *ap_data = 1273 malloc(sizeof(ieee80211_scan_result_link_t)); 1275 1276 ieee80211_scan_result_link_t *ap_data = 1277 malloc(sizeof(ieee80211_scan_result_link_t)); 1278 if (!ap_data) 1279 return ENOMEM; 1280 1274 1281 memset(ap_data, 0, sizeof(ieee80211_scan_result_link_t)); 1275 1282 link_initialize(&ap_data->link); 1276 1283 1277 memcpy(ap_data->scan_result.bssid.address, 1278 1279 memcpy(ap_data->scan_result.ssid, ssid, 1280 1281 1282 if (uint16_t_le2host(beacon_body->capability) & CAP_SECURITY) {1283 ap_data->scan_result.security.type = 1284 1284 memcpy(ap_data->scan_result.bssid.address, 1285 mgmt_header->bssid, ETH_ADDR); 1286 memcpy(ap_data->scan_result.ssid, ssid, 1287 ssid_ie_header->length + 1); 1288 1289 if (uint16_t_le2host(beacon_body->capability) & CAP_SECURITY) { 1290 ap_data->scan_result.security.type = 1291 IEEE80211_SECURITY_WEP; 1285 1292 } else { 1286 ap_data->scan_result.security.type = 1287 1293 ap_data->scan_result.security.type = 1294 IEEE80211_SECURITY_OPEN; 1288 1295 ap_data->scan_result.security.auth = -1; 1289 1296 ap_data->scan_result.security.pair_alg = -1; … … 1292 1299 1293 1300 void *rest_ies_start = ssid_start + ssid_ie_header->length; 1294 size_t rest_buffer_size = 1295 buffer_size -1296 1297 1298 1299 1300 1301 ieee80211_process_ies(ieee80211_dev, ap_data, rest_ies_start, 1302 1301 size_t rest_buffer_size = 1302 buffer_size - 1303 sizeof(ieee80211_mgmt_header_t) - 1304 sizeof(ieee80211_beacon_start_t) - 1305 sizeof(ieee80211_ie_header_t) - 1306 ssid_ie_header->length; 1307 1308 ieee80211_process_ies(ieee80211_dev, ap_data, rest_ies_start, 1309 rest_buffer_size); 1303 1310 1304 1311 ap_data->last_beacon = time(NULL); … … 1312 1319 } 1313 1320 1314 /** 1315 * Process authentication response. 1316 * 1321 /** Process authentication response. 1322 * 1317 1323 * @param ieee80211_dev Pointer to IEEE 802.11 device structure. 1318 * @param mgmt_header Pointer to start of management frame header.1319 * 1324 * @param mgmt_header Pointer to start of management frame header. 1325 * 1320 1326 * @return EOK if succeed, negative error code otherwise. 1327 * 1321 1328 */ 1322 1329 static int ieee80211_process_auth_response(ieee80211_dev_t *ieee80211_dev, 1323 1330 ieee80211_mgmt_header_t *mgmt_header) 1324 1331 { 1325 1332 ieee80211_auth_body_t *auth_body = 1326 (ieee80211_auth_body_t *) 1327 ((void *)mgmt_header + sizeof(ieee80211_mgmt_header_t)); 1328 1329 if(auth_body->status != 0) { 1330 ieee80211_set_auth_phase(ieee80211_dev, 1331 IEEE80211_AUTH_DISCONNECTED); 1332 } else { 1333 ieee80211_set_auth_phase(ieee80211_dev, 1334 IEEE80211_AUTH_AUTHENTICATED); 1335 } 1333 (ieee80211_auth_body_t *) 1334 ((void *) mgmt_header + sizeof(ieee80211_mgmt_header_t)); 1335 1336 if (auth_body->status != 0) 1337 ieee80211_set_auth_phase(ieee80211_dev, 1338 IEEE80211_AUTH_DISCONNECTED); 1339 else 1340 ieee80211_set_auth_phase(ieee80211_dev, 1341 IEEE80211_AUTH_AUTHENTICATED); 1336 1342 1337 1343 fibril_mutex_lock(&ieee80211_dev->gen_mutex); … … 1342 1348 } 1343 1349 1344 /** 1345 * Process association response. 1346 * 1350 /** Process association response. 1351 * 1347 1352 * @param ieee80211_dev Pointer to IEEE 802.11 device structure. 1348 * @param mgmt_header Pointer to start of management frame header.1349 * 1353 * @param mgmt_header Pointer to start of management frame header. 1354 * 1350 1355 * @return EOK if succeed, negative error code otherwise. 1356 * 1351 1357 */ 1352 1358 static int ieee80211_process_assoc_response(ieee80211_dev_t *ieee80211_dev, 1353 1359 ieee80211_mgmt_header_t *mgmt_header) 1354 1360 { 1355 1361 ieee80211_assoc_resp_body_t *assoc_resp = 1356 (ieee80211_assoc_resp_body_t *) ((void *)mgmt_header +1357 1358 1359 if (assoc_resp->status != 0) {1360 ieee80211_set_auth_phase(ieee80211_dev, 1361 1362 }else {1363 ieee80211_dev->bssid_info.aid = 1364 1365 ieee80211_set_auth_phase(ieee80211_dev, 1366 1362 (ieee80211_assoc_resp_body_t *) ((void *) mgmt_header + 1363 sizeof(ieee80211_mgmt_header_t)); 1364 1365 if (assoc_resp->status != 0) 1366 ieee80211_set_auth_phase(ieee80211_dev, 1367 IEEE80211_AUTH_DISCONNECTED); 1368 else { 1369 ieee80211_dev->bssid_info.aid = 1370 uint16_t_le2host(assoc_resp->aid); 1371 ieee80211_set_auth_phase(ieee80211_dev, 1372 IEEE80211_AUTH_ASSOCIATED); 1367 1373 ieee80211_dev->ops->bssid_change(ieee80211_dev, true); 1368 1374 } … … 1376 1382 1377 1383 static int ieee80211_process_4way_handshake(ieee80211_dev_t *ieee80211_dev, 1378 1379 { 1380 ieee80211_eapol_key_frame_t *key_frame = 1381 1382 1383 ieee80211_scan_result_link_t *auth_link = 1384 1385 1384 void *buffer, size_t buffer_size) 1385 { 1386 ieee80211_eapol_key_frame_t *key_frame = 1387 (ieee80211_eapol_key_frame_t *) buffer; 1388 1389 ieee80211_scan_result_link_t *auth_link = 1390 ieee80211_dev->bssid_info.res_link; 1391 1386 1392 ieee80211_scan_result_t *auth_data = &auth_link->scan_result; 1387 1393 1388 1394 /* We don't support 802.1X authentication yet. */ 1389 if (auth_data->security.auth == IEEE80211_AUTH_AKM_8021X) {1395 if (auth_data->security.auth == IEEE80211_AUTH_AKM_8021X) 1390 1396 return ENOTSUP; 1391 }1392 1397 1393 1398 uint8_t *ptk = ieee80211_dev->bssid_info.ptk; 1394 1399 uint8_t *gtk = ieee80211_dev->bssid_info.gtk; 1395 1400 uint8_t gtk_id = 1; 1396 1401 1397 1402 bool handshake_done = false; 1398 1403 1399 bool old_wpa = 1400 1404 bool old_wpa = 1405 auth_data->security.type == IEEE80211_SECURITY_WPA; 1401 1406 1402 1407 bool key_phase = 1403 uint16_t_be2host(key_frame->key_info) &1404 1405 1406 bool final_phase = 1407 uint16_t_be2host(key_frame->key_info) &1408 1409 1410 bool ccmp_used = 1411 auth_data->security.pair_alg == IEEE80211_SECURITY_SUITE_CCMP||1412 auth_data->security.group_alg == IEEE80211_SECURITY_SUITE_CCMP;1408 uint16_t_be2host(key_frame->key_info) & 1409 IEEE80211_EAPOL_KEY_KEYINFO_MIC; 1410 1411 bool final_phase = 1412 uint16_t_be2host(key_frame->key_info) & 1413 IEEE80211_EAPOL_KEY_KEYINFO_SECURE; 1414 1415 bool ccmp_used = 1416 (auth_data->security.pair_alg == IEEE80211_SECURITY_SUITE_CCMP) || 1417 (auth_data->security.group_alg == IEEE80211_SECURITY_SUITE_CCMP); 1413 1418 1414 1419 size_t ptk_key_length, gtk_key_length; 1415 1420 hash_func_t mic_hash; 1416 if (ccmp_used) {1421 if (ccmp_used) 1417 1422 mic_hash = HASH_SHA1; 1418 } else {1423 else 1419 1424 mic_hash = HASH_MD5; 1420 } 1421 1422 if(auth_data->security.pair_alg == IEEE80211_SECURITY_SUITE_CCMP) { 1425 1426 if (auth_data->security.pair_alg == IEEE80211_SECURITY_SUITE_CCMP) 1423 1427 ptk_key_length = IEEE80211_PTK_CCMP_LENGTH; 1424 } else {1428 else 1425 1429 ptk_key_length = IEEE80211_PTK_TKIP_LENGTH; 1426 } 1427 1428 if(auth_data->security.group_alg == IEEE80211_SECURITY_SUITE_CCMP) { 1430 1431 if (auth_data->security.group_alg == IEEE80211_SECURITY_SUITE_CCMP) 1429 1432 gtk_key_length = IEEE80211_GTK_CCMP_LENGTH; 1430 } else {1433 else 1431 1434 gtk_key_length = IEEE80211_GTK_TKIP_LENGTH; 1432 } 1433 1434 size_t output_size = 1435 sizeof(eth_header_t) + 1436 sizeof(ieee80211_eapol_key_frame_t); 1437 1438 if(!(uint16_t_be2host(key_frame->key_info) & 1439 IEEE80211_EAPOL_KEY_KEYINFO_MIC)) { 1435 1436 size_t output_size = 1437 sizeof(eth_header_t) + 1438 sizeof(ieee80211_eapol_key_frame_t); 1439 1440 if (!(uint16_t_be2host(key_frame->key_info) & 1441 IEEE80211_EAPOL_KEY_KEYINFO_MIC)) 1440 1442 output_size += auth_link->auth_ie_len; 1441 } 1442 1443 1443 1444 nic_t *nic = nic_get_from_ddf_dev(ieee80211_dev->ddf_dev); 1444 1445 nic_address_t nic_address; 1445 1446 nic_query_address(nic, &nic_address); 1446 1447 1447 1448 void *output_buffer = malloc(output_size); 1449 if (!output_buffer) 1450 return ENOMEM; 1451 1448 1452 memset(output_buffer, 0, output_size); 1449 1453 1450 1454 /* Setup ethernet header. */ 1451 1455 eth_header_t *eth_header = (eth_header_t *) output_buffer; 1452 memcpy(eth_header->dest_addr, auth_data->bssid.address, 1456 memcpy(eth_header->dest_addr, auth_data->bssid.address, ETH_ADDR); 1453 1457 memcpy(eth_header->src_addr, nic_address.address, ETH_ADDR); 1454 1458 eth_header->proto = host2uint16_t_be(ETH_TYPE_PAE); 1455 1459 1456 1460 ieee80211_eapol_key_frame_t *output_key_frame = 1457 (ieee80211_eapol_key_frame_t *)1458 1459 1461 (ieee80211_eapol_key_frame_t *) 1462 (output_buffer + sizeof(eth_header_t)); 1463 1460 1464 /* Copy content of incoming EAPOL-Key frame. */ 1461 memcpy((void *) output_key_frame, buffer, 1462 1463 1465 memcpy((void *) output_key_frame, buffer, 1466 sizeof(ieee80211_eapol_key_frame_t)); 1467 1464 1468 output_key_frame->proto_version = 0x1; 1465 1469 output_key_frame->body_length = 1466 host2uint16_t_be(output_size - sizeof(eth_header_t) - 4); 1467 output_key_frame->key_info &= 1468 ~host2uint16_t_be( 1469 IEEE80211_EAPOL_KEY_KEYINFO_ACK 1470 ); 1471 1472 if(key_phase) { 1473 output_key_frame->key_info &= 1474 ~host2uint16_t_be( 1475 IEEE80211_EAPOL_KEY_KEYINFO_ENCDATA 1476 ); 1477 output_key_frame->key_info &= 1478 ~host2uint16_t_be( 1479 IEEE80211_EAPOL_KEY_KEYINFO_INSTALL 1480 ); 1470 host2uint16_t_be(output_size - sizeof(eth_header_t) - 4); 1471 output_key_frame->key_info &= 1472 ~host2uint16_t_be(IEEE80211_EAPOL_KEY_KEYINFO_ACK); 1473 1474 if (key_phase) { 1475 output_key_frame->key_info &= 1476 ~host2uint16_t_be(IEEE80211_EAPOL_KEY_KEYINFO_ENCDATA); 1477 output_key_frame->key_info &= 1478 ~host2uint16_t_be(IEEE80211_EAPOL_KEY_KEYINFO_INSTALL); 1481 1479 output_key_frame->key_data_length = 0; 1482 1480 memset(output_key_frame->key_nonce, 0, 32); … … 1484 1482 memset(output_key_frame->key_rsc, 0, 8); 1485 1483 memset(output_key_frame->eapol_key_iv, 0, 16); 1486 1484 1487 1485 /* Derive GTK and save it. */ 1488 if (final_phase) {1489 uint16_t key_data_length = 1490 1486 if (final_phase) { 1487 uint16_t key_data_length = 1488 uint16_t_be2host(key_frame->key_data_length); 1491 1489 uint8_t key_data[key_data_length]; 1492 uint8_t *data_ptr = (uint8_t *) (buffer +1493 1494 1490 uint8_t *data_ptr = (uint8_t *) 1491 (buffer + sizeof(ieee80211_eapol_key_frame_t)); 1492 1495 1493 int rc; 1496 1494 uint8_t work_key[32]; 1497 1498 if (ccmp_used) {1499 rc = ieee80211_aes_key_unwrap(ptk + KEK_OFFSET, 1500 1495 1496 if (ccmp_used) { 1497 rc = ieee80211_aes_key_unwrap(ptk + KEK_OFFSET, 1498 data_ptr, key_data_length, key_data); 1501 1499 } else { 1502 1500 memcpy(work_key, key_frame->eapol_key_iv, 16); 1503 1501 memcpy(work_key + 16, ptk + KEK_OFFSET, 16); 1504 rc = ieee80211_rc4_key_unwrap(work_key, 1505 1502 rc = ieee80211_rc4_key_unwrap(work_key, 1503 data_ptr, key_data_length, key_data); 1506 1504 } 1507 1505 1508 if (rc == EOK) {1506 if (rc == EOK) { 1509 1507 uint8_t *key_data_ptr = old_wpa ? key_data : 1510 1511 1512 1513 if (key_data_ptr) {1508 ieee80211_process_ies(ieee80211_dev, 1509 NULL, key_data, key_data_length); 1510 1511 if (key_data_ptr) { 1514 1512 uint8_t *key_ptr; 1515 if(old_wpa) { 1513 1514 if (old_wpa) 1516 1515 key_ptr = key_data_ptr; 1517 }else {1516 else { 1518 1517 gtk_id = *key_data_ptr & 0x3; 1519 1518 key_ptr = key_data_ptr + 2; 1520 1519 } 1521 1520 1522 1521 memcpy(gtk, key_ptr, gtk_key_length); 1523 1522 handshake_done = true; … … 1526 1525 } 1527 1526 } else { 1528 output_key_frame->key_info |= 1529 host2uint16_t_be( 1530 IEEE80211_EAPOL_KEY_KEYINFO_MIC 1531 ); 1527 output_key_frame->key_info |= 1528 host2uint16_t_be(IEEE80211_EAPOL_KEY_KEYINFO_MIC); 1532 1529 output_key_frame->key_data_length = 1533 host2uint16_t_be(auth_link->auth_ie_len); 1534 memcpy((void *)output_key_frame + 1535 sizeof(ieee80211_eapol_key_frame_t), 1536 auth_link->auth_ie, 1537 auth_link->auth_ie_len); 1538 1530 host2uint16_t_be(auth_link->auth_ie_len); 1531 memcpy((void *) output_key_frame + 1532 sizeof(ieee80211_eapol_key_frame_t), 1533 auth_link->auth_ie, auth_link->auth_ie_len); 1534 1539 1535 /* Compute PMK. */ 1540 1536 uint8_t pmk[PBKDF2_KEY_LENGTH]; 1541 1537 pbkdf2((uint8_t *) ieee80211_dev->bssid_info.password, 1542 1543 1544 1545 1538 str_size(ieee80211_dev->bssid_info.password), 1539 (uint8_t *) auth_data->ssid, 1540 str_size(auth_data->ssid), pmk); 1541 1546 1542 uint8_t *anonce = key_frame->key_nonce; 1547 1543 1548 1544 /* Generate SNONCE. */ 1549 1545 uint8_t snonce[32]; 1550 1546 rnd_sequence(snonce, 32); 1551 1547 1552 1548 memcpy(output_key_frame->key_nonce, snonce, 32); 1553 1549 1554 1550 uint8_t *dest_addr = eth_header->dest_addr; 1555 1551 uint8_t *src_addr = eth_header->src_addr; 1556 1552 1557 1553 /* Derive PTK and save it. */ 1558 1554 uint8_t crypt_data[PRF_CRYPT_DATA_LENGTH]; 1559 memcpy(crypt_data, 1560 min_sequence(dest_addr, src_addr, ETH_ADDR), 1561 ETH_ADDR); 1562 memcpy(crypt_data + ETH_ADDR, 1563 max_sequence(dest_addr, src_addr, ETH_ADDR), 1564 ETH_ADDR); 1565 memcpy(crypt_data + 2*ETH_ADDR, 1566 min_sequence(anonce, snonce, 32), 1567 32); 1568 memcpy(crypt_data + 2*ETH_ADDR + 32, 1569 max_sequence(anonce, snonce, 32), 1570 32); 1555 memcpy(crypt_data, 1556 min_sequence(dest_addr, src_addr, ETH_ADDR), ETH_ADDR); 1557 memcpy(crypt_data + ETH_ADDR, 1558 max_sequence(dest_addr, src_addr, ETH_ADDR), ETH_ADDR); 1559 memcpy(crypt_data + 2*ETH_ADDR, 1560 min_sequence(anonce, snonce, 32), 32); 1561 memcpy(crypt_data + 2*ETH_ADDR + 32, 1562 max_sequence(anonce, snonce, 32), 32); 1571 1563 ieee80211_prf(pmk, crypt_data, ptk, ptk_key_length); 1572 1564 } 1573 1565 1574 1566 /* Compute MIC of key frame data from KCK part of PTK. */ 1575 1567 uint8_t mic[mic_hash]; 1576 hmac(ptk, 16, (uint8_t *) output_key_frame, 1577 1578 1568 hmac(ptk, 16, (uint8_t *) output_key_frame, 1569 output_size - sizeof(eth_header_t), mic, mic_hash); 1570 1579 1571 memcpy(output_key_frame->key_mic, mic, 16); 1580 1572 1581 1573 ieee80211_send_frame(nic, output_buffer, output_size); 1582 1574 1583 1575 free(output_buffer); 1584 1576 1585 1577 ieee80211_key_config_t key_config; 1586 1578 1587 1579 /* Insert Pairwise key. */ 1588 if ((key_phase && old_wpa) || (final_phase && !old_wpa)) {1580 if ((key_phase && old_wpa) || (final_phase && !old_wpa)) { 1589 1581 key_config.suite = auth_data->security.pair_alg; 1590 1582 key_config.flags = 1591 IEEE80211_KEY_FLAG_TYPE_PAIRWISE; 1592 memcpy(key_config.data, 1593 ptk + TK_OFFSET, 1594 ptk_key_length - TK_OFFSET); 1595 1583 IEEE80211_KEY_FLAG_TYPE_PAIRWISE; 1584 memcpy(key_config.data, 1585 ptk + TK_OFFSET, ptk_key_length - TK_OFFSET); 1586 1596 1587 ieee80211_dev->ops->key_config(ieee80211_dev, 1597 1588 &key_config, true); 1598 1589 } 1599 1590 1600 1591 /* Insert Group key. */ 1601 if (final_phase) {1592 if (final_phase) { 1602 1593 key_config.id = gtk_id; 1603 1594 key_config.suite = auth_data->security.group_alg; 1604 key_config.flags = 1605 IEEE80211_KEY_FLAG_TYPE_GROUP; 1595 key_config.flags = IEEE80211_KEY_FLAG_TYPE_GROUP; 1606 1596 memcpy(key_config.data, gtk, gtk_key_length); 1607 1597 1608 1598 ieee80211_dev->ops->key_config(ieee80211_dev, 1609 1610 } 1611 1599 &key_config, true); 1600 } 1601 1612 1602 /* Signal successful handshake completion. */ 1613 if (handshake_done) {1603 if (handshake_done) { 1614 1604 fibril_mutex_lock(&ieee80211_dev->gen_mutex); 1615 1605 fibril_condvar_signal(&ieee80211_dev->gen_cond); … … 1621 1611 1622 1612 static int ieee80211_process_eapol_frame(ieee80211_dev_t *ieee80211_dev, 1623 void *buffer, size_t buffer_size) 1624 { 1625 ieee80211_eapol_key_frame_t *key_frame = 1626 (ieee80211_eapol_key_frame_t *) buffer; 1627 if(ieee80211_is_eapol_key_frame(key_frame)) { 1613 void *buffer, size_t buffer_size) 1614 { 1615 ieee80211_eapol_key_frame_t *key_frame = 1616 (ieee80211_eapol_key_frame_t *) buffer; 1617 1618 if (ieee80211_is_eapol_key_frame(key_frame)) 1628 1619 return ieee80211_process_4way_handshake(ieee80211_dev, buffer, 1629 buffer_size); 1630 } 1620 buffer_size); 1631 1621 1632 1622 return EOK; 1633 1623 } 1634 1624 1635 /** 1636 * Process data frame. 1637 * 1625 /** Process data frame. 1626 * 1638 1627 * @param ieee80211_dev Pointer to IEEE 802.11 device structure. 1639 * @param buffer Data buffer starting with IEEE 802.11 data header.1640 * @param buffer_size Size of buffer.1641 * 1628 * @param buffer Data buffer starting with IEEE 802.11 data header. 1629 * @param buffer_size Size of buffer. 1630 * 1642 1631 * @return EOK if succeed, negative error code otherwise. 1643 */ 1644 static int ieee80211_process_data(ieee80211_dev_t *ieee80211_dev, 1645 void *buffer, size_t buffer_size) 1646 { 1647 ieee80211_data_header_t *data_header = 1648 (ieee80211_data_header_t *) buffer; 1649 1650 if(ieee80211_has_data_frame(data_header->frame_ctrl)) { 1632 * 1633 */ 1634 static int ieee80211_process_data(ieee80211_dev_t *ieee80211_dev, 1635 void *buffer, size_t buffer_size) 1636 { 1637 ieee80211_data_header_t *data_header = 1638 (ieee80211_data_header_t *) buffer; 1639 1640 if (ieee80211_has_data_frame(data_header->frame_ctrl)) { 1651 1641 nic_t *nic = nic_get_from_ddf_dev(ieee80211_dev->ddf_dev); 1652 size_t strip_length = sizeof(ieee80211_data_header_t) + 1653 1642 size_t strip_length = sizeof(ieee80211_data_header_t) + 1643 ARRAY_SIZE(rfc1042_header); 1654 1644 1655 1645 /* TODO: Different by used security alg. */ 1656 1646 /* TODO: Trim frame by used security alg. */ 1657 1647 // TODO: Distinguish used key (pair/group) by dest address ? 1658 if (ieee80211_is_encrypted_frame(data_header->frame_ctrl)) {1648 if (ieee80211_is_encrypted_frame(data_header->frame_ctrl)) 1659 1649 strip_length += 8; 1660 }1661 1650 1662 1651 /* Process 4-way authentication handshake. */ 1663 1652 uint16_t *proto = (uint16_t *) (buffer + strip_length); 1664 if (uint16_t_be2host(*proto) == ETH_TYPE_PAE) {1653 if (uint16_t_be2host(*proto) == ETH_TYPE_PAE) 1665 1654 return ieee80211_process_eapol_frame(ieee80211_dev, 1666 buffer + strip_length + sizeof(uint16_t), 1667 buffer_size - strip_length - sizeof(uint16_t)); 1668 } 1669 1670 /* Note: ETH protocol ID is already there, so we don't create 1671 * whole ETH header. */ 1672 size_t frame_size = 1673 buffer_size - strip_length + sizeof(eth_header_t)-2; 1655 buffer + strip_length + sizeof(uint16_t), 1656 buffer_size - strip_length - sizeof(uint16_t)); 1657 1658 /* 1659 * Note: ETH protocol ID is already there, so we don't create 1660 * whole ETH header. 1661 */ 1662 size_t frame_size = 1663 buffer_size - strip_length + sizeof(eth_header_t) - 2; 1674 1664 nic_frame_t *frame = nic_alloc_frame(nic, frame_size); 1675 1676 if(frame == NULL) {1665 1666 if(frame == NULL) 1677 1667 return ENOMEM; 1678 } 1679 1680 uint8_t *src_addr = 1681 ieee80211_is_fromds_frame(data_header->frame_ctrl) ? 1682 data_header->address3 : data_header->address2; 1683 uint8_t *dest_addr = 1684 ieee80211_is_tods_frame(data_header->frame_ctrl) ? 1685 data_header->address3 : data_header->address1; 1686 1687 eth_header_t *eth_header = 1688 (eth_header_t *) frame->data; 1668 1669 uint8_t *src_addr = 1670 ieee80211_is_fromds_frame(data_header->frame_ctrl) ? 1671 data_header->address3 : data_header->address2; 1672 uint8_t *dest_addr = 1673 ieee80211_is_tods_frame(data_header->frame_ctrl) ? 1674 data_header->address3 : data_header->address1; 1675 1676 eth_header_t *eth_header = (eth_header_t *) frame->data; 1689 1677 memcpy(eth_header->src_addr, src_addr, ETH_ADDR); 1690 1678 memcpy(eth_header->dest_addr, dest_addr, ETH_ADDR); 1691 1692 memcpy(frame->data + sizeof(eth_header_t)-2, 1693 buffer + strip_length, 1694 buffer_size - strip_length); 1695 1679 1680 memcpy(frame->data + sizeof(eth_header_t) - 2, 1681 buffer + strip_length, buffer_size - strip_length); 1682 1696 1683 nic_received_frame(nic, frame); 1697 1684 } … … 1700 1687 } 1701 1688 1702 /** 1703 * IEEE 802.11 RX frames handler. 1704 * 1689 /** IEEE 802.11 RX frames handler. 1690 * 1705 1691 * @param ieee80211_dev Pointer to IEEE 802.11 device structure. 1706 * @param buffer Buffer with data.1707 * @param buffer_size Size of buffer.1708 * 1692 * @param buffer Buffer with data. 1693 * @param buffer_size Size of buffer. 1694 * 1709 1695 * @return EOK if succeed, negative error code otherwise. 1696 * 1710 1697 */ 1711 1698 int ieee80211_rx_handler(ieee80211_dev_t *ieee80211_dev, void *buffer, 1712 1699 size_t buffer_size) 1713 1700 { 1714 1701 uint16_t frame_ctrl = *((uint16_t *) buffer); 1715 if(ieee80211_is_mgmt_frame(frame_ctrl)) { 1702 1703 if (ieee80211_is_mgmt_frame(frame_ctrl)) { 1716 1704 ieee80211_mgmt_header_t *mgmt_header = 1717 1718 1719 if (ieee80211_is_probe_response_frame(mgmt_header->frame_ctrl) ||1720 ieee80211_is_beacon_frame(mgmt_header->frame_ctrl)) {1705 (ieee80211_mgmt_header_t *) buffer; 1706 1707 if ((ieee80211_is_probe_response_frame(mgmt_header->frame_ctrl)) || 1708 (ieee80211_is_beacon_frame(mgmt_header->frame_ctrl))) 1721 1709 return ieee80211_process_probe_response(ieee80211_dev, 1722 mgmt_header, buffer_size); 1723 } 1724 1725 if(ieee80211_is_auth_frame(mgmt_header->frame_ctrl)) { 1710 mgmt_header, buffer_size); 1711 1712 if (ieee80211_is_auth_frame(mgmt_header->frame_ctrl)) 1726 1713 return ieee80211_process_auth_response(ieee80211_dev, 1727 mgmt_header); 1728 } 1729 1730 if(ieee80211_is_assoc_response_frame(mgmt_header->frame_ctrl)) { 1714 mgmt_header); 1715 1716 if (ieee80211_is_assoc_response_frame(mgmt_header->frame_ctrl)) 1731 1717 return ieee80211_process_assoc_response(ieee80211_dev, 1732 mgmt_header); 1733 } 1734 } else if(ieee80211_is_data_frame(frame_ctrl)) { 1735 return ieee80211_process_data(ieee80211_dev, buffer, 1736 buffer_size); 1737 } 1718 mgmt_header); 1719 } else if (ieee80211_is_data_frame(frame_ctrl)) 1720 return ieee80211_process_data(ieee80211_dev, buffer, 1721 buffer_size); 1738 1722 1739 1723 return EOK;
Note:
See TracChangeset
for help on using the changeset viewer.