diff options
author | Eyal Shapira <eyal@wizery.com> | 2012-01-03 13:47:00 +0200 |
---|---|---|
committer | Arik Nemtsov <arik@wizery.com> | 2012-08-02 13:03:59 +0300 |
commit | 474c453f3ada343260e6f46be0ebe6c4913974f4 (patch) | |
tree | cf05adc0c1411d290242257781f09059d80c66db | |
parent | 3a8dd1b140fe743fa4513c05673e0684f7cd34dd (diff) | |
download | external_wpa_supplicant_8_ti-474c453f3ada343260e6f46be0ebe6c4913974f4.zip external_wpa_supplicant_8_ti-474c453f3ada343260e6f46be0ebe6c4913974f4.tar.gz external_wpa_supplicant_8_ti-474c453f3ada343260e6f46be0ebe6c4913974f4.tar.bz2 |
driver_nl80211: rx filters - add support for longer patterns
- Add support for long patterns (longer than 8 bytes)
- Separate Rx filters static configuration from code
- Add DHCP and ARP Rx filters
Signed-off-by: Eyal Shapira <eyal@wizery.com>
Signed-off-by: Assaf Azulay <assaf@ti.com>
-rw-r--r-- | src/drivers/driver_nl80211.c | 201 |
1 files changed, 138 insertions, 63 deletions
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 6f561fc..bf67aba 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -8886,54 +8886,128 @@ static int nl80211_pmkid(struct i802_bss *bss, int cmd, const u8 *bssid, return -ENOBUFS; } -#define RX_SELF_FILTER 0 -#define RX_BROADCAST_FILTER 1 -#define RX_IPV4_MULTICAST_FILTER 2 -#define RX_IPV6_MULTICAST_FILTER 3 -#define NR_RX_FILTERS 4 +#ifdef ANDROID + +#define MAX_PATTERN_SIZE 256 +#define MAX_MASK_SIZE (MAX_PATTERN_SIZE/8) + +/* Describes a single RX filter configuration */ +struct rx_filter { + /* name - A human recongmizable name for the filter */ + char *name; + + /* get_pattern_handler - A handler which enables the user to configure + * the pattern dynamically (For example filter according to the HW addr). + * If NULL the static pattern configured will be used. + * buf - the pattern will be copied to buf + * buflen - the size of buf + * arg - A generic input argumet which can be passed to the handler + */ + int (* get_pattern_handler) (u8 *buf, int buflen, void* arg); + + /* pattern - A static pattern to filter + * This array contains the bytes of the pattern. The mask field + * indicates which bytes should be used in the filter and which + * can be discarded + */ + u8 pattern[MAX_PATTERN_SIZE]; -static const u8 filter_bcast[] = {0xff,0xff,0xff,0xff,0xff,0xff}; -static const u8 filter_ipv4mc[] = {0x01,0x00,0x5e}; -static const u8 filter_ipv6mc[] = {0x33,0x33}; + /* pattern_len - The number of bytes used in pattern */ + u8 pattern_len; -static int nl80211_get_wowlan_pat(struct i802_bss *bss, u8 *buf, int buflen, - u8* mask, int filter) + /* mask - A bit mask indicating which bytes in pattern should be + * used for filtering. Each bit here corresponds to a byte in pattern + */ + u8 mask[MAX_MASK_SIZE]; + + /* mask_len - The number of bytes used in mask */ + u8 mask_len; +}; + +static u8 *nl80211_rx_filter_get_pattern(struct rx_filter *filter, void *arg) { - int len = 0, ret; - if (buflen < ETH_ALEN) - return -1; + if (filter->get_pattern_handler) { + if (filter->get_pattern_handler(filter->pattern, + filter->pattern_len, arg)) { + return NULL; + } + } - switch(filter) { - case RX_SELF_FILTER: - ret = linux_get_ifhwaddr(bss->drv->ioctl_sock, - bss->ifname, buf); - if (ret) - return -1; - len = ETH_ALEN; - *mask = 0x3F; - break; - case RX_BROADCAST_FILTER: - memcpy(buf, filter_bcast, sizeof(filter_bcast)); - len = ETH_ALEN; - *mask = 0x3F; - break; - case RX_IPV4_MULTICAST_FILTER: - memcpy(buf, filter_ipv4mc, sizeof(filter_ipv4mc)); - len = sizeof(filter_ipv4mc); - *mask = 0x7; /* 3 bytes */ - break; - case RX_IPV6_MULTICAST_FILTER: - memcpy(buf, filter_ipv6mc, sizeof(filter_ipv6mc)); - len = sizeof(filter_ipv6mc); - *mask = 0x3; /* 2 bytes */ - break; - default: - len = -1; - break; + return filter->pattern; +} + +static int +nl80211_self_filter_get_pattern_handler(u8 *buf, int buflen, void *arg) +{ + int ret; + struct i802_bss *bss = (struct i802_bss *)arg; + + ret = linux_get_ifhwaddr(bss->drv->global->ioctl_sock, + bss->ifname, buf); + if (ret) { + wpa_printf(MSG_ERROR, "Failed to get own HW addr (%d)", ret); + return -1; } - return len; + return 0; } +static struct rx_filter rx_filters[] = { + {.name = "self", + .pattern = {}, + .pattern_len = 6, + .mask = { BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) }, + .mask_len = 1, + .get_pattern_handler = nl80211_self_filter_get_pattern_handler, + }, + + {.name = "bcast", + .pattern = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, + .pattern_len = 6, + .mask = { BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) }, + .mask_len = 1, + }, + + {.name = "ipv4mc", + .pattern = {0x01,0x00,0x5E}, + .pattern_len = 3, + .mask = { BIT(0) | BIT(1) | BIT(2) }, + .mask_len = 1, + }, + + {.name = "ipv6mc", + .pattern = {0x33,0x33}, + .pattern_len = 2, + .mask = { BIT(0) | BIT(1) }, + .mask_len = 1, + }, + + {.name = "arp", + .pattern = {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , + 0 , 0 , 0 , 0 , 0x08, 0x06}, + .pattern_len = 14, + .mask = { 0, /* OCTET 1 */ + BIT(4) | BIT(5) }, /* OCTET 2 */ + .mask_len = 2, + }, + + {.name = "dhcp", + .pattern = {0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , + 0 , 0 , 0 , 0 , 0 , 0 , 0x45, 0 , + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0x11, + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , + 0 , 0 , 0 , 0 , 0x00, 0x44}, + .pattern_len = 38, + .mask = { 0, /* OCTET 1 */ + BIT(6), /* OCTET 2 */ + BIT(7), /* OCTET 3 */ + 0, /* OCTET 4 */ + BIT(4) | BIT(5) }, /* OCTET 5 */ + .mask_len = 5, + }, +}; + +#define NR_RX_FILTERS (int)(sizeof(rx_filters) / sizeof(struct rx_filter)) + static int nl80211_set_wowlan_triggers(struct i802_bss *bss, int enable) { struct nl_msg *msg, *pats = NULL; @@ -8967,28 +9041,27 @@ static int nl80211_set_wowlan_triggers(struct i802_bss *bss, int enable) } for (i = 0; i < NR_RX_FILTERS; i++) { - if (bss->drv->wowlan_triggers & (1 << i)) { - u8 patbuf[ETH_ALEN], patmask; - int patlen; - int patnr = 1; - int j; - - patlen = nl80211_get_wowlan_pat(bss, patbuf, - sizeof(patbuf), - &patmask, i); - if (!patlen) - continue; - else if (patlen < 0) { - ret = -1; - break; - } - pat = nla_nest_start(pats, patnr++); - NLA_PUT(pats, NL80211_WOWLAN_PKTPAT_MASK, - 1, &patmask); - NLA_PUT(pats, NL80211_WOWLAN_PKTPAT_PATTERN, - patlen, patbuf); - nla_nest_end(pats, pat); - } + struct rx_filter *rx_filter = &rx_filters[i]; + int patnr = 1; + u8 *pattern; + + if (!(bss->drv->wowlan_triggers & (1 << i))) + continue; + + pattern = nl80211_rx_filter_get_pattern(rx_filter, bss); + if (!pattern) + continue; + + pat = nla_nest_start(pats, patnr++); + NLA_PUT(pats, NL80211_WOWLAN_PKTPAT_MASK, + rx_filter->mask_len, + rx_filter->mask); + + NLA_PUT(pats, NL80211_WOWLAN_PKTPAT_PATTERN, + rx_filter->pattern_len, + pattern); + + nla_nest_end(pats, pat); } } @@ -9043,6 +9116,8 @@ static int nl80211_parse_wowlan_trigger_nr(char *s) return i; } +#endif /* ANDROID */ + static int nl80211_add_pmkid(void *priv, const u8 *bssid, const u8 *pmkid) { struct i802_bss *bss = priv; |