|
@@ -37,6 +37,7 @@
|
|
|
|
|
|
#include <linux/ip.h>
|
|
#include <linux/ip.h>
|
|
#include <linux/module.h>
|
|
#include <linux/module.h>
|
|
|
|
+#include <linux/udp.h>
|
|
|
|
|
|
/*
|
|
/*
|
|
*NOTICE!!!: This file will be very big, we should
|
|
*NOTICE!!!: This file will be very big, we should
|
|
@@ -1074,64 +1075,52 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx)
|
|
if (!ieee80211_is_data(fc))
|
|
if (!ieee80211_is_data(fc))
|
|
return false;
|
|
return false;
|
|
|
|
|
|
|
|
+ ip = (const struct iphdr *)(skb->data + mac_hdr_len +
|
|
|
|
+ SNAP_SIZE + PROTOC_TYPE_SIZE);
|
|
|
|
+ ether_type = be16_to_cpup((__be16 *)
|
|
|
|
+ (skb->data + mac_hdr_len + SNAP_SIZE));
|
|
|
|
|
|
- ip = (struct iphdr *)((u8 *) skb->data + mac_hdr_len +
|
|
|
|
- SNAP_SIZE + PROTOC_TYPE_SIZE);
|
|
|
|
- ether_type = *(u16 *) ((u8 *) skb->data + mac_hdr_len + SNAP_SIZE);
|
|
|
|
- /* ether_type = ntohs(ether_type); */
|
|
|
|
-
|
|
|
|
- if (ETH_P_IP == ether_type) {
|
|
|
|
- if (IPPROTO_UDP == ip->protocol) {
|
|
|
|
- struct udphdr *udp = (struct udphdr *)((u8 *) ip +
|
|
|
|
- (ip->ihl << 2));
|
|
|
|
- if (((((u8 *) udp)[1] == 68) &&
|
|
|
|
- (((u8 *) udp)[3] == 67)) ||
|
|
|
|
- ((((u8 *) udp)[1] == 67) &&
|
|
|
|
- (((u8 *) udp)[3] == 68))) {
|
|
|
|
- /*
|
|
|
|
- * 68 : UDP BOOTP client
|
|
|
|
- * 67 : UDP BOOTP server
|
|
|
|
- */
|
|
|
|
- RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV),
|
|
|
|
- DBG_DMESG, "dhcp %s !!\n",
|
|
|
|
- is_tx ? "Tx" : "Rx");
|
|
|
|
-
|
|
|
|
- if (is_tx) {
|
|
|
|
- rtlpriv->enter_ps = false;
|
|
|
|
- schedule_work(&rtlpriv->
|
|
|
|
- works.lps_change_work);
|
|
|
|
- ppsc->last_delaylps_stamp_jiffies =
|
|
|
|
- jiffies;
|
|
|
|
- }
|
|
|
|
|
|
+ switch (ether_type) {
|
|
|
|
+ case ETH_P_IP: {
|
|
|
|
+ struct udphdr *udp;
|
|
|
|
+ u16 src;
|
|
|
|
+ u16 dst;
|
|
|
|
|
|
- return true;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- } else if (ETH_P_ARP == ether_type) {
|
|
|
|
- if (is_tx) {
|
|
|
|
- rtlpriv->enter_ps = false;
|
|
|
|
- schedule_work(&rtlpriv->works.lps_change_work);
|
|
|
|
- ppsc->last_delaylps_stamp_jiffies = jiffies;
|
|
|
|
- }
|
|
|
|
|
|
+ if (ip->protocol != IPPROTO_UDP)
|
|
|
|
+ return false;
|
|
|
|
+ udp = (struct udphdr *)((u8 *)ip + (ip->ihl << 2));
|
|
|
|
+ src = be16_to_cpu(udp->source);
|
|
|
|
+ dst = be16_to_cpu(udp->dest);
|
|
|
|
|
|
- return true;
|
|
|
|
- } else if (ETH_P_PAE == ether_type) {
|
|
|
|
|
|
+ /* If this case involves port 68 (UDP BOOTP client) connecting
|
|
|
|
+ * with port 67 (UDP BOOTP server), then return true so that
|
|
|
|
+ * the lowest speed is used.
|
|
|
|
+ */
|
|
|
|
+ if (!((src == 68 && dst == 67) || (src == 67 && dst == 68)))
|
|
|
|
+ return false;
|
|
|
|
+
|
|
|
|
+ RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
|
|
|
|
+ "dhcp %s !!\n", is_tx ? "Tx" : "Rx");
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ case ETH_P_ARP:
|
|
|
|
+ break;
|
|
|
|
+ case ETH_P_PAE:
|
|
RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
|
|
RT_TRACE(rtlpriv, (COMP_SEND | COMP_RECV), DBG_DMESG,
|
|
"802.1X %s EAPOL pkt!!\n", is_tx ? "Tx" : "Rx");
|
|
"802.1X %s EAPOL pkt!!\n", is_tx ? "Tx" : "Rx");
|
|
-
|
|
|
|
- if (is_tx) {
|
|
|
|
- rtlpriv->enter_ps = false;
|
|
|
|
- schedule_work(&rtlpriv->works.lps_change_work);
|
|
|
|
- ppsc->last_delaylps_stamp_jiffies = jiffies;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return true;
|
|
|
|
- } else if (ETH_P_IPV6 == ether_type) {
|
|
|
|
- /* IPv6 */
|
|
|
|
- return true;
|
|
|
|
|
|
+ break;
|
|
|
|
+ case ETH_P_IPV6:
|
|
|
|
+ /* TODO: Is this right? */
|
|
|
|
+ return false;
|
|
|
|
+ default:
|
|
|
|
+ return false;
|
|
}
|
|
}
|
|
-
|
|
|
|
- return false;
|
|
|
|
|
|
+ if (is_tx) {
|
|
|
|
+ rtlpriv->enter_ps = false;
|
|
|
|
+ schedule_work(&rtlpriv->works.lps_change_work);
|
|
|
|
+ ppsc->last_delaylps_stamp_jiffies = jiffies;
|
|
|
|
+ }
|
|
|
|
+ return true;
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(rtl_is_special_data);
|
|
EXPORT_SYMBOL_GPL(rtl_is_special_data);
|
|
|
|
|