From b163867de7f60b445ed0963e426aa80ed6f1f959 Mon Sep 17 00:00:00 2001 From: Amit Singh Date: Tue, 16 Jul 2019 20:29:13 +0530 Subject: [PATCH] CA API to retrieve the some internal values in TCP socket https://github.sec.samsung.net/RS7-IOTIVITY/IoTivity/pull/537/commits/cebbe139c44e3001a7a4ad4a09a80ceb2478ecbd (cherry-picked from cebbe139c44e3001a7a4ad4a09a80ceb2478ecbd) Change-Id: Ibb9139afc3e2da1b88288c1f6a14c8676b23adbf Signed-off-by: Amit Singh Signed-off-by: Kush Agrawal Signed-off-by: Sudipto Bal --- resource/csdk/connectivity/api/cautilinterface.h | 66 +++++++++ resource/csdk/connectivity/inc/catcpadapter.h | 9 ++ .../connectivity/src/tcp_adapter/catcpadapter.c | 154 +++++++++++++++++++++ .../csdk/connectivity/util/src/cautilinterface.c | 16 +++ 4 files changed, 245 insertions(+) diff --git a/resource/csdk/connectivity/api/cautilinterface.h b/resource/csdk/connectivity/api/cautilinterface.h index 28fc94e..8bd3a27 100644 --- a/resource/csdk/connectivity/api/cautilinterface.h +++ b/resource/csdk/connectivity/api/cautilinterface.h @@ -61,6 +61,71 @@ typedef struct CMConfigureInfo_t cmInfo; } CAUtilConfig_t; +#define MAX_IP_LENGTH 46 + +typedef struct +{ + /* These 4 values are Kernel dependent and can be extracted only when Kernel is + built with enabling to monitor these values*/ + u_int32_t tcpi_snd_nxt; + u_int32_t tcpi_rcv_nxt; + u_int32_t tcpi_rcv_wnd; + u_int8_t tcpi_rcv_wscale; + /*....*/ + u_int8_t tcpi_src_addr[MAX_IP_LENGTH]; + u_int32_t tcpi_src_port; + u_int8_t tcpi_dst_addr[MAX_IP_LENGTH]; + u_int32_t tcpi_dst_port; + u_int32_t ip_version; + void* info; +} TCPHeaderInfo; + +typedef struct +{ + u_int8_t tcpi_state; + u_int8_t tcpi_ca_state; + u_int8_t tcpi_retransmits; + u_int8_t tcpi_probes; + u_int8_t tcpi_backoff; + u_int8_t tcpi_options; + u_int8_t tcpi_snd_wscale : 4, tcpi_rcv_wscale : 4; + + /* TCP Keep Alive Offload */ + u_int32_t tcpi_snd_nxt; + u_int32_t tcpi_rcv_nxt; + u_int32_t tcpi_rcv_wnd; + + u_int32_t tcpi_rto; + u_int32_t tcpi_ato; + u_int32_t tcpi_snd_mss; + u_int32_t tcpi_rcv_mss; + + u_int32_t tcpi_unacked; + u_int32_t tcpi_sacked; + u_int32_t tcpi_lost; + u_int32_t tcpi_retrans; + u_int32_t tcpi_fackets; + + /* Times. */ + u_int32_t tcpi_last_data_sent; + u_int32_t tcpi_last_ack_sent; + u_int32_t tcpi_last_data_recv; + u_int32_t tcpi_last_ack_recv; + + /* Metrics. */ + u_int32_t tcpi_pmtu; + u_int32_t tcpi_rcv_ssthresh; + u_int32_t tcpi_rtt; + u_int32_t tcpi_rttvar; + u_int32_t tcpi_snd_ssthresh; + u_int32_t tcpi_snd_cwnd; + u_int32_t tcpi_advmss; + u_int32_t tcpi_reordering; + u_int32_t tcpi_rcv_rtt; + u_int32_t tcpi_rcv_space; + u_int32_t tcpi_total_retrans; +} TCPInfo; + /** * Callback function type for connection status changes delivery. * @param[out] info Remote endpoint information. @@ -359,6 +424,7 @@ void CAUtilSkipTCPCloseOnInterfaceDown(bool state); CAResult_t CAUtilStartGattServer(); CAResult_t CAUtilStopGattServer(); +CAResult_t CAGetTCPIPHeader(CATransportAdapter_t adapter, int flag, TCPHeaderInfo* info); #ifdef __cplusplus } /* extern "C" */ diff --git a/resource/csdk/connectivity/inc/catcpadapter.h b/resource/csdk/connectivity/inc/catcpadapter.h index 00f1cf3..9b17ff7 100644 --- a/resource/csdk/connectivity/inc/catcpadapter.h +++ b/resource/csdk/connectivity/inc/catcpadapter.h @@ -30,6 +30,7 @@ #include "cathreadpool.h" #include "cainterface.h" #include +#include "cautilinterface.h" #ifdef __cplusplus extern "C" @@ -204,6 +205,12 @@ CAResult_t CAStopTCP(); */ void CATerminateTCP(); +/** + * Gets TCP Header Information + * @return ::CA_STATUS_OK or Appropriate error code. + */ +CAResult_t CAGetTCPIPHeaderInfo(CATransportFlags_t flag, TCPHeaderInfo* tcpHeaderInfo); + #ifdef TCP_ADAPTER /** * Set connection status changes callback to process KeepAlive. @@ -211,6 +218,8 @@ void CATerminateTCP(); * @param[in] ConnHandler Connection status changes callback. */ void CATCPSetKeepAliveCallbacks(CAKeepAliveConnectionCallback ConnHandler); + + #endif #ifdef __cplusplus diff --git a/resource/csdk/connectivity/src/tcp_adapter/catcpadapter.c b/resource/csdk/connectivity/src/tcp_adapter/catcpadapter.c index ea55c74..c97c5c2 100644 --- a/resource/csdk/connectivity/src/tcp_adapter/catcpadapter.c +++ b/resource/csdk/connectivity/src/tcp_adapter/catcpadapter.c @@ -18,10 +18,17 @@ * ******************************************************************/ +#include +#include +#include +#include #include #include #include #include +#include +#include +#include #ifndef __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS @@ -39,6 +46,7 @@ #include "caremotehandler.h" #include "logger.h" #include "oic_malloc.h" + #ifdef __WITH_TLS__ #include "ca_adapter_net_ssl.h" #endif @@ -63,6 +71,9 @@ typedef struct #define CA_TCP_SELECT_TIMEOUT 10 +#define CA_IPV4_VERSION 4 + +#define CA_IPV6_VERSION 6 /** * Mutex to synchronize TCP adapter access. */ @@ -815,6 +826,149 @@ void CADataDestroyer(void *data, uint32_t size) CAFreeTCPData(TCPData); } +void CAGetTCPLocalIP(CATransportFlags_t flag, char* localIP) +{ + //int targetPort; + char targetIP[MAX_IP_LENGTH]; + memset(&targetIP, 0x00, sizeof(targetIP)); + struct ifaddrs *ifp = NULL; + struct ifaddrs *ifa = NULL; + + if (-1 == getifaddrs(&ifp)) { + return; + } + + for (ifa = ifp; ifa; ifa = ifa->ifa_next) + { + if (!ifa->ifa_addr) { + continue; + } + int family = ifa->ifa_addr->sa_family; + + if (CA_IPV6 & flag) { + if ((ifa->ifa_flags & IFF_LOOPBACK) || AF_INET6 != family) { + continue; + } + struct sockaddr_in6 *in = (struct sockaddr_in6*) ifa->ifa_addr; + inet_ntop(AF_INET6, &in->sin6_addr, targetIP, MAX_IP_LENGTH); + //targetPort = ntohs(in->sin6_port); + } else if (CA_IPV4 & flag) { + if ((ifa->ifa_flags & IFF_LOOPBACK) || AF_INET != family) { + continue; + } + struct sockaddr_in *in = (struct sockaddr_in*) ifa->ifa_addr; + inet_ntop(AF_INET, &in->sin_addr, targetIP, MAX_IP_LENGTH); + //targetPort = ntohs(in->sin_port); + } + break; + } + + strncpy(localIP, targetIP, MAX_IP_LENGTH); + //*localport = targetPort; + OIC_LOG_V(DEBUG, TAG, "src_addr = %s", localIP); +} + +int CAGetSocketInformation(u_int8_t* destIP, u_int32_t *destPort){ + + oc_mutex_lock(g_mutexAdapter); + uint32_t length = u_arraylist_length(caglobals.tcp.svrlist); + for (size_t i = 0; i < length; i++) + { + CATCPSessionInfo_t *svritem = (CATCPSessionInfo_t *) u_arraylist_get( + caglobals.tcp.svrlist, i); + if (!svritem) + { + continue; + } + + if (svritem->state == CONNECTED) + { + strncpy((char *)destIP, svritem->sep.endpoint.addr, MAX_IP_LENGTH); + *destPort = svritem->sep.endpoint.port; + OIC_LOG_V(INFO, TAG, "Dest Ip : %s, Dest Port : %d", destIP, *destPort); + oc_mutex_unlock(g_mutexAdapter); + return svritem->fd; + } + } + oc_mutex_unlock(g_mutexAdapter); + return -1; +} + +CAResult_t CAGetTCPIPHeaderInfo(CATransportFlags_t flag, TCPHeaderInfo* tcpHeaderInfo) +{ + CAResult_t res = CA_STATUS_OK; + VERIFY_NON_NULL(tcpHeaderInfo, TAG, "tcpHeaderInfo"); + + TCPInfo info; + int len = sizeof(info); + + OIC_LOG_V(INFO, TAG, "Flags passed is = %d", flag); + int socket_fd; + //Get socketfd, destination ip and port. + socket_fd = CAGetSocketInformation(tcpHeaderInfo->tcpi_dst_addr, &(tcpHeaderInfo->tcpi_dst_port)); + if(socket_fd == -1){ + OIC_LOG(ERROR, TAG, "getsocket Failed"); + return CA_STATUS_FAILED; + } + + OIC_LOG_V(INFO, TAG, "Socket Interface is = %d", socket_fd); + OIC_LOG_V(INFO, TAG, "Port Number is = %d", tcpHeaderInfo->tcpi_dst_port); + + if (getsockopt(socket_fd, SOL_TCP, TCP_INFO, (void *)&info, (socklen_t *)&len) == 0) + { + OIC_LOG(DEBUG, TAG, "getsockopt Success"); + unsigned int source_port = 0; + struct sockaddr address; + socklen_t source_len = sizeof(address);; + char source_ip[MAX_IP_LENGTH]; + bzero(&source_ip, MAX_IP_LENGTH); + + // Get Local Ip and Port + if (CA_IPV6 & flag) { + struct sockaddr_in6 *sourceAddrInfo; + getsockname(socket_fd, &address, &source_len); + sourceAddrInfo = (struct sockaddr_in6*)&address; + inet_ntop(AF_INET6, &sourceAddrInfo->sin6_addr, source_ip, sizeof(source_ip)); + source_port = ntohs(sourceAddrInfo->sin6_port); + tcpHeaderInfo->ip_version = CA_IPV6_VERSION; + } else if (CA_IPV4 & flag) { + struct sockaddr_in *sourceAddrInfo; + getsockname(socket_fd, &address, &source_len); + sourceAddrInfo = (struct sockaddr_in*)&address; + inet_ntop(AF_INET, &sourceAddrInfo->sin_addr, source_ip, sizeof(source_ip)); + source_port = ntohs(sourceAddrInfo->sin_port); + tcpHeaderInfo->ip_version = CA_IPV4_VERSION; + } + + //GET Local IP and port + strncpy((char *)tcpHeaderInfo->tcpi_src_addr, source_ip, MAX_IP_LENGTH); + tcpHeaderInfo->tcpi_src_port = source_port; + tcpHeaderInfo->tcpi_rcv_nxt = info.tcpi_rcv_nxt; + tcpHeaderInfo->tcpi_snd_nxt = info.tcpi_snd_nxt; + tcpHeaderInfo->tcpi_rcv_wnd = info.tcpi_rcv_wnd; + tcpHeaderInfo->tcpi_rcv_wscale = info.tcpi_rcv_wscale; + } + else { + OIC_LOG(INFO, TAG, "getsockopt Fail"); + OIC_LOG_V(INFO, TAG, "getsockopt error %s", strerror(errno)); + res = CA_SOCKET_OPERATION_FAILED; + } + + OIC_LOG(INFO, TAG, "========tcpHeaderInfo========="); + OIC_LOG_V(INFO, TAG, "src_addr = %s", tcpHeaderInfo->tcpi_src_addr); + OIC_LOG_V(INFO, TAG, "src_port = %d", tcpHeaderInfo->tcpi_src_port); + OIC_LOG_V(INFO, TAG, "dst_addr = %s", tcpHeaderInfo->tcpi_dst_addr); + OIC_LOG_V(INFO, TAG, "dst_port = %d", tcpHeaderInfo->tcpi_dst_port); + OIC_LOG_V(INFO, TAG, "version = %d", tcpHeaderInfo->ip_version); + OIC_LOG_V(INFO, TAG, "seq_num = 0x%02x", tcpHeaderInfo->tcpi_snd_nxt); + OIC_LOG_V(INFO, TAG, "ack_num = 0x%02x", tcpHeaderInfo->tcpi_rcv_nxt); + OIC_LOG_V(INFO, TAG, "wnd = 0x%02x", tcpHeaderInfo->tcpi_rcv_wnd); + OIC_LOG_V(INFO, TAG, "wscale = %d", tcpHeaderInfo->tcpi_rcv_wscale); + OIC_LOG(INFO, TAG, "========================"); + + return res; +} + #ifdef SINGLE_THREAD size_t CAGetTotalLengthFromPacketHeader(const unsigned char *recvBuffer, size_t size) { diff --git a/resource/csdk/connectivity/util/src/cautilinterface.c b/resource/csdk/connectivity/util/src/cautilinterface.c index 4724dfc..d009987 100644 --- a/resource/csdk/connectivity/util/src/cautilinterface.c +++ b/resource/csdk/connectivity/util/src/cautilinterface.c @@ -499,3 +499,19 @@ CAResult_t CAUtilStopGattServer() #endif return res; } + +CAResult_t CAGetTCPIPHeader(CATransportAdapter_t adapter, int flag, TCPHeaderInfo* info) +{ + CAResult_t res = CA_STATUS_OK; +#ifdef TCP_ADAPTER + if (CA_ADAPTER_TCP & adapter) { + res = CAGetTCPIPHeaderInfo(flag,info); + } + else + res = CA_NOT_SUPPORTED; +#else + res = CA_NOT_SUPPORTED; + OIC_LOG(DEBUG, TAG, "Not supported!"); +#endif + return res; +} -- 2.7.4