diff options
Diffstat (limited to 'ipanat/src')
-rw-r--r-- | ipanat/src/Makefile.am | 19 | ||||
-rw-r--r-- | ipanat/src/ipa_nat_drv.c | 42 | ||||
-rw-r--r-- | ipanat/src/ipa_nat_drvi.c | 93 |
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, |