[qca-nss-clients] IPv6 default subnet support.

Change-Id: I048568d65b55e51298ef2dc982de9f1931d74bee
Signed-off-by: mandrw <mandrw@codeaurora.org>
diff --git a/ipsecmgr/nss_ipsecmgr_priv.h b/ipsecmgr/nss_ipsecmgr_priv.h
index 6f0c503..91c9511 100644
--- a/ipsecmgr/nss_ipsecmgr_priv.h
+++ b/ipsecmgr/nss_ipsecmgr_priv.h
@@ -88,6 +88,8 @@
 #define NSS_IPSECMGR_MAX_BUF_SZ 512
 #define NSS_IPSECMGR_PROTO_NEXT_HDR_ANY 0xff
 
+#define NSS_IPSECMGR_V6_SUBNET_BITS (sizeof(uint32_t) * 2 * BITS_PER_BYTE)
+
 struct nss_ipsecmgr_ref;
 struct nss_ipsecmgr_key;
 struct nss_ipsecmgr_priv;
@@ -602,6 +604,7 @@
 	*data = v;
 	*mask = NSS_IPSECMGR_GENMASK(31, 0);
 }
+
 /*
  * nss_ipsecmgr_key_clear_32()
  * 	clear 32-bit mask from the specified position
@@ -615,6 +618,19 @@
 }
 
 /*
+ * nss_ipsecmgr_key_clear_64()
+ * 	clear 32-bit mask from the specified position
+ */
+static inline void nss_ipsecmgr_key_clear_64(struct nss_ipsecmgr_key *key, enum nss_ipsecmgr_key_pos p)
+{
+	uint16_t idx;
+
+	idx = BIT_WORD(p) % NSS_IPSECMGR_MAX_KEY_WORDS;
+	key->mask[idx] = 0;
+	key->mask[idx + 1] = 0;
+}
+
+/*
  * nss_ipsecmgr_key_read_n()
  * 	read n nnumber of values from the specified position using mask
  */
@@ -1050,12 +1066,30 @@
 	return addr[0];
 }
 
+/*
+ * nss_ipsecmgr_verify_v4_subnet()
+ * 	verify if v4 subnet mask is not empty when v4 subnet is empty.
+ */
 static inline bool nss_ipsecmgr_verify_v4_subnet(struct nss_ipsecmgr_encap_v4_subnet *v4_subnet)
 {
 	return !v4_subnet->dst_subnet && v4_subnet->dst_mask;
 }
 
 /*
+ * nss_ipsecmgr_verify_v6_subnet()
+ * 	verify if v6 subnet mask is not empty when v6 subnet is empty.
+ */
+static inline bool nss_ipsecmgr_verify_v6_subnet(struct nss_ipsecmgr_encap_v6_subnet *v6_subnet)
+{
+	bool subnet, mask;
+
+	subnet = bitmap_empty((unsigned long *)v6_subnet->dst_subnet, NSS_IPSECMGR_V6_SUBNET_BITS);
+	mask = bitmap_empty((unsigned long *)v6_subnet->dst_mask, NSS_IPSECMGR_V6_SUBNET_BITS);
+
+	return subnet && !mask;
+}
+
+/*
  * Reference Object API(s)
  */
 void nss_ipsecmgr_ref_init(struct nss_ipsecmgr_ref *ref, nss_ipsecmgr_ref_update_t update, nss_ipsecmgr_ref_free_t free);
diff --git a/ipsecmgr/nss_ipsecmgr_sa.c b/ipsecmgr/nss_ipsecmgr_sa.c
index 54d1610..64f160d 100644
--- a/ipsecmgr/nss_ipsecmgr_sa.c
+++ b/ipsecmgr/nss_ipsecmgr_sa.c
@@ -751,6 +751,11 @@
 
 	case NSS_IPSECMGR_FLOW_TYPE_V6_SUBNET:
 
+		if (nss_ipsecmgr_verify_v6_subnet(&flow->data.v6_subnet)) {
+			nss_ipsecmgr_warn("%p:invalid subnet and mask\n", tun);
+			return false;
+		}
+
 		nss_ipsecmgr_copy_v6_sa(&info.nim, &sa->data.v6);
 		nss_ipsecmgr_copy_sa_data(&info.nim, data);
 
