/* ****************************************************************************** * SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipsctp_mib.c,v $ $Revision: 1.11 $ * $Source: /home/interpeak/CVSRoot/ipsctp/src/ipsctp_mib.c,v $ * $Author: kenneth $ $Date: 2010-09-22 18:57:04 $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * Design and implementation by Jiangang Yang ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #include "ipsctp_config.h" /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #define IPCOM_USE_CLIB_PROTO #include #include #include #include #include "ipnet_usr_sock.h" #include "ipsctp.h" #include "ipsctp_h.h" #ifdef IPSCTP_MIB /* **************************************************************************** * 4 EXTERN PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 5 DEFINES **************************************************************************** */ /* **************************************************************************** * 6 TYPES **************************************************************************** */ /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 8 DATA **************************************************************************** */ /* **************************************************************************** * 9 STATIC FUNCTIONS **************************************************************************** */ /* **************************************************************************** * 10 GLOBAL FUNCTIONS **************************************************************************** */ /* **************************************************************************** * 11 PUBLIC FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipsctp_mib_stats_lookup *=========================================================================== * Description: get SCTP global statistics * Parameters: * Returns: */ IP_PUBLIC int ipsctp_mib_stats_lookup(Ipsctp_mib_stats **stats) { void *suspend_handle; if (stats == IP_NULL) return -1; *stats = ipcom_malloc(sizeof(Ipsctp_mib_stats)); if (*stats == IP_NULL) return -1; suspend_handle = ipnet_suspend_stack(); if (suspend_handle == IP_NULL) { ipcom_free(*stats); *stats = IP_NULL; return -1; } **stats = ipsctp->mib_stats; ipnet_resume_stack(suspend_handle); return 0; } /* *=========================================================================== * ipsctp_mib_stats_lookup *=========================================================================== * Description: get SCTP global statistics * Parameters: * Returns: */ IP_PUBLIC void ipsctp_mib_stats_get(Ipsctp_mib_stats **stats) { if (stats == IP_NULL) return; *stats = &ipsctp->mib_stats; return; } /* *=========================================================================== * ipsctp_mib_params_lookup *=========================================================================== * Description: get SCTP global parameters * Parameters: * Returns: */ IP_PUBLIC int ipsctp_mib_params_lookup(Ipsctp_params **params) { void *suspend_handle; if (params == IP_NULL) return -1; *params = ipcom_malloc(sizeof(Ipsctp_params)); if (*params == IP_NULL) return -1; suspend_handle = ipnet_suspend_stack(); if (suspend_handle == IP_NULL) { ipcom_free(*params); *params = IP_NULL; return -1; } (*params)->sctpRtoInitial = (Ip_u32)ipcom_sysvar_get_as_int0("ipsctp.Rto.Initial", IPSCTP_RTO_INITIAL_DEFAULT); (*params)->sctpRtoMax = (Ip_u32)ipcom_sysvar_get_as_int0("ipsctp.Rto.Max", IPSCTP_RTO_MAX_DEFAULT); (*params)->sctpRtoMin = (Ip_u32)ipcom_sysvar_get_as_int0("ipsctp.Rto.Min", IPSCTP_RTO_MIN_DEFAULT); (*params)->sctpRtoAlgorithm = (Ip_s32)ipcom_sysvar_get_as_int0("ipsctp.Rto.Algorithm", IPSCTP_RTO_ALGORITHM_DEFAULT); (*params)->sctpMaxAssocs = (Ip_s32)ipcom_sysvar_get_as_int0("ipsctp.Max.Associations", IPSCTP_MAX_ASSOCIATIONS_DEFAULT); (*params)->sctpValCookieLife = (Ip_u32)ipcom_sysvar_get_as_int0("ipsctp.Valid.Cookie.Life", IPSCTP_VALID_COOKIE_LIFE_DEFAULT); (*params)->sctpMaxInitRetr = (Ip_u32)ipcom_sysvar_get_as_int0("ipsctp.Max.Init.Retransmits", IPSCTP_MAX_INIT_RETRANSMITS_DEFAULT); ipnet_resume_stack(suspend_handle); return 0; } /* *=========================================================================== * ipsctp_mib_assoc_entry_lookup *=========================================================================== * Description: get SCTP Association entry. * Parameters: * Returns: */ IP_PUBLIC Ipsctp_assoc_entry * ipsctp_mib_assoc_entry_lookup(Ip_u32 vtag, int /*boolean_t*/ getnext) { Ipsctp_tcb *tcb; Ipsctp_assoc_entry *assoc_entry; void *suspend_handle; assoc_entry = ipcom_calloc(1, sizeof(Ipsctp_assoc_entry)); if (assoc_entry == IP_NULL) return IP_NULL; ipcom_memset(assoc_entry, 0, sizeof(*assoc_entry)); suspend_handle = ipnet_suspend_stack(); if (suspend_handle == IP_NULL) { ipcom_free(assoc_entry); return IP_NULL; } /* find matching TCB from SCTP HashTable */ if (vtag != 0) { /* get next tcb from hashtable */ unsigned hash_index; void *obj = IP_NULL; Ipsctp_tcb_lookup_key key; Ipsctp_hash *head = ipsctp->tcb_hashtable; ipcom_memset(&key, 0, sizeof(key)); key.vtag = vtag; key.strict_match = 0; /* find the current one */ #ifdef IPCOM_FORWARDER_NAE hash_index = ipsctp_hash_key_hash_func(head,&key) % head->size; #else hash_index = head->key_hash_func(&key) % head->size; #endif while ((hash_index < head->size) && ((obj = head->table[hash_index]) != IP_NULL)) { #ifdef IPCOM_FORWARDER_NAE if(ipsctp_hash_obj_key_cmp_func(head,obj,&key)) #else if (head->obj_key_cmp(obj, &key)) #endif break; hash_index = hash_index + 1; } if (getnext) { /* find the next one */ hash_index = hash_index + 1; obj = IP_NULL; while ((hash_index < head->size) && ((obj = head->table[hash_index]) == IP_NULL)) { hash_index = hash_index + 1; } } tcb = obj; } else if(getnext) { /* get first tcb from hashtable */ unsigned hash_index = 0; void *obj = IP_NULL; Ipsctp_hash *head = ipsctp->tcb_hashtable; while ((hash_index < head->size) && ((obj = head->table[hash_index]) == IP_NULL)) { hash_index = hash_index + 1; } tcb = obj; } else { tcb = IP_NULL; } if (tcb == IP_NULL) { ipcom_free(assoc_entry); assoc_entry = IP_NULL; goto exit_func; } assoc_entry->sctpAssocId = tcb->my_vtag; assoc_entry->sctpAssocRemHostName[0] = '\0'; assoc_entry->sctpAssocHeartBeatInterval = tcb->hb_interval; assoc_entry->sctpAssocLocalPort = tcb->instance->lport; assoc_entry->sctpAssocRemPort = tcb->rport; #ifdef IPCOM_USE_INET if (tcb->primary_transport->paddr.sa.sa_family == IP_AF_INET) { assoc_entry->sctpAssocRemPrimAddrType = 1 ; *(Ip_u32 *)assoc_entry->sctpAssocRemPrimAddr = tcb->primary_transport->paddr.sin.sin_addr.s_addr; } #endif #ifdef IPCOM_USE_INET6 if (tcb->primary_transport->paddr.sa.sa_family == IP_AF_INET6) { assoc_entry->sctpAssocRemPrimAddrType = 2 ; ((Ip_u32 *)assoc_entry->sctpAssocRemPrimAddr)[0] = tcb->primary_transport->paddr.sin6.sin6_addr.in6.addr32[0]; ((Ip_u32 *)assoc_entry->sctpAssocRemPrimAddr)[1] = tcb->primary_transport->paddr.sin6.sin6_addr.in6.addr32[1]; ((Ip_u32 *)assoc_entry->sctpAssocRemPrimAddr)[2] = tcb->primary_transport->paddr.sin6.sin6_addr.in6.addr32[2]; ((Ip_u32 *)assoc_entry->sctpAssocRemPrimAddr)[3] = tcb->primary_transport->paddr.sin6.sin6_addr.in6.addr32[3]; } #endif assoc_entry->sctpAssocHeartBeatInterval = tcb->hb_interval; assoc_entry->sctpAssocState = tcb->state; assoc_entry->sctpAssocInStreams = tcb->streamincnt; assoc_entry->sctpAssocOutStreams = tcb->streamoutcnt; assoc_entry->sctpAssocMaxRetr = tcb->max_send_times; assoc_entry->sctpAssocPrimProcess = 0; assoc_entry->sctpAssocT1expireds = tcb->cnt_timo_init + tcb->cnt_timo_cookie; assoc_entry->sctpAssocT2expireds = tcb->cnt_timo_shutdown + tcb->cnt_timo_shutdownack; assoc_entry->sctpAssocRtxChunks = tcb->marked_retrans; assoc_entry->sctpAssocStartTime = tcb->start_time; assoc_entry->sctpAssocDiscontinuityTime = tcb->discontinuity_time; exit_func: ipnet_resume_stack(suspend_handle); return assoc_entry; } /* *=========================================================================== * ipsctp_mib_set_assoc_state *=========================================================================== * Description: set SCTP Association entry state. * Parameters: * Returns: */ IP_PUBLIC void ipsctp_mib_set_assoc_state(Ipsctp_assoc_entry *assoc_entry, Ip_s32 state) { Ipnet_sig *sig; Ipcom_pipe *pipe; if (assoc_entry == IP_NULL || (state >= IPSCTP_STATE_CLOSED && state < IPSCTP_STATE_MAX)) return; sig = ipcom_slab_alloc(ipnet->slabs.poll); if (sig == IP_NULL) { return; } else { ipnet_usr_sock_init_sig(sig, IPNET_SIG_SCTP_SET_STATE); sig->d.sctp_set_state.vtag = assoc_entry->sctpAssocId; sig->d.sctp_set_state.state = state; pipe = ipnet_usr_sock_get_pipe(); ipcom_pipe_send(pipe, sig); } return; } /* *=========================================================================== * ipsctp_mib_assoc_local_addr_entry_lookup *=========================================================================== * Description: get SCTP Association entry. * Parameters: * Returns: */ IP_PUBLIC Ipsctp_assoc_local_addr_entry * ipsctp_mib_assoc_local_addr_entry_lookup(Ip_u32 vtag, Ip_s32 addrType, Ip_u8 *addr, int get_next) { Ipsctp_tcb *tcb = IP_NULL; Ipsctp_assoc_local_addr_entry *assoc_addr = IP_NULL; void *suspend_handle; unsigned hash_index = 0; Ipsctp_hash *head = ipsctp->tcb_hashtable; suspend_handle = ipnet_suspend_stack(); if (suspend_handle == IP_NULL) return IP_NULL; if (vtag != 0) { void *obj = IP_NULL; Ipsctp_tcb_lookup_key key; ipcom_memset(&key, 0, sizeof(key)); key.vtag = vtag; key.strict_match = 0; /* find the current one */ #ifdef IPCOM_FORWARDER_NAE hash_index = ipsctp_hash_key_hash_func(head,&key) % head->size; #else hash_index = head->key_hash_func(&key) % head->size; #endif while ((hash_index < head->size) && ((obj = head->table[hash_index]) != IP_NULL)) { #ifdef IPCOM_FORWARDER_NAE if(ipsctp_hash_obj_key_cmp_func(head,obj,&key)) #else if (head->obj_key_cmp(obj, &key)) #endif { tcb = obj; break; } hash_index = hash_index + 1; } } else if (get_next) { /* get first tcb from hashtable */ goto next_tcb_first_addr; } else { tcb = IP_NULL; } if (tcb == IP_NULL) { goto exit_func; } find_address_entry: /* get local address entry */ { Ipsctp_addr *local_addr; Ipsctp_laddr_entry *laddr_entry; laddr_entry = (Ipsctp_laddr_entry *)ipcom_list_first(&tcb->instance->laddr_list); while (laddr_entry) { local_addr = &laddr_entry->laddr; if (addr == IP_NULL) { break; } #ifdef IPCOM_USE_INET if (addrType == 1 && local_addr->sa.sa_family == IP_AF_INET && (*(Ip_u32 *)addr) == local_addr->sin.sin_addr.s_addr ) { break; } #endif #ifdef IPCOM_USE_INET6 if (addrType == 2 && local_addr->sa.sa_family == IP_AF_INET6 && IP_IN6_ARE_ADDR_EQUAL(addr, &local_addr->sin6.sin6_addr)) { break; } #endif laddr_entry = (Ipsctp_laddr_entry *)ipcom_list_next(&laddr_entry->next); } /*found_addr_entry:*/ if (laddr_entry) { if (get_next) { laddr_entry = (Ipsctp_laddr_entry *)ipcom_list_next(&laddr_entry->next); if (laddr_entry != IP_NULL) { local_addr = &laddr_entry->laddr; get_next = 0; } } } else { goto exit_func; } if (laddr_entry && local_addr) { assoc_addr = ipcom_calloc(1, sizeof(*assoc_addr)); if (assoc_addr == IP_NULL) { goto exit_func; } #ifdef IPCOM_USE_INET if (local_addr->sa.sa_family == IP_AF_INET) { assoc_addr->sctpAssocLocalAddrType = 1; *(Ip_u32 *)assoc_addr->sctpAssocLocalAddr = local_addr->sin.sin_addr.s_addr; } #endif #ifdef IPCOM_USE_INET6 if (local_addr->sa.sa_family == IP_AF_INET6) { assoc_addr->sctpAssocLocalAddrType = 2; ((Ip_u32 *)assoc_addr->sctpAssocLocalAddr)[0] = local_addr->sin6.sin6_addr.in6.addr32[0]; ((Ip_u32 *)assoc_addr->sctpAssocLocalAddr)[1] = local_addr->sin6.sin6_addr.in6.addr32[1]; ((Ip_u32 *)assoc_addr->sctpAssocLocalAddr)[2] = local_addr->sin6.sin6_addr.in6.addr32[2]; ((Ip_u32 *)assoc_addr->sctpAssocLocalAddr)[3] = local_addr->sin6.sin6_addr.in6.addr32[3]; } #endif assoc_addr->sctpAssocLocalAddrStartTime = laddr_entry->start_time; assoc_addr->sctpAssocId = tcb->my_vtag; goto exit_func; } } if (!get_next) goto exit_func; /* get next tcb from hashtable */ hash_index = hash_index + 1; next_tcb_first_addr: tcb = IP_NULL; while ((hash_index < head->size) && ((tcb = head->table[hash_index]) == IP_NULL)) { hash_index = hash_index + 1; } /* find the first address entry of this TCB */ if (tcb) { addr = IP_NULL; get_next = 0; addrType = 0; goto find_address_entry; } exit_func: ipnet_resume_stack(suspend_handle); return assoc_addr; } /* *=========================================================================== * ipsctp_mib_assoc_rem_addr_entry_lookup *=========================================================================== * Description: get SCTP Association entry. * Parameters: * Returns: */ IP_PUBLIC Ipsctp_assoc_rem_addr_entry * ipsctp_mib_assoc_rem_addr_entry_lookup(Ip_u32 vtag, Ip_s32 addrType, Ip_u8 *addr, int get_next) { Ipsctp_tcb *tcb = IP_NULL; Ipsctp_assoc_rem_addr_entry *assoc_addr = IP_NULL; void *suspend_handle; unsigned hash_index = 0; Ipsctp_hash *head = ipsctp->tcb_hashtable; suspend_handle = ipnet_suspend_stack(); if (suspend_handle == IP_NULL) return IP_NULL; if (vtag != 0) { void *obj = IP_NULL; Ipsctp_tcb_lookup_key key; ipcom_memset(&key, 0, sizeof(key)); key.vtag = vtag; key.strict_match = 0; /* find the current one */ #ifdef IPCOM_FORWARDER_NAE hash_index = ipsctp_hash_key_hash_func(head,&key) % head->size; #else hash_index = head->key_hash_func(&key) % head->size; #endif while ((hash_index < head->size) && ((obj = head->table[hash_index]) != IP_NULL)) { #ifdef IPCOM_FORWARDER_NAE if(ipsctp_hash_obj_key_cmp_func(head,obj,&key)) #else if (head->obj_key_cmp(obj, &key)) #endif { tcb = obj; break; } hash_index = hash_index + 1; } } else if (get_next) { /* get first tcb from hashtable */ goto next_tcb_first_addr; } else { tcb = IP_NULL; } if (tcb == IP_NULL) { goto exit_func; } find_address_entry: /* get remote address entry */ { Ipsctp_addr *rem_addr; Ipsctp_transport *transport_entry; transport_entry = (Ipsctp_transport *)ipcom_list_first(&tcb->transport_list); while (transport_entry) { rem_addr = &transport_entry->paddr; if (addr == IP_NULL) { break; } #ifdef IPCOM_USE_INET if (addrType == 1 && rem_addr->sa.sa_family == IP_AF_INET && (*(Ip_u32 *)addr) == rem_addr->sin.sin_addr.s_addr ) { break; } #endif #ifdef IPCOM_USE_INET6 if (addrType == 2 && rem_addr->sa.sa_family == IP_AF_INET6 && IP_IN6_ARE_ADDR_EQUAL(addr, &rem_addr->sin6.sin6_addr)) { break; } #endif transport_entry = (Ipsctp_transport *)ipcom_list_next(&transport_entry->trans_next); } /*found_addr_entry:*/ if (transport_entry) { if (get_next) { transport_entry = (Ipsctp_transport *)ipcom_list_next(&transport_entry->trans_next); if (transport_entry != IP_NULL) { rem_addr = &transport_entry->paddr; get_next = 0; } } } else { goto exit_func; } if (transport_entry && rem_addr) { assoc_addr = ipcom_calloc(1, sizeof(*assoc_addr)); if (assoc_addr == IP_NULL) { goto exit_func; } #ifdef IPCOM_USE_INET if (rem_addr->sa.sa_family == IP_AF_INET) { assoc_addr->sctpAssocRemAddrType = 1; *(Ip_u32 *)assoc_addr->sctpAssocRemAddr = rem_addr->sin.sin_addr.s_addr; } #endif #ifdef IPCOM_USE_INET6 if (rem_addr->sa.sa_family == IP_AF_INET6) { assoc_addr->sctpAssocRemAddrType = 2; ((Ip_u32 *)assoc_addr->sctpAssocRemAddr)[0] = rem_addr->sin6.sin6_addr.in6.addr32[0]; ((Ip_u32 *)assoc_addr->sctpAssocRemAddr)[1] = rem_addr->sin6.sin6_addr.in6.addr32[1]; ((Ip_u32 *)assoc_addr->sctpAssocRemAddr)[2] = rem_addr->sin6.sin6_addr.in6.addr32[2]; ((Ip_u32 *)assoc_addr->sctpAssocRemAddr)[3] = rem_addr->sin6.sin6_addr.in6.addr32[3]; } #endif if (IP_BIT_ISSET(transport_entry->state, IPSCTP_ADDR_REACHABLE)) { assoc_addr->sctpAssocRemAddrActive = 1; } else { assoc_addr->sctpAssocRemAddrActive = 2; } if (IP_BIT_ISSET(transport_entry->state, IPSCTP_ADDR_NOHB)) { assoc_addr->sctpAssocRemAddrHBActive = 2; } else { assoc_addr->sctpAssocRemAddrHBActive = 1; } assoc_addr->sctpAssocRemAddrRTO = transport_entry->rto; assoc_addr->sctpAssocRemAddrMaxPathRtx = transport_entry->err_thresh; assoc_addr->sctpAssocRemAddrRtx = transport_entry->marked_retrans; assoc_addr->sctpAssocRemAddrStartTime = transport_entry->start_time; assoc_addr->sctpAssocId = tcb->my_vtag; goto exit_func; } } if (!get_next) goto exit_func; /* get next tcb from hashtable */ hash_index = hash_index + 1; next_tcb_first_addr: tcb = IP_NULL; while ((hash_index < head->size) && ((tcb = head->table[hash_index]) == IP_NULL)) { hash_index = hash_index + 1; } /* find the first address entry of this TCB */ if (tcb) { addr = IP_NULL; get_next = 0; addrType = 0; goto find_address_entry; } exit_func: ipnet_resume_stack(suspend_handle); return assoc_addr; } #endif /* **************************************************************************** * END OF FILE **************************************************************************** */