diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-10-29 16:05:51 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-10-29 16:05:51 -0400 |
commit | ab3d59d265e772e734c36fe738809cb1a910f566 (patch) | |
tree | b6d29908d3d45b078d025341b1cc272ba4c0a6d0 /net | |
parent | 42d36074e53eadfd79e6db518b5caf8fba914f8b (diff) | |
parent | 8c6e30936a7893a85f6222084f0f26aceb81137a (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless
Conflicts:
drivers/net/wireless/mwifiex/cfg80211.c
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/ibss.c | 2 | ||||
-rw-r--r-- | net/mac80211/rx.c | 74 | ||||
-rw-r--r-- | net/mac80211/util.c | 42 | ||||
-rw-r--r-- | net/wireless/core.c | 3 | ||||
-rw-r--r-- | net/wireless/reg.c | 5 | ||||
-rw-r--r-- | net/wireless/util.c | 14 |
6 files changed, 104 insertions, 36 deletions
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 3d5332e367f8..c7386b2b767e 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -1110,7 +1110,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
1110 | sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; | 1110 | sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH; |
1111 | sdata->u.ibss.ibss_join_req = jiffies; | 1111 | sdata->u.ibss.ibss_join_req = jiffies; |
1112 | 1112 | ||
1113 | memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); | 1113 | memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len); |
1114 | sdata->u.ibss.ssid_len = params->ssid_len; | 1114 | sdata->u.ibss.ssid_len = params->ssid_len; |
1115 | 1115 | ||
1116 | mutex_unlock(&sdata->u.ibss.mtx); | 1116 | mutex_unlock(&sdata->u.ibss.mtx); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index d07216ab5f72..8c1f1527d671 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -531,6 +531,11 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx) | |||
531 | 531 | ||
532 | if (ieee80211_is_action(hdr->frame_control)) { | 532 | if (ieee80211_is_action(hdr->frame_control)) { |
533 | u8 category; | 533 | u8 category; |
534 | |||
535 | /* make sure category field is present */ | ||
536 | if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE) | ||
537 | return RX_DROP_MONITOR; | ||
538 | |||
534 | mgmt = (struct ieee80211_mgmt *)hdr; | 539 | mgmt = (struct ieee80211_mgmt *)hdr; |
535 | category = mgmt->u.action.category; | 540 | category = mgmt->u.action.category; |
536 | if (category != WLAN_CATEGORY_MESH_ACTION && | 541 | if (category != WLAN_CATEGORY_MESH_ACTION && |
@@ -883,14 +888,16 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx) | |||
883 | */ | 888 | */ |
884 | if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION && | 889 | if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION && |
885 | ieee80211_is_data_present(hdr->frame_control)) { | 890 | ieee80211_is_data_present(hdr->frame_control)) { |
886 | u16 ethertype; | 891 | unsigned int hdrlen; |
887 | u8 *payload; | 892 | __be16 ethertype; |
888 | 893 | ||
889 | payload = rx->skb->data + | 894 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
890 | ieee80211_hdrlen(hdr->frame_control); | 895 | |
891 | ethertype = (payload[6] << 8) | payload[7]; | 896 | if (rx->skb->len < hdrlen + 8) |
892 | if (cpu_to_be16(ethertype) == | 897 | return RX_DROP_MONITOR; |
893 | rx->sdata->control_port_protocol) | 898 | |
899 | skb_copy_bits(rx->skb, hdrlen + 6, ðertype, 2); | ||
900 | if (ethertype == rx->sdata->control_port_protocol) | ||
894 | return RX_CONTINUE; | 901 | return RX_CONTINUE; |
895 | } | 902 | } |
896 | 903 | ||
@@ -1467,11 +1474,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) | |||
1467 | 1474 | ||
1468 | hdr = (struct ieee80211_hdr *)rx->skb->data; | 1475 | hdr = (struct ieee80211_hdr *)rx->skb->data; |
1469 | fc = hdr->frame_control; | 1476 | fc = hdr->frame_control; |
1477 | |||
1478 | if (ieee80211_is_ctl(fc)) | ||
1479 | return RX_CONTINUE; | ||
1480 | |||
1470 | sc = le16_to_cpu(hdr->seq_ctrl); | 1481 | sc = le16_to_cpu(hdr->seq_ctrl); |
1471 | frag = sc & IEEE80211_SCTL_FRAG; | 1482 | frag = sc & IEEE80211_SCTL_FRAG; |
1472 | 1483 | ||
1473 | if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || | 1484 | if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || |
1474 | (rx->skb)->len < 24 || | ||
1475 | is_multicast_ether_addr(hdr->addr1))) { | 1485 | is_multicast_ether_addr(hdr->addr1))) { |
1476 | /* not fragmented */ | 1486 | /* not fragmented */ |
1477 | goto out; | 1487 | goto out; |
@@ -1894,6 +1904,20 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1894 | 1904 | ||
1895 | hdr = (struct ieee80211_hdr *) skb->data; | 1905 | hdr = (struct ieee80211_hdr *) skb->data; |
1896 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 1906 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
1907 | |||
1908 | /* make sure fixed part of mesh header is there, also checks skb len */ | ||
1909 | if (!pskb_may_pull(rx->skb, hdrlen + 6)) | ||
1910 | return RX_DROP_MONITOR; | ||
1911 | |||
1912 | mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); | ||
1913 | |||
1914 | /* make sure full mesh header is there, also checks skb len */ | ||
1915 | if (!pskb_may_pull(rx->skb, | ||
1916 | hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr))) | ||
1917 | return RX_DROP_MONITOR; | ||
1918 | |||
1919 | /* reload pointers */ | ||
1920 | hdr = (struct ieee80211_hdr *) skb->data; | ||
1897 | mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); | 1921 | mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); |
1898 | 1922 | ||
1899 | /* frame is in RMC, don't forward */ | 1923 | /* frame is in RMC, don't forward */ |
@@ -1902,7 +1926,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1902 | mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata)) | 1926 | mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata)) |
1903 | return RX_DROP_MONITOR; | 1927 | return RX_DROP_MONITOR; |
1904 | 1928 | ||
1905 | if (!ieee80211_is_data(hdr->frame_control)) | 1929 | if (!ieee80211_is_data(hdr->frame_control) || |
1930 | !(status->rx_flags & IEEE80211_RX_RA_MATCH)) | ||
1906 | return RX_CONTINUE; | 1931 | return RX_CONTINUE; |
1907 | 1932 | ||
1908 | if (!mesh_hdr->ttl) | 1933 | if (!mesh_hdr->ttl) |
@@ -1916,9 +1941,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1916 | if (is_multicast_ether_addr(hdr->addr1)) { | 1941 | if (is_multicast_ether_addr(hdr->addr1)) { |
1917 | mpp_addr = hdr->addr3; | 1942 | mpp_addr = hdr->addr3; |
1918 | proxied_addr = mesh_hdr->eaddr1; | 1943 | proxied_addr = mesh_hdr->eaddr1; |
1919 | } else { | 1944 | } else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) { |
1945 | /* has_a4 already checked in ieee80211_rx_mesh_check */ | ||
1920 | mpp_addr = hdr->addr4; | 1946 | mpp_addr = hdr->addr4; |
1921 | proxied_addr = mesh_hdr->eaddr2; | 1947 | proxied_addr = mesh_hdr->eaddr2; |
1948 | } else { | ||
1949 | return RX_DROP_MONITOR; | ||
1922 | } | 1950 | } |
1923 | 1951 | ||
1924 | rcu_read_lock(); | 1952 | rcu_read_lock(); |
@@ -1946,12 +1974,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) | |||
1946 | } | 1974 | } |
1947 | skb_set_queue_mapping(skb, q); | 1975 | skb_set_queue_mapping(skb, q); |
1948 | 1976 | ||
1949 | if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) | ||
1950 | goto out; | ||
1951 | |||
1952 | if (!--mesh_hdr->ttl) { | 1977 | if (!--mesh_hdr->ttl) { |
1953 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl); | 1978 | IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl); |
1954 | return RX_DROP_MONITOR; | 1979 | goto out; |
1955 | } | 1980 | } |
1956 | 1981 | ||
1957 | if (!ifmsh->mshcfg.dot11MeshForwarding) | 1982 | if (!ifmsh->mshcfg.dot11MeshForwarding) |
@@ -2358,6 +2383,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2358 | } | 2383 | } |
2359 | break; | 2384 | break; |
2360 | case WLAN_CATEGORY_SELF_PROTECTED: | 2385 | case WLAN_CATEGORY_SELF_PROTECTED: |
2386 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
2387 | sizeof(mgmt->u.action.u.self_prot.action_code))) | ||
2388 | break; | ||
2389 | |||
2361 | switch (mgmt->u.action.u.self_prot.action_code) { | 2390 | switch (mgmt->u.action.u.self_prot.action_code) { |
2362 | case WLAN_SP_MESH_PEERING_OPEN: | 2391 | case WLAN_SP_MESH_PEERING_OPEN: |
2363 | case WLAN_SP_MESH_PEERING_CLOSE: | 2392 | case WLAN_SP_MESH_PEERING_CLOSE: |
@@ -2376,6 +2405,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2376 | } | 2405 | } |
2377 | break; | 2406 | break; |
2378 | case WLAN_CATEGORY_MESH_ACTION: | 2407 | case WLAN_CATEGORY_MESH_ACTION: |
2408 | if (len < (IEEE80211_MIN_ACTION_SIZE + | ||
2409 | sizeof(mgmt->u.action.u.mesh_action.action_code))) | ||
2410 | break; | ||
2411 | |||
2379 | if (!ieee80211_vif_is_mesh(&sdata->vif)) | 2412 | if (!ieee80211_vif_is_mesh(&sdata->vif)) |
2380 | break; | 2413 | break; |
2381 | if (mesh_action_is_path_sel(mgmt) && | 2414 | if (mesh_action_is_path_sel(mgmt) && |
@@ -2918,10 +2951,15 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | |||
2918 | if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc)) | 2951 | if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc)) |
2919 | local->dot11ReceivedFragmentCount++; | 2952 | local->dot11ReceivedFragmentCount++; |
2920 | 2953 | ||
2921 | if (ieee80211_is_mgmt(fc)) | 2954 | if (ieee80211_is_mgmt(fc)) { |
2922 | err = skb_linearize(skb); | 2955 | /* drop frame if too short for header */ |
2923 | else | 2956 | if (skb->len < ieee80211_hdrlen(fc)) |
2957 | err = -ENOBUFS; | ||
2958 | else | ||
2959 | err = skb_linearize(skb); | ||
2960 | } else { | ||
2924 | err = !pskb_may_pull(skb, ieee80211_hdrlen(fc)); | 2961 | err = !pskb_may_pull(skb, ieee80211_hdrlen(fc)); |
2962 | } | ||
2925 | 2963 | ||
2926 | if (err) { | 2964 | if (err) { |
2927 | dev_kfree_skb(skb); | 2965 | dev_kfree_skb(skb); |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index b3a84746d445..9556391b05d7 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -643,13 +643,41 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | |||
643 | break; | 643 | break; |
644 | } | 644 | } |
645 | 645 | ||
646 | if (id != WLAN_EID_VENDOR_SPECIFIC && | 646 | switch (id) { |
647 | id != WLAN_EID_QUIET && | 647 | case WLAN_EID_SSID: |
648 | test_bit(id, seen_elems)) { | 648 | case WLAN_EID_SUPP_RATES: |
649 | elems->parse_error = true; | 649 | case WLAN_EID_FH_PARAMS: |
650 | left -= elen; | 650 | case WLAN_EID_DS_PARAMS: |
651 | pos += elen; | 651 | case WLAN_EID_CF_PARAMS: |
652 | continue; | 652 | case WLAN_EID_TIM: |
653 | case WLAN_EID_IBSS_PARAMS: | ||
654 | case WLAN_EID_CHALLENGE: | ||
655 | case WLAN_EID_RSN: | ||
656 | case WLAN_EID_ERP_INFO: | ||
657 | case WLAN_EID_EXT_SUPP_RATES: | ||
658 | case WLAN_EID_HT_CAPABILITY: | ||
659 | case WLAN_EID_HT_OPERATION: | ||
660 | case WLAN_EID_VHT_CAPABILITY: | ||
661 | case WLAN_EID_VHT_OPERATION: | ||
662 | case WLAN_EID_MESH_ID: | ||
663 | case WLAN_EID_MESH_CONFIG: | ||
664 | case WLAN_EID_PEER_MGMT: | ||
665 | case WLAN_EID_PREQ: | ||
666 | case WLAN_EID_PREP: | ||
667 | case WLAN_EID_PERR: | ||
668 | case WLAN_EID_RANN: | ||
669 | case WLAN_EID_CHANNEL_SWITCH: | ||
670 | case WLAN_EID_EXT_CHANSWITCH_ANN: | ||
671 | case WLAN_EID_COUNTRY: | ||
672 | case WLAN_EID_PWR_CONSTRAINT: | ||
673 | case WLAN_EID_TIMEOUT_INTERVAL: | ||
674 | if (test_bit(id, seen_elems)) { | ||
675 | elems->parse_error = true; | ||
676 | left -= elen; | ||
677 | pos += elen; | ||
678 | continue; | ||
679 | } | ||
680 | break; | ||
653 | } | 681 | } |
654 | 682 | ||
655 | if (calc_crc && id < 64 && (filter & (1ULL << id))) | 683 | if (calc_crc && id < 64 && (filter & (1ULL << id))) |
diff --git a/net/wireless/core.c b/net/wireless/core.c index ce1ad776dfb5..26711f46a3be 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -529,8 +529,7 @@ int wiphy_register(struct wiphy *wiphy) | |||
529 | for (i = 0; i < sband->n_channels; i++) { | 529 | for (i = 0; i < sband->n_channels; i++) { |
530 | sband->channels[i].orig_flags = | 530 | sband->channels[i].orig_flags = |
531 | sband->channels[i].flags; | 531 | sband->channels[i].flags; |
532 | sband->channels[i].orig_mag = | 532 | sband->channels[i].orig_mag = INT_MAX; |
533 | sband->channels[i].max_antenna_gain; | ||
534 | sband->channels[i].orig_mpwr = | 533 | sband->channels[i].orig_mpwr = |
535 | sband->channels[i].max_power; | 534 | sband->channels[i].max_power; |
536 | sband->channels[i].band = band; | 535 | sband->channels[i].band = band; |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 3b8cbbc214db..bcc7d7ee5a51 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -908,7 +908,7 @@ static void handle_channel(struct wiphy *wiphy, | |||
908 | map_regdom_flags(reg_rule->flags) | bw_flags; | 908 | map_regdom_flags(reg_rule->flags) | bw_flags; |
909 | chan->max_antenna_gain = chan->orig_mag = | 909 | chan->max_antenna_gain = chan->orig_mag = |
910 | (int) MBI_TO_DBI(power_rule->max_antenna_gain); | 910 | (int) MBI_TO_DBI(power_rule->max_antenna_gain); |
911 | chan->max_power = chan->orig_mpwr = | 911 | chan->max_reg_power = chan->max_power = chan->orig_mpwr = |
912 | (int) MBM_TO_DBM(power_rule->max_eirp); | 912 | (int) MBM_TO_DBM(power_rule->max_eirp); |
913 | return; | 913 | return; |
914 | } | 914 | } |
@@ -1331,7 +1331,8 @@ static void handle_channel_custom(struct wiphy *wiphy, | |||
1331 | 1331 | ||
1332 | chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags; | 1332 | chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags; |
1333 | chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain); | 1333 | chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain); |
1334 | chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); | 1334 | chan->max_reg_power = chan->max_power = |
1335 | (int) MBM_TO_DBM(power_rule->max_eirp); | ||
1335 | } | 1336 | } |
1336 | 1337 | ||
1337 | static void handle_band_custom(struct wiphy *wiphy, enum ieee80211_band band, | 1338 | static void handle_band_custom(struct wiphy *wiphy, enum ieee80211_band band, |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 343f13c1d31d..5b6c1df72f31 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -311,23 +311,21 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb) | |||
311 | } | 311 | } |
312 | EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); | 312 | EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); |
313 | 313 | ||
314 | static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) | 314 | unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) |
315 | { | 315 | { |
316 | int ae = meshhdr->flags & MESH_FLAGS_AE; | 316 | int ae = meshhdr->flags & MESH_FLAGS_AE; |
317 | /* 7.1.3.5a.2 */ | 317 | /* 802.11-2012, 8.2.4.7.3 */ |
318 | switch (ae) { | 318 | switch (ae) { |
319 | default: | ||
319 | case 0: | 320 | case 0: |
320 | return 6; | 321 | return 6; |
321 | case MESH_FLAGS_AE_A4: | 322 | case MESH_FLAGS_AE_A4: |
322 | return 12; | 323 | return 12; |
323 | case MESH_FLAGS_AE_A5_A6: | 324 | case MESH_FLAGS_AE_A5_A6: |
324 | return 18; | 325 | return 18; |
325 | case (MESH_FLAGS_AE_A4 | MESH_FLAGS_AE_A5_A6): | ||
326 | return 24; | ||
327 | default: | ||
328 | return 6; | ||
329 | } | 326 | } |
330 | } | 327 | } |
328 | EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen); | ||
331 | 329 | ||
332 | int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, | 330 | int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, |
333 | enum nl80211_iftype iftype) | 331 | enum nl80211_iftype iftype) |
@@ -375,6 +373,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, | |||
375 | /* make sure meshdr->flags is on the linear part */ | 373 | /* make sure meshdr->flags is on the linear part */ |
376 | if (!pskb_may_pull(skb, hdrlen + 1)) | 374 | if (!pskb_may_pull(skb, hdrlen + 1)) |
377 | return -1; | 375 | return -1; |
376 | if (meshdr->flags & MESH_FLAGS_AE_A4) | ||
377 | return -1; | ||
378 | if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { | 378 | if (meshdr->flags & MESH_FLAGS_AE_A5_A6) { |
379 | skb_copy_bits(skb, hdrlen + | 379 | skb_copy_bits(skb, hdrlen + |
380 | offsetof(struct ieee80211s_hdr, eaddr1), | 380 | offsetof(struct ieee80211s_hdr, eaddr1), |
@@ -399,6 +399,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr, | |||
399 | /* make sure meshdr->flags is on the linear part */ | 399 | /* make sure meshdr->flags is on the linear part */ |
400 | if (!pskb_may_pull(skb, hdrlen + 1)) | 400 | if (!pskb_may_pull(skb, hdrlen + 1)) |
401 | return -1; | 401 | return -1; |
402 | if (meshdr->flags & MESH_FLAGS_AE_A5_A6) | ||
403 | return -1; | ||
402 | if (meshdr->flags & MESH_FLAGS_AE_A4) | 404 | if (meshdr->flags & MESH_FLAGS_AE_A4) |
403 | skb_copy_bits(skb, hdrlen + | 405 | skb_copy_bits(skb, hdrlen + |
404 | offsetof(struct ieee80211s_hdr, eaddr1), | 406 | offsetof(struct ieee80211s_hdr, eaddr1), |