From c94b73369f21d4bb50adc2d558f7c1a1ba014b73 Mon Sep 17 00:00:00 2001 From: dujeonglee Date: Fri, 24 May 2019 21:05:43 +0900 Subject: [PATCH] [RAMEN9610-19423] wlbt: filter abnormal ipv4 multicast packet Change-Id: I50511db5dcec9a9959670eb843ef87c3def99bcc Signed-off-by: dujeonglee Signed-off-by: Kim Gunho --- drivers/net/wireless/scsc/Kconfig | 6 ++ drivers/net/wireless/scsc/dev.c | 3 + drivers/net/wireless/scsc/dev.h | 7 +- drivers/net/wireless/scsc/ioctl.c | 9 ++ drivers/net/wireless/scsc/mgt.c | 171 +++++++++++++++++++++--------- drivers/net/wireless/scsc/mgt.h | 3 + 6 files changed, 149 insertions(+), 50 deletions(-) diff --git a/drivers/net/wireless/scsc/Kconfig b/drivers/net/wireless/scsc/Kconfig index 05e3b2099d3f..bccc2711fbef 100755 --- a/drivers/net/wireless/scsc/Kconfig +++ b/drivers/net/wireless/scsc/Kconfig @@ -262,3 +262,9 @@ config SCSC_WLAN_STA_ENHANCED_ARP_DETECT ---help--- This option tells whether enhanced arp detection is enabled or not. + +config SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER + bool "Enable abnormal multicast packet filtering in suspend" + default n + ---help--- + This option tells if abnormal multicast packet filtering in suspend is supported or not. diff --git a/drivers/net/wireless/scsc/dev.c b/drivers/net/wireless/scsc/dev.c index 72591471d5b7..a4b5d04ef942 100755 --- a/drivers/net/wireless/scsc/dev.c +++ b/drivers/net/wireless/scsc/dev.c @@ -391,6 +391,9 @@ struct slsi_dev *slsi_dev_attach(struct device *dev, struct scsc_mx *core, struc #endif #ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER sdev->enhanced_pkt_filter_enabled = true; +#endif +#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER + sdev->abnormal_multicast_pkt_filter_enabled = true; #endif sdev->device_state = SLSI_DEVICE_STATE_STOPPED; sdev->current_tspec_id = -1; diff --git a/drivers/net/wireless/scsc/dev.h b/drivers/net/wireless/scsc/dev.h index ea7172795893..7b4582e3c112 100755 --- a/drivers/net/wireless/scsc/dev.h +++ b/drivers/net/wireless/scsc/dev.h @@ -471,6 +471,7 @@ enum slsi_filter_id { SLSI_OPT_IN_TCP4_FILTER_ID, /* 0x87 */ SLSI_OPT_IN_TCP6_FILTER_ID, /* 0x88 */ #endif + SLSI_OPT_OUT_ABNORMAL_MULTICAST_ID, /* 0x88 */ SLSI_REGD_MC_FILTER_ID, /* 0x89 */ }; #else @@ -491,7 +492,8 @@ enum slsi_filter_id { SLSI_OPT_IN_TCP4_FILTER_ID, /* 0x88 */ SLSI_OPT_IN_TCP6_FILTER_ID, /* 0x89 */ #endif - SLSI_REGD_MC_FILTER_ID, /* 0x8A */ + SLSI_OPT_OUT_ABNORMAL_MULTICAST_ID, /* 0x89 */ + SLSI_REGD_MC_FILTER_ID, /* 0x8a */ }; #endif @@ -1164,6 +1166,9 @@ struct slsi_dev { #ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER bool enhanced_pkt_filter_enabled; #endif +#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER + bool abnormal_multicast_pkt_filter_enabled; +#endif }; /* Compact representation of channels a ESS has been seen on diff --git a/drivers/net/wireless/scsc/ioctl.c b/drivers/net/wireless/scsc/ioctl.c index 51bf1098b968..6e75aac7b78a 100755 --- a/drivers/net/wireless/scsc/ioctl.c +++ b/drivers/net/wireless/scsc/ioctl.c @@ -129,6 +129,9 @@ #ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER #define CMD_ENHANCED_PKT_FILTER "ENHANCED_PKT_FILTER" #endif +#ifdef SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER +#define CMD_ABNORMAL_MULTICAST_PKT_FILTER "ABNORMAL_MULTICAST_PKT_FILTER" +#endif #ifdef CONFIG_SCSC_WLAN_SET_NUM_ANTENNAS #define CMD_SET_NUM_ANTENNAS "SET_NUM_ANTENNAS" @@ -2749,6 +2752,12 @@ int slsi_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) ret = slsi_set_enhanced_pkt_filter(dev, enable); #endif +#ifdef SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER + } else if ((strncasecmp(command, CMD_ABNORMAL_MULTICAST_PKT_FILTER, strlen(CMD_ABNORMAL_MULTICAST_PKT_FILTER)) == 0)) { + const u8 enable = *(command + strlen(CMD_ABNORMAL_MULTICAST_PKT_FILTER) + 1) - '0'; + + ret = slsi_set_abnormal_multicast_pkt_filter(dev, enable); +#endif #ifdef CONFIG_SCSC_WLAN_SET_NUM_ANTENNAS } else if (strncasecmp(command, CMD_SET_NUM_ANTENNAS, strlen(CMD_SET_NUM_ANTENNAS)) == 0) { struct netdev_vif *ndev_vif = netdev_priv(dev); diff --git a/drivers/net/wireless/scsc/mgt.c b/drivers/net/wireless/scsc/mgt.c index d688fdb6190e..abf334127ad1 100755 --- a/drivers/net/wireless/scsc/mgt.c +++ b/drivers/net/wireless/scsc/mgt.c @@ -3450,6 +3450,64 @@ static int slsi_set_opt_in_tcp6_packet_filter(struct slsi_dev *sdev, struct net } #endif +#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER +int slsi_set_abnormal_multicast_pkt_filter(struct net_device *dev, u8 enabled) +{ + struct netdev_vif *netdev_vif = netdev_priv(dev); + struct slsi_dev *sdev = netdev_vif->sdev; + int ret = 0; + int is_suspend = 0; + + SLSI_MUTEX_LOCK(sdev->device_config_mutex); + is_suspend = sdev->device_config.user_suspend_mode; + SLSI_MUTEX_UNLOCK(sdev->device_config_mutex); + + if (is_suspend) { + SLSI_ERR(sdev, "Host is in early suspend state.\n"); + return -EPERM; /* set_enhanced_pkt_filter should not be called after suspend */ + } + + sdev->abnormal_multicast_pkt_filter_enabled = enabled; + SLSI_INFO(sdev, "Abnormal multicast packet filter is %s", (enabled ? "enabled" : "disabled")); + return ret; +} + +static int slsi_set_opt_out_abnormal_multicast_packet_filter(struct slsi_dev *sdev, struct net_device *dev) +{ + struct slsi_mlme_pattern_desc pattern_desc[3]; + u8 pkt_filters_len = 0; + int ret = 0; + struct slsi_mlme_pkt_filter_elem pkt_filter_elem; + + /* IPv4 packet */ + pattern_desc[0].offset = 0; /* destination mac address*/ + pattern_desc[0].mask_length = ETH_ALEN; + memset(pattern_desc[0].mask, 0xff, ETH_ALEN); + memcpy(pattern_desc[0].pattern, sdev->hw_addr, ETH_ALEN); + + pattern_desc[1].offset = ETH_ALEN + ETH_ALEN; /* ethhdr->h_proto == IPv4 */ + pattern_desc[1].mask_length = 2; + pattern_desc[1].mask[0] = 0xff; /* Big endian 0xffff */ + pattern_desc[1].mask[1] = 0xff; + pattern_desc[1].pattern[0] = 0x08; /* Big endian 0x0800 */ + pattern_desc[1].pattern[1] = 0x00; + + pattern_desc[2].offset = sizeof(struct ethhdr) + offsetof(struct iphdr, daddr); /* iphdr->daddr starts with 1110 */ + pattern_desc[2].mask_length = 1; + pattern_desc[2].mask[0] = 0xf0; + pattern_desc[2].pattern[0] = 0xe0; /* 224 */ + + slsi_create_packet_filter_element(SLSI_OPT_OUT_ABNORMAL_MULTICAST_ID, + FAPI_PACKETFILTERMODE_OPT_OUT_SLEEP, + 3, pattern_desc, + &pkt_filter_elem, &pkt_filters_len); + + ret = slsi_mlme_set_packet_filter(sdev, dev, pkt_filters_len, 1, &pkt_filter_elem); + + return ret; +} +#endif + static int slsi_set_multicast_packet_filters(struct slsi_dev *sdev, struct net_device *dev) { struct slsi_mlme_pattern_desc pattern_desc; @@ -3539,7 +3597,10 @@ int slsi_clear_packet_filters(struct slsi_dev *sdev, struct net_device *dev) num_filters++; /*TCP IPv6 OPT IN*/ } #endif - +#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER + if (sdev->abnormal_multicast_pkt_filter_enabled) + num_filters++;/* clear abnormal multicast packet */ +#endif pkt_filter_elem = kmalloc((num_filters * sizeof(struct slsi_mlme_pkt_filter_elem)), GFP_KERNEL); if (!pkt_filter_elem) { SLSI_NET_ERR(dev, "ERROR Memory allocation failure"); @@ -3578,6 +3639,13 @@ int slsi_clear_packet_filters(struct slsi_dev *sdev, struct net_device *dev) &pkt_filter_elem[num_filters], &pkt_filters_len); num_filters++; } +#endif +#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER + if (sdev->abnormal_multicast_pkt_filter_enabled) { + slsi_create_packet_filter_element(SLSI_OPT_OUT_ABNORMAL_MULTICAST_ID, 0, 0, NULL, + &pkt_filter_elem[num_filters], &pkt_filters_len); + num_filters++; + } #endif ret = slsi_mlme_set_packet_filter(sdev, dev, pkt_filters_len, num_filters, pkt_filter_elem); kfree(pkt_filter_elem); @@ -3613,6 +3681,14 @@ int slsi_update_packet_filters(struct slsi_dev *sdev, struct net_device *dev) if (ret) return ret; } +#endif + /* install abnormal multicast packet filter */ +#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER + if (sdev->abnormal_multicast_pkt_filter_enabled) { + ret = slsi_set_opt_out_abnormal_multicast_packet_filter(sdev, dev); + if (ret) + return ret; + } #endif return slsi_set_common_packet_filters(sdev, dev); } @@ -3673,60 +3749,57 @@ void slsi_set_packet_filters(struct slsi_dev *sdev, struct net_device *dev) if (ie) { SLSI_NET_DBG1(dev, SLSI_CFG80211, "Connected to HS2 AP "); - if (slsi_is_proxy_arp_supported_on_ap(peer->assoc_resp_ie)) { - SLSI_NET_DBG1(dev, SLSI_CFG80211, "Proxy ARP service supported on HS2 AP "); + if (slsi_is_proxy_arp_supported_on_ap(peer->assoc_resp_ie)) { + SLSI_NET_DBG1(dev, SLSI_CFG80211, "Proxy ARP service supported on HS2 AP "); - /* Opt out Gratuitous ARP packets (ARP Announcement) in active and suspended mode. - * For suspended mode, gratituous ARP is dropped by "opt out all broadcast" that will be - * set in slsi_set_common_packet_filters on screen off - */ - num_pattern_desc = 0; - pattern_desc[num_pattern_desc].offset = 0; /*filtering on MAC destination Address*/ - pattern_desc[num_pattern_desc].mask_length = ETH_ALEN; - SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].mask, addr_mask); - SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].pattern, addr_mask); - num_pattern_desc++; + /* Opt out Gratuitous ARP packets (ARP Announcement) in active and suspended mode. + * For suspended mode, gratituous ARP is dropped by "opt out all broadcast" that will be + * set in slsi_set_common_packet_filters on screen off + */ + num_pattern_desc = 0; + pattern_desc[num_pattern_desc].offset = 0; /*filtering on MAC destination Address*/ + pattern_desc[num_pattern_desc].mask_length = ETH_ALEN; + SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].mask, addr_mask); + SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].pattern, addr_mask); + num_pattern_desc++; - SET_ETHERTYPE_PATTERN_DESC(pattern_desc[num_pattern_desc], ETH_P_ARP); - num_pattern_desc++; + SET_ETHERTYPE_PATTERN_DESC(pattern_desc[num_pattern_desc], ETH_P_ARP); + num_pattern_desc++; - slsi_create_packet_filter_element(SLSI_PROXY_ARP_FILTER_ID, FAPI_PACKETFILTERMODE_OPT_OUT, - num_pattern_desc, pattern_desc, &pkt_filter_elem[num_filters], - &pkt_filters_len); - num_filters++; + slsi_create_packet_filter_element(SLSI_PROXY_ARP_FILTER_ID, FAPI_PACKETFILTERMODE_OPT_OUT, + num_pattern_desc, pattern_desc, &pkt_filter_elem[num_filters], &pkt_filters_len); + num_filters++; #ifndef CONFIG_SCSC_WLAN_BLOCK_IPV6 - /* Opt out unsolicited Neighbor Advertisement packets .For suspended mode, NA is dropped by - * "opt out all IPv6 multicast" already set in slsi_create_common_packet_filters - */ + /* Opt out unsolicited Neighbor Advertisement packets .For suspended mode, NA is dropped by + * "opt out all IPv6 multicast" already set in slsi_create_common_packet_filters + */ + num_pattern_desc = 0; + + pattern_desc[num_pattern_desc].offset = 0; /*filtering on MAC destination Address*/ + pattern_desc[num_pattern_desc].mask_length = ETH_ALEN; + SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].mask, addr_mask); + SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].pattern, solicited_node_addr_mask); + num_pattern_desc++; - num_pattern_desc = 0; - - pattern_desc[num_pattern_desc].offset = 0; /*filtering on MAC destination Address*/ - pattern_desc[num_pattern_desc].mask_length = ETH_ALEN; - SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].mask, addr_mask); - SLSI_ETHER_COPY(pattern_desc[num_pattern_desc].pattern, solicited_node_addr_mask); - num_pattern_desc++; - - SET_ETHERTYPE_PATTERN_DESC(pattern_desc[num_pattern_desc], 0x86DD); - num_pattern_desc++; - - pattern_desc[num_pattern_desc].offset = 0x14; /*filtering on next header*/ - pattern_desc[num_pattern_desc].mask_length = 1; - pattern_desc[num_pattern_desc].mask[0] = 0xff; - pattern_desc[num_pattern_desc].pattern[0] = 0x3a; - num_pattern_desc++; - - pattern_desc[num_pattern_desc].offset = 0x36; /*filtering on ICMP6 packet type*/ - pattern_desc[num_pattern_desc].mask_length = 1; - pattern_desc[num_pattern_desc].mask[0] = 0xff; - pattern_desc[num_pattern_desc].pattern[0] = 0x88; /* Neighbor Advertisement type in ICMPv6 */ - num_pattern_desc++; - - slsi_create_packet_filter_element(SLSI_PROXY_ARP_NA_FILTER_ID, FAPI_PACKETFILTERMODE_OPT_OUT, - num_pattern_desc, pattern_desc, &pkt_filter_elem[num_filters], - &pkt_filters_len); - num_filters++; + SET_ETHERTYPE_PATTERN_DESC(pattern_desc[num_pattern_desc], 0x86DD); + num_pattern_desc++; + + pattern_desc[num_pattern_desc].offset = 0x14; /*filtering on next header*/ + pattern_desc[num_pattern_desc].mask_length = 1; + pattern_desc[num_pattern_desc].mask[0] = 0xff; + pattern_desc[num_pattern_desc].pattern[0] = 0x3a; + num_pattern_desc++; + + pattern_desc[num_pattern_desc].offset = 0x36; /*filtering on ICMP6 packet type*/ + pattern_desc[num_pattern_desc].mask_length = 1; + pattern_desc[num_pattern_desc].mask[0] = 0xff; + pattern_desc[num_pattern_desc].pattern[0] = 0x88; /* Neighbor Advertisement type in ICMPv6 */ + num_pattern_desc++; + + slsi_create_packet_filter_element(SLSI_PROXY_ARP_NA_FILTER_ID, FAPI_PACKETFILTERMODE_OPT_OUT, + num_pattern_desc, pattern_desc, &pkt_filter_elem[num_filters], &pkt_filters_len); + num_filters++; #endif } } diff --git a/drivers/net/wireless/scsc/mgt.h b/drivers/net/wireless/scsc/mgt.h index f44ee5abcc24..98ea8581fde6 100755 --- a/drivers/net/wireless/scsc/mgt.h +++ b/drivers/net/wireless/scsc/mgt.h @@ -483,6 +483,9 @@ int slsi_is_tcp_sync_packet(struct net_device *dev, struct sk_buff *skb); #ifdef CONFIG_SCSC_WLAN_ENHANCED_PKT_FILTER int slsi_set_enhanced_pkt_filter(struct net_device *dev, u8 pkt_filter_enable); #endif +#ifdef CONFIG_SCSC_WLAN_ABNORMAL_MULTICAST_PKT_FILTER +int slsi_set_abnormal_multicast_pkt_filter(struct net_device *dev, u8 enabled); +#endif void slsi_set_packet_filters(struct slsi_dev *sdev, struct net_device *dev); int slsi_update_packet_filters(struct slsi_dev *sdev, struct net_device *dev); int slsi_clear_packet_filters(struct slsi_dev *sdev, struct net_device *dev); -- 2.20.1