ipacm: send all IPv6 framents to IPA apps In case of TCP, if the ipv6 packets are fragmented there is a possibility that the second fragment packets match TCP SYN/FIN/RST rules and packets are routed to apps. This results in connection failure as the primary fragment will be routed correctly to hotspot client. Change-Id: I482b48c4786bda180b6f5d921149fed766c91fe0
diff --git a/ipacm/inc/IPACM_Iface.h b/ipacm/inc/IPACM_Iface.h index 8ff7450..a562613 100644 --- a/ipacm/inc/IPACM_Iface.h +++ b/ipacm/inc/IPACM_Iface.h
@@ -59,7 +59,7 @@ #define IPV4_DEFAULT_FILTERTING_RULES 3 #ifdef FEATURE_IPA_ANDROID -#define IPV6_DEFAULT_FILTERTING_RULES 7 +#define IPV6_DEFAULT_FILTERTING_RULES 8 #else #define IPV6_DEFAULT_FILTERTING_RULES 4 #endif
diff --git a/ipacm/inc/IPACM_Wan.h b/ipacm/inc/IPACM_Wan.h index a4d0557..2049df3 100644 --- a/ipacm/inc/IPACM_Wan.h +++ b/ipacm/inc/IPACM_Wan.h
@@ -1,5 +1,5 @@ /* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -53,9 +53,10 @@ #define IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4 2 #ifdef FEATURE_IPA_ANDROID -#define IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6 6 +#define IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6 7 #define IPA_V2_NUM_TCP_WAN_FILTER_RULE_IPV6 3 #define IPA_V2_NUM_MULTICAST_WAN_FILTER_RULE_IPV6 3 +#define IPA_V2_NUM_FRAG_WAN_FILTER_RULE_IPV6 1 #else #define IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6 3 #endif
diff --git a/ipacm/src/IPACM_Iface.cpp b/ipacm/src/IPACM_Iface.cpp index 173b954..ce3d738 100644 --- a/ipacm/src/IPACM_Iface.cpp +++ b/ipacm/src/IPACM_Iface.cpp
@@ -850,6 +850,36 @@ memcpy(&(m_pFilteringTable->rules[3]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); #ifdef FEATURE_IPA_ANDROID + /* Add the ipv6 tcp fragment filtering rule. */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 1; + flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif + flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<1); + flt_rule_entry.rule.eq_attrib.protocol_eq_present = 1; + flt_rule_entry.rule.eq_attrib.protocol_eq = IPACM_FIREWALL_IPPROTO_TCP; + flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_TCP; + + /* Configuring Fragment Filtering Rule */ + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(flt_rule_entry.rule.attrib)); + /* remove meta data mask since we only install default flt rules once for all modem + PDN*/ + flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA); + + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT; + + memcpy(&(m_pFilteringTable->rules[4]), &flt_rule_entry, + sizeof(struct ipa_flt_rule_add)); + IPACMDBG_H("Add TCP ctrl rules: total num %d\n", IPV6_DEFAULT_FILTERTING_RULES); memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); @@ -891,17 +921,18 @@ /* add TCP FIN rule*/ flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_FIN_SHIFT); flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_FIN_SHIFT); - memcpy(&(m_pFilteringTable->rules[4]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + memcpy(&(m_pFilteringTable->rules[5]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); /* add TCP SYN rule*/ flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_SYN_SHIFT); flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_SYN_SHIFT); - memcpy(&(m_pFilteringTable->rules[5]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + memcpy(&(m_pFilteringTable->rules[6]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); /* add TCP RST rule*/ flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_RST_SHIFT); flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_RST_SHIFT); - memcpy(&(m_pFilteringTable->rules[6]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + memcpy(&(m_pFilteringTable->rules[7]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + #endif if (m_filtering.AddFilteringRule(m_pFilteringTable) == false) {
diff --git a/ipacm/src/IPACM_Wan.cpp b/ipacm/src/IPACM_Wan.cpp index 2e5d873..397a3c6 100644 --- a/ipacm/src/IPACM_Wan.cpp +++ b/ipacm/src/IPACM_Wan.cpp
@@ -3763,13 +3763,63 @@ sizeof(flt_rule_entry.rule.eq_attrib)); memcpy(&(rules[rule_offset + 2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + /* Add the fragment filtering rule. */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + + flt_rule_entry.at_rear = true; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 1; + flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif + flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; + flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<1); + flt_rule_entry.rule.eq_attrib.protocol_eq_present = 1; + flt_rule_entry.rule.eq_attrib.protocol_eq = IPACM_FIREWALL_IPPROTO_TCP; + flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_TCP; + + /* Configuring fragment Filtering Rule */ + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(flt_rule_entry.rule.attrib)); + /* remove meta data mask since we only install default flt rules once for all modem PDN*/ + flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA); + + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT; + + memset(&flt_eq, 0, sizeof(flt_eq)); + memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); + flt_eq.ip = iptype; + if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) + { + IPACMERR("Failed to get eq_attrib\n"); + res = IPACM_FAILURE; + goto fail; + } + + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + + memcpy(&(rules[rule_offset + 3]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + #ifdef FEATURE_IPA_ANDROID IPACM_Wan::num_v6_flt_rule += IPA_V2_NUM_MULTICAST_WAN_FILTER_RULE_IPV6; IPACMDBG_H("Constructed %d default filtering rules for ip type %d\n", IPA_V2_NUM_MULTICAST_WAN_FILTER_RULE_IPV6, iptype); #else IPACM_Wan::num_v6_flt_rule += IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6; - IPACMDBG_H("Constructed %d default filtering rules for ip type %d\n", IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6, iptype); + IPACMDBG_H("Constructed %d default filtering rules for ip type %d\n", + IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6, iptype); #endif + IPACM_Wan::num_v6_flt_rule += IPA_V2_NUM_FRAG_WAN_FILTER_RULE_IPV6; + IPACMDBG_H("Constructed %d default filtering rules for ip type %d\n", + IPA_V2_NUM_FRAG_WAN_FILTER_RULE_IPV6, iptype); } fail: