Changeset 1dcc0b9 in mainline
- Timestamp:
- 2015-04-06T10:47:51Z (10 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- d7dadcb4
- Parents:
- 59fa7ab
- Location:
- uspace
- Files:
-
- 4 added
- 25 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/Makefile
r59fa7ab r1dcc0b9 214 214 lib/fs \ 215 215 lib/block \ 216 lib/crypto \ 216 217 lib/clui \ 217 218 lib/fmtutil \ … … 245 246 lib/mbr \ 246 247 lib/gpt \ 247 lib/ieee80211 248 lib/ieee80211 \ 248 249 249 250 LIBC_BUILD = $(addsuffix .build,$(LIBC)) -
uspace/Makefile.common
r59fa7ab r1dcc0b9 120 120 LIBPOSIX_PREFIX = $(LIB_PREFIX)/posix 121 121 122 LIBCRYPTO_PREFIX = $(LIB_PREFIX)/crypto 122 123 LIBBLOCK_PREFIX = $(LIB_PREFIX)/block 123 124 LIBFS_PREFIX = $(LIB_PREFIX)/fs -
uspace/app/wifi_supplicant/wifi_supplicant.c
r59fa7ab r1dcc0b9 36 36 #include <ieee80211_iface.h> 37 37 38 #include <malloc.h>39 38 #include <errno.h> 40 39 #include <stdio.h> … … 42 41 43 42 #define NAME "wifi_supplicant" 43 44 #define enum_name(name_arr, i) ((i < 0) ? "NA" : name_arr[i]) 45 46 static const char* ieee80211_security_type_strs[] = { 47 "OPEN", "WEP", "WPA", "WPA2" 48 }; 49 50 static const char* ieee80211_security_alg_strs[] = { 51 "WEP40", "WEP104", "CCMP", "TKIP" 52 }; 53 54 static const char* ieee80211_security_auth_strs[] = { 55 "PSK", "8021X" 56 }; 44 57 45 58 static void print_syntax(void) … … 49 62 printf("\t<cmd> is:\n"); 50 63 printf("\tlist - list wifi devices in <index>: <name> format\n"); 51 printf("\tscan <index> - output scan results for given device\n"); 64 printf("\tscan <index> [-n] - output scan results (force scan " 65 "immediately)\n"); 66 printf("\tconnect <index> <ssid_prefix> [<password>] - connect to " 67 "network\n"); 68 printf("\tdisconnect <index> - disconnect from network\n"); 52 69 } 53 70 … … 98 115 } 99 116 100 if(i > count - 1) {117 if(i >= count) { 101 118 printf("Invalid wifi index.\n"); 102 119 free(wifis); … … 104 121 } 105 122 106 async_sess_t *sess = loc_service_connect(EXCHANGE_SERIALIZE, wifis[i], 0); 123 async_sess_t *sess = 124 loc_service_connect(EXCHANGE_SERIALIZE, wifis[i], 0); 107 125 if (sess == NULL) { 108 126 printf("Error connecting to service.\n"); … … 144 162 } 145 163 146 static int wifi_connect(uint32_t index, char *ssid , char *password)147 { 148 assert(ssid );164 static int wifi_connect(uint32_t index, char *ssid_start, char *password) 165 { 166 assert(ssid_start); 149 167 150 168 async_sess_t *sess = get_wifi_by_index(index); 151 169 if (sess == NULL) { 152 printf("Specified WIFI doesn't exist or cannot connect to it.\n"); 170 printf("Specified WIFI doesn't exist or cannot connect to " 171 "it.\n"); 153 172 return EINVAL; 154 173 } 155 174 156 int rc = ieee80211_connect(sess, ssid , password);175 int rc = ieee80211_connect(sess, ssid_start, password); 157 176 if(rc != EOK) { 158 printf("Failed connecting to network. Error: %d\n", rc); 159 return EINVAL; 160 } 161 162 printf("Successfully connected to %s!\n", ssid); 163 164 return EOK; 165 } 166 167 static int wifi_scan(uint32_t index) 168 { 169 ieee80211_scan_results_t scan_results; 170 177 if(rc == EREFUSED) { 178 printf("Device is not ready yet.\n"); 179 } else if(rc == ETIMEOUT) { 180 printf("Timeout when authenticating to network.\n"); 181 } else if(rc == EPERM) { 182 printf("Bad password provided.\n"); 183 } else { 184 printf("Error when connecting to network. " 185 "Error: %d\n", rc); 186 } 187 188 return rc; 189 } 190 191 printf("Successfully connected to network!\n"); 192 193 return EOK; 194 } 195 196 static int wifi_disconnect(uint32_t index) 197 { 171 198 async_sess_t *sess = get_wifi_by_index(index); 172 199 if (sess == NULL) { 173 printf("Specified WIFI doesn't exist or cannot connect to it.\n"); 200 printf("Specified WIFI doesn't exist or cannot connect to " 201 "it.\n"); 174 202 return EINVAL; 175 203 } 176 204 177 int rc = ieee80211_ get_scan_results(sess, &scan_results);205 int rc = ieee80211_disconnect(sess); 178 206 if(rc != EOK) { 179 printf("Failed to fetch scan results. Error: %d\n", rc); 207 if(rc == EREFUSED) { 208 printf("Device is not ready yet.\n"); 209 } else if(rc == EINVAL) { 210 printf("Not connected to any WiFi network.\n"); 211 } else { 212 printf("Error when disconnecting from network. " 213 "Error: %d\n", rc); 214 } 215 return rc; 216 } 217 218 printf("Successfully disconnected.\n"); 219 220 return EOK; 221 } 222 223 static int wifi_scan(uint32_t index, bool now) 224 { 225 ieee80211_scan_results_t scan_results; 226 227 async_sess_t *sess = get_wifi_by_index(index); 228 if (sess == NULL) { 229 printf("Specified WIFI doesn't exist or cannot connect to " 230 "it.\n"); 180 231 return EINVAL; 181 232 } 233 234 int rc = ieee80211_get_scan_results(sess, &scan_results, now); 235 if(rc != EOK) { 236 if(rc == EREFUSED) { 237 printf("Device is not ready yet.\n"); 238 } else { 239 printf("Failed to fetch scan results. Error: %d\n", rc); 240 } 241 242 return rc; 243 } 244 245 if(scan_results.length == 0) 246 return EOK; 247 248 printf("%16.16s %17s %4s %5s %5s %7s %7s\n", 249 "SSID", "MAC", "CHAN", "TYPE", "AUTH", "UNI-ALG", "GRP-ALG"); 182 250 183 251 for(int i = 0; i < scan_results.length; i++) { 184 252 ieee80211_scan_result_t result = scan_results.results[i]; 185 253 186 printf("SSID: %s, MAC addr: %s\n", result.ssid, 187 nic_addr_format(&result.bssid)); 254 printf("%16.16s %17s %4d %5s %5s %7s %7s\n", 255 result.ssid, 256 nic_addr_format(&result.bssid), 257 result.channel, 258 enum_name(ieee80211_security_type_strs, 259 result.security.type), 260 enum_name(ieee80211_security_auth_strs, 261 result.security.auth), 262 enum_name(ieee80211_security_alg_strs, 263 result.security.pair_alg), 264 enum_name(ieee80211_security_alg_strs, 265 result.security.group_alg) 266 ); 188 267 } 189 268 … … 197 276 198 277 if(argc == 2) { 199 if 278 if(!str_cmp(argv[1], "list")) { 200 279 return wifi_list(); 201 280 } 202 281 } else if(argc > 2) { 203 282 rc = str_uint32_t(argv[2], NULL, 10, false, &index); 204 if 283 if(rc != EOK) { 205 284 printf(NAME ": Invalid argument.\n"); 206 285 print_syntax(); 207 286 return EINVAL; 208 287 } 209 if (!str_cmp(argv[1], "scan")) { 210 return wifi_scan(index); 211 } else if (!str_cmp(argv[1], "connect")) { 288 if(!str_cmp(argv[1], "scan")) { 289 bool now = false; 290 if(argc > 3) 291 if(!str_cmp(argv[3], "-n")) 292 now = true; 293 return wifi_scan(index, now); 294 } else if(!str_cmp(argv[1], "connect")) { 212 295 char *pass = NULL; 213 296 if(argc > 3) { … … 216 299 return wifi_connect(index, argv[3], pass); 217 300 } 301 } else if(!str_cmp(argv[1], "disconnect")) { 302 return wifi_disconnect(index); 218 303 } 219 304 } -
uspace/drv/nic/ar9271/Makefile
r59fa7ab r1dcc0b9 34 34 $(LIBDRV_PREFIX)/libdrv.a \ 35 35 $(LIBNIC_PREFIX)/libnic.a \ 36 $(LIBIEEE80211_PREFIX)/libieee80211.a 36 $(LIBIEEE80211_PREFIX)/libieee80211.a \ 37 $(LIBCRYPTO_PREFIX)/libcrypto.a 37 38 38 39 EXTRA_CFLAGS += \ … … 43 44 -I$(LIBNIC_PREFIX)/include \ 44 45 -I$(LIBIEEE80211_PREFIX)/include \ 46 -I$(LIBCRYPTO_PREFIX) 45 47 46 48 BINARY = ar9271 -
uspace/drv/nic/ar9271/ar9271.c
r59fa7ab r1dcc0b9 105 105 static int ar9271_ieee80211_set_freq(ieee80211_dev_t *ieee80211_dev, 106 106 uint16_t freq); 107 static int ar9271_ieee80211_bssid_change(ieee80211_dev_t *ieee80211_dev); 108 static int ar9271_ieee80211_key_config(ieee80211_dev_t *ieee80211_dev, 109 ieee80211_key_config_t *key_conf, bool insert); 107 110 108 111 static driver_ops_t ar9271_driver_ops = { … … 118 121 .start = ar9271_ieee80211_start, 119 122 .tx_handler = ar9271_ieee80211_tx_handler, 120 .set_freq = ar9271_ieee80211_set_freq 123 .set_freq = ar9271_ieee80211_set_freq, 124 .bssid_change = ar9271_ieee80211_bssid_change, 125 .key_config = ar9271_ieee80211_key_config 121 126 }; 122 127 … … 186 191 * 187 192 */ 188 static int ar9271_on_multicast_mode_change(nic_t *nic, nic_multicast_mode_t mode,189 193 static int ar9271_on_multicast_mode_change(nic_t *nic, 194 nic_multicast_mode_t mode, const nic_address_t *addr, size_t addr_cnt) 190 195 { 191 196 /* … … 249 254 * 250 255 */ 251 static int ar9271_on_broadcast_mode_change(nic_t *nic, nic_broadcast_mode_t mode) 256 static int ar9271_on_broadcast_mode_change(nic_t *nic, 257 nic_broadcast_mode_t mode) 252 258 { 253 259 /* … … 271 277 } 272 278 279 static bool ar9271_rx_status_error(uint8_t status) 280 { 281 return (status & AR9271_RX_ERROR_PHY) || (status & AR9271_RX_ERROR_CRC); 282 } 283 273 284 static int ar9271_data_polling(void *arg) 274 285 { 286 assert(arg); 287 275 288 ar9271_t *ar9271 = (ar9271_t *) arg; 276 289 … … 282 295 if(htc_read_data_message(ar9271->htc_device, 283 296 buffer, buffer_size, &transferred_size) == EOK) { 284 ath_usb_data_header_t *data_header =285 (ath_usb_data_header_t *) buffer;286 287 /* Invalid packet. */288 if(data_header->tag != uint16_t_le2host(RX_TAG)) {289 continue;290 }291 292 297 size_t strip_length = 293 298 sizeof(ath_usb_data_header_t) + 294 299 sizeof(htc_frame_header_t) + 295 HTC_RX_HEADER_LENGTH;300 sizeof(htc_rx_status_t); 296 301 297 /* TODO: RX header inspection. */ 302 if(transferred_size < strip_length) 303 continue; 304 305 ath_usb_data_header_t *data_header = 306 (ath_usb_data_header_t *) buffer; 307 308 /* Invalid packet. */ 309 if(data_header->tag != uint16_t_le2host(RX_TAG)) 310 continue; 311 312 htc_rx_status_t *rx_status = 313 (htc_rx_status_t *) ((void *) buffer + 314 sizeof(ath_usb_data_header_t) + 315 sizeof(htc_frame_header_t)); 316 317 uint16_t data_length = 318 uint16_t_be2host(rx_status->data_length); 319 320 int16_t payload_length = 321 transferred_size - strip_length; 322 323 if(payload_length - data_length < 0) 324 continue; 325 326 if(ar9271_rx_status_error(rx_status->status)) 327 continue; 328 298 329 void *strip_buffer = buffer + strip_length; 299 330 300 331 ieee80211_rx_handler(ar9271->ieee80211_dev, 301 332 strip_buffer, 302 transferred_size - strip_length);333 payload_length); 303 334 } 304 335 } … … 316 347 uint16_t freq) 317 348 { 349 assert(ieee80211_dev); 350 318 351 ar9271_t *ar9271 = (ar9271_t *) ieee80211_get_specific(ieee80211_dev); 352 353 //hw_wakeup(ar9271); 319 354 320 355 wmi_send_command(ar9271->htc_device, WMI_DISABLE_INTR, NULL, 0, NULL); … … 344 379 } 345 380 381 static int ar9271_ieee80211_bssid_change(ieee80211_dev_t *ieee80211_dev) 382 { 383 assert(ieee80211_dev); 384 385 ar9271_t *ar9271 = (ar9271_t *) ieee80211_get_specific(ieee80211_dev); 386 387 /* Check if we are connected or disconnected. */ 388 if(ieee80211_is_connected(ieee80211_dev)) { 389 nic_address_t bssid; 390 ieee80211_query_bssid(ieee80211_dev, &bssid); 391 392 htc_sta_msg_t sta_msg; 393 memset(&sta_msg, 0, sizeof(htc_sta_msg_t)); 394 sta_msg.is_vif_sta = 0; 395 sta_msg.max_ampdu = 396 host2uint16_t_be(1 << IEEE80211_MAX_AMPDU_FACTOR); 397 sta_msg.sta_index = 1; 398 sta_msg.vif_index = 0; 399 memcpy(&sta_msg.addr, bssid.address, ETH_ADDR); 400 401 wmi_send_command(ar9271->htc_device, WMI_NODE_CREATE, 402 (uint8_t *) &sta_msg, sizeof(sta_msg), NULL); 403 404 htc_rate_msg_t rate_msg; 405 memset(&rate_msg, 0, sizeof(htc_rate_msg_t)); 406 rate_msg.sta_index = 1; 407 rate_msg.is_new = 1; 408 rate_msg.legacy_rates_count = 409 ARRAY_SIZE(ieee80211bg_data_rates); 410 memcpy(&rate_msg.legacy_rates, 411 ieee80211bg_data_rates, 412 ARRAY_SIZE(ieee80211bg_data_rates)); 413 414 wmi_send_command(ar9271->htc_device, WMI_RC_RATE_UPDATE, 415 (uint8_t *) &rate_msg, sizeof(rate_msg), NULL); 416 417 hw_set_rx_filter(ar9271, true); 418 } else { 419 uint8_t station_id = 1; 420 wmi_send_command(ar9271->htc_device, WMI_NODE_REMOVE, 421 &station_id, sizeof(station_id), NULL); 422 423 hw_set_rx_filter(ar9271, false); 424 } 425 426 hw_set_bssid(ar9271); 427 428 return EOK; 429 } 430 431 static int ar9271_ieee80211_key_config(ieee80211_dev_t *ieee80211_dev, 432 ieee80211_key_config_t *key_conf, bool insert) 433 { 434 assert(ieee80211_dev); 435 assert(key_conf); 436 437 ar9271_t *ar9271 = (ar9271_t *) ieee80211_get_specific(ieee80211_dev); 438 439 uint32_t key[5]; 440 uint32_t key_type; 441 uint32_t reg_ptr; 442 void *data_start; 443 444 if(insert) { 445 nic_address_t bssid; 446 ieee80211_query_bssid(ieee80211_dev, &bssid); 447 448 switch(key_conf->suite) { 449 case IEEE80211_SECURITY_SUITE_WEP40: 450 key_type = AR9271_KEY_TABLE_TYPE_WEP40; 451 break; 452 case IEEE80211_SECURITY_SUITE_WEP104: 453 key_type = AR9271_KEY_TABLE_TYPE_WEP104; 454 break; 455 case IEEE80211_SECURITY_SUITE_TKIP: 456 key_type = AR9271_KEY_TABLE_TYPE_TKIP; 457 break; 458 case IEEE80211_SECURITY_SUITE_CCMP: 459 key_type = AR9271_KEY_TABLE_TYPE_CCMP; 460 break; 461 default: 462 key_type = -1; 463 } 464 465 if(key_conf->flags & IEEE80211_KEY_FLAG_TYPE_PAIRWISE) { 466 reg_ptr = AR9271_KEY_TABLE_STA; 467 } else { 468 reg_ptr = AR9271_KEY_TABLE_GRP; 469 } 470 471 if(key_conf->suite == IEEE80211_SECURITY_SUITE_TKIP) { 472 // TODO 473 } else { 474 data_start = (void *) key_conf->data; 475 476 key[0] = uint32_t_le2host( 477 *((uint32_t *) data_start)); 478 key[1] = uint16_t_le2host( 479 *((uint16_t *) (data_start + 4))); 480 key[2] = uint32_t_le2host( 481 *((uint32_t *) (data_start + 6))); 482 key[3] = uint16_t_le2host( 483 *((uint16_t *) (data_start + 10))); 484 key[4] = uint32_t_le2host( 485 *((uint32_t *) (data_start + 12))); 486 487 if(key_conf->suite == IEEE80211_SECURITY_SUITE_WEP40 || 488 key_conf->suite == IEEE80211_SECURITY_SUITE_WEP104) { 489 key[4] &= 0xFF; 490 } 491 492 wmi_reg_write(ar9271->htc_device, reg_ptr + 0, key[0]); 493 wmi_reg_write(ar9271->htc_device, reg_ptr + 4, key[1]); 494 wmi_reg_write(ar9271->htc_device, reg_ptr + 8, key[2]); 495 wmi_reg_write(ar9271->htc_device, reg_ptr + 12, key[3]); 496 wmi_reg_write(ar9271->htc_device, reg_ptr + 16, key[4]); 497 wmi_reg_write(ar9271->htc_device, reg_ptr + 20, 498 key_type); 499 } 500 501 uint32_t macL, macH; 502 if(key_conf->flags & IEEE80211_KEY_FLAG_TYPE_PAIRWISE) { 503 data_start = (void *) bssid.address; 504 macL = uint32_t_le2host(*((uint32_t *) data_start)); 505 macH = uint16_t_le2host(*((uint16_t *) 506 (data_start + 4))); 507 } else { 508 macL = macH = 0; 509 } 510 511 macL >>= 1; 512 macL |= (macH & 1) << 31; 513 macH >>= 1; 514 macH |= 0x8000; 515 516 wmi_reg_write(ar9271->htc_device, reg_ptr + 24, macL); 517 wmi_reg_write(ar9271->htc_device, reg_ptr + 28, macH); 518 519 if(key_conf->flags & IEEE80211_KEY_FLAG_TYPE_GROUP) 520 ieee80211_setup_key_confirm(ieee80211_dev, true); 521 } else { 522 // TODO 523 } 524 525 return EOK; 526 } 527 346 528 static int ar9271_ieee80211_tx_handler(ieee80211_dev_t *ieee80211_dev, 347 529 void *buffer, size_t buffer_size) 348 530 { 531 assert(ieee80211_dev); 532 349 533 size_t complete_size, offset; 350 534 void *complete_buffer; … … 355 539 uint16_t frame_ctrl = *((uint16_t *) buffer); 356 540 if(ieee80211_is_data_frame(frame_ctrl)) { 357 offset = sizeof(htc_frame_header_t); 541 offset = sizeof(htc_tx_data_header_t) + 542 sizeof(htc_frame_header_t); 358 543 complete_size = buffer_size + offset; 359 544 complete_buffer = malloc(complete_size); 545 memset(complete_buffer, 0, complete_size); 546 547 /* 548 * Because we handle just station mode yet, node ID and VIF ID 549 * are fixed. 550 */ 551 htc_tx_data_header_t *data_header = 552 (htc_tx_data_header_t *) 553 (complete_buffer + sizeof(htc_frame_header_t)); 554 /* TODO: Distinguish data type. */ 555 data_header->data_type = HTC_DATA_NORMAL; 556 data_header->node_idx = 1; 557 data_header->vif_idx = 0; 558 /* TODO: There I should probably handle slot number. */ 559 data_header->cookie = 0; 560 561 if(ieee80211_query_using_key(ieee80211_dev)) { 562 data_header->keyix = AR9271_STA_KEY_INDEX; 563 int sec_suite = 564 ieee80211_get_security_suite(ieee80211_dev); 565 switch(sec_suite) { 566 case IEEE80211_SECURITY_SUITE_WEP40: 567 case IEEE80211_SECURITY_SUITE_WEP104: 568 data_header->key_type = 569 AR9271_KEY_TYPE_WEP; 570 break; 571 case IEEE80211_SECURITY_SUITE_TKIP: 572 data_header->key_type = 573 AR9271_KEY_TYPE_TKIP; 574 break; 575 case IEEE80211_SECURITY_SUITE_CCMP: 576 data_header->key_type = 577 AR9271_KEY_TYPE_AES; 578 break; 579 } 580 } else { 581 data_header->key_type = 0; 582 data_header->keyix = 0xFF; 583 } 584 360 585 endpoint = ar9271->htc_device->endpoints.data_be_endpoint; 361 586 } else { … … 366 591 memset(complete_buffer, 0, complete_size); 367 592 593 /* 594 * Because we handle just station mode yet, node ID and VIF ID 595 * are fixed. 596 */ 368 597 htc_tx_management_header_t *mgmt_header = 369 598 (htc_tx_management_header_t *) 370 599 (complete_buffer + sizeof(htc_frame_header_t)); 600 mgmt_header->node_idx = 0; 601 mgmt_header->vif_idx = 0; 602 /* TODO: There I should probably handle slot number. */ 603 mgmt_header->cookie = 0; 371 604 mgmt_header->keyix = 0xFF; 372 605 … … 387 620 static int ar9271_ieee80211_start(ieee80211_dev_t *ieee80211_dev) 388 621 { 622 assert(ieee80211_dev); 623 389 624 ar9271_t *ar9271 = (ar9271_t *) ieee80211_get_specific(ieee80211_dev); 390 625 … … 434 669 435 670 ar9271->starting_up = false; 671 ieee80211_set_ready(ieee80211_dev, true); 672 673 usb_log_info("Device fully initialized.\n"); 436 674 437 675 return EOK; -
uspace/drv/nic/ar9271/ar9271.h
r59fa7ab r1dcc0b9 46 46 #define AR9271_LED_PIN 15 47 47 48 /** Nominal value for AR9271 noise floor calibration. */ 49 #define AR9271_CALIB_NOMINAL_VALUE_2GHZ -118 50 51 /** RX errors values. */ 52 #define AR9271_RX_ERROR_CRC 0x01 53 #define AR9271_RX_ERROR_PHY 0x02 54 55 /** Key index used for device in station mode. */ 56 #define AR9271_STA_KEY_INDEX 4 57 58 /* HW encryption key indicator. */ 59 enum ath9k_key_type { 60 AR9271_KEY_TYPE_CLEAR, 61 AR9271_KEY_TYPE_WEP, 62 AR9271_KEY_TYPE_AES, 63 AR9271_KEY_TYPE_TKIP, 64 }; 65 48 66 /** AR9271 Registers */ 49 67 typedef enum { … … 75 93 AR9271_GPIO_OUT_MUX_AS_OUT = 0x0, /**< GPIO set mux as output */ 76 94 77 /* Wakeuprelated registers */95 /* RTC related registers */ 78 96 AR9271_RTC_RC = 0x7000, 79 97 AR9271_RTC_RC_MAC_WARM = 0x00000001, … … 86 104 AR9271_RTC_STATUS_SHUTDOWN = 0x00000001, 87 105 AR9271_RTC_STATUS_ON = 0x00000002, 106 AR9271_RTC_SLEEP_CLOCK = 0x7048, 107 AR9271_RTC_SLEEP_CLOCK_FORCE_DERIVED = 0x2, 88 108 AR9271_RTC_FORCE_WAKE = 0x704C, 89 109 AR9271_RTC_FORCE_WAKE_ENABLE = 0x00000001, … … 93 113 AR9271_STATION_ID0 = 0x8000, /**< STA Address Lower 32 Bits */ 94 114 AR9271_STATION_ID1 = 0x8004, /**< STA Address Upper 16 Bits */ 95 AR9271_BSSID0 = 0x8008, 96 AR9271_BSSID1 = 0x800C, 97 AR9271_BSSID_MASK0 = 0x80E0, 98 AR9271_BSSID_MASK1 = 0x80E4, 115 AR9271_BSSID0 = 0x8008, /**< BSSID Lower 32 Bits */ 116 AR9271_BSSID1 = 0x800C, /**< BSSID Upper 16 Bits */ 117 AR9271_BSSID_MASK0 = 0x80E0, /**< BSSID Mask Lower 32 Bits */ 118 AR9271_BSSID_MASK1 = 0x80E4, /**< BSSID Mask Upper 16 Bits */ 99 119 AR9271_STATION_ID1_MASK = 0x0000FFFF, 100 120 AR9271_STATION_ID1_POWER_SAVING = 0x00040000, 121 AR9271_MULTICAST_FILTER1 = 0x8040, 122 AR9271_MULTICAST_FILTER2 = 0x8044, 123 AR9271_DIAG = 0x8048, 101 124 102 125 /* RX filtering register */ … … 110 133 AR9271_RX_FILTER_PROBEREQ = 0x00000080, 111 134 AR9271_RX_FILTER_MYBEACON = 0x00000200, 112 AR9271_MULTICAST_FILTER1 = 0x8040, 113 AR9271_MULTICAST_FILTER2 = 0x8044, 114 AR9271_DIAG = 0x8048, 135 AR9271_RX_FILTER_MCAST_BCAST_ALL = 0x00008000, 136 137 /* Key related registers */ 138 AR9271_KEY_TABLE_GRP = 0x8820, 139 AR9271_KEY_TABLE_STA = 0x8880, 140 AR9271_KEY_TABLE_TYPE_WEP40 = 0x0, 141 AR9271_KEY_TABLE_TYPE_WEP104 = 0x1, 142 AR9271_KEY_TABLE_TYPE_TKIP = 0x4, 143 AR9271_KEY_TABLE_TYPE_CCMP = 0x6, 115 144 116 145 /* Physical layer registers */ … … 118 147 AR9271_ADC_CONTROL = 0x982C, 119 148 AR9271_AGC_CONTROL = 0x9860, 149 AR9271_PHY_CAL = 0x9864, 120 150 AR9271_PHY_SYNTH_CONTROL = 0x9874, 121 151 AR9271_PHY_SPECTRAL_SCAN = 0x9910, -
uspace/drv/nic/ar9271/ath_usb.h
r59fa7ab r1dcc0b9 57 57 typedef struct { 58 58 uint16_t length; /**< Little Endian value! */ 59 uint16_t tag; /**< Little Endian value! */59 uint16_t tag; /**< Little Endian value! */ 60 60 } ath_usb_data_header_t; 61 61 -
uspace/drv/nic/ar9271/htc.c
r59fa7ab r1dcc0b9 75 75 76 76 nic_address_t addr; 77 nic_t *nic = nic_get_from_ddf_dev(ieee80211_get_ddf_dev(htc_device->ieee80211_dev)); 77 nic_t *nic = 78 nic_get_from_ddf_dev( 79 ieee80211_get_ddf_dev(htc_device->ieee80211_dev) 80 ); 78 81 nic_query_address(nic, &addr); 79 82 … … 128 131 wmi_reg_write(htc_device, AR9271_STATION_ID1, id1); 129 132 130 /* TODO: Set BSSID mask for AP mode. */131 132 133 return EOK; 133 134 } -
uspace/drv/nic/ar9271/htc.h
r59fa7ab r1dcc0b9 45 45 46 46 #define HTC_RTS_THRESHOLD 2304 47 #define HTC_R X_HEADER_LENGTH 4048 49 /** 50 * HTC message IDs 47 #define HTC_RATES_MAX_LENGTH 30 48 49 /** 50 * HTC message IDs. 51 51 */ 52 52 typedef enum { … … 59 59 60 60 /** 61 * HTC response message status codes 61 * HTC response message status codes. 62 62 */ 63 63 typedef enum { … … 70 70 71 71 /** 72 * HTC operating mode definition 72 * HTC operating mode definition. 73 73 */ 74 74 typedef enum { … … 80 80 81 81 /** 82 * HTC endpoint numbers 82 * HTC data type indicator. 83 */ 84 typedef enum { 85 HTC_DATA_AMPDU = 1, 86 HTC_DATA_NORMAL = 2, 87 HTC_DATA_BEACON = 3, 88 HTC_DATA_MGMT = 4 89 } htc_data_type_t; 90 91 /** 92 * HTC endpoint numbers. 83 93 */ 84 94 typedef struct { … … 96 106 97 107 /** 98 * HTC device data 108 * HTC device data. 99 109 */ 100 110 typedef struct { … … 119 129 120 130 /** 121 * HTC frame header structure 131 * HTC frame header structure. 122 132 */ 123 133 typedef struct { … … 126 136 uint16_t payload_length; /**< Big Endian value! */ 127 137 uint8_t control_bytes[4]; 128 129 /* Message payload starts after the header. */130 138 } __attribute__((packed)) htc_frame_header_t; 131 139 132 140 /** 133 * HTC management TX frame header structure 141 * HTC management TX frame header structure. 134 142 */ 135 143 typedef struct { … … 145 153 146 154 /** 147 * HTC ready message structure 155 * HTC data TX frame header structure. 156 */ 157 typedef struct { 158 uint8_t data_type; 159 uint8_t node_idx; 160 uint8_t vif_idx; 161 uint8_t tidno; 162 uint32_t flags; /**< Big Endian value! */ 163 uint8_t key_type; 164 uint8_t keyix; 165 uint8_t cookie; 166 uint8_t pad; 167 } __attribute__((packed)) htc_tx_data_header_t; 168 169 /** 170 * HTC ready message structure. 148 171 */ 149 172 typedef struct { … … 157 180 158 181 /** 159 * HTC service message structure 182 * HTC service message structure. 160 183 */ 161 184 typedef struct { … … 171 194 172 195 /** 173 * HTC service response message structure 196 * HTC service response message structure. 174 197 */ 175 198 typedef struct { … … 184 207 185 208 /** 186 * HTC credits config message structure 209 * HTC credits config message structure. 187 210 */ 188 211 typedef struct { … … 193 216 194 217 /** 195 * HTC new virtual interface message 218 * HTC new virtual interface message. 196 219 */ 197 220 typedef struct { … … 205 228 206 229 /** 207 * HTC new station message 230 * HTC new station message. 208 231 */ 209 232 typedef struct { … … 231 254 uint8_t pad; 232 255 } __attribute__((packed)) htc_cap_msg_t; 256 257 typedef struct { 258 uint8_t sta_index; 259 uint8_t is_new; 260 uint32_t cap_flags; /**< Big Endian value! */ 261 uint8_t legacy_rates_count; 262 uint8_t legacy_rates[HTC_RATES_MAX_LENGTH]; 263 uint16_t pad; 264 } htc_rate_msg_t; 265 266 /** 267 * HTC RX status structure used in incoming HTC data messages. 268 */ 269 typedef struct { 270 uint64_t timestamp; /**< Big Endian value! */ 271 uint16_t data_length; /**< Big Endian value! */ 272 uint8_t status; 273 uint8_t phy_err; 274 int8_t rssi; 275 int8_t rssi_ctl[3]; 276 int8_t rssi_ext[3]; 277 uint8_t keyix; 278 uint8_t rate; 279 uint8_t antenna; 280 uint8_t more; 281 uint8_t is_aggr; 282 uint8_t more_aggr; 283 uint8_t num_delims; 284 uint8_t flags; 285 uint8_t dummy; 286 uint32_t evm0; /**< Big Endian value! */ 287 uint32_t evm1; /**< Big Endian value! */ 288 uint32_t evm2; /**< Big Endian value! */ 289 } htc_rx_status_t; 233 290 234 291 /** -
uspace/drv/nic/ar9271/hw.c
r59fa7ab r1dcc0b9 43 43 44 44 /** 45 * Try to wait for register value repeatedly until timeout defined by device 46 * is reached. 45 * Try to wait for register value repeatedly until timeout is reached. 47 46 * 48 47 * @param ar9271 Device structure. … … 264 263 } 265 264 265 static int hw_activate_phy(ar9271_t *ar9271) 266 { 267 wmi_reg_write(ar9271->htc_device, AR9271_PHY_ACTIVE, 1); 268 udelay(1000); 269 270 return EOK; 271 } 272 266 273 static int hw_set_operating_mode(ar9271_t *ar9271, 267 274 ieee80211_operating_mode_t op_mode) … … 305 312 static int hw_noise_floor_calibration(ar9271_t *ar9271) 306 313 { 314 uint32_t value; 315 wmi_reg_read(ar9271->htc_device, AR9271_PHY_CAL, &value); 316 value &= 0xFFFFFE00; 317 value |= (((uint32_t) AR9271_CALIB_NOMINAL_VALUE_2GHZ << 1) & 0x1FF); 318 wmi_reg_write(ar9271->htc_device, AR9271_PHY_CAL, value); 319 320 wmi_reg_clear_bit(ar9271->htc_device, AR9271_AGC_CONTROL, 321 AR9271_AGC_CONTROL_NF_CALIB_EN); 322 323 wmi_reg_clear_bit(ar9271->htc_device, AR9271_AGC_CONTROL, 324 AR9271_AGC_CONTROL_NF_NOT_UPDATE); 325 326 wmi_reg_set_bit(ar9271->htc_device, AR9271_AGC_CONTROL, 327 AR9271_AGC_CONTROL_NF_CALIB); 328 329 int rc = hw_read_wait(ar9271, AR9271_AGC_CONTROL, 330 AR9271_AGC_CONTROL_NF_CALIB, 0); 331 if(rc != EOK) { 332 usb_log_error("Failed to wait for NF calibration.\n"); 333 return rc; 334 } 335 307 336 wmi_reg_set_bit(ar9271->htc_device, AR9271_AGC_CONTROL, 308 337 AR9271_AGC_CONTROL_NF_CALIB_EN); … … 348 377 } 349 378 379 int hw_wakeup(ar9271_t *ar9271) 380 { 381 int rc; 382 383 uint32_t rtc_status; 384 wmi_reg_read(ar9271->htc_device, AR9271_RTC_STATUS, &rtc_status); 385 if((rtc_status & AR9271_RTC_STATUS_MASK) == AR9271_RTC_STATUS_SHUTDOWN) { 386 rc = hw_reset_power_on(ar9271); 387 if(rc != EOK) { 388 usb_log_info("Failed to HW reset power on.\n"); 389 return rc; 390 } 391 392 rc = hw_set_reset(ar9271, false); 393 if(rc != EOK) { 394 usb_log_info("Failed to HW warm reset.\n"); 395 return rc; 396 } 397 } 398 399 wmi_reg_set_bit(ar9271->htc_device, AR9271_RTC_FORCE_WAKE, 400 AR9271_RTC_FORCE_WAKE_ENABLE); 401 402 size_t i; 403 for(i = 0; i < HW_WAIT_LOOPS; i++) { 404 wmi_reg_read(ar9271->htc_device, AR9271_RTC_STATUS, 405 &rtc_status); 406 if((rtc_status & AR9271_RTC_STATUS_MASK) == 407 AR9271_RTC_STATUS_ON) { 408 break; 409 } 410 wmi_reg_set_bit(ar9271->htc_device, AR9271_RTC_FORCE_WAKE, 411 AR9271_RTC_FORCE_WAKE_ENABLE); 412 udelay(50); 413 } 414 415 if(i == HW_WAIT_LOOPS) { 416 return EINVAL; 417 } else { 418 return EOK; 419 } 420 } 421 350 422 int hw_freq_switch(ar9271_t *ar9271, uint16_t freq) 351 423 { … … 361 433 if(rc != EOK) { 362 434 usb_log_error("Failed to HW set frequency.\n"); 435 return rc; 436 } 437 438 rc = hw_activate_phy(ar9271); 439 if(rc != EOK) { 440 usb_log_error("Failed to activate physical layer.\n"); 363 441 return rc; 364 442 } … … 376 454 } 377 455 378 static int hw_set_rx_filter(ar9271_t *ar9271)456 int hw_set_rx_filter(ar9271_t *ar9271, bool assoc) 379 457 { 380 458 uint32_t filter_bits; 381 459 382 /* TODO: Do proper filtering here. */ 460 uint32_t additional_bits = 0; 461 462 if(assoc) { 463 additional_bits |= AR9271_RX_FILTER_MYBEACON; 464 } else { 465 additional_bits |= AR9271_RX_FILTER_BEACON; 466 } 383 467 384 468 filter_bits = AR9271_RX_FILTER_UNI | AR9271_RX_FILTER_MULTI | 385 AR9271_RX_FILTER_BROAD | AR9271_RX_FILTER_BEACON;469 AR9271_RX_FILTER_BROAD | additional_bits; 386 470 387 471 wmi_reg_write(ar9271->htc_device, AR9271_RX_FILTER, filter_bits); 472 473 return EOK; 474 } 475 476 int hw_set_bssid(ar9271_t *ar9271) 477 { 478 ieee80211_dev_t *ieee80211_dev = ar9271->ieee80211_dev; 479 480 nic_address_t bssid; 481 ieee80211_query_bssid(ieee80211_dev, &bssid); 482 483 uint32_t *first_4bytes = (uint32_t *) &bssid.address; 484 uint16_t *last_2bytes = (uint16_t *) &bssid.address[4]; 485 486 wmi_reg_write(ar9271->htc_device, AR9271_BSSID0, 487 uint32_t_le2host(*first_4bytes)); 488 489 wmi_reg_write(ar9271->htc_device, AR9271_BSSID1, 490 uint16_t_le2host(*last_2bytes) | 491 ((ieee80211_get_aid(ieee80211_dev) & 0x3FFF) << 16)); 388 492 389 493 return EOK; … … 395 499 AR9271_COMMAND_RX_ENABLE); 396 500 397 int rc = hw_set_rx_filter(ar9271 );501 int rc = hw_set_rx_filter(ar9271, false); 398 502 if(rc != EOK) { 399 503 usb_log_error("Failed to set RX filtering.\n"); … … 410 514 } 411 515 412 static int hw_activate_phy(ar9271_t *ar9271)413 {414 wmi_reg_write(ar9271->htc_device, AR9271_PHY_ACTIVE, 1);415 udelay(1000);416 417 return EOK;418 }419 420 516 static int hw_init_pll(ar9271_t *ar9271) 421 517 { … … 423 519 424 520 /* Some magic here (set for 2GHz channels). But VERY important :-) */ 425 pll = (0x5 << 10) & 0x00003C00; 426 pll |= 0x2C & 0x000003FF; 521 pll = (0x5 << 10) | 0x2C; 427 522 428 523 wmi_reg_write(ar9271->htc_device, AR9271_RTC_PLL_CONTROL, pll); 429 524 430 return EOK; 431 } 432 433 static int hw_set_init_values(ar9271_t *ar9271) 525 wmi_reg_write(ar9271->htc_device, AR9271_RTC_SLEEP_CLOCK, 526 AR9271_RTC_SLEEP_CLOCK_FORCE_DERIVED); 527 wmi_reg_set_bit(ar9271->htc_device, AR9271_RTC_FORCE_WAKE, 528 AR9271_RTC_FORCE_WAKE_ENABLE); 529 530 return EOK; 531 } 532 533 static void hw_set_init_values(ar9271_t *ar9271) 434 534 { 435 535 uint32_t reg_offset, reg_value; … … 458 558 wmi_reg_write(ar9271->htc_device, reg_offset, reg_value); 459 559 } 460 461 return EOK;462 560 } 463 561 … … 533 631 } 534 632 535 rc = hw_set_init_values(ar9271); 536 if(rc != EOK) { 537 usb_log_error("Failed to set device init values.\n"); 538 return rc; 539 } 633 hw_set_init_values(ar9271); 540 634 541 635 /* Set physical layer mode. */ … … 586 680 /* Byteswap TX and RX data buffer words. */ 587 681 wmi_reg_write(ar9271->htc_device, AR9271_CONFIG, 0xA); 588 589 usb_log_info("HW reset done.\n");590 682 591 683 return EOK; -
uspace/drv/nic/ar9271/hw.h
r59fa7ab r1dcc0b9 45 45 extern int hw_rx_init(ar9271_t *ar9271); 46 46 extern int hw_reset(ar9271_t *ar9271); 47 extern int hw_wakeup(ar9271_t *ar9271); 48 extern int hw_set_bssid(ar9271_t *ar9271); 49 extern int hw_set_rx_filter(ar9271_t *ar9271, bool assoc); 47 50 48 51 #endif /* ATHEROS_HW_H */ -
uspace/drv/nic/ar9271/wmi.c
r59fa7ab r1dcc0b9 231 231 size_t buffer_size = header_size + command_length; 232 232 void *buffer = malloc(buffer_size); 233 memcpy(buffer+header_size, command_buffer, command_length); 233 234 if(command_buffer != NULL) { 235 memcpy(buffer+header_size, command_buffer, command_length); 236 } 234 237 235 238 /* Set up WMI header */ … … 261 264 262 265 /* Read response. */ 263 rc = htc_read_control_message(htc_device, response_buffer, 264 response_buffer_size, NULL); 265 if(rc != EOK) { 266 free(buffer); 267 usb_log_error("Failed to receive WMI message response. " 268 "Error: %d\n", rc); 269 return rc; 270 } 266 /* TODO: Ignoring WMI management RX messages ~ TX statuses etc. */ 267 uint16_t cmd_id; 268 do { 269 rc = htc_read_control_message(htc_device, response_buffer, 270 response_buffer_size, NULL); 271 if(rc != EOK) { 272 free(buffer); 273 usb_log_error("Failed to receive WMI message response. " 274 "Error: %d\n", rc); 275 return rc; 276 } 277 278 if(response_buffer_size < sizeof(htc_frame_header_t) + 279 sizeof(wmi_command_header_t)) { 280 free(buffer); 281 usb_log_error("Corrupted response received.\n"); 282 return EINVAL; 283 } 284 285 wmi_command_header_t *wmi_hdr = (wmi_command_header_t *) 286 ((void*) response_buffer + sizeof(htc_frame_header_t)); 287 cmd_id = uint16_t_be2host(wmi_hdr->command_id); 288 } while(cmd_id & WMI_MGMT_CMD_MASK); 271 289 272 290 if(clean_resp_buffer) { -
uspace/drv/nic/ar9271/wmi.h
r59fa7ab r1dcc0b9 42 42 #define WMI_SERVICE_GROUP 1 43 43 #define CREATE_SERVICE_ID(group, i) (int) (((int) group << 8) | (int) (i)) 44 45 #define WMI_MGMT_CMD_MASK 0x1000 44 46 45 47 /** … … 117 119 extern int wmi_reg_write(htc_device_t *htc_device, uint32_t reg_offset, 118 120 uint32_t val); 119 extern int wmi_reg_set_clear_bit(htc_device_t *htc_device, uint32_t reg_offset,120 uint32_t set_bit, uint32_t clear_bit);121 extern int wmi_reg_set_clear_bit(htc_device_t *htc_device, 122 uint32_t reg_offset, uint32_t set_bit, uint32_t clear_bit); 121 123 extern int wmi_reg_set_bit(htc_device_t *htc_device, uint32_t reg_offset, 122 124 uint32_t set_bit); -
uspace/lib/c/include/ieee80211/ieee80211.h
r59fa7ab r1dcc0b9 41 41 #include <adt/list.h> 42 42 #include <nic/nic.h> 43 #include <time.h> 43 44 44 /* Max length of scan results array. */45 /** Max length of scan results array. */ 45 46 #define IEEE80211_MAX_RESULTS_LENGTH 32 46 47 47 /* Max SSID length including null character. */48 /** Max SSID length including null character. */ 48 49 #define IEEE80211_MAX_SSID_LENGTH 35 50 51 /** WiFi security authentication method indicator. */ 52 typedef enum { 53 IEEE80211_SECURITY_OPEN, 54 IEEE80211_SECURITY_WEP, 55 IEEE80211_SECURITY_WPA, 56 IEEE80211_SECURITY_WPA2 57 } ieee80211_security_type_t; 58 59 /** WiFi security suite indicator. */ 60 typedef enum { 61 IEEE80211_SECURITY_SUITE_WEP40, 62 IEEE80211_SECURITY_SUITE_WEP104, 63 IEEE80211_SECURITY_SUITE_CCMP, 64 IEEE80211_SECURITY_SUITE_TKIP 65 } ieee80211_security_suite_t; 66 67 /** WiFi security authentication method indicator. */ 68 typedef enum { 69 IEEE80211_SECURITY_AUTH_PSK, 70 IEEE80211_SECURITY_AUTH_8021X 71 } ieee80211_security_auth_t; 72 73 /** Structure for indicating security network security settings. */ 74 typedef struct { 75 int type; 76 int group_alg; 77 int pair_alg; 78 int auth; 79 } ieee80211_security_t; 49 80 50 81 /** Structure with scan result info. */ … … 52 83 nic_address_t bssid; 53 84 char ssid[IEEE80211_MAX_SSID_LENGTH]; 85 uint8_t channel; 86 ieee80211_security_t security; 54 87 } ieee80211_scan_result_t; 55 88 56 /** Listof scan results info. */89 /** Array of scan results info. */ 57 90 typedef struct { 58 91 uint8_t length; -
uspace/lib/drv/generic/remote_ieee80211.c
r59fa7ab r1dcc0b9 47 47 typedef enum { 48 48 IEEE80211_GET_SCAN_RESULTS, 49 IEEE80211_CONNECT 49 IEEE80211_CONNECT, 50 IEEE80211_DISCONNECT 50 51 } ieee80211_funcs_t; 51 52 … … 59 60 */ 60 61 int ieee80211_get_scan_results(async_sess_t *dev_sess, 61 ieee80211_scan_results_t *results )62 ieee80211_scan_results_t *results, bool now) 62 63 { 63 64 assert(results); … … 65 66 async_exch_t *exch = async_exchange_begin(dev_sess); 66 67 67 aid_t aid = async_send_ 1(exch, DEV_IFACE_ID(IEEE80211_DEV_IFACE),68 IEEE80211_GET_SCAN_RESULTS, NULL);68 aid_t aid = async_send_2(exch, DEV_IFACE_ID(IEEE80211_DEV_IFACE), 69 IEEE80211_GET_SCAN_RESULTS, now, NULL); 69 70 int rc = async_data_read_start(exch, results, sizeof(ieee80211_scan_results_t)); 70 71 async_exchange_end(exch); … … 73 74 async_wait_for(aid, &res); 74 75 75 if (rc != EOK) 76 if(res != EOK) 77 return (int) res; 78 else 76 79 return rc; 77 78 return (int) res;79 80 } 80 81 … … 82 83 * 83 84 * @param[in] dev_sess Device session. 84 * @param[in] ssid Network SSID.85 * @param[in] ssid_start Network SSID prefix. 85 86 * @param[in] password Network password (pass empty string if not needed). 86 87 * … … 88 89 * negative error code otherwise. 89 90 */ 90 int ieee80211_connect(async_sess_t *dev_sess, char *ssid , char *password)91 { 92 assert(ssid );91 int ieee80211_connect(async_sess_t *dev_sess, char *ssid_start, char *password) 92 { 93 assert(ssid_start); 93 94 94 95 sysarg_t rc_orig; … … 99 100 IEEE80211_CONNECT, NULL); 100 101 101 sysarg_t rc = async_data_write_start(exch, ssid, str_size(ssid) + 1); 102 sysarg_t rc = async_data_write_start(exch, ssid_start, 103 str_size(ssid_start) + 1); 102 104 if (rc != EOK) { 103 105 async_exchange_end(exch); … … 132 134 } 133 135 136 /** Disconnect device from network. 137 * 138 * @param[in] dev_sess Device session. 139 * 140 * @return EOK If the operation was successfully completed, 141 * negative error code otherwise. 142 */ 143 int ieee80211_disconnect(async_sess_t *dev_sess) 144 { 145 async_exch_t *exch = async_exchange_begin(dev_sess); 146 int rc = async_req_1_0(exch, DEV_IFACE_ID(IEEE80211_DEV_IFACE), 147 IEEE80211_DISCONNECT); 148 async_exchange_end(exch); 149 150 return rc; 151 } 152 134 153 static void remote_ieee80211_get_scan_results(ddf_fun_t *fun, void *iface, 135 154 ipc_callid_t callid, ipc_call_t *call) … … 141 160 memset(&scan_results, 0, sizeof(ieee80211_scan_results_t)); 142 161 143 int rc = ieee80211_iface->get_scan_results(fun, &scan_results); 162 bool now = IPC_GET_ARG2(*call); 163 164 int rc = ieee80211_iface->get_scan_results(fun, &scan_results, now); 144 165 if (rc == EOK) { 145 166 ipc_callid_t data_callid; … … 170 191 assert(ieee80211_iface->connect); 171 192 172 char ssid [MAX_STRING_SIZE];193 char ssid_start[MAX_STRING_SIZE]; 173 194 char password[MAX_STRING_SIZE]; 174 195 … … 187 208 } 188 209 189 int rc = async_data_write_finalize(data_callid, ssid , len);210 int rc = async_data_write_finalize(data_callid, ssid_start, len); 190 211 if (rc != EOK) { 191 212 async_answer_0(data_callid, EINVAL); … … 213 234 } 214 235 215 rc = ieee80211_iface->connect(fun, ssid, password); 216 236 rc = ieee80211_iface->connect(fun, ssid_start, password); 237 238 async_answer_0(callid, rc); 239 } 240 241 static void remote_ieee80211_disconnect(ddf_fun_t *fun, void *iface, 242 ipc_callid_t callid, ipc_call_t *call) 243 { 244 ieee80211_iface_t *ieee80211_iface = (ieee80211_iface_t *) iface; 245 assert(ieee80211_iface->disconnect); 246 int rc = ieee80211_iface->disconnect(fun); 217 247 async_answer_0(callid, rc); 218 248 } … … 223 253 static const remote_iface_func_ptr_t remote_ieee80211_iface_ops[] = { 224 254 [IEEE80211_GET_SCAN_RESULTS] = remote_ieee80211_get_scan_results, 225 [IEEE80211_CONNECT] = remote_ieee80211_connect 255 [IEEE80211_CONNECT] = remote_ieee80211_connect, 256 [IEEE80211_DISCONNECT] = remote_ieee80211_disconnect 226 257 }; 227 258 -
uspace/lib/drv/include/ieee80211_iface.h
r59fa7ab r1dcc0b9 39 39 #include <async.h> 40 40 41 extern int ieee80211_get_scan_results(async_sess_t *, ieee80211_scan_results_t *); 41 extern int ieee80211_get_scan_results(async_sess_t *, 42 ieee80211_scan_results_t *, bool); 42 43 extern int ieee80211_connect(async_sess_t *, char *, char *); 44 extern int ieee80211_disconnect(async_sess_t *); 43 45 44 46 #endif -
uspace/lib/drv/include/ops/ieee80211.h
r59fa7ab r1dcc0b9 47 47 * @param fun IEEE 802.11 function. 48 48 * @param results Structure where to put scan results. 49 * @param now Whether to initiate scan immediately. 49 50 * 50 51 * @return EOK if succeed, negative error code otherwise. 51 52 */ 52 int (*get_scan_results)(ddf_fun_t *, ieee80211_scan_results_t * );53 int (*get_scan_results)(ddf_fun_t *, ieee80211_scan_results_t *, bool); 53 54 54 55 /** 55 56 * Connect IEEE 802.11 device to specified network. 57 * 56 58 * @param fun IEEE 802.11 function. 57 59 * @param ssid Network SSID. … … 61 63 */ 62 64 int (*connect)(ddf_fun_t *, char *, char *); 65 66 /** 67 * Disconnect IEEE 802.11 device from network. 68 * 69 * @param fun IEEE 802.11 function. 70 * 71 * @return EOK if succeed, negative error code otherwise. 72 */ 73 int (*disconnect)(ddf_fun_t *); 63 74 } ieee80211_iface_t; 64 75 -
uspace/lib/ieee80211/Makefile
r59fa7ab r1dcc0b9 1 1 # 2 # Copyright (c) 2005 Martin Decky 3 # Copyright (c) 2007 Jakub Jermar 2 # Copyright (c) 2015 Jan Kolarik 4 3 # All rights reserved. 5 4 # … … 33 32 LIBS = \ 34 33 $(LIBDRV_PREFIX)/libdrv.a \ 35 $(LIBNIC_PREFIX)/libnic.a 34 $(LIBNIC_PREFIX)/libnic.a \ 35 $(LIBCRYPTO_PREFIX)/libcrypto.a 36 36 37 37 EXTRA_CFLAGS += \ 38 38 -Iinclude \ 39 39 -I$(LIBDRV_PREFIX)/include \ 40 -I$(LIBNIC_PREFIX)/include 40 -I$(LIBNIC_PREFIX)/include \ 41 -I$(LIBCRYPTO_PREFIX) 41 42 42 43 SOURCES = \ -
uspace/lib/ieee80211/include/ieee80211.h
r59fa7ab r1dcc0b9 57 57 #define IEEE80211_CHANNEL_GAP 5 58 58 59 /* Max AMPDU factor. */ 60 #define IEEE80211_MAX_AMPDU_FACTOR 13 61 62 /* Max passphrase length in WPA/WPA2 protocols. */ 63 #define IEEE80211_WPA_MAX_PASSWORD_LENGTH 64 64 65 /** IEEE 802.11 b/g supported data rates in units of 500 kb/s. */ 66 static const uint8_t ieee80211bg_data_rates[] = { 67 2, 4, 11, 12, 18, 22, 24, 36, 48, 72, 96, 108 68 }; 69 59 70 /** Device operating modes. */ 60 71 typedef enum { … … 65 76 } ieee80211_operating_mode_t; 66 77 78 /** Key flags. */ 79 typedef enum { 80 IEEE80211_KEY_FLAG_TYPE_PAIRWISE = 0x01, 81 IEEE80211_KEY_FLAG_TYPE_GROUP = 0x02 82 } ieee80211_key_flags_t; 83 84 /** Key config structure. */ 85 typedef struct { 86 uint8_t id; 87 uint8_t flags; 88 ieee80211_security_suite_t suite; 89 uint8_t data[32]; 90 } ieee80211_key_config_t; 91 67 92 /** IEEE 802.11 callback functions. */ 68 93 typedef struct { … … 109 134 */ 110 135 int (*set_freq)(struct ieee80211_dev *, uint16_t); 136 137 /** 138 * Callback to inform device about BSSID change. 139 * 140 * @param ieee80211_dev Pointer to IEEE 802.11 device structure. 141 * 142 * @return EOK if succeed, negative error code otherwise. 143 */ 144 int (*bssid_change)(struct ieee80211_dev *); 145 146 /** 147 * Callback to setup encryption key in IEEE 802.11 device. 148 * 149 * @param ieee80211_dev Pointer to IEEE 802.11 device structure. 150 * @param key_conf Key config structure. 151 * @param insert True to insert this key to device, false to remove it. 152 * 153 * @return EOK if succeed, negative error code otherwise. 154 */ 155 int (*key_config)(struct ieee80211_dev *, 156 ieee80211_key_config_t *key_conf, bool); 111 157 } ieee80211_ops_t; 112 158 … … 124 170 void *specific); 125 171 extern ddf_dev_t *ieee80211_get_ddf_dev(ieee80211_dev_t* ieee80211_dev); 126 extern ieee80211_operating_mode_t ieee80211_query_current_op_mode(ieee80211_dev_t *ieee80211_dev); 172 extern ieee80211_operating_mode_t 173 ieee80211_query_current_op_mode(ieee80211_dev_t *ieee80211_dev); 127 174 extern uint16_t ieee80211_query_current_freq(ieee80211_dev_t *ieee80211_dev); 175 extern void ieee80211_query_bssid(ieee80211_dev_t* ieee80211_dev, 176 nic_address_t *bssid); 177 extern bool ieee80211_is_connected(ieee80211_dev_t* ieee80211_dev); 128 178 extern void ieee80211_report_current_op_mode(ieee80211_dev_t *ieee80211_dev, 129 179 ieee80211_operating_mode_t op_mode); 130 180 extern void ieee80211_report_current_freq(ieee80211_dev_t *ieee80211_dev, 131 181 uint16_t freq); 182 extern uint16_t ieee80211_get_aid(ieee80211_dev_t* ieee80211_dev); 183 extern int ieee80211_get_security_suite(ieee80211_dev_t* ieee80211_dev); 184 extern bool ieee80211_is_ready(ieee80211_dev_t* ieee80211_dev); 185 extern void ieee80211_set_ready(ieee80211_dev_t* ieee80211_dev, bool ready); 186 extern bool ieee80211_query_using_key(ieee80211_dev_t* ieee80211_dev); 187 extern void ieee80211_setup_key_confirm(ieee80211_dev_t* ieee80211_dev, 188 bool using_key); 132 189 133 190 extern bool ieee80211_is_data_frame(uint16_t frame_ctrl); … … 135 192 extern bool ieee80211_is_beacon_frame(uint16_t frame_ctrl); 136 193 extern bool ieee80211_is_probe_response_frame(uint16_t frame_ctrl); 194 extern bool ieee80211_is_auth_frame(uint16_t frame_ctrl); 195 extern bool ieee80211_is_assoc_response_frame(uint16_t frame_ctrl); 137 196 138 197 /* Worker functions. */ -
uspace/lib/ieee80211/include/ieee80211_iface_impl.h
r59fa7ab r1dcc0b9 45 45 46 46 extern int ieee80211_get_scan_results_impl(ddf_fun_t *fun, 47 ieee80211_scan_results_t *results); 48 extern int ieee80211_connect_impl(ddf_fun_t *fun, char *ssid, char *password); 47 ieee80211_scan_results_t *results, bool now); 48 extern int ieee80211_connect_impl(ddf_fun_t *fun, char *ssid_start, 49 char *password); 50 extern int ieee80211_disconnect_impl(ddf_fun_t *fun); 49 51 50 52 #endif /* LIB_IEEE80211_IFACE_IMPL_H */ -
uspace/lib/ieee80211/include/ieee80211_impl.h
r59fa7ab r1dcc0b9 43 43 44 44 extern int ieee80211_start_impl(ieee80211_dev_t *ieee80211_dev); 45 extern int ieee80211_tx_handler_impl(ieee80211_dev_t *ieee80211_dev, void *buffer, 46 size_t buffer_size); 47 extern int ieee80211_set_freq_impl(ieee80211_dev_t *ieee80211_dev, uint16_t freq); 45 extern int ieee80211_tx_handler_impl(ieee80211_dev_t *ieee80211_dev, 46 void *buffer, size_t buffer_size); 47 extern int ieee80211_set_freq_impl(ieee80211_dev_t *ieee80211_dev, 48 uint16_t freq); 49 extern int ieee80211_bssid_change_impl(ieee80211_dev_t *ieee80211_dev); 50 extern int ieee80211_key_config_impl(ieee80211_dev_t *ieee80211_dev, 51 ieee80211_key_config_t *key_conf, bool insert); 48 52 extern int ieee80211_scan_impl(ieee80211_dev_t *ieee80211_dev); 53 extern int ieee80211_prf(uint8_t *key, uint8_t *data, uint8_t *hash, 54 hash_func_t hash_sel); 55 extern int ieee80211_aes_key_unwrap(uint8_t *kek, uint8_t *data, 56 size_t data_size, uint8_t *output); 57 extern int rnd_sequence(uint8_t *sequence, size_t length); 58 extern uint8_t *min_sequence(uint8_t *seq1, uint8_t *seq2, size_t size); 59 extern uint8_t *max_sequence(uint8_t *seq1, uint8_t *seq2, size_t size); 49 60 50 61 #endif /* LIB_IEEE80211_IMPL_H */ -
uspace/lib/ieee80211/include/ieee80211_private.h
r59fa7ab r1dcc0b9 40 40 #define LIBNET_IEEE80211_PRIVATE_H 41 41 42 #include <fibril_synch.h> 42 43 #include <byteorder.h> 43 44 #include <ddf/driver.h> … … 46 47 #include <ieee80211/ieee80211.h> 47 48 #include "ieee80211.h" 49 50 /* Timeout in us for waiting to authentication/association response. */ 51 #define AUTH_TIMEOUT 200000 52 53 /* Timeout in us for waiting to finish 4-way handshake process. */ 54 #define HANDSHAKE_TIMEOUT 3000000 55 56 /* Max period to rerun scan. */ 57 #define MAX_SCAN_SPAN_SEC 30 58 59 /* Max time to keep scan result. */ 60 #define MAX_KEEP_SCAN_SPAN_SEC 120 61 62 /* Security bit in capability info field. */ 63 #define CAP_SECURITY 0x10 64 65 /* Protocol type used in EAPOL frames. */ 66 #define ETH_TYPE_PAE 0x888E 67 68 /* WPA OUI used in vendor specific IE. */ 69 #define WPA_OUI 0x0050F201 70 71 /* GTK OUI used in vendor specific IE. */ 72 #define GTK_OUI 0x000FAC01 73 74 /* Max PTK key length. */ 75 #define MAX_PTK_LENGTH 64 76 77 /* Max GTK key length. */ 78 #define MAX_GTK_LENGTH 64 79 80 /* KEK offset inside PTK. */ 81 #define KEK_OFFSET 16 82 83 /* TK offset inside PTK. */ 84 #define TK_OFFSET 32 85 86 /* Length of CCMP header we need to reserve. */ 87 #define IEEE80211_CCMP_HEADER_LENGTH 8 88 89 /* 90 * Length of data to be encrypted by PRF function: 91 * NONCE + SNONCE (2 * 32) + DEST_MAC + SOURCE_MAC (2 * ETH_ADDR) 92 */ 93 #define PRF_CRYPT_DATA_LENGTH 2*32 + 2*ETH_ADDR 94 95 /** IEEE 802.11 PTK key length. */ 96 typedef enum { 97 IEEE80211_PTK_CCMP_LENGTH = 48, 98 IEEE80211_PTK_TKIP_LENGTH = 64 99 } ieee80211_ptk_length_t; 100 101 /** IEEE 802.11 GTK key length. */ 102 typedef enum { 103 IEEE80211_GTK_CCMP_LENGTH = 16, 104 IEEE80211_GTK_TKIP_LENGTH = 32 105 } ieee80211_gtk_length_t; 48 106 49 107 /** IEEE 802.11 frame types. */ … … 55 113 } ieee80211_frame_type_t; 56 114 57 /** IEEE 802.11 frame subtypes. */115 /** IEEE 802.11 management frame subtypes. */ 58 116 typedef enum { 59 117 IEEE80211_MGMT_ASSOC_REQ_FRAME = 0x00, … … 64 122 IEEE80211_MGMT_PROBE_RESP_FRAME = 0x50, 65 123 IEEE80211_MGMT_BEACON_FRAME = 0x80, 66 IEEE80211_MGMT_DI ASSOC_FRAME = 0xA0,124 IEEE80211_MGMT_DISASSOC_FRAME = 0xA0, 67 125 IEEE80211_MGMT_AUTH_FRAME = 0xB0, 68 126 IEEE80211_MGMT_DEAUTH_FRAME = 0xC0, 69 } ieee80211_frame_subtype_t; 127 } ieee80211_frame_mgmt_subtype_t; 128 129 /** IEEE 802.11 data frame subtypes. */ 130 typedef enum { 131 IEEE80211_DATA_DATA_FRAME = 0x0000, 132 IEEE80211_DATA_QOS_FRAME = 0x0080 133 } ieee80211_frame_data_subtype_t; 70 134 71 135 /** IEEE 802.11 frame control value masks. */ … … 73 137 IEEE80211_FRAME_CTRL_FRAME_TYPE = 0x000C, 74 138 IEEE80211_FRAME_CTRL_FRAME_SUBTYPE = 0x00F0, 75 } ieee80211_frame_control_mask_t; 139 IEEE80211_FRAME_CTRL_PROTECTED = 0x4000 140 } ieee80211_frame_ctrl_mask_t; 141 142 /** IEEE 802.11 frame control DS field values. */ 143 typedef enum { 144 IEEE80211_FRAME_CTRL_TODS = 0x0100, 145 IEEE80211_FRAME_CTRL_FROMDS = 0x0200 146 } ieee80211_frame_ctrl_ds_t; 147 148 /** IEEE 802.11 authentication cipher suites values. */ 149 typedef enum { 150 IEEE80211_AUTH_CIPHER_TKIP = 0x02, 151 IEEE80211_AUTH_CIPHER_CCMP = 0x04 152 } ieee80211_auth_cipher_type_t; 153 154 /** IEEE 802.11 AKM suites values. */ 155 typedef enum { 156 IEEE80211_AUTH_AKM_8021X = 0x01, 157 IEEE80211_AUTH_AKM_PSK = 0x02 158 } ieee80211_auth_akm_type_t; 159 160 typedef enum { 161 IEEE80211_EAPOL_START = 0x1, 162 IEEE80211_EAPOL_KEY = 0x3 163 } ieee80211_eapol_frame_type_t; 164 165 typedef enum { 166 IEEE80211_EAPOL_KEY_KEYINFO_KEYTYPE = 0x0008, 167 IEEE80211_EAPOL_KEY_KEYINFO_INSTALL = 0x0040, 168 IEEE80211_EAPOL_KEY_KEYINFO_ACK = 0x0080, 169 IEEE80211_EAPOL_KEY_KEYINFO_MIC = 0x0100, 170 IEEE80211_EAPOL_KEY_KEYINFO_SECURE = 0x0200, 171 IEEE80211_EAPOL_KEY_KEYINFO_ENCDATA = 0x1000 172 } ieee80211_eapol_key_keyinfo_t; 76 173 77 174 /** IEEE 802.11 information element types. */ … … 80 177 IEEE80211_RATES_IE = 1, /**< Supported data rates. */ 81 178 IEEE80211_CHANNEL_IE = 3, /**< Current channel number. */ 82 IEEE80211_EXT_RATES_IE = 50 /**< Extended data rates. */ 179 IEEE80211_CHALLENGE_IE = 16, /**< Challenge text. */ 180 IEEE80211_RSN_IE = 48, /**< RSN. */ 181 IEEE80211_EXT_RATES_IE = 50, /**< Extended data rates. */ 182 IEEE80211_VENDOR_IE = 221 /**< Vendor specific IE. */ 83 183 } ieee80211_ie_type_t; 184 185 /** IEEE 802.11 authentication phases. */ 186 typedef enum { 187 IEEE80211_AUTH_DISCONNECTED, 188 IEEE80211_AUTH_AUTHENTICATED, 189 IEEE80211_AUTH_ASSOCIATED 190 } ieee80211_auth_phase_t; 191 192 /** Link with scan result info. */ 193 typedef struct { 194 link_t link; 195 time_t last_beacon; 196 ieee80211_scan_result_t scan_result; 197 uint8_t rsn_copy[256]; 198 size_t rsn_copy_len; 199 } ieee80211_scan_result_link_t; 200 201 /** List of scan results info. */ 202 typedef struct { 203 list_t list; 204 time_t last_scan; 205 fibril_mutex_t scan_mutex; 206 size_t size; 207 } ieee80211_scan_result_list_t; 208 209 /** BSSID info. */ 210 typedef struct { 211 uint16_t aid; 212 char password[IEEE80211_WPA_MAX_PASSWORD_LENGTH]; 213 uint8_t ptk[MAX_PTK_LENGTH]; 214 uint8_t gtk[MAX_GTK_LENGTH]; 215 ieee80211_scan_result_link_t *res_link; 216 } ieee80211_bssid_info_t; 84 217 85 218 /** IEEE 802.11 WiFi device structure. */ … … 103 236 ieee80211_operating_mode_t current_op_mode; 104 237 238 /** Info about BSSID we are connected to. */ 239 ieee80211_bssid_info_t bssid_info; 240 241 /** 242 * Flag indicating that data traffic is encrypted by HW key 243 * that is set up in device. 244 */ 245 bool using_hw_key; 246 105 247 /** BSSIDs we listen to. */ 106 248 nic_address_t bssid_mask; 107 249 108 250 /** List of APs in neighborhood. */ 109 ieee80211_scan_results_t ap_list; 110 111 /* TODO: Probably to be removed later - nic.open function is now 112 * executed multiple times, have to find out reason and fix it. 113 */ 251 ieee80211_scan_result_list_t ap_list; 252 253 /** Current sequence number used in data frames. */ 254 uint16_t sequence_number; 255 256 /** Current authentication phase. */ 257 ieee80211_auth_phase_t current_auth_phase; 258 259 /** General purpose guard. */ 260 fibril_mutex_t gen_mutex; 261 262 /** General purpose condition variable. */ 263 fibril_condvar_t gen_cond; 264 265 /** Indicates whether device is fully initialized. */ 266 bool ready; 267 114 268 /** Indicates whether driver has already started. */ 115 269 bool started; 116 270 }; 271 272 /** IEEE 802.3 (ethernet) header. */ 273 typedef struct { 274 uint8_t dest_addr[ETH_ADDR]; 275 uint8_t src_addr[ETH_ADDR]; 276 uint16_t proto; /**< Big Endian value! */ 277 } __attribute__((packed)) __attribute__ ((aligned(2))) 278 eth_header_t; 117 279 118 280 /** IEEE 802.11 management header structure. */ … … 124 286 uint8_t bssid[ETH_ADDR]; 125 287 uint16_t seq_ctrl; /**< Little Endian value! */ 126 } __attribute__((packed)) __attribute__ ((aligned(2))) ieee80211_mgmt_header_t; 288 } __attribute__((packed)) __attribute__ ((aligned(2))) 289 ieee80211_mgmt_header_t; 127 290 128 291 /** IEEE 802.11 data header structure. */ … … 134 297 uint8_t address3[ETH_ADDR]; 135 298 uint16_t seq_ctrl; /**< Little Endian value! */ 136 uint8_t address4[ETH_ADDR]; 137 uint16_t qos_ctrl; /**< Little Endian value! */ 138 } __attribute__((packed)) __attribute__ ((aligned(2))) ieee80211_data_header_t; 299 } __attribute__((packed)) __attribute__ ((aligned(2))) 300 ieee80211_data_header_t; 139 301 140 302 /** IEEE 802.11 information element header. */ … … 142 304 uint8_t element_id; 143 305 uint8_t length; 144 } __attribute__((packed)) __attribute__ ((aligned(2))) ieee80211_ie_header_t; 306 } __attribute__((packed)) __attribute__ ((aligned(2))) 307 ieee80211_ie_header_t; 145 308 146 309 /** IEEE 802.11 authentication frame body. */ … … 149 312 uint16_t auth_trans_no; /**< Little Endian value! */ 150 313 uint16_t status; /**< Little Endian value! */ 151 } __attribute__((packed)) __attribute__ ((aligned(2))) ieee80211_auth_body_t; 314 } __attribute__((packed)) __attribute__ ((aligned(2))) 315 ieee80211_auth_body_t; 316 317 /** IEEE 802.11 deauthentication frame body. */ 318 typedef struct { 319 uint16_t reason; /**< Little Endian value! */ 320 } __attribute__((packed)) __attribute__ ((aligned(2))) 321 ieee80211_deauth_body_t; 322 323 /** IEEE 802.11 association request frame body. */ 324 typedef struct { 325 uint16_t capability; /**< Little Endian value! */ 326 uint16_t listen_interval; /**< Little Endian value! */ 327 } __attribute__((packed)) __attribute__ ((aligned(2))) 328 ieee80211_assoc_req_body_t; 329 330 /** IEEE 802.11 association response frame body. */ 331 typedef struct { 332 uint16_t capability; /**< Little Endian value! */ 333 uint16_t status; /**< Little Endian value! */ 334 uint16_t aid; /**< Little Endian value! */ 335 } __attribute__((packed)) __attribute__ ((aligned(2))) 336 ieee80211_assoc_resp_body_t; 152 337 153 338 /** IEEE 802.11 beacon frame body start. */ 154 339 typedef struct { 155 340 uint8_t timestamp[8]; 156 uint16_t beacon_interval; 157 uint16_t capability; 158 } __attribute__((packed)) __attribute__ ((aligned(2))) ieee80211_beacon_start_t; 159 160 extern int ieee80211_probe_request(ieee80211_dev_t *ieee80211_dev); 161 extern int ieee80211_probe_auth(ieee80211_dev_t *ieee80211_dev); 341 uint16_t beacon_interval; /**< Little Endian value! */ 342 uint16_t capability; /**< Little Endian value! */ 343 } __attribute__((packed)) __attribute__ ((aligned(2))) 344 ieee80211_beacon_start_t; 345 346 /** IEEE 802.11i EAPOL-Key frame format. */ 347 typedef struct { 348 uint8_t proto_version; 349 uint8_t packet_type; 350 uint16_t body_length; /**< Big Endian value! */ 351 uint8_t descriptor_type; 352 uint16_t key_info; /**< Big Endian value! */ 353 uint16_t key_length; /**< Big Endian value! */ 354 uint8_t key_replay_counter[8]; 355 uint8_t key_nonce[32]; 356 uint8_t eapol_key_iv[16]; 357 uint8_t key_rsc[8]; 358 uint8_t reserved[8]; 359 uint8_t key_mic[16]; 360 uint16_t key_data_length; /**< Big Endian value! */ 361 } __attribute__((packed)) ieee80211_eapol_key_frame_t; 362 363 #define ieee80211_scan_result_list_foreach(results, iter) \ 364 list_foreach((results).list, link, ieee80211_scan_result_link_t, (iter)) 365 366 static inline void ieee80211_scan_result_list_init( 367 ieee80211_scan_result_list_t *results) 368 { 369 list_initialize(&results->list); 370 fibril_mutex_initialize(&results->scan_mutex); 371 } 372 373 static inline void ieee80211_scan_result_list_remove( 374 ieee80211_scan_result_list_t *results, 375 ieee80211_scan_result_link_t *result) 376 { 377 list_remove(&result->link); 378 results->size--; 379 } 380 381 static inline void ieee80211_scan_result_list_append( 382 ieee80211_scan_result_list_t *results, 383 ieee80211_scan_result_link_t *result) 384 { 385 list_append(&result->link, &results->list); 386 results->size++; 387 } 388 389 extern int ieee80211_probe_request(ieee80211_dev_t *ieee80211_dev, 390 char *ssid); 391 extern int ieee80211_authenticate(ieee80211_dev_t *ieee80211_dev); 392 extern int ieee80211_associate(ieee80211_dev_t *ieee80211_dev, 393 char *password); 394 extern int ieee80211_deauthenticate(ieee80211_dev_t *ieee80211_dev); 162 395 163 396 #endif /* LIBN_IEEE80211_H */ -
uspace/lib/ieee80211/src/ieee80211.c
r59fa7ab r1dcc0b9 36 36 */ 37 37 38 #include <stdio.h> 39 #include <crypto.h> 40 #include <str.h> 38 41 #include <macros.h> 39 42 #include <errno.h> … … 45 48 #include <ops/ieee80211.h> 46 49 50 #define IEEE80211_DATA_RATES_SIZE 8 51 #define IEEE80211_EXT_DATA_RATES_SIZE 4 52 53 /** Frame encapsulation used in IEEE 802.11. */ 54 static const uint8_t rfc1042_header[] = { 55 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x00 56 }; 57 47 58 /** Broadcast MAC address used to spread probe request through channel. */ 48 59 static const uint8_t ieee80211_broadcast_mac_addr[] = { … … 50 61 }; 51 62 52 /** IEEE 802.11 b/g supported data rates in units of 500 kb/s. */ 53 static const uint8_t ieee80211bg_data_rates[] = { 54 2, 4, 11, 12, 18, 22, 24, 36 55 }; 56 57 /** IEEE 802.11 b/g extended supported data rates in units of 500 kb/s. 58 * 59 * These are defined separately, because probe request message can 60 * only handle up to 8 data rates in supported rates IE. 61 */ 62 static const uint8_t ieee80211bg_ext_data_rates[] = { 63 48, 72, 96, 108 64 }; 65 63 /** 64 * Check data frame. 65 * 66 * @param frame_ctrl Frame control field in little endian (!). 67 * 68 * @return True if it is data frame, otherwise false. 69 */ 66 70 inline bool ieee80211_is_data_frame(uint16_t frame_ctrl) 67 71 { … … 72 76 } 73 77 78 /** 79 * Check management frame. 80 * 81 * @param frame_ctrl Frame control field in little endian (!). 82 * 83 * @return True if it is management frame, otherwise false. 84 */ 74 85 inline bool ieee80211_is_mgmt_frame(uint16_t frame_ctrl) 75 86 { … … 80 91 } 81 92 93 /** 94 * Check management beacon frame. 95 * 96 * @param frame_ctrl Frame control field in little endian (!). 97 * 98 * @return True if it is beacon frame, otherwise false. 99 */ 82 100 inline bool ieee80211_is_beacon_frame(uint16_t frame_ctrl) 83 101 { … … 88 106 } 89 107 108 /** 109 * Check management probe response frame. 110 * 111 * @param frame_ctrl Frame control field in little endian (!). 112 * 113 * @return True if it is probe resp frame, otherwise false. 114 */ 90 115 inline bool ieee80211_is_probe_response_frame(uint16_t frame_ctrl) 91 116 { … … 97 122 98 123 /** 124 * Check management authentication frame. 125 * 126 * @param frame_ctrl Frame control field in little endian (!). 127 * 128 * @return True if it is auth frame, otherwise false. 129 */ 130 inline bool ieee80211_is_auth_frame(uint16_t frame_ctrl) 131 { 132 frame_ctrl = uint16_t_le2host(frame_ctrl); 133 134 return (frame_ctrl & IEEE80211_FRAME_CTRL_FRAME_SUBTYPE) 135 == IEEE80211_MGMT_AUTH_FRAME; 136 } 137 138 /** 139 * Check management association response frame. 140 * 141 * @param frame_ctrl Frame control field in little endian (!). 142 * 143 * @return True if it is assoc resp frame, otherwise false. 144 */ 145 inline bool ieee80211_is_assoc_response_frame(uint16_t frame_ctrl) 146 { 147 frame_ctrl = uint16_t_le2host(frame_ctrl); 148 149 return (frame_ctrl & IEEE80211_FRAME_CTRL_FRAME_SUBTYPE) 150 == IEEE80211_MGMT_ASSOC_RESP_FRAME; 151 } 152 153 /** 154 * Check data frame "to distribution system" direction. 155 * 156 * @param frame_ctrl Frame control field in little endian (!). 157 * 158 * @return True if it is TODS frame, otherwise false. 159 */ 160 static inline bool ieee80211_is_tods_frame(uint16_t frame_ctrl) 161 { 162 frame_ctrl = uint16_t_le2host(frame_ctrl); 163 164 return (frame_ctrl & IEEE80211_FRAME_CTRL_TODS); 165 } 166 167 /** 168 * Check data frame "from distribution system" direction. 169 * 170 * @param frame_ctrl Frame control field in little endian (!). 171 * 172 * @return True if it is FROMDS frame, otherwise false. 173 */ 174 static inline bool ieee80211_is_fromds_frame(uint16_t frame_ctrl) 175 { 176 frame_ctrl = uint16_t_le2host(frame_ctrl); 177 178 return (frame_ctrl & IEEE80211_FRAME_CTRL_FROMDS); 179 } 180 181 /** 182 * Check if it is data frame containing payload data. 183 * 184 * @param frame_ctrl Frame control field in little endian (!). 185 * 186 * @return True if it has payload data, otherwise false. 187 */ 188 static inline bool ieee80211_has_data_frame(uint16_t frame_ctrl) 189 { 190 frame_ctrl = uint16_t_le2host(frame_ctrl); 191 192 return (frame_ctrl & (IEEE80211_FRAME_CTRL_FRAME_TYPE | 0x40)) 193 == IEEE80211_DATA_FRAME; 194 } 195 196 /** 197 * Check if it is encrypted frame. 198 * 199 * @param frame_ctrl Frame control field in little endian (!). 200 * 201 * @return True if the frame is encrypted, otherwise false. 202 */ 203 static inline bool ieee80211_is_encrypted_frame(uint16_t frame_ctrl) 204 { 205 frame_ctrl = uint16_t_le2host(frame_ctrl); 206 207 return (frame_ctrl & IEEE80211_FRAME_CTRL_PROTECTED) != 0; 208 } 209 210 /** 211 * Check if PAE packet is EAPOL-Key frame. 212 * 213 * @param key_frame Pointer to start of EAPOL frame. 214 * 215 * @return True if it is EAPOL-Key frame, otherwise false. 216 */ 217 static inline bool ieee80211_is_eapol_key_frame(ieee80211_eapol_key_frame_t 218 *key_frame) 219 { 220 return (key_frame->packet_type == IEEE80211_EAPOL_KEY); 221 } 222 223 224 /** 225 * Generate packet sequence number. 226 * 227 * @param ieee80211_dev IEEE 802.11 device. 228 * 229 * @return True if it has payload data, otherwise false. 230 */ 231 static uint16_t ieee80211_get_sequence_number(ieee80211_dev_t *ieee80211_dev) 232 { 233 uint16_t ret_val = ieee80211_dev->sequence_number; 234 ieee80211_dev->sequence_number += (1 << 4); 235 return ret_val; 236 } 237 238 /** 99 239 * Get driver-specific structure for IEEE 802.11 device. 100 240 * … … 139 279 * @return Current IEEE 802.11 operating mode. 140 280 */ 141 ieee80211_operating_mode_t ieee80211_query_current_op_mode(ieee80211_dev_t* ieee80211_dev) 281 ieee80211_operating_mode_t ieee80211_query_current_op_mode(ieee80211_dev_t* 282 ieee80211_dev) 142 283 { 143 284 return ieee80211_dev->current_op_mode; … … 154 295 { 155 296 return ieee80211_dev->current_freq; 297 } 298 299 /** 300 * Query BSSID the device is connected to. 301 * 302 * @param ieee80211_dev IEEE 802.11 device. 303 * @param bssid Pointer to structure where should be stored BSSID. 304 */ 305 void ieee80211_query_bssid(ieee80211_dev_t* ieee80211_dev, 306 nic_address_t *bssid) 307 { 308 if(bssid) { 309 ieee80211_scan_result_t *auth_data = 310 &ieee80211_dev->bssid_info.res_link->scan_result; 311 312 memcpy(bssid, (void *)&auth_data->bssid, sizeof(nic_address_t)); 313 } 314 } 315 316 /** 317 * Get AID of network we are connected to. 318 * 319 * @param ieee80211_dev IEEE 802.11 device. 320 * 321 * @return AID. 322 */ 323 uint16_t ieee80211_get_aid(ieee80211_dev_t* ieee80211_dev) 324 { 325 return ieee80211_dev->bssid_info.aid; 326 } 327 328 /** 329 * Get security suite used for HW encryption. 330 * 331 * @param ieee80211_dev IEEE 802.11 device. 332 * 333 * @return Security suite indicator. 334 */ 335 int ieee80211_get_security_suite(ieee80211_dev_t* ieee80211_dev) 336 { 337 ieee80211_scan_result_link_t *auth_link = 338 ieee80211_dev->bssid_info.res_link; 339 340 return auth_link->scan_result.security.pair_alg; 341 } 342 343 /** 344 * Check if IEEE 802.11 device is connected to network. 345 * 346 * @param ieee80211_dev IEEE 802.11 device. 347 * 348 * @return True if device is connected to network, otherwise false. 349 */ 350 bool ieee80211_is_connected(ieee80211_dev_t* ieee80211_dev) 351 { 352 return ieee80211_dev->current_auth_phase == IEEE80211_AUTH_ASSOCIATED; 156 353 } 157 354 … … 178 375 { 179 376 ieee80211_dev->current_freq = freq; 377 } 378 379 /** 380 * Check if IEEE 802.11 device is ready (fully initialized). 381 * 382 * @param ieee80211_dev IEEE 802.11 device. 383 * 384 * @return True if device is ready to work, otherwise false. 385 */ 386 bool ieee80211_is_ready(ieee80211_dev_t* ieee80211_dev) 387 { 388 fibril_mutex_lock(&ieee80211_dev->gen_mutex); 389 bool ready_state = ieee80211_dev->ready; 390 fibril_mutex_unlock(&ieee80211_dev->gen_mutex); 391 392 return ready_state; 393 } 394 395 /** 396 * Set IEEE 802.11 device to ready state. 397 * 398 * @param ieee80211_dev IEEE 802.11 device. 399 * @param ready Ready state to be set. 400 */ 401 void ieee80211_set_ready(ieee80211_dev_t* ieee80211_dev, bool ready) 402 { 403 fibril_mutex_lock(&ieee80211_dev->gen_mutex); 404 ieee80211_dev->ready = ready; 405 fibril_mutex_unlock(&ieee80211_dev->gen_mutex); 406 } 407 408 extern bool ieee80211_query_using_key(ieee80211_dev_t* ieee80211_dev) 409 { 410 return ieee80211_dev->using_hw_key; 411 } 412 413 void ieee80211_setup_key_confirm(ieee80211_dev_t* ieee80211_dev, 414 bool using_key) 415 { 416 ieee80211_dev->using_hw_key = using_key; 180 417 } 181 418 … … 209 446 } 210 447 211 /** 448 /** 212 449 * Send frame handler. 450 * 451 * @param nic Pointer to NIC device. 452 * @param data Data buffer. 453 * @param size Data buffer size. 213 454 */ 214 455 static void ieee80211_send_frame(nic_t *nic, void *data, size_t size) … … 217 458 nic_get_specific(nic); 218 459 219 ieee80211_dev->ops->tx_handler(ieee80211_dev, data, size); 460 if(!ieee80211_is_connected(ieee80211_dev)) { 461 return; 462 } 463 464 ieee80211_scan_result_t *auth_data = 465 &ieee80211_dev->bssid_info.res_link->scan_result; 466 467 /* We drop part of IEEE 802.3 ethernet header. */ 468 size_t drop_bytes = sizeof(eth_header_t) - 2; 469 470 size_t complete_size = (size - drop_bytes) + 471 sizeof(ieee80211_data_header_t) + 472 ARRAY_SIZE(rfc1042_header); 473 474 /* Init crypto data. */ 475 size_t add_size = 0; 476 uint16_t crypto = 0; 477 uint8_t add_data[8]; 478 memset(add_data, 0, 8); 479 480 if(ieee80211_dev->using_hw_key) { 481 int sec_suite = auth_data->security.pair_alg; 482 switch(sec_suite) { 483 case IEEE80211_SECURITY_SUITE_CCMP: 484 add_size = IEEE80211_CCMP_HEADER_LENGTH; 485 add_data[3] = 0x20; 486 break; 487 default: 488 break; 489 } 490 491 crypto = uint16_t_le2host(IEEE80211_FRAME_CTRL_PROTECTED); 492 } 493 494 complete_size += add_size; 495 496 void *complete_buffer = malloc(complete_size); 497 memset(complete_buffer, 0, complete_size); 498 499 if(add_size) { 500 memcpy(complete_buffer + sizeof(ieee80211_data_header_t), 501 add_data, add_size); 502 } 503 504 memcpy(complete_buffer + sizeof(ieee80211_data_header_t) + add_size, 505 rfc1042_header, 506 ARRAY_SIZE(rfc1042_header)); 507 508 memcpy(complete_buffer + 509 sizeof(ieee80211_data_header_t) + 510 ARRAY_SIZE(rfc1042_header) + add_size, 511 data + drop_bytes, size - drop_bytes); 512 513 ieee80211_data_header_t *data_header = 514 (ieee80211_data_header_t *) complete_buffer; 515 data_header->frame_ctrl = 516 uint16_t_le2host(IEEE80211_DATA_FRAME) | 517 uint16_t_le2host(IEEE80211_DATA_DATA_FRAME) | 518 uint16_t_le2host(IEEE80211_FRAME_CTRL_TODS) | 519 crypto; 520 data_header->seq_ctrl = ieee80211_get_sequence_number(ieee80211_dev); 521 522 /* BSSID, SA, DA. */ 523 memcpy(data_header->address1, auth_data->bssid.address, ETH_ADDR); 524 memcpy(data_header->address2, data + ETH_ADDR, ETH_ADDR); 525 memcpy(data_header->address3, data, ETH_ADDR); 526 527 ieee80211_dev->ops->tx_handler(ieee80211_dev, 528 complete_buffer, 529 complete_size); 530 531 free(complete_buffer); 220 532 } 221 533 … … 246 558 ieee80211_ops->set_freq = ieee80211_set_freq_impl; 247 559 560 if(!ieee80211_ops->bssid_change) 561 ieee80211_ops->bssid_change = 562 ieee80211_bssid_change_impl; 563 564 if(!ieee80211_ops->key_config) 565 ieee80211_ops->key_config = ieee80211_key_config_impl; 566 248 567 if(!ieee80211_ops->scan) 249 568 ieee80211_ops->scan = ieee80211_scan_impl; … … 257 576 if(nic_dev_ops) 258 577 if (!nic_dev_ops->interfaces[IEEE80211_DEV_IFACE]) 259 nic_dev_ops->interfaces[IEEE80211_DEV_IFACE] = ieee80211_iface; 578 nic_dev_ops->interfaces[IEEE80211_DEV_IFACE] = 579 ieee80211_iface; 260 580 261 581 if(!ieee80211_iface->get_scan_results) 262 ieee80211_iface->get_scan_results = ieee80211_get_scan_results_impl; 582 ieee80211_iface->get_scan_results = 583 ieee80211_get_scan_results_impl; 263 584 264 585 if(!ieee80211_iface->connect) 265 586 ieee80211_iface->connect = ieee80211_connect_impl; 587 588 if(!ieee80211_iface->disconnect) 589 ieee80211_iface->disconnect = ieee80211_disconnect_impl; 266 590 } else { 267 591 return EINVAL; … … 304 628 ieee80211_dev->ddf_dev = ddf_dev; 305 629 ieee80211_dev->started = false; 630 ieee80211_dev->ready = false; 631 ieee80211_dev->using_hw_key = false; 306 632 ieee80211_dev->current_op_mode = IEEE80211_OPMODE_STATION; 633 ieee80211_dev->current_auth_phase = IEEE80211_AUTH_DISCONNECTED; 307 634 memcpy(ieee80211_dev->bssid_mask.address, ieee80211_broadcast_mac_addr, 308 635 ETH_ADDR); 636 637 ieee80211_scan_result_list_init(&ieee80211_dev->ap_list); 638 639 fibril_mutex_initialize(&ieee80211_dev->gen_mutex); 640 fibril_condvar_initialize(&ieee80211_dev->gen_cond); 309 641 310 642 /* Bind NIC to device */ … … 373 705 } 374 706 707 /** 708 * Convert frequency value to channel number. 709 * 710 * @param freq IEEE 802.11 operating frequency. 711 * 712 * @return Operating channel number. 713 */ 375 714 static uint8_t ieee80211_freq_to_channel(uint16_t freq) 376 715 { … … 378 717 } 379 718 719 static void ieee80211_prepare_ie_header(void **ie_header, 720 uint8_t id, uint8_t length, void *data) 721 { 722 ieee80211_ie_header_t *header = 723 (ieee80211_ie_header_t *) *ie_header; 724 725 header->element_id = id; 726 header->length = length; 727 728 memcpy(*ie_header + sizeof(ieee80211_ie_header_t), data, length); 729 730 *ie_header = (void *) ((void *) header + 731 sizeof(ieee80211_ie_header_t) + length); 732 } 733 380 734 /** 381 735 * Probe request implementation. 382 736 * 383 737 * @param ieee80211_dev Pointer to IEEE 802.11 device structure. 738 * @param ssid Probing SSID or NULL if broadcast. 384 739 * 385 740 * @return EOK if succeed, negative error code otherwise. 386 741 */ 387 int ieee80211_probe_request(ieee80211_dev_t *ieee80211_dev )742 int ieee80211_probe_request(ieee80211_dev_t *ieee80211_dev, char *ssid) 388 743 { 389 744 nic_t *nic = nic_get_from_ddf_dev(ieee80211_dev->ddf_dev); … … 391 746 nic_query_address(nic, &nic_address); 392 747 393 size_t data_rates_size = ARRAY_SIZE(ieee80211bg_data_rates); 394 size_t ext_data_rates_size = ARRAY_SIZE(ieee80211bg_ext_data_rates); 395 396 /* 3 headers - (rates, ext rates, current channel) and their data 397 * lengths + pad. 748 size_t ssid_data_size = (ssid != NULL) ? str_size(ssid) : 0; 749 size_t channel_data_size = 1; 750 751 uint8_t channel = 752 ieee80211_freq_to_channel(ieee80211_dev->current_freq); 753 754 /* 4 headers - (ssid, rates, ext rates, current channel) and their data 755 * lengths. 398 756 */ 399 757 size_t payload_size = 400 sizeof(ieee80211_ie_header_t) * 3 + 401 data_rates_size + ext_data_rates_size + sizeof(uint8_t) + 2; 758 sizeof(ieee80211_ie_header_t) * 4 + 759 ssid_data_size + 760 IEEE80211_DATA_RATES_SIZE + IEEE80211_EXT_DATA_RATES_SIZE + 761 channel_data_size; 402 762 403 763 size_t buffer_size = sizeof(ieee80211_mgmt_header_t) + payload_size; … … 415 775 memcpy(mgmt_header->src_addr, nic_address.address, ETH_ADDR); 416 776 memcpy(mgmt_header->bssid, ieee80211_broadcast_mac_addr, ETH_ADDR); 417 418 /* Jump to payload -> header + padding. */ 419 ieee80211_ie_header_t *rates_ie_header = (ieee80211_ie_header_t *) 420 ((void *)buffer + sizeof(ieee80211_mgmt_header_t) + 2); 421 rates_ie_header->element_id = IEEE80211_RATES_IE; 422 rates_ie_header->length = data_rates_size; 423 memcpy(rates_ie_header + sizeof(ieee80211_ie_header_t), 424 ieee80211bg_data_rates, 425 data_rates_size); 426 427 ieee80211_ie_header_t *ext_rates_ie_header = (ieee80211_ie_header_t *) 428 ((void *)rates_ie_header + sizeof(ieee80211_ie_header_t) + 429 data_rates_size); 430 ext_rates_ie_header->element_id = IEEE80211_EXT_RATES_IE; 431 ext_rates_ie_header->length = ext_data_rates_size; 432 memcpy(ext_rates_ie_header + sizeof(ieee80211_ie_header_t), 433 ieee80211bg_ext_data_rates, 434 ext_data_rates_size); 435 436 ieee80211_ie_header_t *chan_ie_header = (ieee80211_ie_header_t *) 437 ((void *)ext_rates_ie_header + sizeof(ieee80211_ie_header_t) + 438 ext_data_rates_size); 439 chan_ie_header->element_id = IEEE80211_CHANNEL_IE; 440 chan_ie_header->length = 1; 441 uint8_t *it = (uint8_t *) ((void *)chan_ie_header + 442 sizeof(ieee80211_ie_header_t)); 443 *it = ieee80211_freq_to_channel(ieee80211_dev->current_freq); 777 mgmt_header->seq_ctrl = 778 host2uint16_t_le(ieee80211_get_sequence_number(ieee80211_dev)); 779 780 /* Jump to payload. */ 781 void *it = (void *) buffer + sizeof(ieee80211_mgmt_header_t); 782 ieee80211_prepare_ie_header(&it, IEEE80211_SSID_IE, ssid_data_size, 783 (void *) ssid); 784 ieee80211_prepare_ie_header(&it, IEEE80211_RATES_IE, 785 IEEE80211_DATA_RATES_SIZE, 786 (void *) &ieee80211bg_data_rates); 787 ieee80211_prepare_ie_header(&it, IEEE80211_EXT_RATES_IE, 788 IEEE80211_EXT_DATA_RATES_SIZE, 789 (void *) &ieee80211bg_data_rates[IEEE80211_DATA_RATES_SIZE]); 790 ieee80211_prepare_ie_header(&it, IEEE80211_CHANNEL_IE, 791 channel_data_size, (void *) &channel); 444 792 445 793 ieee80211_dev->ops->tx_handler(ieee80211_dev, buffer, buffer_size); … … 451 799 452 800 /** 453 * Probeauthentication implementation.801 * IEEE 802.11 authentication implementation. 454 802 * 455 803 * @param ieee80211_dev Pointer to IEEE 802.11 device structure. … … 457 805 * @return EOK if succeed, negative error code otherwise. 458 806 */ 459 int ieee80211_probe_auth(ieee80211_dev_t *ieee80211_dev) 460 { 461 uint8_t test_bssid[] = {0x14, 0xF6, 0x5A, 0xAF, 0x5E, 0xB7}; 462 807 int ieee80211_authenticate(ieee80211_dev_t *ieee80211_dev) 808 { 463 809 nic_t *nic = nic_get_from_ddf_dev(ieee80211_dev->ddf_dev); 464 810 nic_address_t nic_address; 465 811 nic_query_address(nic, &nic_address); 466 812 813 ieee80211_scan_result_t *auth_data = 814 &ieee80211_dev->bssid_info.res_link->scan_result; 815 467 816 size_t buffer_size = sizeof(ieee80211_mgmt_header_t) + 468 817 sizeof(ieee80211_auth_body_t); 818 469 819 void *buffer = malloc(buffer_size); 470 820 memset(buffer, 0, buffer_size); … … 477 827 IEEE80211_MGMT_AUTH_FRAME 478 828 ); 479 memcpy(mgmt_header->dest_addr, test_bssid, ETH_ADDR);829 memcpy(mgmt_header->dest_addr, auth_data->bssid.address, ETH_ADDR); 480 830 memcpy(mgmt_header->src_addr, nic_address.address, ETH_ADDR); 481 memcpy(mgmt_header->bssid, test_bssid, ETH_ADDR);831 memcpy(mgmt_header->bssid, auth_data->bssid.address, ETH_ADDR); 482 832 483 833 ieee80211_auth_body_t *auth_body = … … 485 835 (buffer + sizeof(ieee80211_mgmt_header_t)); 486 836 auth_body->auth_alg = host2uint16_t_le(0); 487 auth_body->auth_trans_no = host2uint16_t_le( 0);837 auth_body->auth_trans_no = host2uint16_t_le(1); 488 838 489 839 ieee80211_dev->ops->tx_handler(ieee80211_dev, buffer, buffer_size); … … 494 844 } 495 845 846 /** 847 * IEEE 802.11 association implementation. 848 * 849 * @param ieee80211_dev Pointer to IEEE 802.11 device structure. 850 * @param password Passphrase to be used in encrypted communication or NULL 851 * for open networks. 852 * 853 * @return EOK if succeed, negative error code otherwise. 854 */ 855 int ieee80211_associate(ieee80211_dev_t *ieee80211_dev, char *password) 856 { 857 nic_t *nic = nic_get_from_ddf_dev(ieee80211_dev->ddf_dev); 858 nic_address_t nic_address; 859 nic_query_address(nic, &nic_address); 860 861 ieee80211_scan_result_link_t *auth_link = 862 ieee80211_dev->bssid_info.res_link; 863 864 ieee80211_scan_result_t *auth_data = &auth_link->scan_result; 865 866 size_t ssid_data_size = str_size(auth_data->ssid); 867 868 size_t payload_size = 869 sizeof(ieee80211_ie_header_t) * 3 + 870 ssid_data_size + 871 IEEE80211_DATA_RATES_SIZE + 872 IEEE80211_EXT_DATA_RATES_SIZE; 873 874 size_t buffer_size = 875 sizeof(ieee80211_mgmt_header_t) + 876 sizeof(ieee80211_assoc_req_body_t) + 877 payload_size; 878 879 if(auth_data->security.type == IEEE80211_SECURITY_WPA2) { 880 buffer_size += auth_link->rsn_copy_len; 881 } 882 883 void *buffer = malloc(buffer_size); 884 memset(buffer, 0, buffer_size); 885 886 ieee80211_mgmt_header_t *mgmt_header = 887 (ieee80211_mgmt_header_t *) buffer; 888 889 mgmt_header->frame_ctrl = host2uint16_t_le( 890 IEEE80211_MGMT_FRAME | 891 IEEE80211_MGMT_ASSOC_REQ_FRAME 892 ); 893 memcpy(mgmt_header->dest_addr, auth_data->bssid.address, ETH_ADDR); 894 memcpy(mgmt_header->src_addr, nic_address.address, ETH_ADDR); 895 memcpy(mgmt_header->bssid, auth_data->bssid.address, ETH_ADDR); 896 897 ieee80211_assoc_req_body_t *assoc_body = 898 (ieee80211_assoc_req_body_t *) 899 (buffer + sizeof(ieee80211_mgmt_header_t)); 900 assoc_body->listen_interval = host2uint16_t_le(1); 901 902 /* Jump to payload. */ 903 void *it = buffer + sizeof(ieee80211_mgmt_header_t) + 904 sizeof(ieee80211_assoc_req_body_t); 905 ieee80211_prepare_ie_header(&it, IEEE80211_SSID_IE, 906 ssid_data_size, (void *) auth_data->ssid); 907 ieee80211_prepare_ie_header(&it, IEEE80211_RATES_IE, 908 IEEE80211_DATA_RATES_SIZE, 909 (void *) &ieee80211bg_data_rates); 910 ieee80211_prepare_ie_header(&it, IEEE80211_EXT_RATES_IE, 911 IEEE80211_EXT_DATA_RATES_SIZE, 912 (void *) &ieee80211bg_data_rates[IEEE80211_DATA_RATES_SIZE]); 913 914 if(auth_data->security.type != IEEE80211_SECURITY_OPEN) { 915 assoc_body->capability |= host2uint16_t_le(CAP_SECURITY); 916 } 917 918 if(auth_data->security.type == IEEE80211_SECURITY_WPA2) { 919 memcpy(it, auth_link->rsn_copy, auth_link->rsn_copy_len); 920 } 921 922 ieee80211_dev->ops->tx_handler(ieee80211_dev, buffer, buffer_size); 923 924 /* 925 * Save password and SSID to be used in eventual authentication 926 * handshake. 927 */ 928 memcpy(ieee80211_dev->bssid_info.password, password, 929 str_size(password)); 930 931 free(buffer); 932 933 return EOK; 934 } 935 936 /** 937 * IEEE 802.11 deauthentication implementation. 938 * 939 * @param ieee80211_dev Pointer to IEEE 802.11 device structure. 940 * 941 * @return EOK if succeed, negative error code otherwise. 942 */ 943 int ieee80211_deauthenticate(ieee80211_dev_t *ieee80211_dev) 944 { 945 ieee80211_scan_result_t *auth_data = 946 &ieee80211_dev->bssid_info.res_link->scan_result; 947 948 ieee80211_dev->current_auth_phase = IEEE80211_AUTH_DISCONNECTED; 949 ieee80211_dev->bssid_info.aid = (uint16_t) -1; 950 memcpy(auth_data->bssid.address, ieee80211_broadcast_mac_addr, 951 ETH_ADDR); 952 953 nic_t *nic = nic_get_from_ddf_dev(ieee80211_dev->ddf_dev); 954 nic_address_t nic_address; 955 nic_query_address(nic, &nic_address); 956 957 size_t buffer_size = sizeof(ieee80211_mgmt_header_t) + 958 sizeof(ieee80211_deauth_body_t); 959 void *buffer = malloc(buffer_size); 960 memset(buffer, 0, buffer_size); 961 962 ieee80211_mgmt_header_t *mgmt_header = 963 (ieee80211_mgmt_header_t *) buffer; 964 965 mgmt_header->frame_ctrl = host2uint16_t_le( 966 IEEE80211_MGMT_FRAME | 967 IEEE80211_MGMT_DEAUTH_FRAME 968 ); 969 memcpy(mgmt_header->dest_addr, auth_data->bssid.address, ETH_ADDR); 970 memcpy(mgmt_header->src_addr, nic_address.address, ETH_ADDR); 971 memcpy(mgmt_header->bssid, auth_data->bssid.address, ETH_ADDR); 972 973 ieee80211_dev->ops->tx_handler(ieee80211_dev, buffer, buffer_size); 974 975 free(buffer); 976 977 ieee80211_dev->ops->bssid_change(ieee80211_dev); 978 979 return EOK; 980 } 981 982 static void ieee80211_process_auth_info(ieee80211_scan_result_link_t *ap_data, 983 void *buffer) 984 { 985 uint8_t *it = (uint8_t *) buffer; 986 987 uint16_t *version = (uint16_t *) it; 988 if(uint16_t_le2host(*version) != 0x1) { 989 ap_data->scan_result.security.type = -1; 990 return; 991 } 992 993 it += sizeof(uint16_t); 994 995 uint32_t group_cipher = *(it+3); 996 switch(group_cipher) { 997 case IEEE80211_AUTH_CIPHER_TKIP: 998 ap_data->scan_result.security.group_alg = 999 IEEE80211_SECURITY_SUITE_TKIP; 1000 break; 1001 case IEEE80211_AUTH_CIPHER_CCMP: 1002 ap_data->scan_result.security.group_alg = 1003 IEEE80211_SECURITY_SUITE_CCMP; 1004 break; 1005 default: 1006 ap_data->scan_result.security.group_alg = -1; 1007 } 1008 1009 it += 4*sizeof(uint8_t); 1010 1011 uint16_t *pairwise_count = (uint16_t *) it; 1012 uint32_t pairwise_cipher = *(it+sizeof(uint16_t)+3); 1013 switch(pairwise_cipher) { 1014 case IEEE80211_AUTH_CIPHER_TKIP: 1015 ap_data->scan_result.security.pair_alg = 1016 IEEE80211_SECURITY_SUITE_TKIP; 1017 break; 1018 case IEEE80211_AUTH_CIPHER_CCMP: 1019 ap_data->scan_result.security.pair_alg = 1020 IEEE80211_SECURITY_SUITE_CCMP; 1021 break; 1022 default: 1023 ap_data->scan_result.security.pair_alg = -1; 1024 } 1025 1026 it += 2*sizeof(uint16_t) + 1027 uint16_t_le2host(*pairwise_count)*sizeof(uint32_t); 1028 1029 uint32_t auth_suite = *(it+3); 1030 switch(auth_suite) { 1031 case IEEE80211_AUTH_AKM_PSK: 1032 ap_data->scan_result.security.auth = 1033 IEEE80211_SECURITY_AUTH_PSK; 1034 break; 1035 case IEEE80211_AUTH_AKM_8021X: 1036 ap_data->scan_result.security.auth = 1037 IEEE80211_SECURITY_AUTH_8021X; 1038 break; 1039 default: 1040 ap_data->scan_result.security.auth = -1; 1041 } 1042 } 1043 1044 static uint32_t uint32_from_uint8_seq(uint8_t *seq) 1045 { 1046 return (*seq << 24) + (*(seq+1) << 16) + (*(seq+2) << 8) + *(seq+3); 1047 } 1048 1049 static uint8_t *ieee80211_process_ies(ieee80211_dev_t *ieee80211_dev, 1050 ieee80211_scan_result_link_t *ap_data, void *buffer, size_t buffer_size) 1051 { 1052 void *it = buffer; 1053 while((it + sizeof(ieee80211_ie_header_t)) < buffer + buffer_size) { 1054 ieee80211_ie_header_t *ie_header = 1055 (ieee80211_ie_header_t *) it; 1056 uint8_t *channel; 1057 switch(ie_header->element_id) { 1058 case IEEE80211_CHANNEL_IE: 1059 channel = (uint8_t *) 1060 (it + sizeof(ieee80211_ie_header_t)); 1061 ap_data->scan_result.channel = *channel; 1062 break; 1063 case IEEE80211_RSN_IE: 1064 if(!ap_data) 1065 break; 1066 ap_data->scan_result.security.type = 1067 IEEE80211_SECURITY_WPA2; 1068 ieee80211_process_auth_info(ap_data, 1069 it + sizeof(ieee80211_ie_header_t)); 1070 ap_data->rsn_copy_len = ie_header->length + 1071 sizeof(ieee80211_ie_header_t); 1072 memcpy(ap_data->rsn_copy, 1073 it, 1074 ap_data->rsn_copy_len); 1075 break; 1076 case IEEE80211_VENDOR_IE: 1077 if(uint32_from_uint8_seq(it + 1078 sizeof(ieee80211_ie_header_t)) == 1079 WPA_OUI) { 1080 if(ap_data->scan_result.security.type == 1081 IEEE80211_SECURITY_WPA2) { 1082 break; 1083 } 1084 ap_data->scan_result.security.type = 1085 IEEE80211_SECURITY_WPA; 1086 ieee80211_process_auth_info(ap_data, 1087 it + 1088 sizeof(ieee80211_ie_header_t) + 1089 sizeof(uint32_t)); 1090 } else if(uint32_from_uint8_seq(it + 1091 sizeof(ieee80211_ie_header_t)) == 1092 GTK_OUI) { 1093 return it + 1094 sizeof(ieee80211_ie_header_t) + 1095 sizeof(uint32_t) + 2; 1096 } 1097 } 1098 it += sizeof(ieee80211_ie_header_t) + ie_header->length; 1099 } 1100 1101 return NULL; 1102 } 1103 496 1104 /** 497 1105 * Process probe response and store results. 498 1106 * 499 1107 * @param ieee80211_dev Pointer to IEEE 802.11 device structure. 1108 * @param mgmt_header Pointer to start of management frame header. 500 1109 * 501 1110 * @return EOK if succeed, negative error code otherwise. 502 1111 */ 503 1112 static int ieee80211_process_probe_response(ieee80211_dev_t *ieee80211_dev, 1113 ieee80211_mgmt_header_t *mgmt_header, size_t buffer_size) 1114 { 1115 ieee80211_beacon_start_t *beacon_body = (ieee80211_beacon_start_t *) 1116 ((void *)mgmt_header + sizeof(ieee80211_mgmt_header_t)); 1117 1118 ieee80211_ie_header_t *ssid_ie_header = (ieee80211_ie_header_t *) 1119 ((void *)beacon_body + sizeof(ieee80211_beacon_start_t)); 1120 1121 /* Not empty SSID. */ 1122 if(ssid_ie_header->length > 0) { 1123 fibril_mutex_t *scan_mutex = &ieee80211_dev->ap_list.scan_mutex; 1124 1125 fibril_mutex_lock(scan_mutex); 1126 1127 ieee80211_scan_result_list_t *result_list = 1128 &ieee80211_dev->ap_list; 1129 1130 uint8_t *ssid_start = (uint8_t *) ((void *)ssid_ie_header + 1131 sizeof(ieee80211_ie_header_t)); 1132 char ssid[IEEE80211_MAX_SSID_LENGTH]; 1133 memcpy(ssid, ssid_start, ssid_ie_header->length); 1134 ssid[ssid_ie_header->length] = '\0'; 1135 1136 /* Check whether SSID is already in results. */ 1137 ieee80211_scan_result_list_foreach(*result_list, result) { 1138 if(!str_cmp(ssid, result->scan_result.ssid)) { 1139 result->last_beacon = time(NULL); 1140 fibril_mutex_unlock(scan_mutex); 1141 return EOK; 1142 } 1143 } 1144 1145 /* Results are full. */ 1146 if(result_list->size == IEEE80211_MAX_RESULTS_LENGTH - 1) { 1147 fibril_mutex_unlock(scan_mutex); 1148 return EOK; 1149 } 1150 1151 ieee80211_scan_result_link_t *ap_data = 1152 malloc(sizeof(ieee80211_scan_result_link_t)); 1153 memset(ap_data, 0, sizeof(ieee80211_scan_result_link_t)); 1154 link_initialize(&ap_data->link); 1155 1156 memcpy(ap_data->scan_result.bssid.address, 1157 mgmt_header->bssid, ETH_ADDR); 1158 memcpy(ap_data->scan_result.ssid, ssid, 1159 ssid_ie_header->length + 1); 1160 1161 if(uint16_t_le2host(beacon_body->capability) & CAP_SECURITY) { 1162 ap_data->scan_result.security.type = 1163 IEEE80211_SECURITY_WEP; 1164 } else { 1165 ap_data->scan_result.security.type = 1166 IEEE80211_SECURITY_OPEN; 1167 ap_data->scan_result.security.auth = -1; 1168 ap_data->scan_result.security.pair_alg = -1; 1169 ap_data->scan_result.security.group_alg = -1; 1170 } 1171 1172 void *rest_ies_start = ssid_start + ssid_ie_header->length; 1173 size_t rest_buffer_size = 1174 buffer_size - 1175 sizeof(ieee80211_mgmt_header_t) - 1176 sizeof(ieee80211_beacon_start_t) - 1177 sizeof(ieee80211_ie_header_t) - 1178 ssid_ie_header->length; 1179 1180 ieee80211_process_ies(ieee80211_dev, ap_data, rest_ies_start, 1181 rest_buffer_size); 1182 1183 ap_data->last_beacon = time(NULL); 1184 1185 ieee80211_scan_result_list_append(result_list, ap_data); 1186 1187 fibril_mutex_unlock(scan_mutex); 1188 } 1189 1190 return EOK; 1191 } 1192 1193 /** 1194 * Process authentication response. 1195 * 1196 * @param ieee80211_dev Pointer to IEEE 802.11 device structure. 1197 * @param mgmt_header Pointer to start of management frame header. 1198 * 1199 * @return EOK if succeed, negative error code otherwise. 1200 */ 1201 static int ieee80211_process_auth_response(ieee80211_dev_t *ieee80211_dev, 504 1202 ieee80211_mgmt_header_t *mgmt_header) 505 1203 { 506 ieee80211_ie_header_t *ssid_ie_header = (ieee80211_ie_header_t *) 507 ((void *)mgmt_header + sizeof(ieee80211_mgmt_header_t) + 508 sizeof(ieee80211_beacon_start_t)); 509 510 if(ssid_ie_header->length > 0) { 511 uint8_t *results_length = &ieee80211_dev->ap_list.length; 512 513 ieee80211_scan_result_t *ap_data = 514 &ieee80211_dev->ap_list.results[(*results_length)++]; 515 516 memset(ap_data, 0, sizeof(ieee80211_scan_result_t)); 517 518 uint8_t *ssid_start = (uint8_t *) 519 ((void *)ssid_ie_header + 520 sizeof(ieee80211_ie_header_t)); 521 522 memcpy(ap_data->bssid.address, mgmt_header->bssid, ETH_ADDR); 523 memcpy(ap_data->ssid, ssid_start, ssid_ie_header->length); 524 ap_data->ssid[ssid_ie_header->length] = '\0'; 1204 fibril_mutex_lock(&ieee80211_dev->gen_mutex); 1205 1206 ieee80211_dev->current_auth_phase = IEEE80211_AUTH_AUTHENTICATED; 1207 1208 fibril_condvar_signal(&ieee80211_dev->gen_cond); 1209 fibril_mutex_unlock(&ieee80211_dev->gen_mutex); 1210 1211 return EOK; 1212 } 1213 1214 /** 1215 * Process association response. 1216 * 1217 * @param ieee80211_dev Pointer to IEEE 802.11 device structure. 1218 * @param mgmt_header Pointer to start of management frame header. 1219 * 1220 * @return EOK if succeed, negative error code otherwise. 1221 */ 1222 static int ieee80211_process_assoc_response(ieee80211_dev_t *ieee80211_dev, 1223 ieee80211_mgmt_header_t *mgmt_header) 1224 { 1225 ieee80211_scan_result_t *auth_data = 1226 &ieee80211_dev->bssid_info.res_link->scan_result; 1227 1228 fibril_mutex_lock(&ieee80211_dev->gen_mutex); 1229 1230 ieee80211_assoc_resp_body_t *assoc_resp = 1231 (ieee80211_assoc_resp_body_t *) ((void *)mgmt_header + 1232 sizeof(ieee80211_mgmt_header_t)); 1233 1234 ieee80211_dev->bssid_info.aid = uint16_t_le2host(assoc_resp->aid); 1235 memcpy(auth_data->bssid.address, mgmt_header->bssid, ETH_ADDR); 1236 1237 ieee80211_dev->current_auth_phase = IEEE80211_AUTH_ASSOCIATED; 1238 1239 ieee80211_dev->ops->bssid_change(ieee80211_dev); 1240 1241 fibril_condvar_signal(&ieee80211_dev->gen_cond); 1242 fibril_mutex_unlock(&ieee80211_dev->gen_mutex); 1243 1244 return EOK; 1245 } 1246 1247 static int ieee80211_process_4way_handshake(ieee80211_dev_t *ieee80211_dev, 1248 void *buffer, size_t buffer_size) 1249 { 1250 ieee80211_eapol_key_frame_t *key_frame = 1251 (ieee80211_eapol_key_frame_t *) buffer; 1252 1253 bool handshake_done = false; 1254 1255 ieee80211_scan_result_link_t *auth_link = 1256 ieee80211_dev->bssid_info.res_link; 1257 1258 ieee80211_scan_result_t *auth_data = &auth_link->scan_result; 1259 uint8_t *ptk = ieee80211_dev->bssid_info.ptk; 1260 uint8_t *gtk = ieee80211_dev->bssid_info.gtk; 1261 1262 size_t ptk_key_length, gtk_key_length; 1263 hash_func_t hash_sel; 1264 switch(auth_data->security.pair_alg) { 1265 case IEEE80211_SECURITY_SUITE_CCMP: 1266 ptk_key_length = IEEE80211_PTK_CCMP_LENGTH; 1267 hash_sel = HASH_SHA1; 1268 break; 1269 default: 1270 return ENOTSUP; 1271 } 1272 1273 switch(auth_data->security.group_alg) { 1274 case IEEE80211_SECURITY_SUITE_CCMP: 1275 gtk_key_length = IEEE80211_GTK_CCMP_LENGTH; 1276 break; 1277 default: 1278 return ENOTSUP; 1279 } 1280 1281 size_t output_size = 1282 sizeof(eth_header_t) + 1283 sizeof(ieee80211_eapol_key_frame_t); 1284 1285 if(!(uint16_t_be2host(key_frame->key_info) & 1286 IEEE80211_EAPOL_KEY_KEYINFO_SECURE)) { 1287 output_size += auth_link->rsn_copy_len; 1288 } 1289 1290 nic_t *nic = nic_get_from_ddf_dev(ieee80211_dev->ddf_dev); 1291 nic_address_t nic_address; 1292 nic_query_address(nic, &nic_address); 1293 1294 void *output_buffer = malloc(output_size); 1295 memset(output_buffer, 0, output_size); 1296 1297 /* Setup ethernet header. */ 1298 eth_header_t *eth_header = (eth_header_t *) output_buffer; 1299 memcpy(eth_header->dest_addr, auth_data->bssid.address, ETH_ADDR); 1300 memcpy(eth_header->src_addr, nic_address.address, ETH_ADDR); 1301 eth_header->proto = host2uint16_t_be(ETH_TYPE_PAE); 1302 1303 ieee80211_eapol_key_frame_t *output_key_frame = 1304 (ieee80211_eapol_key_frame_t *) 1305 (output_buffer + sizeof(eth_header_t)); 1306 1307 /* Copy content of incoming EAPOL-Key frame. */ 1308 memcpy((void *) output_key_frame, buffer, 1309 sizeof(ieee80211_eapol_key_frame_t)); 1310 1311 output_key_frame->proto_version = 0x1; 1312 output_key_frame->key_length = 0; 1313 output_key_frame->body_length = 1314 host2uint16_t_be(output_size - sizeof(eth_header_t)-4); 1315 output_key_frame->key_info &= 1316 ~host2uint16_t_be( 1317 IEEE80211_EAPOL_KEY_KEYINFO_ACK 1318 ); 1319 1320 /* 1321 * Check if it is last or first incoming message in 4-way 1322 * handshake. 1323 */ 1324 if(uint16_t_be2host(key_frame->key_info) & 1325 IEEE80211_EAPOL_KEY_KEYINFO_SECURE) { 1326 output_key_frame->key_info &= 1327 ~host2uint16_t_be( 1328 IEEE80211_EAPOL_KEY_KEYINFO_ENCDATA 1329 ); 1330 output_key_frame->key_info &= 1331 ~host2uint16_t_be( 1332 IEEE80211_EAPOL_KEY_KEYINFO_INSTALL 1333 ); 1334 output_key_frame->key_data_length = 0; 1335 output_key_frame->key_length = 0; 1336 memset(output_key_frame->key_nonce, 0, 32); 1337 memset(output_key_frame->key_mic, 0, 16); 1338 memset(output_key_frame->key_rsc, 0, 8); 1339 memset(output_key_frame->eapol_key_iv, 0, 16); 1340 1341 /* Derive GTK and save it. */ 1342 uint16_t key_data_length = 1343 uint16_t_be2host(key_frame->key_data_length); 1344 uint16_t decrypt_len = key_data_length - 8; 1345 uint8_t key_data[decrypt_len]; 1346 uint8_t *data_ptr = (uint8_t *) (buffer + 1347 sizeof(ieee80211_eapol_key_frame_t)); 1348 if(ieee80211_aes_key_unwrap(ptk + KEK_OFFSET, data_ptr, 1349 key_data_length, key_data) == EOK) { 1350 1351 uint8_t *key_ptr = ieee80211_process_ies(ieee80211_dev, 1352 NULL, key_data, decrypt_len); 1353 1354 if(key_ptr) { 1355 memcpy(gtk, key_ptr, gtk_key_length); 1356 handshake_done = true; 1357 } 1358 } 1359 } else { 1360 output_key_frame->key_info |= 1361 host2uint16_t_be( 1362 IEEE80211_EAPOL_KEY_KEYINFO_MIC 1363 ); 1364 output_key_frame->key_data_length = 1365 host2uint16_t_be(auth_link->rsn_copy_len); 1366 memcpy((void *)output_key_frame + 1367 sizeof(ieee80211_eapol_key_frame_t), 1368 auth_link->rsn_copy, 1369 auth_link->rsn_copy_len); 1370 1371 /* Compute PMK. */ 1372 uint8_t pmk[PBKDF2_KEY_LENGTH]; 1373 pbkdf2((uint8_t *) ieee80211_dev->bssid_info.password, 1374 str_size(ieee80211_dev->bssid_info.password), 1375 (uint8_t *) auth_data->ssid, 1376 str_size(auth_data->ssid), pmk, hash_sel); 1377 1378 uint8_t *anonce = key_frame->key_nonce; 1379 1380 /* Generate SNONCE. */ 1381 uint8_t snonce[32]; 1382 rnd_sequence(snonce, 32); 1383 1384 memcpy(output_key_frame->key_nonce, snonce, 32); 1385 1386 uint8_t *dest_addr = eth_header->dest_addr; 1387 uint8_t *src_addr = eth_header->src_addr; 1388 1389 /* Derive PTK and save it. */ 1390 uint8_t prf_result[ptk_key_length]; 1391 uint8_t crypt_data[PRF_CRYPT_DATA_LENGTH]; 1392 memcpy(crypt_data, 1393 min_sequence(dest_addr, src_addr, ETH_ADDR), 1394 ETH_ADDR); 1395 memcpy(crypt_data + ETH_ADDR, 1396 max_sequence(dest_addr, src_addr, ETH_ADDR), 1397 ETH_ADDR); 1398 memcpy(crypt_data + 2*ETH_ADDR, 1399 min_sequence(anonce, snonce, 32), 1400 32); 1401 memcpy(crypt_data + 2*ETH_ADDR + 32, 1402 max_sequence(anonce, snonce, 32), 1403 32); 1404 ieee80211_prf(pmk, crypt_data, prf_result, hash_sel); 1405 memcpy(ptk, prf_result, ptk_key_length); 1406 } 1407 1408 /* Compute MIC of key frame data from KCK part of PTK. */ 1409 uint8_t mic[SHA1_HASH_LENGTH]; 1410 hmac(ptk, 16, (uint8_t *) output_key_frame, 1411 output_size - sizeof(eth_header_t), mic, hash_sel); 1412 1413 memcpy(output_key_frame->key_mic, mic, 16); 1414 1415 ieee80211_send_frame(nic, output_buffer, output_size); 1416 1417 free(output_buffer); 1418 1419 if(handshake_done) { 1420 /* Insert keys into device. */ 1421 1422 /* Pairwise key. */ 1423 ieee80211_key_config_t key_config; 1424 key_config.suite = auth_data->security.pair_alg; 1425 key_config.flags = 1426 IEEE80211_KEY_FLAG_TYPE_PAIRWISE; 1427 memcpy(key_config.data, 1428 ptk + TK_OFFSET, 1429 ptk_key_length - TK_OFFSET); 1430 1431 ieee80211_dev->ops->key_config(ieee80211_dev, 1432 &key_config, true); 1433 1434 /* Group key. */ 1435 key_config.suite = auth_data->security.group_alg; 1436 key_config.flags = 1437 IEEE80211_KEY_FLAG_TYPE_GROUP; 1438 memcpy(key_config.data, gtk, gtk_key_length); 1439 1440 ieee80211_dev->ops->key_config(ieee80211_dev, 1441 &key_config, true); 1442 1443 /* Signal successful handshake completion. */ 1444 fibril_mutex_lock(&ieee80211_dev->gen_mutex); 1445 fibril_condvar_signal(&ieee80211_dev->gen_cond); 1446 fibril_mutex_unlock(&ieee80211_dev->gen_mutex); 1447 } 1448 1449 return EOK; 1450 } 1451 1452 static int ieee80211_process_eapol_frame(ieee80211_dev_t *ieee80211_dev, 1453 void *buffer, size_t buffer_size) 1454 { 1455 ieee80211_eapol_key_frame_t *key_frame = 1456 (ieee80211_eapol_key_frame_t *) buffer; 1457 if(ieee80211_is_eapol_key_frame(key_frame)) { 1458 return ieee80211_process_4way_handshake(ieee80211_dev, buffer, 1459 buffer_size); 1460 } 1461 1462 return EOK; 1463 } 1464 1465 /** 1466 * Process data frame. 1467 * 1468 * @param ieee80211_dev Pointer to IEEE 802.11 device structure. 1469 * @param buffer Data buffer starting with IEEE 802.11 data header. 1470 * @param buffer_size Size of buffer. 1471 * 1472 * @return EOK if succeed, negative error code otherwise. 1473 */ 1474 static int ieee80211_process_data(ieee80211_dev_t *ieee80211_dev, 1475 void *buffer, size_t buffer_size) 1476 { 1477 ieee80211_data_header_t *data_header = 1478 (ieee80211_data_header_t *) buffer; 1479 1480 if(ieee80211_has_data_frame(data_header->frame_ctrl)) { 1481 nic_t *nic = nic_get_from_ddf_dev(ieee80211_dev->ddf_dev); 1482 size_t strip_length = sizeof(ieee80211_data_header_t) + 1483 ARRAY_SIZE(rfc1042_header); 1484 1485 /* TODO: Probably different by used security alg. */ 1486 if(ieee80211_is_encrypted_frame(data_header->frame_ctrl)) { 1487 strip_length += 8; 1488 } 1489 1490 /* Process 4-way authentication handshake. */ 1491 uint16_t *proto = (uint16_t *) (buffer + strip_length); 1492 if(uint16_t_be2host(*proto) == ETH_TYPE_PAE) { 1493 return ieee80211_process_eapol_frame(ieee80211_dev, 1494 buffer + strip_length + sizeof(uint16_t), 1495 buffer_size - strip_length - sizeof(uint16_t)); 1496 } 1497 1498 /* Note: ETH protocol ID is already there, so we don't create 1499 * whole ETH header. */ 1500 size_t frame_size = 1501 buffer_size - strip_length + sizeof(eth_header_t)-2; 1502 nic_frame_t *frame = nic_alloc_frame(nic, frame_size); 1503 1504 if(frame == NULL) { 1505 return ENOMEM; 1506 } 1507 1508 uint8_t *src_addr = 1509 ieee80211_is_fromds_frame(data_header->frame_ctrl) ? 1510 data_header->address3 : data_header->address2; 1511 uint8_t *dest_addr = 1512 ieee80211_is_tods_frame(data_header->frame_ctrl) ? 1513 data_header->address3 : data_header->address1; 1514 1515 eth_header_t *eth_header = 1516 (eth_header_t *) frame->data; 1517 memcpy(eth_header->src_addr, src_addr, ETH_ADDR); 1518 memcpy(eth_header->dest_addr, dest_addr, ETH_ADDR); 1519 1520 memcpy(frame->data + sizeof(eth_header_t)-2, 1521 buffer + strip_length, 1522 buffer_size - strip_length); 1523 1524 nic_received_frame(nic, frame); 525 1525 } 526 1526 … … 548 1548 ieee80211_is_beacon_frame(mgmt_header->frame_ctrl)) { 549 1549 return ieee80211_process_probe_response(ieee80211_dev, 1550 mgmt_header, buffer_size); 1551 } 1552 1553 if(ieee80211_is_auth_frame(mgmt_header->frame_ctrl)) { 1554 return ieee80211_process_auth_response(ieee80211_dev, 550 1555 mgmt_header); 551 1556 } 552 // TODO 1557 1558 if(ieee80211_is_assoc_response_frame(mgmt_header->frame_ctrl)) { 1559 return ieee80211_process_assoc_response(ieee80211_dev, 1560 mgmt_header); 1561 } 553 1562 } else if(ieee80211_is_data_frame(frame_ctrl)) { 554 nic_t *nic = nic_get_from_ddf_dev(ieee80211_dev->ddf_dev); 555 size_t frame_size = buffer_size - sizeof(ieee80211_data_header_t); 556 nic_frame_t *frame = nic_alloc_frame(nic, frame_size); 557 if (frame != NULL) { 558 memcpy(frame->data, 559 buffer + sizeof(ieee80211_data_header_t), 560 frame_size); 561 nic_received_frame(nic, frame); 562 } 563 } else { 564 // TODO 1563 return ieee80211_process_data(ieee80211_dev, buffer, 1564 buffer_size); 565 1565 } 566 1566 -
uspace/lib/ieee80211/src/ieee80211_iface_impl.c
r59fa7ab r1dcc0b9 27 27 */ 28 28 29 #include <st dio.h>29 #include <str.h> 30 30 #include <errno.h> 31 31 … … 42 42 */ 43 43 44 /** 45 * Implementation of fetching scan results. 46 * 47 * @param fun Device function. 48 * @param results Structure where should be stored scan results. 49 * 50 * @return EOK. 51 */ 44 52 int ieee80211_get_scan_results_impl(ddf_fun_t *fun, 45 ieee80211_scan_results_t *results )53 ieee80211_scan_results_t *results, bool now) 46 54 { 47 55 nic_t *nic_data = nic_get_from_ddf_fun(fun); 48 56 ieee80211_dev_t *ieee80211_dev = nic_get_specific(nic_data); 49 57 58 if(!ieee80211_is_ready(ieee80211_dev)) 59 return EREFUSED; 60 61 fibril_mutex_lock(&ieee80211_dev->ap_list.scan_mutex); 62 time_t scan_span = time(NULL) - ieee80211_dev->ap_list.last_scan; 63 fibril_mutex_unlock(&ieee80211_dev->ap_list.scan_mutex); 64 65 if(now || scan_span > MAX_SCAN_SPAN_SEC) { 66 ieee80211_dev->ops->scan(ieee80211_dev); 67 } 68 69 fibril_mutex_lock(&ieee80211_dev->ap_list.scan_mutex); 50 70 if(results) { 51 memcpy(results, &ieee80211_dev->ap_list, 52 sizeof(ieee80211_scan_results_t)); 53 } 71 ieee80211_scan_result_list_t *result_list = 72 &ieee80211_dev->ap_list; 73 74 int i = 0; 75 ieee80211_scan_result_list_foreach(*result_list, result) { 76 memcpy(&results->results[i], 77 &result->scan_result, 78 sizeof(ieee80211_scan_result_t)); 79 i++; 80 } 81 82 results->length = i; 83 } 84 fibril_mutex_unlock(&ieee80211_dev->ap_list.scan_mutex); 54 85 55 86 return EOK; 56 87 } 57 88 58 int ieee80211_connect_impl(ddf_fun_t *fun, char *ssid, char *password) 59 { 60 assert(ssid); 89 static uint16_t ieee80211_channel_to_freq(uint8_t channel) 90 { 91 return IEEE80211_CHANNEL_GAP * (channel - 1) + IEEE80211_FIRST_FREQ; 92 } 93 94 /** 95 * Working procedure of connect function. 96 * 97 * @param ieee80211_dev Pointer to IEEE 802.11 device. 98 * @param auth_data Selected AP data we want to connect to. 99 * 100 * @return EOK if everything OK, ETIMEOUT when timeout during authenticating. 101 */ 102 static int ieee80211_connect_proc(ieee80211_dev_t *ieee80211_dev, 103 ieee80211_scan_result_link_t *auth_data, char *password) 104 { 105 int rc; 106 107 ieee80211_dev->bssid_info.res_link = auth_data; 108 109 /* Set channel. */ 110 rc = ieee80211_dev->ops->set_freq(ieee80211_dev, 111 ieee80211_channel_to_freq(auth_data->scan_result.channel)); 112 if(rc != EOK) 113 return rc; 114 115 /* Try to authenticate. */ 116 ieee80211_authenticate(ieee80211_dev); 117 fibril_mutex_lock(&ieee80211_dev->gen_mutex); 118 rc = fibril_condvar_wait_timeout(&ieee80211_dev->gen_cond, 119 &ieee80211_dev->gen_mutex, 120 AUTH_TIMEOUT); 121 fibril_mutex_unlock(&ieee80211_dev->gen_mutex); 122 if(rc != EOK) 123 return rc; 124 if(ieee80211_dev->current_auth_phase != IEEE80211_AUTH_AUTHENTICATED) 125 return EINVAL; 126 127 /* Try to associate. */ 128 ieee80211_associate(ieee80211_dev, password); 129 fibril_mutex_lock(&ieee80211_dev->gen_mutex); 130 rc = fibril_condvar_wait_timeout(&ieee80211_dev->gen_cond, 131 &ieee80211_dev->gen_mutex, 132 AUTH_TIMEOUT); 133 fibril_mutex_unlock(&ieee80211_dev->gen_mutex); 134 if(rc != EOK) 135 return rc; 136 if(ieee80211_dev->current_auth_phase != IEEE80211_AUTH_ASSOCIATED) 137 return EINVAL; 138 139 /* On open network, we are finished. */ 140 if(auth_data->scan_result.security.type == IEEE80211_SECURITY_OPEN) 141 return EOK; 142 143 /* Otherwise wait for 4-way handshake to complete. */ 144 fibril_mutex_lock(&ieee80211_dev->gen_mutex); 145 rc = fibril_condvar_wait_timeout(&ieee80211_dev->gen_cond, 146 &ieee80211_dev->gen_mutex, 147 HANDSHAKE_TIMEOUT); 148 fibril_mutex_unlock(&ieee80211_dev->gen_mutex); 149 if(rc != EOK) 150 return rc; 151 if(ieee80211_dev->current_auth_phase != IEEE80211_AUTH_ASSOCIATED) 152 return EINVAL; 153 154 return EOK; 155 } 156 157 /** 158 * Implementation of connecting to specified SSID. 159 * 160 * @param fun Device function. 161 * @param ssid_start SSID prefix of access point we want to connect to. 162 * 163 * @return EOK if everything OK, ETIMEOUT when timeout during authenticating, 164 * EINVAL when SSID not in scan results list, EPERM when incorrect password 165 * passed. 166 */ 167 int ieee80211_connect_impl(ddf_fun_t *fun, char *ssid_start, char *password) 168 { 169 assert(ssid_start); 61 170 assert(password); 62 171 63 /*64 172 nic_t *nic_data = nic_get_from_ddf_fun(fun); 65 173 ieee80211_dev_t *ieee80211_dev = nic_get_specific(nic_data); 66 */ 67 68 // TODO 69 70 return EOK; 174 175 if(!ieee80211_is_ready(ieee80211_dev)) 176 return EREFUSED; 177 178 if(ieee80211_is_connected(ieee80211_dev)) { 179 int rc = ieee80211_dev->iface->disconnect(fun); 180 if(rc != EOK) 181 return rc; 182 } 183 184 fibril_mutex_lock(&ieee80211_dev->ap_list.scan_mutex); 185 186 ieee80211_scan_result_list_foreach(ieee80211_dev->ap_list, result) { 187 if(!str_lcmp(ssid_start, 188 result->scan_result.ssid, 189 str_size(ssid_start))) { 190 fibril_mutex_unlock(&ieee80211_dev->ap_list.scan_mutex); 191 return ieee80211_connect_proc(ieee80211_dev, result, 192 password); 193 } 194 } 195 196 fibril_mutex_unlock(&ieee80211_dev->ap_list.scan_mutex); 197 198 return EINVAL; 199 } 200 201 /** 202 * Implementation of disconnecting device from network. 203 * 204 * @param fun Device function. 205 * 206 * @return EOK if everything OK, EINVAL when not connected to any network. 207 */ 208 int ieee80211_disconnect_impl(ddf_fun_t *fun) 209 { 210 nic_t *nic_data = nic_get_from_ddf_fun(fun); 211 ieee80211_dev_t *ieee80211_dev = nic_get_specific(nic_data); 212 213 if(!ieee80211_is_ready(ieee80211_dev)) 214 return EREFUSED; 215 216 if(!ieee80211_is_connected(ieee80211_dev)) { 217 return EINVAL; 218 } else { 219 return ieee80211_deauthenticate(ieee80211_dev); 220 } 71 221 } 72 222 -
uspace/lib/ieee80211/src/ieee80211_impl.c
r59fa7ab r1dcc0b9 36 36 */ 37 37 38 #include <stdio.h> 39 #include <crypto.h> 40 #include <stdlib.h> 38 41 #include <errno.h> 39 42 … … 81 84 82 85 /** 86 * Default implementation of IEEE802.11 BSSID change function. 87 * 88 * @param ieee80211_dev Structure of IEEE802.11 device. 89 * 90 * @return EOK. 91 */ 92 int ieee80211_bssid_change_impl(ieee80211_dev_t *ieee80211_dev) 93 { 94 return EOK; 95 } 96 97 /** 98 * Default implementation of IEEE802.11 key config function. 99 * 100 * @param ieee80211_dev Structure of IEEE802.11 device. 101 * 102 * @return EOK. 103 */ 104 int ieee80211_key_config_impl(ieee80211_dev_t *ieee80211_dev, 105 ieee80211_key_config_t *key_conf, bool insert) 106 { 107 return EOK; 108 } 109 110 /** 83 111 * Default implementation of IEEE802.11 scan function. 84 112 * 85 113 * @param ieee80211_dev Structure of IEEE802.11 device. 86 * @param results Pointer to structure where should be scan results stored.114 * @param clear Whether to clear current scan results. 87 115 * 88 116 * @return EOK if succeed, negative error code otherwise. … … 90 118 int ieee80211_scan_impl(ieee80211_dev_t *ieee80211_dev) 91 119 { 120 if(ieee80211_is_connected(ieee80211_dev)) 121 return EOK; 122 123 fibril_mutex_lock(&ieee80211_dev->ap_list.scan_mutex); 124 125 /* Remove old entries we don't receive beacons from. */ 126 ieee80211_scan_result_list_t *result_list = 127 &ieee80211_dev->ap_list; 128 list_foreach_safe(result_list->list, cur_link, next_link) { 129 ieee80211_scan_result_link_t *cur_result = 130 list_get_instance(cur_link, 131 ieee80211_scan_result_link_t, 132 link); 133 if((time(NULL) - cur_result->last_beacon) > 134 MAX_KEEP_SCAN_SPAN_SEC) { 135 ieee80211_scan_result_list_remove(result_list, 136 cur_result); 137 } 138 } 139 140 fibril_mutex_unlock(&ieee80211_dev->ap_list.scan_mutex); 141 92 142 uint16_t orig_freq = ieee80211_dev->current_freq; 93 143 … … 96 146 freq += IEEE80211_CHANNEL_GAP) { 97 147 ieee80211_dev->ops->set_freq(ieee80211_dev, freq); 98 ieee80211_probe_request(ieee80211_dev );148 ieee80211_probe_request(ieee80211_dev, NULL); 99 149 100 150 /* Wait for probe responses. */ … … 104 154 ieee80211_dev->ops->set_freq(ieee80211_dev, orig_freq); 105 155 106 return EOK; 156 fibril_mutex_lock(&ieee80211_dev->ap_list.scan_mutex); 157 time(&ieee80211_dev->ap_list.last_scan); 158 fibril_mutex_unlock(&ieee80211_dev->ap_list.scan_mutex); 159 160 return EOK; 161 } 162 163 /** 164 * Pseudorandom function used for IEEE 802.11 pairwise key computation. 165 * 166 * @param key Key with PBKDF2 encrypted passphrase. 167 * @param data Concatenated sequence of both mac addresses and nonces. 168 * @param hash Output parameter for result hash (48 byte value). 169 * @param hash_sel Hash function selector. 170 * 171 * @return EINVAL when key or data not specified, ENOMEM when pointer for 172 * output hash result is not allocated, otherwise EOK. 173 */ 174 int ieee80211_prf(uint8_t *key, uint8_t *data, uint8_t *hash, 175 hash_func_t hash_sel) 176 { 177 if(!key || !data) 178 return EINVAL; 179 180 if(!hash) 181 return ENOMEM; 182 183 size_t hash_length, result_length; 184 switch(hash_sel) { 185 case HASH_MD5: 186 hash_length = MD5_HASH_LENGTH; 187 result_length = IEEE80211_PTK_TKIP_LENGTH; 188 break; 189 case HASH_SHA1: 190 hash_length = SHA1_HASH_LENGTH; 191 result_length = IEEE80211_PTK_CCMP_LENGTH; 192 break; 193 default: 194 hash_length = 0; 195 result_length = 0; 196 } 197 198 size_t iters = ((result_length * 8) + 159) / 160; 199 200 const char *a = "Pairwise key expansion"; 201 uint8_t result[hash_length*iters]; 202 uint8_t temp[hash_length]; 203 size_t data_size = PRF_CRYPT_DATA_LENGTH + str_size(a) + 2; 204 uint8_t work_arr[data_size]; 205 memset(work_arr, 0, data_size); 206 207 memcpy(work_arr, a, str_size(a)); 208 memcpy(work_arr + str_size(a) + 1, data, PRF_CRYPT_DATA_LENGTH); 209 210 for(uint8_t i = 0; i < iters; i++) { 211 memcpy(work_arr + data_size - 1, &i, 1); 212 hmac(key, PBKDF2_KEY_LENGTH, work_arr, data_size, temp, 213 hash_sel); 214 memcpy(result + i*hash_length, temp, hash_length); 215 } 216 217 memcpy(hash, result, result_length); 218 219 return EOK; 220 } 221 222 int ieee80211_aes_key_unwrap(uint8_t *kek, uint8_t *data, size_t data_size, 223 uint8_t *output) 224 { 225 if(!kek || !data) 226 return EINVAL; 227 228 if(!output) 229 return ENOMEM; 230 231 uint32_t n = data_size/8 - 1; 232 uint8_t work_data[n*8]; 233 uint8_t work_input[AES_CIPHER_LENGTH]; 234 uint8_t work_output[AES_CIPHER_LENGTH]; 235 uint8_t *work_block; 236 uint8_t a[8]; 237 memcpy(a, data, 8); 238 uint64_t mask = 0xFF; 239 uint8_t shift, shb; 240 241 memcpy(work_data, data + 8, n*8); 242 for(int j = 5; j >=0; j--) { 243 for(int i = n; i > 0; i--) { 244 for(size_t k = 0; k < 8; k++) { 245 shift = 56 - 8*k; 246 shb = ((n*j+i) & (mask << shift)) >> shift; 247 a[k] ^= shb; 248 } 249 work_block = work_data + (i-1)*8; 250 memcpy(work_input, a, 8); 251 memcpy(work_input + 8, work_block, 8); 252 aes_decrypt(kek, work_input, work_output); 253 memcpy(a, work_output, 8); 254 memcpy(work_data + (i-1)*8, work_output + 8, 8); 255 } 256 } 257 258 size_t it; 259 for(it = 0; it < 8; it++) { 260 if(a[it] != 0xA6) 261 break; 262 } 263 264 if(it == 8) { 265 memcpy(output, work_data, n*8); 266 return EOK; 267 } else { 268 return EINVAL; 269 } 270 } 271 272 int rnd_sequence(uint8_t *sequence, size_t length) 273 { 274 if(!sequence) 275 return ENOMEM; 276 277 for(size_t i = 0; i < length; i++) { 278 sequence[i] = (uint8_t) rand(); 279 } 280 281 return EOK; 282 } 283 284 uint8_t *min_sequence(uint8_t *seq1, uint8_t *seq2, size_t size) 285 { 286 if(!seq1 || !seq2) 287 return NULL; 288 289 for(size_t i = 0; i < size; i++) { 290 if(seq1[i] < seq2[i]) { 291 return seq1; 292 } else if(seq1[i] > seq2[i]) { 293 return seq2; 294 } 295 } 296 297 return seq1; 298 } 299 300 uint8_t *max_sequence(uint8_t *seq1, uint8_t *seq2, size_t size) 301 { 302 uint8_t *min = min_sequence(seq1, seq2, size); 303 if(min == seq1) { 304 return seq2; 305 } else { 306 return seq1; 307 } 107 308 } 108 309
Note:
See TracChangeset
for help on using the changeset viewer.