Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0ac48f80 authored by Jinwei Chen's avatar Jinwei Chen Committed by snandini
Browse files

qcacmn: Add 802.1Q/802.1AD support for DHCP/EAPOL/ARP data check

If the data ether header contains 802.1Q and 802.1AD tag,
current API to identify DHCP/ARP/EAPOL frame will not work properly,
for 802.1Q/802.1AD frame, there is extra 4 or 8 bytes in ether header.
Add 802.1Q and 802.1AD support for DHCP/EAPOL/ARP check.

Change-Id: Ibf00bd9e1497ba9700abca10d840104a73238f56
CRs-Fixed: 2771942
parent 0405e9a5
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -51,6 +51,8 @@
#define QDF_NBUF_TRAC_DHCP_SRV_PORT		67
#define QDF_NBUF_TRAC_DHCP_CLI_PORT		68
#define QDF_NBUF_TRAC_ETH_TYPE_OFFSET		12
#define QDF_NBUF_TRAC_VLAN_ETH_TYPE_OFFSET	16
#define QDF_NBUF_TRAC_DOUBLE_VLAN_ETH_TYPE_OFFSET	20
#define QDF_NBUF_TRAC_EAPOL_ETH_TYPE		0x888E
#define QDF_NBUF_TRAC_WAPI_ETH_TYPE		0x88b4
#define QDF_NBUF_TRAC_ARP_ETH_TYPE		0x0806
@@ -84,7 +86,11 @@
#define QDF_NBUF_TRAC_DHCP6_SRV_PORT		547
#define QDF_NBUF_TRAC_DHCP6_CLI_PORT		546
#define QDF_NBUF_TRAC_MDNS_SRC_N_DST_PORT	5353

#define QDF_NBUF_TRAC_IP_OFFSET		14
#define QDF_NBUF_TRAC_VLAN_IP_OFFSET		18
#define QDF_NBUF_TRAC_DOUBLE_VLAN_IP_OFFSET	22
/* One dword for IPv4 header size unit */
#define QDF_NBUF_IPV4_HDR_SIZE_UNIT	4

/* EAPOL Related MASK */
#define EAPOL_PACKET_TYPE_OFFSET		15
+2 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2014-2019 The Linux Foundation. All rights reserved.
 * Copyright (c) 2014-2020 The Linux Foundation. All rights reserved.
 *
 * Permission to use, copy, modify, and/or distribute this software for
 * any purpose with or without fee is hereby granted, provided that the
@@ -61,6 +61,7 @@ typedef __in6_addr_t in6_addr_t;
#define QDF_ETH_TYPE_IPV4              0x0800  /* IPV4 */
#define QDF_ETH_TYPE_IPV6              0x86dd  /* IPV6 */
#define QDF_ETH_TYPE_8021Q             0x8100  /* 802.1Q vlan protocol */
#define QDF_ETH_TYPE_8021AD            0x88a8  /* 802.1AD vlan protocol */
#define QDF_IEEE80211_4ADDR_HDR_LEN     30
#define QDF_IEEE80211_3ADDR_HDR_LEN     24
#define QDF_IEEE80211_FC0_SUBTYPE_QOS   0x80
+79 −15
Original line number Diff line number Diff line
@@ -118,6 +118,61 @@ static qdf_atomic_t nbuf_count;
static bool is_initial_mem_debug_disabled;
#endif

/**
 *  __qdf_nbuf_get_ip_offset - Get IPV4/V6 header offset
 * @data: Pointer to network data buffer
 *
 * Get the IP header offset in case of 8021Q and 8021AD
 * tag is present in L2 header.
 *
 * Return: IP header offset
 */
static inline uint8_t __qdf_nbuf_get_ip_offset(uint8_t *data)
{
	uint16_t ether_type;

	ether_type = *(uint16_t *)(data +
				   QDF_NBUF_TRAC_ETH_TYPE_OFFSET);

	if (unlikely(ether_type == QDF_SWAP_U16(QDF_ETH_TYPE_8021Q)))
		return QDF_NBUF_TRAC_VLAN_IP_OFFSET;
	else if (unlikely(ether_type == QDF_SWAP_U16(QDF_ETH_TYPE_8021AD)))
		return QDF_NBUF_TRAC_DOUBLE_VLAN_IP_OFFSET;

	return QDF_NBUF_TRAC_IP_OFFSET;
}

qdf_export_symbol(__qdf_nbuf_get_ip_offset);

/**
 *  __qdf_nbuf_get_ether_type - Get the ether type
 * @data: Pointer to network data buffer
 *
 * Get the ether type in case of 8021Q and 8021AD tag
 * is present in L2 header, e.g for the returned ether type
 * value, if IPV4 data ether type 0x0800, return 0x0008.
 *
 * Return ether type.
 */
