319-cfg80211-add-function-for-802.3-conversion-with-sepa.patch 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. From: Felix Fietkau <nbd@openwrt.org>
  2. Date: Tue, 2 Feb 2016 14:39:09 +0100
  3. Subject: [PATCH] cfg80211: add function for 802.3 conversion with separate
  4. output buffer
  5. Use skb_copy_bits in preparation for allowing fragmented skbs
  6. Signed-off-by: Felix Fietkau <nbd@openwrt.org>
  7. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  8. ---
  9. --- a/net/wireless/util.c
  10. +++ b/net/wireless/util.c
  11. @@ -393,9 +393,9 @@ unsigned int ieee80211_get_hdrlen_from_s
  12. }
  13. EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
  14. -unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
  15. +static unsigned int __ieee80211_get_mesh_hdrlen(u8 flags)
  16. {
  17. - int ae = meshhdr->flags & MESH_FLAGS_AE;
  18. + int ae = flags & MESH_FLAGS_AE;
  19. /* 802.11-2012, 8.2.4.7.3 */
  20. switch (ae) {
  21. default:
  22. @@ -407,21 +407,31 @@ unsigned int ieee80211_get_mesh_hdrlen(s
  23. return 18;
  24. }
  25. }
  26. +
  27. +unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
  28. +{
  29. + return __ieee80211_get_mesh_hdrlen(meshhdr->flags);
  30. +}
  31. EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
  32. -int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
  33. - enum nl80211_iftype iftype)
  34. +static int __ieee80211_data_to_8023(struct sk_buff *skb, struct ethhdr *ehdr,
  35. + const u8 *addr, enum nl80211_iftype iftype)
  36. {
  37. struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
  38. - u16 hdrlen, ethertype;
  39. - u8 *payload;
  40. - u8 dst[ETH_ALEN];
  41. - u8 src[ETH_ALEN] __aligned(2);
  42. + struct {
  43. + u8 hdr[ETH_ALEN] __aligned(2);
  44. + __be16 proto;
  45. + } payload;
  46. + struct ethhdr tmp;
  47. + u16 hdrlen;
  48. + u8 mesh_flags = 0;
  49. if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
  50. return -1;
  51. hdrlen = ieee80211_hdrlen(hdr->frame_control);
  52. + if (skb->len < hdrlen + 8)
  53. + return -1;
  54. /* convert IEEE 802.11 header + possible LLC headers into Ethernet
  55. * header
  56. @@ -432,8 +442,11 @@ int ieee80211_data_to_8023(struct sk_buf
  57. * 1 0 BSSID SA DA n/a
  58. * 1 1 RA TA DA SA
  59. */
  60. - memcpy(dst, ieee80211_get_DA(hdr), ETH_ALEN);
  61. - memcpy(src, ieee80211_get_SA(hdr), ETH_ALEN);
  62. + memcpy(tmp.h_dest, ieee80211_get_DA(hdr), ETH_ALEN);
  63. + memcpy(tmp.h_source, ieee80211_get_SA(hdr), ETH_ALEN);
  64. +
  65. + if (iftype == NL80211_IFTYPE_MESH_POINT)
  66. + skb_copy_bits(skb, hdrlen, &mesh_flags, 1);
  67. switch (hdr->frame_control &
  68. cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
  69. @@ -450,44 +463,31 @@ int ieee80211_data_to_8023(struct sk_buf
  70. iftype != NL80211_IFTYPE_STATION))
  71. return -1;
  72. if (iftype == NL80211_IFTYPE_MESH_POINT) {
  73. - struct ieee80211s_hdr *meshdr =
  74. - (struct ieee80211s_hdr *) (skb->data + hdrlen);
  75. - /* make sure meshdr->flags is on the linear part */
  76. - if (!pskb_may_pull(skb, hdrlen + 1))
  77. - return -1;
  78. - if (meshdr->flags & MESH_FLAGS_AE_A4)
  79. + if (mesh_flags & MESH_FLAGS_AE_A4)
  80. return -1;
  81. - if (meshdr->flags & MESH_FLAGS_AE_A5_A6) {
  82. + if (mesh_flags & MESH_FLAGS_AE_A5_A6) {
  83. skb_copy_bits(skb, hdrlen +
  84. offsetof(struct ieee80211s_hdr, eaddr1),
  85. - dst, ETH_ALEN);
  86. - skb_copy_bits(skb, hdrlen +
  87. - offsetof(struct ieee80211s_hdr, eaddr2),
  88. - src, ETH_ALEN);
  89. + tmp.h_dest, 2 * ETH_ALEN);
  90. }
  91. - hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
  92. + hdrlen += __ieee80211_get_mesh_hdrlen(mesh_flags);
  93. }
  94. break;
  95. case cpu_to_le16(IEEE80211_FCTL_FROMDS):
  96. if ((iftype != NL80211_IFTYPE_STATION &&
  97. iftype != NL80211_IFTYPE_P2P_CLIENT &&
  98. iftype != NL80211_IFTYPE_MESH_POINT) ||
  99. - (is_multicast_ether_addr(dst) &&
  100. - ether_addr_equal(src, addr)))
  101. + (is_multicast_ether_addr(tmp.h_dest) &&
  102. + ether_addr_equal(tmp.h_source, addr)))
  103. return -1;
  104. if (iftype == NL80211_IFTYPE_MESH_POINT) {
  105. - struct ieee80211s_hdr *meshdr =
  106. - (struct ieee80211s_hdr *) (skb->data + hdrlen);
  107. - /* make sure meshdr->flags is on the linear part */
  108. - if (!pskb_may_pull(skb, hdrlen + 1))
  109. - return -1;
  110. - if (meshdr->flags & MESH_FLAGS_AE_A5_A6)
  111. + if (mesh_flags & MESH_FLAGS_AE_A5_A6)
  112. return -1;
  113. - if (meshdr->flags & MESH_FLAGS_AE_A4)
  114. + if (mesh_flags & MESH_FLAGS_AE_A4)
  115. skb_copy_bits(skb, hdrlen +
  116. offsetof(struct ieee80211s_hdr, eaddr1),
  117. - src, ETH_ALEN);
  118. - hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
  119. + tmp.h_source, ETH_ALEN);
  120. + hdrlen += __ieee80211_get_mesh_hdrlen(mesh_flags);
  121. }
  122. break;
  123. case cpu_to_le16(0):
  124. @@ -498,33 +498,33 @@ int ieee80211_data_to_8023(struct sk_buf
  125. break;
  126. }
  127. - if (!pskb_may_pull(skb, hdrlen + 8))
  128. - return -1;
  129. -
  130. - payload = skb->data + hdrlen;
  131. - ethertype = (payload[6] << 8) | payload[7];
  132. + skb_copy_bits(skb, hdrlen, &payload, sizeof(payload));
  133. + tmp.h_proto = payload.proto;
  134. - if (likely((ether_addr_equal(payload, rfc1042_header) &&
  135. - ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
  136. - ether_addr_equal(payload, bridge_tunnel_header))) {
  137. + if (likely((ether_addr_equal(payload.hdr, rfc1042_header) &&
  138. + tmp.h_proto != htons(ETH_P_AARP) &&
  139. + tmp.h_proto != htons(ETH_P_IPX)) ||
  140. + ether_addr_equal(payload.hdr, bridge_tunnel_header)))
  141. /* remove RFC1042 or Bridge-Tunnel encapsulation and
  142. * replace EtherType */
  143. - skb_pull(skb, hdrlen + 6);
  144. - memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN);
  145. - memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN);
  146. - } else {
  147. - struct ethhdr *ehdr;
  148. - __be16 len;
  149. + hdrlen += ETH_ALEN + 2;
  150. + else
  151. + tmp.h_proto = htons(skb->len);
  152. - skb_pull(skb, hdrlen);
  153. - len = htons(skb->len);
  154. + pskb_pull(skb, hdrlen);
  155. +
  156. + if (!ehdr)
  157. ehdr = (struct ethhdr *) skb_push(skb, sizeof(struct ethhdr));
  158. - memcpy(ehdr->h_dest, dst, ETH_ALEN);
  159. - memcpy(ehdr->h_source, src, ETH_ALEN);
  160. - ehdr->h_proto = len;
  161. - }
  162. + memcpy(ehdr, &tmp, sizeof(tmp));
  163. +
  164. return 0;
  165. }
  166. +
  167. +int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
  168. + enum nl80211_iftype iftype)
  169. +{
  170. + return __ieee80211_data_to_8023(skb, NULL, addr, iftype);
  171. +}
  172. EXPORT_SYMBOL(ieee80211_data_to_8023);
  173. int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,