diff options
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r-- | net/mac80211/util.c | 46 |
1 files changed, 41 insertions, 5 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index f6e4cef92021..32f7a3b3d43c 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -572,24 +572,40 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | |||
572 | size_t left = len; | 572 | size_t left = len; |
573 | u8 *pos = start; | 573 | u8 *pos = start; |
574 | bool calc_crc = filter != 0; | 574 | bool calc_crc = filter != 0; |
575 | DECLARE_BITMAP(seen_elems, 256); | ||
575 | 576 | ||
577 | bitmap_zero(seen_elems, 256); | ||
576 | memset(elems, 0, sizeof(*elems)); | 578 | memset(elems, 0, sizeof(*elems)); |
577 | elems->ie_start = start; | 579 | elems->ie_start = start; |
578 | elems->total_len = len; | 580 | elems->total_len = len; |
579 | 581 | ||
580 | while (left >= 2) { | 582 | while (left >= 2) { |
581 | u8 id, elen; | 583 | u8 id, elen; |
584 | bool elem_parse_failed; | ||
582 | 585 | ||
583 | id = *pos++; | 586 | id = *pos++; |
584 | elen = *pos++; | 587 | elen = *pos++; |
585 | left -= 2; | 588 | left -= 2; |
586 | 589 | ||
587 | if (elen > left) | 590 | if (elen > left) { |
591 | elems->parse_error = true; | ||
588 | break; | 592 | break; |
593 | } | ||
594 | |||
595 | if (id != WLAN_EID_VENDOR_SPECIFIC && | ||
596 | id != WLAN_EID_QUIET && | ||
597 | test_bit(id, seen_elems)) { | ||
598 | elems->parse_error = true; | ||
599 | left -= elen; | ||
600 | pos += elen; | ||
601 | continue; | ||
602 | } | ||
589 | 603 | ||
590 | if (calc_crc && id < 64 && (filter & (1ULL << id))) | 604 | if (calc_crc && id < 64 && (filter & (1ULL << id))) |
591 | crc = crc32_be(crc, pos - 2, elen + 2); | 605 | crc = crc32_be(crc, pos - 2, elen + 2); |
592 | 606 | ||
607 | elem_parse_failed = false; | ||
608 | |||
593 | switch (id) { | 609 | switch (id) { |
594 | case WLAN_EID_SSID: | 610 | case WLAN_EID_SSID: |
595 | elems->ssid = pos; | 611 | elems->ssid = pos; |
@@ -615,7 +631,8 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | |||
615 | if (elen >= sizeof(struct ieee80211_tim_ie)) { | 631 | if (elen >= sizeof(struct ieee80211_tim_ie)) { |
616 | elems->tim = (void *)pos; | 632 | elems->tim = (void *)pos; |
617 | elems->tim_len = elen; | 633 | elems->tim_len = elen; |
618 | } | 634 | } else |
635 | elem_parse_failed = true; | ||
619 | break; | 636 | break; |
620 | case WLAN_EID_IBSS_PARAMS: | 637 | case WLAN_EID_IBSS_PARAMS: |
621 | elems->ibss_params = pos; | 638 | elems->ibss_params = pos; |
@@ -664,10 +681,14 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | |||
664 | case WLAN_EID_HT_CAPABILITY: | 681 | case WLAN_EID_HT_CAPABILITY: |
665 | if (elen >= sizeof(struct ieee80211_ht_cap)) | 682 | if (elen >= sizeof(struct ieee80211_ht_cap)) |
666 | elems->ht_cap_elem = (void *)pos; | 683 | elems->ht_cap_elem = (void *)pos; |
684 | else | ||
685 | elem_parse_failed = true; | ||
667 | break; | 686 | break; |
668 | case WLAN_EID_HT_INFORMATION: | 687 | case WLAN_EID_HT_INFORMATION: |
669 | if (elen >= sizeof(struct ieee80211_ht_info)) | 688 | if (elen >= sizeof(struct ieee80211_ht_info)) |
670 | elems->ht_info_elem = (void *)pos; | 689 | elems->ht_info_elem = (void *)pos; |
690 | else | ||
691 | elem_parse_failed = true; | ||
671 | break; | 692 | break; |
672 | case WLAN_EID_MESH_ID: | 693 | case WLAN_EID_MESH_ID: |
673 | elems->mesh_id = pos; | 694 | elems->mesh_id = pos; |
@@ -676,6 +697,8 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | |||
676 | case WLAN_EID_MESH_CONFIG: | 697 | case WLAN_EID_MESH_CONFIG: |
677 | if (elen >= sizeof(struct ieee80211_meshconf_ie)) | 698 | if (elen >= sizeof(struct ieee80211_meshconf_ie)) |
678 | elems->mesh_config = (void *)pos; | 699 | elems->mesh_config = (void *)pos; |
700 | else | ||
701 | elem_parse_failed = true; | ||
679 | break; | 702 | break; |
680 | case WLAN_EID_PEER_MGMT: | 703 | case WLAN_EID_PEER_MGMT: |
681 | elems->peering = pos; | 704 | elems->peering = pos; |
@@ -696,6 +719,8 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | |||
696 | case WLAN_EID_RANN: | 719 | case WLAN_EID_RANN: |
697 | if (elen >= sizeof(struct ieee80211_rann_ie)) | 720 | if (elen >= sizeof(struct ieee80211_rann_ie)) |
698 | elems->rann = (void *)pos; | 721 | elems->rann = (void *)pos; |
722 | else | ||
723 | elem_parse_failed = true; | ||
699 | break; | 724 | break; |
700 | case WLAN_EID_CHANNEL_SWITCH: | 725 | case WLAN_EID_CHANNEL_SWITCH: |
701 | elems->ch_switch_elem = pos; | 726 | elems->ch_switch_elem = pos; |
@@ -724,10 +749,18 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | |||
724 | break; | 749 | break; |
725 | } | 750 | } |
726 | 751 | ||
752 | if (elem_parse_failed) | ||
753 | elems->parse_error = true; | ||
754 | else | ||
755 | set_bit(id, seen_elems); | ||
756 | |||
727 | left -= elen; | 757 | left -= elen; |
728 | pos += elen; | 758 | pos += elen; |
729 | } | 759 | } |
730 | 760 | ||
761 | if (left != 0) | ||
762 | elems->parse_error = true; | ||
763 | |||
731 | return crc; | 764 | return crc; |
732 | } | 765 | } |
733 | 766 | ||
@@ -737,7 +770,8 @@ void ieee802_11_parse_elems(u8 *start, size_t len, | |||
737 | ieee802_11_parse_elems_crc(start, len, elems, 0, 0); | 770 | ieee802_11_parse_elems_crc(start, len, elems, 0, 0); |
738 | } | 771 | } |
739 | 772 | ||
740 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) | 773 | void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, |
774 | bool bss_notify) | ||
741 | { | 775 | { |
742 | struct ieee80211_local *local = sdata->local; | 776 | struct ieee80211_local *local = sdata->local; |
743 | struct ieee80211_tx_queue_params qparam; | 777 | struct ieee80211_tx_queue_params qparam; |
@@ -807,7 +841,9 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) | |||
807 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { | 841 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { |
808 | sdata->vif.bss_conf.qos = | 842 | sdata->vif.bss_conf.qos = |
809 | sdata->vif.type != NL80211_IFTYPE_STATION; | 843 | sdata->vif.type != NL80211_IFTYPE_STATION; |
810 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS); | 844 | if (bss_notify) |
845 | ieee80211_bss_info_change_notify(sdata, | ||
846 | BSS_CHANGED_QOS); | ||
811 | } | 847 | } |
812 | } | 848 | } |
813 | 849 | ||
@@ -829,7 +865,7 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | |||
829 | else | 865 | else |
830 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; | 866 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; |
831 | 867 | ||
832 | ieee80211_set_wmm_default(sdata); | 868 | ieee80211_set_wmm_default(sdata, true); |
833 | } | 869 | } |
834 | 870 | ||
835 | u32 ieee80211_mandatory_rates(struct ieee80211_local *local, | 871 | u32 ieee80211_mandatory_rates(struct ieee80211_local *local, |