static bool ath6kl_parse_data_pkt_for_wake_lock(struct ath6kl *ar,
						struct sk_buff *skb)
{
	struct net_device *ndev;
	struct ath6kl_vif *vif;
	struct ethhdr *hdr;
	bool need_wake = false;
	u16 dst_port;

	vif = ath6kl_vif_first(ar);
	if (!vif)
		return need_wake;

	if (skb->len < sizeof(struct ethhdr))
		return need_wake;

	hdr = (struct ethhdr *) skb->data;

	if (!is_multicast_ether_addr(hdr->h_dest)) {
		switch (ntohs(hdr->h_proto)) {
		case 0x0800: /* IP */
			need_wake = ath6kl_parse_ip_pkt_for_wake_lock(skb);
			break;
		case 0x888e: /* EAPOL */
		case 0x88c7: /* RSN_PREAUTH */
		case 0x88b4: /* WAPI */
			need_wake = true;
			break;
		default:
			break;
		}
	} else if (!is_broadcast_ether_addr(hdr->h_dest)) {
		if (skb->len >= 14 + 20) { /* mDNS packets */
			u8 *dst_ipaddr = (u8 *)(skb->data + 14 + 20 - 4);
			ndev = vif->ndev;
			if (((dst_ipaddr[3] & 0xf8) == 0xf8) &&
				(vif->nw_type == AP_NETWORK ||
				(ndev->flags & IFF_ALLMULTI ||
				ndev->flags & IFF_MULTICAST)))
					need_wake = true;
		}
	} else if (vif->nw_type == AP_NETWORK) {
		switch (ntohs(hdr->h_proto)) {
		case 0x0800: /* IP */
			if (skb->len >= 14 + 20 + 2) {
				dst_port = *(u16 *)(skb->data + 14 + 20);
				/* dhcp req */
				need_wake = (ntohs(dst_port) == 0x43);
			}
			break;
		case 0x0806:
			need_wake = true;
		default:
			break;
		}
	}

	return need_wake;
}
Exemplo n.º 2
0
static bool ath6kl_parse_data_pkt_for_wake_lock(struct ath6kl *ar,
						struct sk_buff *skb)
{
	struct net_device *ndev;
	struct ath6kl_vif *vif;
	struct ethhdr *hdr;
	bool need_wake = false;
	u16 dst_port;

	vif = ath6kl_vif_first(ar);
	if (!vif)
		return need_wake;

	if (skb->len < sizeof(struct ethhdr))
		return need_wake;

	hdr = (struct ethhdr *) skb->data;

#if 0 // by bbelief
	if (test_and_clear_bit(WOW_RESUME_PRINT, &ar->flag)) {
		ath6kl_dbg(ATH6KL_DBG_SUSPEND,
			   "(wow) dest mac:%pM, src mac:%pM, type/len :%04x\n",
			   hdr->h_dest, hdr->h_source,
			   be16_to_cpu(hdr->h_proto));
	}
#endif

	if (!is_multicast_ether_addr(hdr->h_dest)) {
		switch (ntohs(hdr->h_proto)) {
		case 0x0800: /* IP */
			need_wake = ath6kl_parse_ip_pkt_for_wake_lock(skb);
			break;
		case 0x888e: /* EAPOL */
		case 0x88c7: /* RSN_PREAUTH */
		case 0x88b4: /* WAPI */
			need_wake = true;
			break;
		default:
			break;
		}
	} else if (!is_broadcast_ether_addr(hdr->h_dest)) {
		if (skb->len >= 14 + 20) { /* mDNS packets */
			u8 *dst_ipaddr = (u8 *)(skb->data + 14 + 20 - 4);
			ndev = vif->ndev;
			if (((dst_ipaddr[3] & 0xf8) == 0xf8) &&
				(vif->nw_type == AP_NETWORK ||
				(ndev->flags & IFF_ALLMULTI ||
				ndev->flags & IFF_MULTICAST)))
					need_wake = true;
		}
	} else if (vif->nw_type == AP_NETWORK) {
		switch (ntohs(hdr->h_proto)) {
		case 0x0800: /* IP */
			if (skb->len >= 14 + 20 + 2) {
				dst_port = *(u16 *)(skb->data + 14 + 20);
				/* dhcp req */
				need_wake = (ntohs(dst_port) == 0x43);
			}
			break;
		case 0x0806:
			need_wake = true;
		default:
			break;
		}
	}

	return need_wake;
}