static inline uint16_t __qdf_nbuf_get_ether_type(uint8_t *data)
{
	uint16_t ether_type;

	ether_type = *(uint16_t *)(data +
				   QDF_NBUF_TRAC_ETH_TYPE_OFFSET);

	if (unlikely(ether_type == QDF_SWAP_U16(QDF_ETH_TYPE_8021Q)))
		ether_type = *(uint16_t *)(data +
				QDF_NBUF_TRAC_VLAN_ETH_TYPE_OFFSET);
	else if (unlikely(ether_type == QDF_SWAP_U16(QDF_ETH_TYPE_8021AD)))
		ether_type = *(uint16_t *)(data +
				QDF_NBUF_TRAC_DOUBLE_VLAN_ETH_TYPE_OFFSET);

	return ether_type;
}

qdf_export_symbol(__qdf_nbuf_get_ether_type);

/**
 * qdf_nbuf_tx_desc_count_display() - Displays the packet counter
 *
@@ -1322,12 +1377,21 @@ bool __qdf_nbuf_data_is_ipv4_dhcp_pkt(uint8_t *data)
{
	uint16_t sport;
	uint16_t dport;
	uint8_t ipv4_offset;
	uint8_t ipv4_hdr_len;
	struct iphdr *iphdr;

	sport = (uint16_t)(*(uint16_t *)(data + QDF_NBUF_TRAC_IPV4_OFFSET +
					 QDF_NBUF_TRAC_IPV4_HEADER_SIZE));
	dport = (uint16_t)(*(uint16_t *)(data + QDF_NBUF_TRAC_IPV4_OFFSET +
					 QDF_NBUF_TRAC_IPV4_HEADER_SIZE +
					 sizeof(uint16_t)));
	if (__qdf_nbuf_get_ether_type(data) !=
	    QDF_SWAP_U16(QDF_NBUF_TRAC_IPV4_ETH_TYPE))
		return false;

	ipv4_offset = __qdf_nbuf_get_ip_offset(data);
	iphdr = (struct iphdr *)(data + ipv4_offset);
	ipv4_hdr_len = iphdr->ihl * QDF_NBUF_IPV4_HDR_SIZE_UNIT;

	sport = *(uint16_t *)(data + ipv4_offset + ipv4_hdr_len);
	dport = *(uint16_t *)(data + ipv4_offset + ipv4_hdr_len +
			      sizeof(uint16_t));

	if (((sport == QDF_SWAP_U16(QDF_NBUF_TRAC_DHCP_SRV_PORT)) &&
	     (dport == QDF_SWAP_U16(QDF_NBUF_TRAC_DHCP_CLI_PORT))) ||
@@ -1352,8 +1416,7 @@ bool __qdf_nbuf_data_is_ipv4_eapol_pkt(uint8_t *data)
{
	uint16_t ether_type;

	ether_type = (uint16_t)(*(uint16_t *)(data +
				QDF_NBUF_TRAC_ETH_TYPE_OFFSET));
	ether_type = __qdf_nbuf_get_ether_type(data);

	if (ether_type == QDF_SWAP_U16(QDF_NBUF_TRAC_EAPOL_ETH_TYPE))
		return true;
@@ -1421,8 +1484,7 @@ bool __qdf_nbuf_data_is_ipv4_arp_pkt(uint8_t *data)
{
	uint16_t ether_type;

	ether_type = (uint16_t)(*(uint16_t *)(data +
				QDF_NBUF_TRAC_ETH_TYPE_OFFSET));
	ether_type = __qdf_nbuf_get_ether_type(data);

	if (ether_type == QDF_SWAP_U16(QDF_NBUF_TRAC_ARP_ETH_TYPE))
		return true;
@@ -1797,10 +1859,12 @@ bool __qdf_nbuf_data_is_ipv6_dhcp_pkt(uint8_t *data)
{
	uint16_t sport;
	uint16_t dport;
	uint8_t ipv6_offset;

	sport = *(uint16_t *)(data + QDF_NBUF_TRAC_IPV6_OFFSET +
	ipv6_offset = __qdf_nbuf_get_ip_offset(data);
	sport = *(uint16_t *)(data + ipv6_offset +
			      QDF_NBUF_TRAC_IPV6_HEADER_SIZE);
	dport = *(uint16_t *)(data + QDF_NBUF_TRAC_IPV6_OFFSET +
	dport = *(uint16_t *)(data + ipv6_offset +
			      QDF_NBUF_TRAC_IPV6_HEADER_SIZE +
			      sizeof(uint16_t));