blob: cf154861e796b77e72f2c880c8407378496b6957 [file] [log] [blame]
#ifndef __QTN_WOWLAN_H__
#define __QTN_WOWLAN_H__
#include <qtn/qtn_net_packet.h>
#define WOWLAN_MATCH_TYPE_DEFAULT 0
#define WOWLAN_MATCH_TYPE_L2 1
#define WOWLAN_MATCH_TYPE_UDP 2
#ifndef IEEE80211_ADDR_BCAST
#define IEEE80211_ADDR_BCAST(a) ((a)[0] == 0xff && (a)[1] == 0xff && (a)[2] == 0xff && \
(a)[3] == 0xff && (a)[4] == 0xff && (a)[5] == 0xff)
#endif
RUBY_INLINE uint16_t get_udp_dst_port(const void *iphdr)
{
const struct qtn_ipv4 *ipv4 = (const struct qtn_ipv4 *)iphdr;
const uint8_t proto = ipv4->proto;
if (proto == QTN_IP_PROTO_UDP) {
const struct qtn_udp *udp = (struct qtn_udp *)((uint8_t *)ipv4 + sizeof(struct qtn_ipv4));
return udp->dst_port;
}
return 0;
}
RUBY_INLINE uint8_t wowlan_is_magic_packet(uint16_t ether_type, const void *eth_hdr, const void *iphdr,
uint16_t wowlan_match_type, uint16_t config_ether_type, uint16_t config_udp_port)
{
const struct ether_header *eh = (struct ether_header *)eth_hdr;
if (wowlan_match_type == WOWLAN_MATCH_TYPE_DEFAULT) {
if (IEEE80211_ADDR_BCAST(eh->ether_dhost))/*broadcast*/
return 1;
if (ether_type == htons(ETHERTYPE_WAKE_ON_LAN))/* ehter type is 0x0842*/
return 1;
if (ether_type == htons(ETHERTYPE_IP)) {
uint16_t udp_dst = get_udp_dst_port(iphdr);
if (udp_dst == htons(7) || udp_dst == htons(9))
return 1;
}
} else if (wowlan_match_type == WOWLAN_MATCH_TYPE_L2) {
if (ether_type == htons(config_ether_type))/* ehter type is 0x0842 or user defined*/
return 1;
} else if (wowlan_match_type == WOWLAN_MATCH_TYPE_UDP) {
if (ether_type == htons(ETHERTYPE_IP)) {
uint16_t udp_dst = get_udp_dst_port(iphdr);
if (((config_udp_port == 0xffff) && (udp_dst == htons(7) || udp_dst == htons(9))) ||
(udp_dst == htons(config_udp_port)))
return 1;
}
}
return 0;
}
#endif