]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - net/wireless/util.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec
[mirror_ubuntu-bionic-kernel.git] / net / wireless / util.c
index c1238d582fd190c4ecb87b3b005d6527ca597dd9..c69160694b6c0c173b5805f09a588083f0070b0e 100644 (file)
@@ -158,32 +158,30 @@ static void set_mandatory_flags_band(struct ieee80211_supported_band *sband)
        case NL80211_BAND_2GHZ:
                want = 7;
                for (i = 0; i < sband->n_bitrates; i++) {
-                       if (sband->bitrates[i].bitrate == 10) {
+                       switch (sband->bitrates[i].bitrate) {
+                       case 10:
+                       case 20:
+                       case 55:
+                       case 110:
                                sband->bitrates[i].flags |=
                                        IEEE80211_RATE_MANDATORY_B |
                                        IEEE80211_RATE_MANDATORY_G;
                                want--;
-                       }
-
-                       if (sband->bitrates[i].bitrate == 20 ||
-                           sband->bitrates[i].bitrate == 55 ||
-                           sband->bitrates[i].bitrate == 110 ||
-                           sband->bitrates[i].bitrate == 60 ||
-                           sband->bitrates[i].bitrate == 120 ||
-                           sband->bitrates[i].bitrate == 240) {
+                               break;
+                       case 60:
+                       case 120:
+                       case 240:
                                sband->bitrates[i].flags |=
                                        IEEE80211_RATE_MANDATORY_G;
                                want--;
-                       }
-
-                       if (sband->bitrates[i].bitrate != 10 &&
-                           sband->bitrates[i].bitrate != 20 &&
-                           sband->bitrates[i].bitrate != 55 &&
-                           sband->bitrates[i].bitrate != 110)
+                               /* fall through */
+                       default:
                                sband->bitrates[i].flags |=
                                        IEEE80211_RATE_ERP_G;
+                               break;
+                       }
                }
-               WARN_ON(want != 0 && want != 3 && want != 6);
+               WARN_ON(want != 0 && want != 3);
                break;
        case NL80211_BAND_60GHZ:
                /* check for mandatory HT MCS 1..4 */
@@ -530,121 +528,6 @@ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
 }
 EXPORT_SYMBOL(ieee80211_data_to_8023_exthdr);
 
-int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
-                            enum nl80211_iftype iftype,
-                            const u8 *bssid, bool qos)
-{
-       struct ieee80211_hdr hdr;
-       u16 hdrlen, ethertype;
-       __le16 fc;
-       const u8 *encaps_data;
-       int encaps_len, skip_header_bytes;
-       int nh_pos, h_pos;
-       int head_need;
-
-       if (unlikely(skb->len < ETH_HLEN))
-               return -EINVAL;
-
-       nh_pos = skb_network_header(skb) - skb->data;
-       h_pos = skb_transport_header(skb) - skb->data;
-
-       /* convert Ethernet header to proper 802.11 header (based on
-        * operation mode) */
-       ethertype = (skb->data[12] << 8) | skb->data[13];
-       fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
-
-       switch (iftype) {
-       case NL80211_IFTYPE_AP:
-       case NL80211_IFTYPE_AP_VLAN:
-       case NL80211_IFTYPE_P2P_GO:
-               fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
-               /* DA BSSID SA */
-               memcpy(hdr.addr1, skb->data, ETH_ALEN);
-               memcpy(hdr.addr2, addr, ETH_ALEN);
-               memcpy(hdr.addr3, skb->data + ETH_ALEN, ETH_ALEN);
-               hdrlen = 24;
-               break;
-       case NL80211_IFTYPE_STATION:
-       case NL80211_IFTYPE_P2P_CLIENT:
-               fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
-               /* BSSID SA DA */
-               memcpy(hdr.addr1, bssid, ETH_ALEN);
-               memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
-               memcpy(hdr.addr3, skb->data, ETH_ALEN);
-               hdrlen = 24;
-               break;
-       case NL80211_IFTYPE_OCB:
-       case NL80211_IFTYPE_ADHOC:
-               /* DA SA BSSID */
-               memcpy(hdr.addr1, skb->data, ETH_ALEN);
-               memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
-               memcpy(hdr.addr3, bssid, ETH_ALEN);
-               hdrlen = 24;
-               break;
-       default:
-               return -EOPNOTSUPP;
-       }
-
-       if (qos) {
-               fc |= cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
-               hdrlen += 2;
-       }
-
-       hdr.frame_control = fc;
-       hdr.duration_id = 0;
-       hdr.seq_ctrl = 0;
-
-       skip_header_bytes = ETH_HLEN;
-       if (ethertype == ETH_P_AARP || ethertype == ETH_P_IPX) {
-               encaps_data = bridge_tunnel_header;
-               encaps_len = sizeof(bridge_tunnel_header);
-               skip_header_bytes -= 2;
-       } else if (ethertype >= ETH_P_802_3_MIN) {
-               encaps_data = rfc1042_header;
-               encaps_len = sizeof(rfc1042_header);
-               skip_header_bytes -= 2;
-       } else {
-               encaps_data = NULL;
-               encaps_len = 0;
-       }
-
-       skb_pull(skb, skip_header_bytes);
-       nh_pos -= skip_header_bytes;
-       h_pos -= skip_header_bytes;
-
-       head_need = hdrlen + encaps_len - skb_headroom(skb);
-
-       if (head_need > 0 || skb_cloned(skb)) {
-               head_need = max(head_need, 0);
-               if (head_need)
-                       skb_orphan(skb);
-
-               if (pskb_expand_head(skb, head_need, 0, GFP_ATOMIC))
-                       return -ENOMEM;
-       }
-
-       if (encaps_data) {
-               memcpy(skb_push(skb, encaps_len), encaps_data, encaps_len);
-               nh_pos += encaps_len;
-               h_pos += encaps_len;
-       }
-
-       memcpy(skb_push(skb, hdrlen), &hdr, hdrlen);
-
-       nh_pos += hdrlen;
-       h_pos += hdrlen;
-
-       /* Update skb pointers to various headers since this modified frame
-        * is going to go through Linux networking code that may potentially
-        * need things like pointer to IP header. */
-       skb_reset_mac_header(skb);
-       skb_set_network_header(skb, nh_pos);
-       skb_set_transport_header(skb, h_pos);
-
-       return 0;
-}
-EXPORT_SYMBOL(ieee80211_data_from_8023);
-
 static void
 __frame_add_frag(struct sk_buff *skb, struct page *page,
                 void *ptr, int len, int size)
