cfg80211: Remove default dynamic PS timeout value
[linux-drm-fsl-dcu.git] / net / wireless / util.c
index 23557c1d0a9caafd0e8c7b211846c9bd0f8a32b0..7acb81b9675dc66597f2f1048ab2675542191939 100644 (file)
@@ -227,8 +227,11 @@ unsigned int ieee80211_hdrlen(__le16 fc)
        if (ieee80211_is_data(fc)) {
                if (ieee80211_has_a4(fc))
                        hdrlen = 30;
-               if (ieee80211_is_data_qos(fc))
+               if (ieee80211_is_data_qos(fc)) {
                        hdrlen += IEEE80211_QOS_CTL_LEN;
+                       if (ieee80211_has_order(fc))
+                               hdrlen += IEEE80211_HT_CTL_LEN;
+               }
                goto out;
        }
 
@@ -327,11 +330,18 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
                if (iftype == NL80211_IFTYPE_MESH_POINT) {
                        struct ieee80211s_hdr *meshdr =
                                (struct ieee80211s_hdr *) (skb->data + hdrlen);
-                       hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
+                       /* make sure meshdr->flags is on the linear part */
+                       if (!pskb_may_pull(skb, hdrlen + 1))
+                               return -1;
                        if (meshdr->flags & MESH_FLAGS_AE_A5_A6) {
-                               memcpy(dst, meshdr->eaddr1, ETH_ALEN);
-                               memcpy(src, meshdr->eaddr2, ETH_ALEN);
+                               skb_copy_bits(skb, hdrlen +
+                                       offsetof(struct ieee80211s_hdr, eaddr1),
+                                       dst, ETH_ALEN);
+                               skb_copy_bits(skb, hdrlen +
+                                       offsetof(struct ieee80211s_hdr, eaddr2),
+                                       src, ETH_ALEN);
                        }
+                       hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
                }
                break;
        case cpu_to_le16(IEEE80211_FCTL_FROMDS):
@@ -343,9 +353,14 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
                if (iftype == NL80211_IFTYPE_MESH_POINT) {
                        struct ieee80211s_hdr *meshdr =
                                (struct ieee80211s_hdr *) (skb->data + hdrlen);
-                       hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
+                       /* make sure meshdr->flags is on the linear part */
+                       if (!pskb_may_pull(skb, hdrlen + 1))
+                               return -1;
                        if (meshdr->flags & MESH_FLAGS_AE_A4)
-                               memcpy(src, meshdr->eaddr1, ETH_ALEN);
+                               skb_copy_bits(skb, hdrlen +
+                                       offsetof(struct ieee80211s_hdr, eaddr1),
+                                       src, ETH_ALEN);
+                       hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
                }
                break;
        case cpu_to_le16(0):
@@ -354,7 +369,7 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
                break;
        }
 
-       if (unlikely(skb->len - hdrlen < 8))
+       if (!pskb_may_pull(skb, hdrlen + 8))
                return -1;
 
        payload = skb->data + hdrlen;