/* ****************************************************************************** * SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipnet_cmd_netstat.c,v $ $Revision: 1.87.10.8 $ * $Source: /home/interpeak/CVSRoot/ipnet2/src/ipnet_cmd_netstat.c,v $ * $Author: blan $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * Design and implementation by Kenneth Jonsson ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ #ifdef IPCOM_KERNEL #undef IPCOM_KERNEL #endif #include "ipnet_config.h" /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #define IPCOM_USE_CLIB_PROTO #include #include #include #include #include #include "ipnet.h" #include "ipnet_h.h" #include "ipnet_ctrl.h" #include "ipnet_route.h" #include "ipnet_routesock.h" #include "ipnet_cmd.h" #include "ipnet_usr_sock.h" #ifdef IPSCTP #include #endif /* **************************************************************************** * 4 DEFINES **************************************************************************** */ #define IPNET_NETSTAT_STRLEN 256 /* **************************************************************************** * 5 TYPES **************************************************************************** */ /* **************************************************************************** * 6 EXTERN PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 8 DATA **************************************************************************** */ IP_STATIC Ipcom_cmd_int_str_map af_map[] = { { IP_AF_INET, "INET" }, { IP_AF_INET6, "INET6" }, { -1, IP_NULL } }; IP_STATIC Ipcom_cmd_int_str_map proto_map[] = { { IP_IPPROTO_TCP, "TCP" }, { IP_IPPROTO_UDP, "UDP" }, { IP_IPPROTO_UDPLITE, "UDPLite" }, { IP_IPPROTO_ICMP, "ICMP" }, { IP_IPPROTO_IGMP, "IGMP" }, { IP_IPPROTO_ICMPV6, "ICMP6" }, { IP_IPPROTO_IP, "IP" }, { IP_IPPROTO_IPV4, "IPv4" }, { IP_IPPROTO_IPV6, "IPv6" }, { IP_IPPROTO_OSPFIGP, "OSPFIGP" }, { IP_IPPROTO_RSVP, "RSVP" }, { IP_IPPROTO_PIM, "PIM" }, { IP_IPPROTO_SCTP, "SCTP" }, { -1, IP_NULL } }; #if defined(IPTCP) && !defined(IP_PORT_LAS) IP_STATIC IP_CONST char *tcp_state_list[] = { "", "CLOSED", "LISTEN", "SYN_SENT", "SYN_RCVD", "ESTABLISHED", "CLOSE_WAIT", "FIN_WAIT_1", "CLOSING", "LAST_ACK", "FIN_WAIT_2", "TIME_WAIT" }; #endif /* IPTCP */ #if defined(IPSCTP) && !defined(IP_PORT_LAS) IP_STATIC IP_CONST char *netstat_sctp_state_list[] = { "LISTEN", "CLOSED", "COOKIE_WAIT", "COOKIE_ECHOED", "ESTABLISHED", "SHUTDOWN_PENDING", "SHUTDOWN_SENT", "SHUTDOWN_RECEIVED", "SHUTDOWN_ACK_SENT", "UNKNOWN" }; #endif /* IPSCTP */ /* **************************************************************************** * 9 LOCAL FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipnet_cmd_netstat_is_contiguous *=========================================================================== * Description: Checks if the specified mask is contiguous. * Parameters: mask - a networks mask. * Returns: IP_TRUE if the mask is contiguous. * */ IP_STATIC Ip_bool ipnet_cmd_netstat_is_contiguous(struct Ip_sockaddr *mask) { Ip_bool is_contiguous = IP_TRUE; #ifdef IPCOM_USE_INET if (mask->sa_family == IP_AF_INET) { /* Only AF_INET masks can be non-contiguous */ Ip_u32 contiguous_mask = 0; ipnet_route_create_mask(&contiguous_mask, ipcom_sockaddr_to_prefixlen(mask)); is_contiguous = (ipcom_memcmp(&contiguous_mask, &((struct Ip_sockaddr_in *)mask)->sin_addr, sizeof(contiguous_mask)) == 0); } #else IPCOM_UNUSED_ARG(mask); #endif /* !IPCOM_USE_INET */ return is_contiguous; } /* *=========================================================================== * ipnet_netstat_print_routes *=========================================================================== * Description: Prints the content of the routing tables (FIB). * Parameters: af - Address family (0 for all). * rtab_index - The route table to print. * policy - The policy index of the router. * no_dns - IP_TRUE if the addresses should not be resolved to * there DNS names. * Returns: * */ IP_STATIC void ipnet_netstat_print_routes(int af, Ip_u32 table, Ip_bool no_dns, Ip_bool show_llinfo) { char str[IPNET_NETSTAT_STRLEN]; char str2[16]; int name[6]; Ip_u8 *route_buf; Ip_size_t route_buf_len; Ip_size_t offset; int current_proto = 0; struct Ipnet_rt_msghdr *rt; struct Ip_sockaddr *addrs[IPNET_RTAX_MAX]; if (af == 0) { #ifdef IPCOM_USE_INET ipnet_netstat_print_routes(IP_AF_INET, table, no_dns, show_llinfo); #endif #ifdef IPCOM_USE_INET6 ipnet_netstat_print_routes(IP_AF_INET6, table, no_dns, show_llinfo); #endif return; } name[0] = IP_CTL_NET; name[1] = IP_AF_ROUTE; name[2] = 0; name[3] = af; name[4] = IP_NET_RT_DUMP; name[5] = 0; if (ipcom_sysctl(name, 6, IP_NULL, &route_buf_len, IP_NULL, 0) < 0) { ipcom_printf("Failed to get the length needed for the route buffer: %s", ipcom_strerror(ipcom_errno)); return; } if (route_buf_len == 0) { ipcom_printf("table=%u on VR=%u does not exists or is empty"IP_LF, (unsigned)table, ipcom_proc_vr_get()); return; } route_buf = ipcom_malloc(route_buf_len); if (route_buf == IP_NULL) { ipcom_printf("Out of memory"); return; } if (ipcom_sysctl(name, 6, route_buf, &route_buf_len, IP_NULL, 0) < 0) { ipcom_printf("Failed to get the route entries: %s", ipcom_strerror(ipcom_errno)); goto leave; } for (offset = 0; offset < route_buf_len; offset += rt->rtm_msglen) { rt = (struct Ipnet_rt_msghdr *) &route_buf[offset]; if (show_llinfo == IP_FALSE && IP_BIT_ISSET(rt->rtm_flags, IPNET_RTF_LLINFO)) continue; ipnet_cmd_init_addrs(rt + 1, rt->rtm_addrs, addrs); if (rt->rtm_table != table) continue; if (addrs[IPNET_RTAX_DST]->sa_family != current_proto) { struct Ip_sioc_route_table sioc_rt; int s; /* First entry in this address family, print header */ current_proto = addrs[IPNET_RTAX_DST]->sa_family; sioc_rt.vr = (Ip_u16) ipcom_proc_vr_get(); sioc_rt.table = table; s = ipcom_socket(current_proto, IP_SOCK_DGRAM, 0); ipcom_printf("\n"); ipcom_printf("%s route table - vr: %u, table: %u", ipcom_cmd_key_to_str(af_map, current_proto, str, sizeof(str)), sioc_rt.vr, (unsigned)sioc_rt.table); if (ipcom_socketioctl(s, IP_SIOCGROUTETABNAME, &sioc_rt) == 0) ipcom_printf(", name: %s", sioc_rt.name); ipcom_printf("\n%-32s%-30s%-9s%-6s%-6s%-6s\n", "Destination", "Gateway", "Flags", "Use", "If", "Metric"); ipcom_socketclose(s); } (void)ipcom_cmd_sockaddr_to_str(addrs[IPNET_RTAX_DST], IP_FALSE, no_dns, str, sizeof(str)); if (addrs[IPNET_RTAX_NETMASK] != IP_NULL) { if (ipnet_cmd_netstat_is_contiguous(addrs[IPNET_RTAX_NETMASK])) { ipcom_strcat(str, "/"); ipcom_sprintf(str2, "%d", ipcom_sockaddr_to_prefixlen(addrs[IPNET_RTAX_NETMASK])); } else { ipcom_strcat(str, ":"); ipcom_cmd_sockaddr_to_str(addrs[IPNET_RTAX_NETMASK], IP_FALSE, IP_TRUE, str2, sizeof(str2)); } ipcom_strcat(str, str2); } ipcom_printf("%-31s ", str); if (addrs[IPNET_RTAX_GATEWAY]) { ipcom_printf("%-29s ", ipcom_cmd_sockaddr_to_str( addrs[IPNET_RTAX_GATEWAY], IP_FALSE, no_dns, str, sizeof(str))); } else if (rt->rtm_index != 0) { ipcom_sprintf(str2, "link#%ld", rt->rtm_index); ipcom_printf("%-29s ", str2); } else ipcom_printf("%-29s ", "*"); ipcom_printf("%-9s", ipnet_cmd_rt_flags_to_str_short(rt->rtm_flags, IP_FALSE)); ipcom_printf("%-6ld", rt->rtm_use); if (rt->rtm_index != 0) ipcom_printf("%-6s", ipcom_if_indextoname(rt->rtm_index, str)); else ipcom_printf("%-6s", "*"); ipcom_printf(" %-5ld", rt->rtm_rmx.rmx_hopcount); ipcom_printf("\n"); } leave: ipcom_free(route_buf); } /* *=========================================================================== * ipnet_netstat_print_entries *=========================================================================== * Description: Prints the status of IPNET sockets. * Parameters: af - The address family to print status for or -1 for all * address family types. * proto - The protocol to print status for or -1 for all * protocols. * show_unconnected - IP_TRUE if both connected and unconnected * sockets status should be printed. * no_dns - IP_TRUE if the addresses should not be resolved to * there DNS names. * show_procs - IP_TRUE if the PID owning a socket should be * displayed. * sock_data - buffer where information about all sockets * should be stored. * Returns: * */ #ifndef IP_PORT_LAS IP_STATIC void ipnet_netstat_print_entries(int af, int vr, int proto, Ip_bool show_unconnected, Ip_bool no_dns, Ip_bool show_procs, struct Ipnet_tag_sock_data sock_data[]) { int p, x, a, y, fd; char str[IPNET_NETSTAT_STRLEN]; struct Ipnet_tag_sock_data tag; int ret; Ip_u16 dport; ipcom_memset(&tag, 0, sizeof(tag)); tag.hdr.type = IPNET_CTRL_NEW_ENUM_SOCK_DATA; tag.hdr.size = sizeof(tag); for (fd = 0; ; fd++) { ret = ipnet_ctrl(&tag.hdr); if (ret == IPNET_CTRL_ENUM_DONE) break; if (ret < 0) { ipcom_printf("ipnet_ctrl() failed (%d)\n", -ret); return; } tag.hdr.type = IPNET_CTRL_CONT_ENUM_SOCK_DATA; sock_data[fd] = tag; } /* Create a end of socket list entry */ sock_data[fd].fd = -1; for (y = 0; af_map[y].key != -1; y++) { if (af != -1) a = af; else a = af_map[y].key; ipcom_printf("%s sockets\n", ipcom_cmd_key_to_str(af_map, a, str, sizeof(str))); ipcom_printf("%-6s", "Prot"); #ifndef IP_PORT_VXWORKS ipcom_printf("%-5s", "Fd"); #endif ipcom_printf("%-7s%-7s", "Recv-Q", "Send-Q"); ipcom_printf("%-30s%-30s%-12s", "Local Address", "Foreign Address", "State"); if (show_procs) #ifdef IP_PORT_VXWORKS ipcom_printf("TID"); #else ipcom_printf("PID"); #endif ipcom_printf("\n"); for (x = 0; x < IP_IPPROTO_MAX ; x++) { if (proto == -1) p = x; else p = proto; for (fd = 0; sock_data[fd].fd >= 0; fd++) { tag = sock_data[fd]; if (tag.protocol != p || tag.domain != a) continue; if (tag.vr_index != vr) continue; dport = ip_ntohs(((struct Ip_sockaddr_in *) &tag.daddr)->sin_port); #ifdef IPSCTP if (!show_unconnected) { /* Show only connected sockets for TCP/UDP */ if (dport == 0 && IP_IPPROTO_SCTP != tag.protocol) continue; /* * don't show when the protocol is sctp and the state of the * socket is closed if show_unconnected is FALSE. */ if ((IP_IPPROTO_SCTP == tag.protocol) && (IP_NULL == tag.priv_data)) continue; } #else if (!show_unconnected && dport == 0) /* Show only connected sockets */ continue; #endif ipcom_printf("%-5s ", ipcom_cmd_key_to_str(proto_map, tag.protocol, str, sizeof(str))); #ifndef IP_PORT_VXWORKS ipcom_printf("%-4d ", tag.fd); #endif ipcom_printf("%-6d %-6d ", tag.rcv_bytes, tag.snd_bytes); #ifdef IPSCTP if ((IP_IPPROTO_SCTP == tag.protocol) && (IP_NULL != tag.priv_data)) { Ipsctp_netstatinfo *netstatinfo = IP_NULL; Ipsctp_netstat_tcbinfo *tcbinfo = IP_NULL; Ip_bool first = IP_TRUE; Ip_bool new_tcb = IP_TRUE; Ip_u32 diff_count = 0; Ip_u32 min_count = 0; Ip_u32 which_big = 0; /* 1:local,2:remote */ Ip_u32 i = 0; Ip_u32 j = 0; netstatinfo = tag.priv_data; for (i = 0; i < netstatinfo->tcb_count; i++) { new_tcb = IP_TRUE; tcbinfo = &netstatinfo->tcb[i]; if (tcbinfo->raddr_count <= netstatinfo->laddr_count) { which_big = 1; min_count = tcbinfo->raddr_count; diff_count = netstatinfo->laddr_count - tcbinfo->raddr_count; } else { which_big = 2; min_count = netstatinfo->laddr_count; diff_count = tcbinfo->raddr_count - netstatinfo->laddr_count; } for (j = 0; j < min_count; j++) { if (IP_TRUE == first) first = IP_FALSE; else { #ifndef IP_PORT_VXWORKS ipcom_printf("%-5s", " "); #endif ipcom_printf("%-20s", " "); } ipcom_printf("%-29s ", ipcom_cmd_sockaddr_to_str(&netstatinfo->laddr[j].sa, IP_TRUE, no_dns, str, sizeof(str))); ipcom_printf("%-29s ", ipcom_cmd_sockaddr_to_str(&tcbinfo->raddr[j].sa, IP_TRUE, no_dns, str, sizeof(str))); if (IP_TRUE == new_tcb) { new_tcb = IP_FALSE; /* 12 bytes is not enough */ ipcom_printf("%-12s", netstat_sctp_state_list[tcbinfo->state]); } ipcom_printf("\n"); } for (; j < diff_count; j++) { #ifndef IP_PORT_VXWORKS ipcom_printf("%-5s", " "); #endif switch (which_big) { case 1: /* local address count is bigger */ ipcom_printf("%-20s%-29s", " ", ipcom_cmd_sockaddr_to_str(&netstatinfo->laddr[j].sa, IP_TRUE, no_dns, str, sizeof(str))); break; case 2: /* remote address count is bigger */ ipcom_printf("%-50s%-29s", " ", ipcom_cmd_sockaddr_to_str(&tcbinfo->raddr[j].sa, IP_TRUE, no_dns, str, sizeof(str))); break; default: break; } ipcom_printf("\n"); } } continue; } #endif /* IPSCTP */ ipcom_printf("%-29s ", ipcom_cmd_sockaddr_to_str(&tag.saddr.addr, IP_TRUE, no_dns, str, sizeof(str))); ipcom_printf("%-29s ", ipcom_cmd_sockaddr_to_str(&tag.daddr.addr, IP_TRUE, no_dns, str, sizeof(str))); #ifdef IPTCP if (tag.protocol == IP_IPPROTO_TCP) ipcom_printf("%-12s", tcp_state_list[tag.tcp_state]); else #endif /* IPTCP */ { #ifdef IPSCTP if (IP_IPPROTO_SCTP == tag.protocol) ipcom_printf("%-12s", "CLOSED"); else #endif /* IPSCTP */ ipcom_printf("%-12s", ""); } if (show_procs) #ifdef IP_PORT_VXWORKS #ifdef _WRS_CONFIG_LP64 ipcom_printf("%p", tag.pid); #else ipcom_printf("%x", tag.pid); #endif #else ipcom_printf("%u", tag.pid); #endif ipcom_printf("\n"); } if (proto != -1) break; } ipcom_printf("\n"); if (af != -1) break; } #ifdef IPSCTP /* free SCTP private data */ for (fd = 0; sock_data[fd].fd >= 0; fd++) { Ipsctp_netstatinfo *netstatinfo = IP_NULL; Ip_u32 i = 0; if ((IP_IPPROTO_SCTP == sock_data[fd].protocol) && (IP_NULL != (netstatinfo = sock_data[fd].priv_data))) /* now, only SCTP use this */ { /* free the memory allocate in ipnetd task */ for (i = 0; i < netstatinfo->tcb_count; i++) { if (netstatinfo->tcb[i].raddr_count > 0) { ipcom_free(netstatinfo->tcb[i].raddr); } } if (netstatinfo->laddr_count > 0) { ipcom_free(netstatinfo->laddr); } ipcom_free(netstatinfo->tcb); ipcom_free(netstatinfo); } } #endif } #endif /* !IP_PORT_LAS */ /*=========================================================================== * ipnet_netstat_init_stat_sig *=========================================================================== * Description: Initializes the statistics signal * Parameters: sig - signal to initialize * proto - protocol to fetch information for. * Returns: * */ #if !defined(IP_PORT_LAS) && defined(IPCOM_USE_MIB2) IP_STATIC void ipnet_netstat_init_stat_sig(Ipnet_sig *sig, int proto) { ipnet_usr_sock_init_sig(sig, IPNET_SIG_STATS); sig->d.stats.proto = proto; } #endif /* *=========================================================================== * ipnet_netstat_print_stats *=========================================================================== * Description: Prints IPNET statistics. * Parameters: proto - The protocol to display statistics for or IP_NULL * for all protocols. * Returns: * */ #if !defined(IP_PORT_LAS) && defined(IPCOM_USE_MIB2) #define IPNET_NETSTAT_PRINT_IP 0x80 #define IPNET_NETSTAT_PRINT_ICMP 0x40 #define IPNET_NETSTAT_PRINT_TCP 0x20 #define IPNET_NETSTAT_PRINT_UDP 0x10 #define IPNET_NETSTAT_PRINT_SCTP 0x08 #define IPNET_NETSTAT_PRINT_IP6 0x04 #define IPNET_NETSTAT_PRINT_ICMP6 0x02 #define IPNET_NETSTAT_PRINT_RAW (IPNET_NETSTAT_PRINT_IP|IPNET_NETSTAT_PRINT_ICMP) #define IPNET_NETSTAT_PRINT_ALL (~0) IP_STATIC void ipnet_netstat_print_stats(const char *proto) { unsigned char mask = 0; Ipnet_sig *sig; sig = ipcom_calloc(1, sizeof(*sig)); if (sig == IP_NULL) { ipcom_printf("Out of memory\n"); return; } if (proto == IP_NULL) mask = (unsigned char) IPNET_NETSTAT_PRINT_ALL; else if (ipcom_strcasecmp(proto, "raw") == 0) mask = IPNET_NETSTAT_PRINT_RAW; else if (ipcom_strcasecmp(proto, "ip") == 0) mask = IPNET_NETSTAT_PRINT_IP; else if (ipcom_strcasecmp(proto, "icmp") == 0) mask = IPNET_NETSTAT_PRINT_ICMP; else if (ipcom_strcasecmp(proto, "tcp") == 0) mask = IPNET_NETSTAT_PRINT_TCP; else if (ipcom_strcasecmp(proto, "udp") == 0) mask = IPNET_NETSTAT_PRINT_UDP; #ifdef IPSCTP else if (ipcom_strcasecmp(proto, "sctp") == 0) mask = IPNET_NETSTAT_PRINT_SCTP; #endif else if (ipcom_strcasecmp(proto, "ip6") == 0) mask = IPNET_NETSTAT_PRINT_IP6; else if (ipcom_strcasecmp(proto, "icmp6") == 0) mask = IPNET_NETSTAT_PRINT_ICMP6; /* Print IP and ICMP stats */ if (IP_BIT_ISSET(mask,IPNET_NETSTAT_PRINT_IP)) { ipnet_netstat_init_stat_sig(sig, IP_IPPROTO_IP); ipcom_pipe_send(ipnet_usr_sock_get_pipe(), sig); ipcom_pipe_recv(sig->response_pipe, (void **)&sig); ip_assert(sig != IP_NULL); if (sig->d.stats.sig_errno == 0) { ipcom_printf("Ip:\n"); ipcom_printf(" %u total packets received\n", sig->d.stats.p.ip.in_receives); if (sig->d.stats.p.ip.in_hdr_errors) ipcom_printf(" %u with invalid headers\n", sig->d.stats.p.ip.in_hdr_errors); if (sig->d.stats.p.ip.in_addr_errors) ipcom_printf(" %u with invalid addresses\n", sig->d.stats.p.ip.in_addr_errors); ipcom_printf(" %u forwarded\n", sig->d.stats.p.ip.forw_datagrams); if (sig->d.stats.p.ip.in_unknown_protos) ipcom_printf(" %u with unknown protocol\n", sig->d.stats.p.ip.in_unknown_protos); ipcom_printf(" %u incoming packets discarded\n", sig->d.stats.p.ip.in_discards); ipcom_printf(" %u incoming packets delivered\n", sig->d.stats.p.ip.in_delivers); ipcom_printf(" %u requests sent out\n", sig->d.stats.p.ip.out_requests); if (sig->d.stats.p.ip.out_discards) ipcom_printf(" %u outgoing packets dropped\n", sig->d.stats.p.ip.out_discards); if (sig->d.stats.p.ip.out_no_routes) ipcom_printf(" %u dropped because of missing route\n", sig->d.stats.p.ip.out_no_routes); if (sig->d.stats.p.ip.reasm_timeout) ipcom_printf(" %u fragments dropped after timeout\n", sig->d.stats.p.ip.reasm_timeout); if (sig->d.stats.p.ip.reasm_reqds) ipcom_printf(" %u reassemblies required\n", sig->d.stats.p.ip.reasm_reqds); if (sig->d.stats.p.ip.reasm_oks) ipcom_printf(" %u packets reassembled ok\n", sig->d.stats.p.ip.reasm_oks); if (sig->d.stats.p.ip.reasm_fails) ipcom_printf(" %u packet reassembles failed\n", sig->d.stats.p.ip.reasm_fails); if (sig->d.stats.p.ip.frag_oks) ipcom_printf(" %u fragments received ok\n", sig->d.stats.p.ip.frag_oks); if (sig->d.stats.p.ip.frag_fails) ipcom_printf(" %u fragments failed\n", sig->d.stats.p.ip.frag_fails); if (sig->d.stats.p.ip.frag_creates) ipcom_printf(" %u fragments created\n", sig->d.stats.p.ip.frag_creates); } else if (sig->d.stats.sig_errno != IP_ERRNO_EPROTONOSUPPORT) goto out; } if (IP_BIT_ISSET(mask,IPNET_NETSTAT_PRINT_ICMP)) { ipnet_netstat_init_stat_sig(sig, IP_IPPROTO_ICMP); ipcom_pipe_send(ipnet_usr_sock_get_pipe(), sig); ipcom_pipe_recv(sig->response_pipe, (void **)&sig); ip_assert(sig != IP_NULL); if (sig->d.stats.sig_errno == 0) { ipcom_printf("Icmp:\n"); ipcom_printf(" %u ICMP messages received\n", sig->d.stats.p.icmp.in_msgs); ipcom_printf(" %u input ICMP message failed\n", sig->d.stats.p.icmp.in_errors); ipcom_printf(" ICMP input histogram:\n"); if (sig->d.stats.p.icmp.in_dest_unreachs) ipcom_printf(" destination unreachable: %u\n", sig->d.stats.p.icmp.in_dest_unreachs); if (sig->d.stats.p.icmp.in_time_excds) ipcom_printf(" timeout in transit: %u\n", sig->d.stats.p.icmp.in_time_excds); if (sig->d.stats.p.icmp.in_parm_probs) ipcom_printf(" wrong parameters: %u\n", sig->d.stats.p.icmp.in_parm_probs); if (sig->d.stats.p.icmp.in_src_quenchs) ipcom_printf(" source quenches: %u\n", sig->d.stats.p.icmp.in_src_quenchs); if (sig->d.stats.p.icmp.in_redirects) ipcom_printf(" redirects: %u\n", sig->d.stats.p.icmp.in_redirects); if (sig->d.stats.p.icmp.in_echos) ipcom_printf(" echo requests: %u\n", sig->d.stats.p.icmp.in_echos); if (sig->d.stats.p.icmp.in_echo_reps) ipcom_printf(" echo replies: %u\n", sig->d.stats.p.icmp.in_echo_reps); if (sig->d.stats.p.icmp.in_timestamps) ipcom_printf(" timestamp request: %u\n", sig->d.stats.p.icmp.in_timestamps); if (sig->d.stats.p.icmp.in_timestamp_reps) ipcom_printf(" timestamp reply: %u\n", sig->d.stats.p.icmp.in_timestamp_reps); if (sig->d.stats.p.icmp.in_addr_masks) ipcom_printf(" address mask request: %u\n", sig->d.stats.p.icmp.in_addr_masks); if (sig->d.stats.p.icmp.in_addr_mask_reps) ipcom_printf(" address mask replies: %u\n", sig->d.stats.p.icmp.in_addr_mask_reps); ipcom_printf(" %u ICMP messages sent\n", sig->d.stats.p.icmp.out_msgs); ipcom_printf(" %u ICMP messages failed\n", sig->d.stats.p.icmp.out_errors); ipcom_printf(" ICMP output histogram:\n"); if (sig->d.stats.p.icmp.out_dest_unreachs) ipcom_printf(" destination unreachable: %u\n", sig->d.stats.p.icmp.out_dest_unreachs); if (sig->d.stats.p.icmp.out_time_excds) ipcom_printf(" time exceeded: %u\n", sig->d.stats.p.icmp.out_time_excds); if (sig->d.stats.p.icmp.out_parm_probs) ipcom_printf(" wrong parameters: %u\n", sig->d.stats.p.icmp.out_parm_probs); if (sig->d.stats.p.icmp.out_src_quenchs) ipcom_printf(" source quench: %u\n", sig->d.stats.p.icmp.out_src_quenchs); if (sig->d.stats.p.icmp.out_redirects) ipcom_printf(" redirect: %u\n", sig->d.stats.p.icmp.out_redirects); if (sig->d.stats.p.icmp.out_echos) ipcom_printf(" echo request: %u\n", sig->d.stats.p.icmp.out_echos); if (sig->d.stats.p.icmp.out_echo_reps) ipcom_printf(" echo replies: %u\n", sig->d.stats.p.icmp.out_echo_reps); if (sig->d.stats.p.icmp.out_timestamps) ipcom_printf(" timestamp requests: %u\n", sig->d.stats.p.icmp.out_timestamps); if (sig->d.stats.p.icmp.out_timestamp_reps) ipcom_printf(" timestamp replies: %u\n", sig->d.stats.p.icmp.out_timestamp_reps); if (sig->d.stats.p.icmp.out_addr_masks) ipcom_printf(" address mask requests: %u\n", sig->d.stats.p.icmp.out_addr_masks); if (sig->d.stats.p.icmp.out_addr_mask_reps) ipcom_printf(" address mask replies: %u\n", sig->d.stats.p.icmp.out_addr_mask_reps); } else if (sig->d.stats.sig_errno != IP_ERRNO_EPROTONOSUPPORT) goto out; } /* Print TCP stats */ if (IP_BIT_ISSET(mask,IPNET_NETSTAT_PRINT_TCP)) { ipnet_netstat_init_stat_sig(sig, IP_IPPROTO_TCP); ipcom_pipe_send(ipnet_usr_sock_get_pipe(), sig); ipcom_pipe_recv(sig->response_pipe, (void **)&sig); ip_assert(sig != IP_NULL); if (sig->d.stats.sig_errno == 0) { ipcom_printf("Tcp:\n"); ipcom_printf(" %u active connection openings\n", sig->d.stats.p.tcp.active_opens); ipcom_printf(" %u passive connection openings\n", sig->d.stats.p.tcp.passive_opens); ipcom_printf(" %u failed connection attempts\n", sig->d.stats.p.tcp.attempt_fails); ipcom_printf(" %u connection resets received\n", sig->d.stats.p.tcp.estab_resets); ipcom_printf(" %u connections established\n", sig->d.stats.p.tcp.curr_estab); ipcom_printf(" %u segments received\n", sig->d.stats.p.tcp.in_segs); ipcom_printf(" %u segments send out\n", sig->d.stats.p.tcp.out_segs); ipcom_printf(" %u segments retransmitted\n", sig->d.stats.p.tcp.retrans_segs); ipcom_printf(" %u bad segments received\n", sig->d.stats.p.tcp.in_errs); ipcom_printf(" %u resets sent\n", sig->d.stats.p.tcp.out_rsts); } else if (sig->d.stats.sig_errno != IP_ERRNO_EPROTONOSUPPORT) goto out; } /* Print UDP stats */ if (IP_BIT_ISSET(mask,IPNET_NETSTAT_PRINT_UDP)) { ipnet_netstat_init_stat_sig(sig, IP_IPPROTO_UDP); ipcom_pipe_send(ipnet_usr_sock_get_pipe(), sig); ipcom_pipe_recv(sig->response_pipe, (void **)&sig); ip_assert(sig != IP_NULL); if (sig->d.stats.sig_errno == 0) { ipcom_printf("Udp:\n"); ipcom_printf(" %u packets received\n", sig->d.stats.p.udp.in_datagrams); ipcom_printf(" %u packets to unknown port received\n", sig->d.stats.p.udp.no_ports); ipcom_printf(" %u packet receive errors\n", sig->d.stats.p.udp.in_errors); ipcom_printf(" %u packets sent\n", sig->d.stats.p.udp.out_datagrams); } else if (sig->d.stats.sig_errno != IP_ERRNO_EPROTONOSUPPORT) goto out; } if (IP_BIT_ISSET(mask,IPNET_NETSTAT_PRINT_IP6)) { ipnet_netstat_init_stat_sig(sig, IP_IPPROTO_IPV6); ipcom_pipe_send(ipnet_usr_sock_get_pipe(), sig); ipcom_pipe_recv(sig->response_pipe, (void **)&sig); ip_assert(sig != IP_NULL); if (sig->d.stats.sig_errno == 0) { ipcom_printf("Ip6:\n"); ipcom_printf(" %u total packets received\n", sig->d.stats.p.ip6.ip6_input); ipcom_printf(" %u packets received with error\n", sig->d.stats.p.ip6.ip6_input_err); ipcom_printf(" %u with header Truncation\n", sig->d.stats.p.ip6.ip6_input_hdr_trunc); ipcom_printf(" %u with invalid data length \n", sig->d.stats.p.ip6.ip6_input_inval_len); ipcom_printf(" %u with invalid extend header\n", sig->d.stats.p.ip6.ip6_input_inval_exthdr); ipcom_printf(" %u packets received not to me\n", sig->d.stats.p.ip6.ip6_input_not_to_me); ipcom_printf(" %u with data size too big\n", sig->d.stats.p.ip6.ip6_input_too_big); ipcom_printf(" %u packets received with time exceeded\n", sig->d.stats.p.ip6.ip6_input_time_exceeded); ipcom_printf(" %u with data size too short\n", sig->d.stats.p.ip6.ip6_input_too_short); ipcom_printf(" %u with tcp multicast\n", sig->d.stats.p.ip6.ip6_input_tcp_multicast); ipcom_printf(" %u with protocol error\n", sig->d.stats.p.ip6.ip6_input_prot_err); ipcom_printf(" %u with header no next\n", sig->d.stats.p.ip6.ip6_input_hdr_no_next); ipcom_printf(" %u packets received for raw\n", sig->d.stats.p.ip6.ip6_input_raw); ipcom_printf(" %u total packets sent out\n", sig->d.stats.p.ip6.ip6_output); ipcom_printf(" %u packets sent with error\n", sig->d.stats.p.ip6.ip6_output_err); ipcom_printf(" %u packets sent with black hole\n", sig->d.stats.p.ip6.ip6_output_blackhole); ipcom_printf(" %u packets sent with header space\n", sig->d.stats.p.ip6.ip6_output_hdr_space); ipcom_printf(" %u packets sent with no route\n", sig->d.stats.p.ip6.ip6_output_noroute); ipcom_printf(" %u packets sent with no memory\n", sig->d.stats.p.ip6.ip6_output_nomem); ipcom_printf(" %u packets sent with no enough buffer\n", sig->d.stats.p.ip6.ip6_output_enobufs); ipcom_printf(" %u packets sent with error probe\n", sig->d.stats.p.ip6.ip6_output_err_probe); ipcom_printf(" %u packets sent with link error\n", sig->d.stats.p.ip6.ip6_output_link_err); } else if (sig->d.stats.sig_errno != IP_ERRNO_EPROTONOSUPPORT) goto out; } if (IP_BIT_ISSET(mask,IPNET_NETSTAT_PRINT_ICMP6)) { ipnet_netstat_init_stat_sig(sig, IP_IPPROTO_ICMPV6); ipcom_pipe_send(ipnet_usr_sock_get_pipe(), sig); ipcom_pipe_recv(sig->response_pipe, (void **)&sig); ip_assert(sig != IP_NULL); if (sig->d.stats.sig_errno == 0) { ipcom_printf("icmp6\n"); ipcom_printf(" %u packets received\n", sig->d.stats.p.icmp6.icmp6_input); ipcom_printf(" %u packets received with error\n", sig->d.stats.p.icmp6.icmp6_input_err); ipcom_printf(" %u packets received with bad checksums\n", sig->d.stats.p.icmp6.icmp6_input_badchksum); ipcom_printf(" %u packets received with no enough memory\n", sig->d.stats.p.icmp6.icmp6_input_nomem); ipcom_printf(" %u no enough memory to send\n", sig->d.stats.p.icmp6.icmp6_send_nomem); } else if (sig->d.stats.sig_errno != IP_ERRNO_EPROTONOSUPPORT) goto out; } #if defined(IPSCTP) && defined(IPSCTP_MIB) /* Print SCTP stats */ if (IP_BIT_ISSET(mask,IPNET_NETSTAT_PRINT_SCTP)) { ipnet_netstat_init_stat_sig(sig, IP_IPPROTO_SCTP); ipcom_pipe_send(ipnet_usr_sock_get_pipe(), sig); ipcom_pipe_recv(sig->response_pipe, (void **)&sig); ip_assert(sig != IP_NULL); if (sig->d.stats.sig_errno == 0) { ipcom_printf("Sctp:\n"); ipcom_printf(" %u current established associations\n", sig->d.stats.p.sctp.sctp_Curr_Estab); ipcom_printf(" %u active established associations\n", sig->d.stats.p.sctp.sctp_Active_Estabs); ipcom_printf(" %u passive established associations\n", sig->d.stats.p.sctp.sctp_Passive_Estabs); ipcom_printf(" %u aborted associations\n", sig->d.stats.p.sctp.sctp_Aborteds); ipcom_printf(" %u shutdown associations\n", sig->d.stats.p.sctp.sctp_Shutdowns); ipcom_printf(" %u out of the blue packets received\n", sig->d.stats.p.sctp.sctp_OutOfBlues); ipcom_printf(" %u invalid checksum packets received\n", sig->d.stats.p.sctp.sctp_Checksum_Errors); ipcom_printf(" %llu control chunks sent\n", sig->d.stats.p.sctp.sctp_Out_Ctrl_Chunks); ipcom_printf(" %llu ordered data chunks sent\n", sig->d.stats.p.sctp.sctp_Out_Order_Chunks); ipcom_printf(" %llu unordered data chunks sent\n", sig->d.stats.p.sctp.sctp_Out_Unorder_Chunks); ipcom_printf(" %llu control chunks received\n", sig->d.stats.p.sctp.sctp_In_Ctrl_Chunks); ipcom_printf(" %llu ordered data chunks received\n", sig->d.stats.p.sctp.sctp_In_Order_Chunks); ipcom_printf(" %llu unordered data chunks received\n", sig->d.stats.p.sctp.sctp_In_Unorder_Chunks); ipcom_printf(" %llu fragmented user messages\n", sig->d.stats.p.sctp.sctp_Frag_UsrMsgs); ipcom_printf(" %llu reassembled user messages\n", sig->d.stats.p.sctp.sctp_Reasm_UsrMsgs); ipcom_printf(" %llu packets sent\n", sig->d.stats.p.sctp.sctp_Out_SCTP_Packs); ipcom_printf(" %llu packets received\n", sig->d.stats.p.sctp.sctp_In_SCTP_Packs); ipcom_printf(" %u discontinuity time\n", sig->d.stats.p.sctp.sctp_Discontinuity_Time); } else if (sig->d.stats.sig_errno != IP_ERRNO_EPROTONOSUPPORT) goto out; } #endif out: if (sig->d.stats.sig_errno && mask) { ipcom_printf("%s\n", ipcom_strerror(sig->d.stats.sig_errno)); if (sig->d.stats.sig_errno == IP_ERRNO_ENOENT) ipcom_printf("Enable MIB-2 support to collect networking statistics.\n"); } ipcom_free(sig); } #endif /* !IP_PORT_LAS && IPCOM_USE_MIB2 */ /* *=========================================================================== * ipnet_netstat_print_usage *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC void ipnet_netstat_print_usage(void) { ipcom_printf(IP_LF "NAME"IP_LF " netstat - show network status"IP_LF IP_LF "SYNOPSIS"IP_LF " netstat -h"IP_LF " netstat [-an] [-f address_family] [-V vr] [-p protocol]"IP_LF " netstat -r [-nl] [-f address_family] [-V vr]"IP_LF " netstat -s [raw|ip|icmp|sctp|udp|tcp|ip6|icmp6]"IP_LF IP_LF "DESCRIPTION"IP_LF " The netstat command symbolically displays the contents of various"IP_LF " network-related data structures."IP_LF IP_LF " -a Show the state of all sockets; normally sockets used by server"IP_LF " processes are not shown."IP_LF " -f "IP_LF " Limit statistics or address control block reports to those of the"IP_LF " specified address family. The following address families are"IP_LF " recognized: inet, for IP_AF_INET; inet6, for IP_AF_INET6."IP_LF " -h Help, this usage menu"IP_LF " -l Do not show routes where the LLINFO flag is set."IP_LF " -n Show network addresses as numbers. Default is to lookup symbolic"IP_LF " names for the addresses."IP_LF " -p "IP_LF " Show statistics about protocol, which is either a well-known name"IP_LF " for a protocol or an alias for it."IP_LF " -r Show the routing tables"IP_LF " Routes have associated flags. The mapping between letters and flags is:"IP_LF " 1 IPNET_RTF_PROTO1 Protocol specific routing flag #1"IP_LF " 2 IPNET_RTF_PROTO1 Protocol specific routing flag #2"IP_LF " B IPNET_RTF_BLACKHOLE Just discard packets (during updates)"IP_LF " C IPNET_RTF_CLONING Generate new routes on use"IP_LF " D IPNET_RTF_DYNAMIC Created dynamically"IP_LF " d IPNET_RTF_DONE Message confirmed"IP_LF " G IPNET_RTF_GATEWAY Destination requires forwarding by intermediary"IP_LF " H IPNET_RTF_HOST Host entry (net otherwise)"IP_LF " L IPNET_RTF_LLINFO Generated by IPv4 ARP or IPv6 NDP"IP_LF " M IPNET_RTF_MASK Subnet mask present"IP_LF " m IPNET_RTF_MODIFIED Modified dynamically"IP_LF " P IPNET_RTF_PREF Add route first, no ECMP"IP_LF " R IPNET_RTF_REJECT Host or net unreachable"IP_LF " S IPNET_RTF_STATIC Manually added"IP_LF " T IPNET_RTF_TUNNELEND The gateway field specifies the tunnel endpoint address"IP_LF " U IPNET_RTF_UP Route usable"IP_LF " X IPNET_RTF_XRESOLVE External daemon translates proto to link address"IP_LF " + IPNET_RTF_MBINDING This route is part of multiple binding"IP_LF " - IPNET_RTF_SKIP Treat this route as a routing lookup failure"IP_LF " -P Show which process that owns the socket."IP_LF " -T Specify route table ID. %d if not specified."IP_LF, IPCOM_ROUTE_TABLE_DEFAULT); ipcom_printf(" -V Specify virtual router index. 0 if not specified."IP_LF " -s Display networking statistics, ip6 and icmp6 are valid under debug mode only."IP_LF IP_LF); } /* **************************************************************************** * 10 PUBLIC FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipnet_cmd_netstat *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC int ipnet_cmd_netstat(int argc, char **argv) { int i, c; int proto = -1; int af = -1; #if !defined(IP_PORT_LAS) && defined(IPCOM_USE_MIB2) const char *proto_name = IP_NULL; const char *stats_name = IP_NULL; #endif #if IPCOM_VR_MAX > 1 int vr = ipcom_proc_vr_get(); int vr_new = vr; #else int vr_new = 0; #endif int table = IPCOM_ROUTE_TABLE_DEFAULT; Ip_bool show_unconnected = IP_FALSE; Ip_bool no_dns = IP_FALSE; Ip_bool show_routes = IP_FALSE; Ip_bool show_llinfo = IP_TRUE; Ip_bool show_processes = IP_FALSE; Ip_bool show_stats = IP_FALSE; Ipcom_getopt opt; ipcom_getopt_clear_r(&opt); while ((c = ipcom_getopt_r(argc, argv, "?hHaf:p:PT:nrV:ls", &opt)) != -1) { switch (c) { case '?': case 'h': case 'H': goto errout; case 'a': show_unconnected = IP_TRUE; break; case 'f': for (i = 0; af_map[i].key != -1; i++) if (ipcom_strcasecmp(opt.optarg, af_map[i].str) == 0) { af = af_map[i].key; break; } if (af_map[i].key == -1) goto errout; break; case 'p': for (i = 0; proto_map[i].key != -1; i++) if (ipcom_strcasecmp(opt.optarg, proto_map[i].str) == 0) { proto = proto_map[i].key; #if !defined(IP_PORT_LAS) && defined(IPCOM_USE_MIB2) proto_name = opt.optarg; #endif break; } if (proto_map[i].key == -1) goto errout; break; case 'P': show_processes = IP_TRUE; break; case 'T': table = ipcom_atoi(opt.optarg); break; case 'r': show_routes = IP_TRUE; break; case 'n': no_dns = IP_TRUE; break; #if IPCOM_VR_MAX > 1 case 'V': vr_new = ipcom_atoi(opt.optarg); break; #endif case 'l': show_llinfo = IP_FALSE; break; case 's': show_stats = IP_TRUE; #if !defined(IP_PORT_LAS) && defined(IPCOM_USE_MIB2) /* Is there a next argument, and is it a non-switch? */ if (argv[opt.optind] != IP_NULL && argv[opt.optind][0] != '-') stats_name = argv[opt.optind]; #endif break; default: break; } } if (show_stats) { #if !defined(IP_PORT_LAS) && defined(IPCOM_USE_MIB2) ipnet_netstat_print_stats(stats_name ? stats_name : proto_name); #else ipcom_printf("Enable MIB-2 support to collect networking statistics.\n"); #endif return 0; } #if IPCOM_VR_MAX > 1 if (vr != vr_new) ipcom_proc_vr_set(vr_new); #endif #ifdef IP_PORT_LAS ipnet_netstat_print_routes(af == -1 ? 0 : af, table, no_dns, show_llinfo); #else if (show_routes) ipnet_netstat_print_routes(af == -1 ? 0 : af, (Ip_u32)table, no_dns, show_llinfo); else { struct Ipnet_tag_sock_data *tsd; tsd = ipcom_calloc((Ip_size_t) (ipnet_conf_max_sockets + 1), sizeof(struct Ipnet_tag_sock_data)); if (tsd == IP_NULL) ipcom_printf("Out of memory"IP_LF); else ipnet_netstat_print_entries(af, vr_new, proto, show_unconnected, no_dns, show_processes, tsd); ipcom_free(tsd); } #endif #if IPCOM_VR_MAX > 1 if (vr != vr_new) ipcom_proc_vr_set(vr); #endif ipcom_printf("\n"); return 0; errout: ipnet_netstat_print_usage(); return 1; } /* **************************************************************************** * END OF FILE **************************************************************************** */