@@ -964,6 +847,9 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev)
                case EVENT_STOPPED:
                        __cfg80211_leave(wiphy_to_rdev(wdev->wiphy), wdev);
                        break;
+               case EVENT_PORT_AUTHORIZED:
+                       __cfg80211_port_authorized(wdev, ev->pa.bssid);
+                       break;
                }
                wdev_unlock(wdev);
 
@@ -1368,13 +1254,29 @@ int cfg80211_get_p2p_attr(const u8 *ies, unsigned int len,
 }
 EXPORT_SYMBOL(cfg80211_get_p2p_attr);
 
-static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id)
+static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id, bool id_ext)
 {
        int i;
 
-       for (i = 0; i < n_ids; i++)
-               if (ids[i] == id)
+       /* Make sure array values are legal */
+       if (WARN_ON(ids[n_ids - 1] == WLAN_EID_EXTENSION))
+               return false;
+
+       i = 0;
+       while (i < n_ids) {
+               if (ids[i] == WLAN_EID_EXTENSION) {
+                       if (id_ext && (ids[i + 1] == id))
+                               return true;
+
+                       i += 2;
+                       continue;
+               }
+
+               if (ids[i] == id && !id_ext)
                        return true;
+
+               i++;
+       }
        return false;
 }
 
@@ -1404,14 +1306,36 @@ size_t ieee80211_ie_split_ric(const u8 *ies, size_t ielen,
 {
        size_t pos = offset;
 
-       while (pos < ielen && ieee80211_id_in_list(ids, n_ids, ies[pos])) {
+       while (pos < ielen) {
+               u8 ext = 0;
+
+               if (ies[pos] == WLAN_EID_EXTENSION)
+                       ext = 2;
+               if ((pos + ext) >= ielen)
+                       break;
+
+               if (!ieee80211_id_in_list(ids, n_ids, ies[pos + ext],
+                                         ies[pos] == WLAN_EID_EXTENSION))
+                       break;
+
                if (ies[pos] == WLAN_EID_RIC_DATA && n_after_ric) {
                        pos = skip_ie(ies, ielen, pos);
 
-                       while (pos < ielen &&
-                              !ieee80211_id_in_list(after_ric, n_after_ric,
-                                                    ies[pos]))
-                               pos = skip_ie(ies, ielen, pos);
+                       while (pos < ielen) {
+                               if (ies[pos] == WLAN_EID_EXTENSION)
+                                       ext = 2;
+                               else
+                                       ext = 0;
+
+                               if ((pos + ext) >= ielen)
+                                       break;
+
+                               if (!ieee80211_id_in_list(after_ric,
+                                                         n_after_ric,
+                                                         ies[pos + ext],
+                                                         ext == 2))
+                                       pos = skip_ie(ies, ielen, pos);
+                       }
                } else {
                        pos = skip_ie(ies, ielen, pos);
                }