summaryrefslogtreecommitdiff
path: root/ipanat/src
diff options
context:
space:
mode:
Diffstat (limited to 'ipanat/src')
-rw-r--r--ipanat/src/Makefile.am19
-rw-r--r--ipanat/src/ipa_nat_drv.c42
-rw-r--r--ipanat/src/ipa_nat_drvi.c93
3 files changed, 146 insertions, 8 deletions
diff --git a/ipanat/src/Makefile.am b/ipanat/src/Makefile.am
index 8bdb9b8..8e2d005 100644
--- a/ipanat/src/Makefile.am
+++ b/ipanat/src/Makefile.am
@@ -1,21 +1,38 @@
AM_CFLAGS = -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs
+if KERNELMODULES
+AM_CFLAGS += -I./../inc $(KERNEL_DIR)/include
+else
AM_CFLAGS += -I./../inc
+endif
#AM_CFLAGS += -DDEBUG -g
common_CFLAGS = -DUSE_GLIB @GLIB_CFLAGS@
+if !KERNELMODULES
common_LDFLAGS = -lrt @GLIB_LIBS@
+endif
+
+if KERNELMODULES
+library_includedir = ../inc $(KERNEL_DIR)/include $(pkgincludedir)
+else
+library_includedir = $(pkgincludedir)
+endif
c_sources = ipa_nat_drv.c \
ipa_nat_drvi.c \
ipa_nat_logi.c
-library_includedir = $(pkgincludedir)
library_include_HEADERS = ./../inc/ipa_nat_drvi.h \
./../inc/ipa_nat_drv.h \
./../inc/ipa_nat_logi.h
+if KERNELMODULES
+noinst_LIBRARIES = libipanat.a
+libipanat_a_C = @C@
+libipanat_a_SOURCES = $(c_sources)
+else
lib_LTLIBRARIES = libipanat.la
libipanat_la_C = @C@
libipanat_la_SOURCES = $(c_sources)
libipanat_la_CFLAGS = $(AM_CFLAGS) $(common_CFLAGS)
libipanat_la_LDFLAGS = -shared $(common_LDFLAGS) -version-info 1:0:0
+endif
diff --git a/ipanat/src/ipa_nat_drv.c b/ipanat/src/ipa_nat_drv.c
index 66504e1..d01a6c9 100644
--- a/ipanat/src/ipa_nat_drv.c
+++ b/ipanat/src/ipa_nat_drv.c
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2013, The Linux Foundation. All rights reserved.
+Copyright (c) 2013 - 2017, 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
@@ -173,3 +173,43 @@ int ipa_nat_query_timestamp(uint32_t tbl_hdl,
}
+/**
+* ipa_nat_modify_pdn() - modify single PDN entry in the PDN config table
+* @table_handle: [in] handle of ipv4 nat table
+* @pdn_index : [in] the index of the entry to be modified
+* @pdn_info : [in] values for the PDN entry to be changed
+*
+* Modify a PDN entry
+*
+* Returns: 0 On Success, negative on failure
+*/
+int ipa_nat_modify_pdn(uint32_t tbl_hdl,
+ uint8_t pdn_index,
+ ipa_nat_pdn_entry *pdn_info)
+{
+ struct ipa_ioc_nat_pdn_entry pdn_data;
+
+ if (0 == tbl_hdl || tbl_hdl > IPA_NAT_MAX_IP4_TBLS) {
+ IPAERR("invalid parameters passed \n");
+ return -EINVAL;
+ }
+
+ if (!pdn_info) {
+ IPAERR("pdn_info is NULL \n");
+ return -EINVAL;
+ }
+
+ if (pdn_index > IPA_MAX_PDN_NUM) {
+ IPAERR("PDN index is out of range %d", pdn_index);
+ return -EINVAL;
+ }
+
+ pdn_data.pdn_index = pdn_index;
+ pdn_data.public_ip = pdn_info->public_ip;
+ pdn_data.src_metadata = pdn_info->src_metadata;
+ pdn_data.dst_metadata = pdn_info->dst_metadata;
+
+ return ipa_nati_modify_pdn(&pdn_data);
+}
+
+
diff --git a/ipanat/src/ipa_nat_drvi.c b/ipanat/src/ipa_nat_drvi.c
index 9b96c44..d309bb3 100644
--- a/ipanat/src/ipa_nat_drvi.c
+++ b/ipanat/src/ipa_nat_drvi.c
@@ -1,5 +1,5 @@
/*
-Copyright (c) 2013, The Linux Foundation. All rights reserved.
+Copyright (c) 2013 - 2017, 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
@@ -33,11 +33,21 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef USE_GLIB
#include <glib.h>
#define strlcpy g_strlcpy
+#else
+static size_t strlcpy(char * dst, const char * src, size_t size) {
+ if (size < 1)
+ return 0;
+ strncpy(dst, src, size - 1);
+ dst[size - 1] = 0;
+ return strlen(dst);
+}
#endif
struct ipa_nat_cache ipv4_nat_cache;
pthread_mutex_t nat_mutex = PTHREAD_MUTEX_INITIALIZER;
+static ipa_nat_pdn_entry pdns[IPA_MAX_PDN_NUM];
+
/* ------------------------------------------
UTILITY FUNCTIONS START
--------------------------------------------*/
@@ -153,6 +163,26 @@ uint32_t Read32BitFieldValue(uint32_t param,
}
}
+/**
+* GetIPAVer(void) - store IPA HW ver in cache
+*
+*
+* Returns: 0 on success, negative on failure
+*/
+int GetIPAVer(void)
+{
+ int ret;
+
+ ret = ioctl(ipv4_nat_cache.ipa_fd, IPA_IOC_GET_HW_VERSION, &ipv4_nat_cache.ver);
+ if (ret != 0) {
+ perror("GetIPAVer(): ioctl error value");
+ IPAERR("unable to get IPA version. Error ;%d\n", ret);
+ IPADBG("ipa fd %d\n", ipv4_nat_cache.ipa_fd);
+ return -EINVAL;
+ }
+ IPADBG("IPA version is %d\n", ipv4_nat_cache.ver);
+ return 0;
+}
/**
* CreateNatDevice() - Create nat devices
@@ -248,6 +278,7 @@ void GetNearestEven(uint16_t num, uint16_t *ret)
/**
* dst_hash() - Find the index into ipv4 base table
+ * @public_ip: [in] public_ip
* @trgt_ip: [in] Target IP address
* @trgt_port: [in] Target port
* @public_port: [in] Public port
@@ -261,13 +292,18 @@ void GetNearestEven(uint16_t num, uint16_t *ret)
*
* Returns: >0 index into ipv4 base table, negative on failure
*/
-static uint16_t dst_hash(uint32_t trgt_ip, uint16_t trgt_port,
- uint16_t public_port, uint8_t proto,
- uint16_t size)
+static uint16_t dst_hash(uint32_t public_ip, uint32_t trgt_ip,
+ uint16_t trgt_port, uint16_t public_port,
+ uint8_t proto, uint16_t size)
{
uint16_t hash = ((uint16_t)(trgt_ip)) ^ ((uint16_t)(trgt_ip >> 16)) ^
(trgt_port) ^ (public_port) ^ (proto);
+ if (ipv4_nat_cache.ver >= IPA_HW_v4_0)
+ hash ^= ((uint16_t)(public_ip)) ^
+ ((uint16_t)(public_ip >> 16));
+
+ IPADBG("public ip 0x%X\n", public_ip);
IPADBG("trgt_ip: 0x%x trgt_port: 0x%x\n", trgt_ip, trgt_port);
IPADBG("public_port: 0x%x\n", public_port);
IPADBG("proto: 0x%x size: 0x%x\n", proto, size);
@@ -682,6 +718,12 @@ int ipa_nati_add_ipv4_tbl(uint32_t public_ip_addr,
return -EINVAL;
}
+ /* store the initial public ip address in the cached pdn table
+ this is backward compatible for pre IPAv4 versions, we will always
+ use this ip as the single PDN address
+ */
+ pdns[0].public_ip = public_ip_addr;
+
/* Return table handle */
ipv4_nat_cache.table_cnt++;
*tbl_hdl = ipv4_nat_cache.table_cnt;
@@ -734,6 +776,11 @@ int ipa_nati_alloc_table(uint16_t number_of_entries,
ipv4_nat_cache.ipa_fd = fd;
}
+ if (GetIPAVer()) {
+ IPAERR("unable to get ipa ver\n");
+ return -EIO;
+ }
+
ret = CreateNatDevice(mem);
return ret;
}
@@ -1014,6 +1061,30 @@ int ipa_nati_query_timestamp(uint32_t tbl_hdl,
return 0;
}
+int ipa_nati_modify_pdn(struct ipa_ioc_nat_pdn_entry *entry)
+{
+ if (entry->public_ip == 0)
+ IPADBG("PDN %d public ip will be set to 0\n", entry->pdn_index);
+
+ if (ioctl(ipv4_nat_cache.ipa_fd, IPA_IOC_NAT_MODIFY_PDN, entry)) {
+ perror("ipa_nati_modify_pdn(): ioctl error value");
+ IPAERR("unable to call modify pdn icotl\n");
+ IPAERR("index %d, ip 0x%X, src_metdata 0x%X, dst_metadata 0x%X\n",
+ entry->pdn_index, entry->public_ip, entry->src_metadata, entry->dst_metadata);
+ IPADBG("ipa fd %d\n", ipv4_nat_cache.ipa_fd);
+ return -EIO;
+ }
+
+ pdns[entry->pdn_index].public_ip = entry->public_ip;
+ pdns[entry->pdn_index].dst_metadata = entry->dst_metadata;
+ pdns[entry->pdn_index].src_metadata = entry->src_metadata;
+
+ IPADBG("posted IPA_IOC_NAT_MODIFY_PDN to kernel successfully and stored in cache\n index %d, ip 0x%X, src_metdata 0x%X, dst_metadata 0x%X\n",
+ entry->pdn_index, entry->public_ip, entry->src_metadata, entry->dst_metadata);
+
+ return 0;
+}
+
int ipa_nati_add_ipv4_rule(uint32_t tbl_hdl,
const ipa_nat_ipv4_rule *clnt_rule,
uint32_t *rule_hdl)
@@ -1023,6 +1094,14 @@ int ipa_nati_add_ipv4_rule(uint32_t tbl_hdl,
struct ipa_nat_indx_tbl_sw_rule index_sw_rule;
uint16_t new_entry, new_index_tbl_entry;
+ /* verify that the rule's PDN is valid */
+ if (clnt_rule->pdn_index >= IPA_MAX_PDN_NUM ||
+ pdns[clnt_rule->pdn_index].public_ip == 0) {
+ IPAERR("invalid parameters, pdn index %d, public ip = 0x%X\n",
+ clnt_rule->pdn_index, pdns[clnt_rule->pdn_index].public_ip);
+ return -EINVAL;
+ }
+
memset(&sw_rule, 0, sizeof(sw_rule));
memset(&index_sw_rule, 0, sizeof(index_sw_rule));
@@ -1114,7 +1193,7 @@ uint16_t ipa_nati_generate_tbl_rule(const ipa_nat_ipv4_rule *clnt_rule,
uint16_t prev = 0, nxt_indx = 0, new_entry;
struct ipa_nat_rule *tbl = NULL, *expn_tbl = NULL;
- pub_ip_addr = tbl_ptr->public_addr;
+ pub_ip_addr = pdns[clnt_rule->pdn_index].public_ip;
tbl = (struct ipa_nat_rule *)tbl_ptr->ipv4_rules_addr;
expn_tbl = (struct ipa_nat_rule *)tbl_ptr->ipv4_expn_rules_addr;
@@ -1126,6 +1205,7 @@ uint16_t ipa_nati_generate_tbl_rule(const ipa_nat_ipv4_rule *clnt_rule,
sw_rule->public_port = clnt_rule->public_port;
sw_rule->target_ip = clnt_rule->target_ip;
sw_rule->target_port = clnt_rule->target_port;
+ sw_rule->pdn_index = clnt_rule->pdn_index;
/* consider only public and private ip fields */
sw_rule->ip_chksum = ipa_nati_calc_ip_cksum(pub_ip_addr,
@@ -1152,10 +1232,11 @@ uint16_t ipa_nati_generate_tbl_rule(const ipa_nat_ipv4_rule *clnt_rule,
*/
sw_rule->time_stamp = 0;
sw_rule->rsvd2 = 0;
+ sw_rule->rsvd3 = 0;
sw_rule->prev_index = 0;
sw_rule->indx_tbl_entry = 0;
- new_entry = dst_hash(clnt_rule->target_ip,
+ new_entry = dst_hash(pub_ip_addr, clnt_rule->target_ip,
clnt_rule->target_port,
clnt_rule->public_port,
clnt_rule->protocol,