| #include <net-snmp/net-snmp-config.h> |
| #include <net-snmp/net-snmp-includes.h> |
| #include <net-snmp/agent/net-snmp-agent-includes.h> |
| |
| #include "sctpAssocTable.h" |
| #include "sctpAssocLocalAddrTable.h" |
| #include "sctpAssocRemAddrTable.h" |
| #include "sctpTables_common.h" |
| |
| #include <util_funcs.h> |
| |
| #include <stdio.h> |
| #include <errno.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include <sys/types.h> |
| #include <sys/sysctl.h> |
| #include <stdint.h> |
| #include <sys/socket.h> |
| #include <netinet/in.h> |
| #include <netinet/sctp.h> |
| #include <netinet/sctp_constants.h> |
| |
| |
| static int |
| parse_assoc_local_addresses(sctpTables_containers * containers, |
| struct xsctp_laddr *xladdr) |
| { |
| int ret; |
| sctpAssocLocalAddrTable_entry *entry; |
| entry = sctpAssocLocalAddrTable_entry_create(); |
| if (entry == NULL) |
| return SNMP_ERR_GENERR; |
| |
| entry->sctpAssocId = 0; |
| if (xladdr->address.sa.sa_family == AF_INET) { |
| entry->sctpAssocLocalAddrType = INETADDRESSTYPE_IPV4; |
| entry->sctpAssocLocalAddr_len = 4; |
| memcpy(entry->sctpAssocLocalAddr, |
| &xladdr->address.sin.sin_addr, |
| entry->sctpAssocLocalAddr_len); |
| } else if (xladdr->address.sa.sa_family == AF_INET6) { |
| entry->sctpAssocLocalAddrType = INETADDRESSTYPE_IPV6; |
| entry->sctpAssocLocalAddr_len = 16; |
| memcpy(entry->sctpAssocLocalAddr, |
| &xladdr->address.sin6.sin6_addr, |
| entry->sctpAssocLocalAddr_len); |
| } |
| entry->sctpAssocLocalAddrStartTime = xladdr->start_time.tv_sec; |
| ret = sctpAssocLocalAddrTable_add_or_update(containers->sctpAssocLocalAddrTable, |
| entry); |
| if (ret != SNMP_ERR_NOERROR) |
| return SNMP_ERR_GENERR; |
| |
| return SNMP_ERR_NOERROR; |
| } |
| |
| static int |
| parse_assoc_xstcb(sctpTables_containers * containers, struct xsctp_tcb *xstcb) |
| { |
| int ret; |
| sctpAssocTable_entry *entry; |
| |
| entry = sctpAssocTable_entry_create(); |
| if (entry == NULL) |
| return SNMP_ERR_GENERR; |
| |
| switch (xstcb->state) { |
| case SCTP_STATE_INUSE: |
| entry->sctpAssocState = SCTPASSOCSTATE_DELETETCB; |
| break; |
| case SCTP_STATE_COOKIE_WAIT: |
| entry->sctpAssocState = SCTPASSOCSTATE_COOKIEWAIT; |
| break; |
| case SCTP_STATE_COOKIE_ECHOED: |
| entry->sctpAssocState = SCTPASSOCSTATE_COOKIEECHOED; |
| break; |
| case SCTP_STATE_OPEN: |
| entry->sctpAssocState = SCTPASSOCSTATE_ESTABLISHED; |
| break; |
| case SCTP_STATE_SHUTDOWN_SENT: |
| entry->sctpAssocState = SCTPASSOCSTATE_SHUTDOWNSENT; |
| break; |
| case SCTP_STATE_SHUTDOWN_RECEIVED: |
| entry->sctpAssocState = SCTPASSOCSTATE_SHUTDOWNRECEIVED; |
| break; |
| case SCTP_STATE_SHUTDOWN_ACK_SENT: |
| entry->sctpAssocState = SCTPASSOCSTATE_SHUTDOWNACKSENT; |
| break; |
| default: |
| case SCTP_STATE_EMPTY: |
| entry->sctpAssocState = SCTPASSOCSTATE_CLOSED; |
| break; |
| }; |
| entry->sctpAssocHeartBeatInterval = xstcb->heartbeat_interval; |
| entry->sctpAssocId = 0; |
| entry->sctpAssocPrimProcess = xstcb->primary_process; |
| entry->sctpAssocLocalPort = xstcb->local_port; |
| entry->sctpAssocRemPort = xstcb->remote_port; |
| entry->sctpAssocHeartBeatInterval = xstcb->heartbeat_interval; |
| entry->sctpAssocInStreams = xstcb->in_streams; |
| entry->sctpAssocOutStreams = xstcb->out_streams; |
| entry->sctpAssocMaxRetr = xstcb->max_nr_retrans; |
| entry->sctpAssocT1expireds = xstcb->T1_expireries; |
| entry->sctpAssocRtxChunks = xstcb->retransmitted_tsns; |
| entry->sctpAssocT2expireds = xstcb->T2_expireries; |
| entry->sctpAssocRemHostName[0] = 0; |
| entry->sctpAssocRemHostName_len = 0; |
| entry->sctpAssocDiscontinuityTime = xstcb->discontinuity_time.tv_sec; |
| entry->sctpAssocStartTime = xstcb->start_time.tv_sec; |
| |
| ret = sctpAssocTable_add_or_update(containers->sctpAssocTable, entry); |
| if (ret != SNMP_ERR_NOERROR) { |
| return ret; |
| } |
| |
| return SNMP_ERR_NOERROR; |
| } |
| |
| |
| static int |
| parse_remaddr_xraddr(sctpTables_containers * containers, |
| struct xsctp_raddr *xraddr) |
| { |
| int ret; |
| sctpAssocRemAddrTable_entry *entry; |
| |
| entry = sctpAssocRemAddrTable_entry_create(); |
| if (entry == NULL) |
| return SNMP_ERR_GENERR; |
| |
| |
| entry->sctpAssocId = 0; |
| |
| if(xraddr->active) |
| entry->sctpAssocRemAddrActive = TRUTHVALUE_TRUE; |
| else |
| entry->sctpAssocRemAddrActive = TRUTHVALUE_FALSE; |
| |
| if (xraddr->heartbeat_enabled) |
| entry->sctpAssocRemAddrHBActive = TRUTHVALUE_TRUE; |
| else |
| entry->sctpAssocRemAddrHBActive = TRUTHVALUE_FALSE; |
| |
| entry->sctpAssocRemAddrRTO = xraddr->rto; |
| entry->sctpAssocRemAddrMaxPathRtx = xraddr->max_path_rtx; |
| entry->sctpAssocRemAddrRtx = xraddr->rtx; |
| entry->sctpAssocRemAddrStartTime = xraddr->start_time.tv_sec; |
| |
| if (xraddr->address.sa.sa_family == AF_INET) { |
| entry->sctpAssocRemAddrType = INETADDRESSTYPE_IPV4; |
| entry->sctpAssocRemAddr_len = 4; |
| memcpy(entry->sctpAssocRemAddr, |
| &xraddr->address.sin.sin_addr, |
| entry->sctpAssocRemAddr_len); |
| } else if (xraddr->address.sa.sa_family == AF_INET6) { |
| entry->sctpAssocRemAddrType = INETADDRESSTYPE_IPV6; |
| entry->sctpAssocRemAddr_len = 16; |
| memcpy(entry->sctpAssocRemAddr, |
| &xraddr->address.sin6.sin6_addr, |
| entry->sctpAssocRemAddr_len); |
| } |
| ret = |
| sctpAssocRemAddrTable_add_or_update(containers-> |
| sctpAssocRemAddrTable, entry); |
| if (ret != SNMP_ERR_NOERROR) { |
| return ret; |
| } |
| return SNMP_ERR_NOERROR; |
| } |
| |
| |
| int |
| sctpTables_arch_load(sctpTables_containers * containers, u_long * flags) |
| { |
| int ret = SNMP_ERR_NOERROR; |
| size_t len; |
| caddr_t buf; |
| unsigned int offset; |
| struct xsctp_inpcb *xinp; |
| struct xsctp_tcb *xstcb; |
| struct xsctp_laddr *xladdr; |
| struct xsctp_raddr *xraddr; |
| |
| |
| *flags |= SCTP_TABLES_LOAD_FLAG_DELETE_INVALID; |
| *flags |= SCTP_TABLES_LOAD_FLAG_AUTO_LOOKUP; |
| len = 0; |
| if (sysctlbyname("net.inet.sctp.assoclist", 0, &len, 0, 0) < 0) { |
| printf("Error %d (%s) could not get the assoclist\n", errno, strerror(errno)); |
| return(-1); |
| } |
| if ((buf = (caddr_t)malloc(len)) == 0) { |
| printf("malloc %lu bytes failed.\n", (long unsigned)len); |
| return(-1); |
| } |
| if (sysctlbyname("net.inet.sctp.assoclist", buf, &len, 0, 0) < 0) { |
| printf("Error %d (%s) could not get the assoclist\n", errno, strerror(errno)); |
| free(buf); |
| return(-1); |
| } |
| offset = 0; |
| xinp = (struct xsctp_inpcb *)(buf + offset); |
| while (xinp->last == 0) { |
| /* for each INP */ |
| offset += sizeof(struct xsctp_inpcb); |
| /* Local addresses */ |
| xladdr = (struct xsctp_laddr *)(buf + offset); |
| while (xladdr->last == 0) { |
| offset += sizeof(struct xsctp_laddr); |
| xladdr = (struct xsctp_laddr *)(buf + offset); |
| } |
| offset += sizeof(struct xsctp_laddr); |
| /* Associations */ |
| xstcb = (struct xsctp_tcb *)(buf + offset); |
| while (xstcb->last == 0) { |
| xstcb = (struct xsctp_tcb *)(buf + offset); |
| offset += sizeof(struct xsctp_tcb); |
| parse_assoc_xstcb(containers, xstcb); |
| /* Local addresses */ |
| xladdr = (struct xsctp_laddr *)(buf + offset); |
| while (xladdr->last == 0) { |
| parse_assoc_local_addresses(containers, xladdr); |
| offset += sizeof(struct xsctp_laddr); |
| xladdr = (struct xsctp_laddr *)(buf + offset); |
| } |
| offset += sizeof(struct xsctp_laddr); |
| |
| /* Remote addresses */ |
| xraddr = (struct xsctp_raddr *)(buf + offset); |
| while (xraddr->last == 0) { |
| parse_remaddr_xraddr(containers, xraddr); |
| offset += sizeof(struct xsctp_raddr); |
| xraddr = (struct xsctp_raddr *)(buf + offset); |
| } |
| offset += sizeof(struct xsctp_raddr); |
| xstcb = (struct xsctp_tcb *)(buf + offset); |
| } |
| offset += sizeof(struct xsctp_tcb); |
| xinp = (struct xsctp_inpcb *)(buf + offset); |
| } |
| free((void *)buf); |
| return ret; |
| } |