@@ -831,6 +836,11 @@
 
 	case NSS_IPSECMGR_FLOW_TYPE_V6_SUBNET:
 
+		if (nss_ipsecmgr_verify_v6_subnet(&flow->data.v6_subnet)) {
+			nss_ipsecmgr_warn("%p:invalid subnet and mask\n", tun);
+			return false;
+		}
+
 		nss_ipsecmgr_copy_v6_sa(&info.nim, &sa->data.v6);
 
 		nss_ipsecmgr_v6_subnet2key(&flow->data.v6_subnet, &info.child_key);
diff --git a/ipsecmgr/nss_ipsecmgr_subnet.c b/ipsecmgr/nss_ipsecmgr_subnet.c
index 2321f0b..f183b95 100644
--- a/ipsecmgr/nss_ipsecmgr_subnet.c
+++ b/ipsecmgr/nss_ipsecmgr_subnet.c
@@ -474,6 +474,14 @@
 	nss_ipsecmgr_key_write_8(key, (uint8_t)net->next_hdr, NSS_IPSECMGR_KEY_POS_IP_PROTO);
 	nss_ipsecmgr_key_write(key, net->dst_subnet, net->dst_mask, NSS_IPSECMGR_KEY_POS_IPV6_DST, 2);
 
+	/*
+	 * clear mask if caller specify protocol as any (0xff).
+	 * this will serve as default entry for any-protocol.
+	 */
+	if (net->next_hdr == NSS_IPSECMGR_PROTO_NEXT_HDR_ANY) {
+		nss_ipsecmgr_key_clear_8(key, NSS_IPSECMGR_KEY_POS_IP_PROTO);
+	}
+
 	key->len = NSS_IPSECMGR_KEY_LEN_IPV6_SUBNET;
 }
 
@@ -554,6 +562,16 @@
 		}
 	}
 
+	/*
+	 * normal lookup failed; check default subnet entry
+	 * - clear the destination netmask before lookup
+	 */
+	nss_ipsecmgr_key_clear_64(&tmp_key, NSS_IPSECMGR_KEY_POS_IPV6_DST);
+
+	ref = nss_ipsecmgr_subnet_lookup(priv, &tmp_key);
+	if (ref) {
+		return ref;
+	}
 	return NULL;
 }
 
diff --git a/netlink/nss_nlipsec.c b/netlink/nss_nlipsec.c
index dadfc5f..1f5f8e4 100644
--- a/netlink/nss_nlipsec.c
+++ b/netlink/nss_nlipsec.c
@@ -211,6 +211,7 @@
 			return -1;
 		}
 		break;
+
 	case NSS_IPSECMGR_FLOW_TYPE_V4_SUBNET:
 		v4_subnet = &encap_flow->data.v4_subnet;
 
@@ -219,6 +220,7 @@
 			return -1;
 		}
 		break;
+
 	case NSS_IPSECMGR_FLOW_TYPE_V6_TUPLE:
 		v6_tuple = &encap_flow->data.v6_tuple;
 
@@ -418,6 +420,7 @@
 
 	case NSS_IPSECMGR_FLOW_TYPE_V6_SUBNET:
 		v6_subnet = &encap_flow->data.v6_subnet;
+
 		if (bitmap_empty((unsigned long *)v6_subnet->dst_subnet, NSS_NLIPV6_SUBNET_BITS) &&
 				!bitmap_empty((unsigned long *)v6_subnet->dst_mask, NSS_NLIPV6_SUBNET_BITS)) {
 			nss_nl_error("Invalid v6 dst_subnet\n");
@@ -442,6 +445,7 @@
 			return -2;
 		}
 		break;
+
 	case NSS_IPSECMGR_SA_TYPE_V6:
 		v6 = &encap_sa->data.v6;
 
@@ -488,6 +492,7 @@
 			return -2;
 		}
 		break;
+
 	case NSS_IPSECMGR_SA_TYPE_V6:
 		v6 = &encap_sa->data.v6;
 
@@ -534,6 +539,7 @@
 			return -2;
 		}
 		break;
+
 	case NSS_IPSECMGR_SA_TYPE_V6:
 		v6 = &decap_sa->data.v6;