| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2008, 2009 open80211s Ltd. | 2 * Copyright (c) 2008, 2009 open80211s Ltd. |
| 3 * Author: Luis Carlos Cobo <luisca@cozybit.com> | 3 * Author: Luis Carlos Cobo <luisca@cozybit.com> |
| 4 * | 4 * |
| 5 * This program is free software; you can redistribute it and/or modify | 5 * This program is free software; you can redistribute it and/or modify |
| 6 * it under the terms of the GNU General Public License version 2 as | 6 * it under the terms of the GNU General Public License version 2 as |
| 7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
| 8 */ | 8 */ |
| 9 #include <linux/gfp.h> | 9 #include <linux/gfp.h> |
| 10 #include <linux/kernel.h> | 10 #include <linux/kernel.h> |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 405 | 405 |
| 406 void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
gmt *mgmt, | 406 void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
gmt *mgmt, |
| 407 size_t len, struct ieee80211_rx_status *rx_status) | 407 size_t len, struct ieee80211_rx_status *rx_status) |
| 408 { | 408 { |
| 409 struct ieee80211_local *local = sdata->local; | 409 struct ieee80211_local *local = sdata->local; |
| 410 struct ieee802_11_elems elems; | 410 struct ieee802_11_elems elems; |
| 411 struct sta_info *sta; | 411 struct sta_info *sta; |
| 412 enum plink_event event; | 412 enum plink_event event; |
| 413 enum plink_frame_type ftype; | 413 enum plink_frame_type ftype; |
| 414 size_t baselen; | 414 size_t baselen; |
| 415 » bool deactivated; | 415 » bool deactivated, matches_local = true; |
| 416 u8 ie_len; | 416 u8 ie_len; |
| 417 u8 *baseaddr; | 417 u8 *baseaddr; |
| 418 __le16 plid, llid, reason; | 418 __le16 plid, llid, reason; |
| 419 #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG | 419 #ifdef CONFIG_MAC80211_VERBOSE_MPL_DEBUG |
| 420 static const char *mplstates[] = { | 420 static const char *mplstates[] = { |
| 421 [PLINK_LISTEN] = "LISTEN", | 421 [PLINK_LISTEN] = "LISTEN", |
| 422 [PLINK_OPN_SNT] = "OPN-SNT", | 422 [PLINK_OPN_SNT] = "OPN-SNT", |
| 423 [PLINK_OPN_RCVD] = "OPN-RCVD", | 423 [PLINK_OPN_RCVD] = "OPN-RCVD", |
| 424 [PLINK_CNF_RCVD] = "CNF_RCVD", | 424 [PLINK_CNF_RCVD] = "CNF_RCVD", |
| 425 [PLINK_ESTAB] = "ESTAB", | 425 [PLINK_ESTAB] = "ESTAB", |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 480 } | 480 } |
| 481 | 481 |
| 482 if (sta && sta->plink_state == PLINK_BLOCKED) { | 482 if (sta && sta->plink_state == PLINK_BLOCKED) { |
| 483 rcu_read_unlock(); | 483 rcu_read_unlock(); |
| 484 return; | 484 return; |
| 485 } | 485 } |
| 486 | 486 |
| 487 /* Now we will figure out the appropriate event... */ | 487 /* Now we will figure out the appropriate event... */ |
| 488 event = PLINK_UNDEFINED; | 488 event = PLINK_UNDEFINED; |
| 489 if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, sdata))) { | 489 if (ftype != PLINK_CLOSE && (!mesh_matches_local(&elems, sdata))) { |
| 490 matches_local = false; |
| 490 switch (ftype) { | 491 switch (ftype) { |
| 491 case PLINK_OPEN: | 492 case PLINK_OPEN: |
| 492 event = OPN_RJCT; | 493 event = OPN_RJCT; |
| 493 break; | 494 break; |
| 494 case PLINK_CONFIRM: | 495 case PLINK_CONFIRM: |
| 495 event = CNF_RJCT; | 496 event = CNF_RJCT; |
| 496 break; | 497 break; |
| 497 case PLINK_CLOSE: | 498 case PLINK_CLOSE: |
| 498 /* avoid warning */ | 499 /* avoid warning */ |
| 499 break; | 500 break; |
| 500 } | 501 } |
| 501 » » spin_lock_bh(&sta->lock); | 502 » } |
| 503 |
| 504 » if (!sta && !matches_local) { |
| 505 » » rcu_read_unlock(); |
| 506 » » reason = cpu_to_le16(MESH_CAPABILITY_POLICY_VIOLATION); |
| 507 » » llid = 0; |
| 508 » » mesh_plink_frame_tx(sdata, PLINK_CLOSE, mgmt->sa, llid, |
| 509 » » » » plid, reason); |
| 510 » » return; |
| 502 } else if (!sta) { | 511 } else if (!sta) { |
| 503 /* ftype == PLINK_OPEN */ | 512 /* ftype == PLINK_OPEN */ |
| 504 u32 rates; | 513 u32 rates; |
| 505 | 514 |
| 506 rcu_read_unlock(); | 515 rcu_read_unlock(); |
| 507 | 516 |
| 508 if (!mesh_plink_free_count(sdata)) { | 517 if (!mesh_plink_free_count(sdata)) { |
| 509 mpl_dbg("Mesh plink error: no more free plinks\n"); | 518 mpl_dbg("Mesh plink error: no more free plinks\n"); |
| 510 return; | 519 return; |
| 511 } | 520 } |
| 512 | 521 |
| 513 rates = ieee80211_sta_get_rates(local, &elems, rx_status->band); | 522 rates = ieee80211_sta_get_rates(local, &elems, rx_status->band); |
| 514 sta = mesh_plink_alloc(sdata, mgmt->sa, rates); | 523 sta = mesh_plink_alloc(sdata, mgmt->sa, rates); |
| 515 if (!sta) { | 524 if (!sta) { |
| 516 mpl_dbg("Mesh plink error: plink table full\n"); | 525 mpl_dbg("Mesh plink error: plink table full\n"); |
| 517 return; | 526 return; |
| 518 } | 527 } |
| 519 if (sta_info_insert_rcu(sta)) { | 528 if (sta_info_insert_rcu(sta)) { |
| 520 rcu_read_unlock(); | 529 rcu_read_unlock(); |
| 521 return; | 530 return; |
| 522 } | 531 } |
| 523 event = OPN_ACPT; | 532 event = OPN_ACPT; |
| 524 spin_lock_bh(&sta->lock); | 533 spin_lock_bh(&sta->lock); |
| 525 » } else { | 534 » } else if (matches_local) { |
| 526 spin_lock_bh(&sta->lock); | 535 spin_lock_bh(&sta->lock); |
| 527 switch (ftype) { | 536 switch (ftype) { |
| 528 case PLINK_OPEN: | 537 case PLINK_OPEN: |
| 529 if (!mesh_plink_free_count(sdata) || | 538 if (!mesh_plink_free_count(sdata) || |
| 530 (sta->plid && sta->plid != plid)) | 539 (sta->plid && sta->plid != plid)) |
| 531 event = OPN_IGNR; | 540 event = OPN_IGNR; |
| 532 else | 541 else |
| 533 event = OPN_ACPT; | 542 event = OPN_ACPT; |
| 534 break; | 543 break; |
| 535 case PLINK_CONFIRM: | 544 case PLINK_CONFIRM: |
| (...skipping 21 matching lines...) Expand all Loading... |
| 557 event = CLS_IGNR; | 566 event = CLS_IGNR; |
| 558 else | 567 else |
| 559 event = CLS_ACPT; | 568 event = CLS_ACPT; |
| 560 break; | 569 break; |
| 561 default: | 570 default: |
| 562 mpl_dbg("Mesh plink: unknown frame subtype\n"); | 571 mpl_dbg("Mesh plink: unknown frame subtype\n"); |
| 563 spin_unlock_bh(&sta->lock); | 572 spin_unlock_bh(&sta->lock); |
| 564 rcu_read_unlock(); | 573 rcu_read_unlock(); |
| 565 return; | 574 return; |
| 566 } | 575 } |
| 576 } else { |
| 577 spin_lock_bh(&sta->lock); |
| 567 } | 578 } |
| 568 | 579 |
| 569 mpl_dbg("Mesh plink (peer, state, llid, plid, event): %pM %s %d %d %d\n"
, | 580 mpl_dbg("Mesh plink (peer, state, llid, plid, event): %pM %s %d %d %d\n"
, |
| 570 mgmt->sa, mplstates[sta->plink_state], | 581 mgmt->sa, mplstates[sta->plink_state], |
| 571 le16_to_cpu(sta->llid), le16_to_cpu(sta->plid), | 582 le16_to_cpu(sta->llid), le16_to_cpu(sta->plid), |
| 572 event); | 583 event); |
| 573 reason = 0; | 584 reason = 0; |
| 574 switch (sta->plink_state) { | 585 switch (sta->plink_state) { |
| 575 /* spin_unlock as soon as state is updated at each case */ | 586 /* spin_unlock as soon as state is updated at each case */ |
| 576 case PLINK_LISTEN: | 587 case PLINK_LISTEN: |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 766 default: | 777 default: |
| 767 /* should not get here, PLINK_BLOCKED is dealt with at the | 778 /* should not get here, PLINK_BLOCKED is dealt with at the |
| 768 * beginning of the function | 779 * beginning of the function |
| 769 */ | 780 */ |
| 770 spin_unlock_bh(&sta->lock); | 781 spin_unlock_bh(&sta->lock); |
| 771 break; | 782 break; |
| 772 } | 783 } |
| 773 | 784 |
| 774 rcu_read_unlock(); | 785 rcu_read_unlock(); |
| 775 } | 786 } |
| OLD | NEW |