[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;