/* FUNCTION: netmain_netstat() * * Display various status tables * * PARAM1: CLI_CTX CLI context * * RETURNS: int 0 if successful, otherwise error code * * netstat -a {-c [-p <protocol>]} -m -q {-s [-p <protocol>]} * * Example invocations: * * ##dump TCP/IPv4, TCP/IPv6, UDP/IPv4, or UDP/IPv6 sockets * net netstat -c -p {tcp | tcp6 | udp | udp6} * * ##dump all sockets (TCP and UDP, IPv4 and IPv6) * net netstat -c * * ##dump statistics for a specific protocol * net netstat -s -p {icmp | icmp6 [-i <interface>] | ip | ip6 | tcp | udp} * * ##dump statistics for all protocols * net netstat -s * * For the ICMPv6 protocol, the user can also enter an identifier to * specify the interface for which ICMPv6 statistics are desired. The * existing code does not provide any mechanism to dump ICMPv6 statistics * for all interfaces via one CLI command. */ STATIC int netmain_netstat(CLI_CTX ctx) { GIO *gio = ctx->gio; if (!CLI_HELP(ctx)) { bool_t all = ((CLI_COUNT(ctx) == 0) ? TRUE : FALSE); /* (datagram and stream) sockets */ if (all || CLI_DEFINED(ctx, 'c')) sock_info(ctx); #ifndef MINI_IP /* mbuf status */ if (all || CLI_DEFINED(ctx, 'm')) mbuf_stat(gio); #endif /* not MINI_IP */ /* queue status */ if (all || CLI_DEFINED(ctx, 'q')) dumpqueues(gio); #ifdef NET_STATS /* (protocol) statistics */ if (all || CLI_DEFINED(ctx, 's')) prot_stat(ctx); #endif } return (0); }
int client_do_pollin(int sockfd, struct link *ln) { if (sockfd == ln->local_sockfd) { if (ln->state & SERVER_PENDING) { sock_debug(sockfd, "%s: server pending", __func__); goto out; } else if (client_do_local_read(sockfd, ln) == -1) { goto clean; } } else if (sockfd == ln->server_sockfd) { if (ln->state & LOCAL_PENDING) { sock_debug(sockfd, "%s: local pending", __func__); goto out; } else if (client_do_server_read(sockfd, ln) == -1) { goto clean; } } out: return 0; clean: sock_info(sockfd, "%s close", __func__); destroy_link(sockfd); return -1; }
int poll_del(int sockfd) { if (sockfd < 0 || sockfd >= nfds) { sock_err(sockfd, "%s: illegal sockfd(%d)", __func__, sockfd); return -1; } clients[sockfd].fd = -1; sock_info(sockfd, "%s: deleted from poll", __func__); return 0; }
int poll_rm(int sockfd, short events) { char events_str[42] = {'\0'}; if (sockfd < 0 || sockfd >= nfds) { sock_err(sockfd, "%s: illegal sockfd(%d)", __func__, sockfd); return -1; } clients[sockfd].events &= ~events; poll_events_string(events, events_str); sock_info(sockfd, "%s: %s", __func__, events_str); return 0; }
int poll_add(int sockfd, short events) { char events_str[42] = {'\0'}; if (sockfd < 0 || sockfd >= nfds) { sock_err(sockfd, "%s: illegal sockfd(%d)", __func__, sockfd); return -1; } if (clients[sockfd].fd != sockfd) { sock_warn(sockfd, "%s: sockfd(%d) not in poll", __func__, sockfd); return -1; } clients[sockfd].events |= events; poll_events_string(events, events_str); sock_info(sockfd, "%s: %s", __func__, events_str); return 0; }
int get_peerinfo (int sockfd, char* addr, size_t alen, int* port) { return sock_info (e_peer, sockfd, addr, alen, port); }
int get_sockinfo (int sockfd, char* addr, size_t alen, int* port) { return sock_info (e_host, sockfd, addr, alen, port); }
int client_do_pollout(int sockfd, struct link *ln) { int ret, optval; int optlen = sizeof(optval); /* write to local */ if (sockfd == ln->local_sockfd) { if (ln->state & LOCAL_SEND_PENDING) { ret = do_send(sockfd, ln, "text", 0); if (ret == -2) { goto clean; } else if (ret == -1) { goto out; } else { ln->state &= ~LOCAL_SEND_PENDING; } /* update socks5 state */ if (!(ln->state & SOCKS5_AUTH_REPLY_SENT)) ln->state &= SOCKS5_AUTH_REPLY_SENT; else if (!(ln->state & SOCKS5_CMD_REPLY_SENT)) ln->state &= SOCKS5_CMD_REPLY_SENT; goto out; } else { poll_rm(sockfd, POLLOUT); } } else if (sockfd == ln->server_sockfd) { /* pending connect finished */ if (!(ln->state & SERVER)) { if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, (void *)&optlen) == -1) { sock_warn(sockfd, "%s: getsockopt() %s", __func__, strerror(errno)); goto clean; } if (optval == 0) { sock_info(sockfd, "%s: pending connect() finished", __func__); ln->time = time(NULL); ln->state |= SERVER; } else { sock_warn(sockfd, "%s: pending connect() failed", __func__); goto clean; } } if (ln->state & SERVER_SEND_PENDING) { /* write to server */ ret = do_send(sockfd, ln, "cipher", 0); if (ret == -2) { goto clean; } else if (ret == -1) { goto out; } else { ln->state &= ~SERVER_SEND_PENDING; if (!(ln->state & SS_TCP_HEADER_SENT)) ln->state |= SS_TCP_HEADER_SENT; goto out; } } else { poll_rm(sockfd, POLLOUT); } } out: return 0; clean: sock_info(sockfd, "%s: close", __func__); destroy_link(sockfd); return -1; }