/* tcpstat.c Created: June 1995 by Philip Homburg */ #define _MINIX_SOURCE #define _POSIX_C_SOURCE 2 #include #undef printf #include #include #include #include #include #ifndef __minix_vmd #include #endif #include #include #include #include #include #include #include #include #include #include #include char *prog_name; tcp_conn_t tcp_conn_table[TCP_CONN_NR]; char values[2 * sizeof(tcp_conn_table) + 1]; int inclListen, numerical, verbose; void print_conn(int i, clock_t now); void usage(void); int main(int argc, char*argv[]) { char *tcp_device; int fd, i; struct svrqueryparam qpar; char *pval; struct timeval uptime; clock_t now; int fl; int a_flag, n_flag, v_flag; (prog_name=strrchr(argv[0], '/')) ? prog_name++ : (prog_name=argv[0]); a_flag= 0; n_flag= 0; v_flag= 0; while ((fl= getopt(argc, argv, "?anv")) != -1) { switch(fl) { case '?': usage(); case 'a': a_flag= 1; break; case 'n': n_flag= 1; break; case 'v': v_flag= 1; break; default: fprintf(stderr, "%s: getopt failed: '%c'\n", prog_name, fl); exit(1); } } inclListen= !!a_flag; numerical= !!n_flag; verbose= !!v_flag; tcp_device= TCP_DEVICE; if ((fd= open(tcp_device, O_RDWR)) == -1) { fprintf(stderr, "%s: unable to open '%s': %s\n", prog_name, tcp_device, strerror(errno)); exit(1); } qpar.param = "tcp_conn_table"; qpar.psize = strlen(qpar.param); qpar.value = values; qpar.vsize = sizeof(values); if (ioctl(fd, NWIOQUERYPARAM, &qpar) == -1) { fprintf(stderr, "%s: queryparam failed: %s\n", prog_name, strerror(errno)); exit(1); } pval= values; if (paramvalue(&pval, tcp_conn_table, sizeof(tcp_conn_table)) != sizeof(tcp_conn_table)) { fprintf(stderr, "%s: unable to decode the results from queryparam\n", prog_name); exit(1); } #ifdef __minix_vmd /* Get the uptime in clock ticks. */ if (sysutime(UTIME_UPTIME, &uptime) == -1) { fprintf(stderr, "%s: sysutime failed: %s\n", prog_name, strerror(errno)); exit(1); } now= uptime.tv_sec * HZ + (uptime.tv_usec*HZ/1000000); #else /* Minix 3 */ now= times(NULL); #endif for (i= 0; itc_flags & TCF_INUSE)) return; if (tcp_conn->tc_state == TCS_LISTEN && !inclListen) return; if (tcp_conn->tc_state == TCS_CLOSED && tcp_conn->tc_fd == NULL && tcp_conn->tc_senddis < now) { return; } printf("%3d", i); a1= tcp_conn->tc_locaddr; p1= tcp_conn->tc_locport; a2= tcp_conn->tc_remaddr; p2= tcp_conn->tc_remport; if (a1 == 0) addr_str= "*"; else if (!numerical && (hostent= gethostbyaddr((char *)&a1, sizeof(a1), AF_INET)) != NULL) { addr_str= hostent->h_name; } else addr_str= inet_ntoa(a1); printf(" %s:", addr_str); if (p1 == 0) printf("*"); else if ((servent= getservbyport(p1, "tcp")) != NULL) { printf("%s", servent->s_name); } else printf("%u", ntohs(p1)); if (tcp_conn->tc_orglisten) printf(" <- "); else printf(" -> "); if (a2 == 0) addr_str= "*"; else if (!numerical && (hostent= gethostbyaddr((char *)&a2, sizeof(a2), AF_INET)) != NULL) { addr_str= hostent->h_name; } else addr_str= inet_ntoa(a2); printf("%s:", addr_str); if (p2 == 0) printf("*"); else if ((servent= getservbyport(p2, "tcp")) != NULL) { printf("%s", servent->s_name); } else printf("%u", ntohs(p2)); printf(" "); no_verbose= 0; switch(tcp_conn->tc_state) { case TCS_CLOSED: printf("CLOSED"); if (tcp_conn->tc_senddis >= now) { printf("(time wait %ld s)", (tcp_conn->tc_senddis-now)/HZ); } no_verbose= 1; break; case TCS_LISTEN: printf("LISTEN"); no_verbose= 1; break; case TCS_SYN_RECEIVED: printf("SYN_RECEIVED"); break; case TCS_SYN_SENT: printf("SYN_SENT"); break; case TCS_ESTABLISHED: printf("ESTABLISHED"); break; case TCS_CLOSING: printf("CLOSING"); break; default: printf("state(%d)", tcp_conn->tc_state); break; } if (tcp_conn->tc_flags & TCF_FIN_RECV) printf(" F<"); if (tcp_conn->tc_flags & TCF_FIN_SENT) { printf(" F>"); if (tcp_conn->tc_SND_UNA == tcp_conn->tc_SND_NXT) printf("+"); } if (tcp_conn->tc_state != TCS_CLOSED && tcp_conn->tc_state != TCS_LISTEN) { printf("\n\t"); printf("RQ: %lu, SQ: %lu, RWnd: %u, SWnd: %lu, SWThresh: %lu", tcp_conn->tc_RCV_NXT - tcp_conn->tc_RCV_LO, tcp_conn->tc_SND_NXT - tcp_conn->tc_SND_UNA, tcp_conn->tc_rcv_wnd, tcp_conn->tc_snd_cwnd - tcp_conn->tc_SND_UNA, tcp_conn->tc_snd_cthresh); } printf("\n"); if (!verbose || no_verbose) return; rtt= tcp_conn->tc_rtt; artt= tcp_conn->tc_artt; drtt= tcp_conn->tc_drtt; printf("\tmss %u, mtu %u%s, rtt %.3f (%.3f+%d*%.3f) s\n", tcp_conn->tc_max_mtu-IP_TCP_MIN_HDR_SIZE, tcp_conn->tc_mtu, (tcp_conn->tc_flags & TCF_PMTU) ? "" : " (no PMTU)", rtt/(HZ+0.0), artt/(HZ+0.0)/TCP_RTT_SCALE, TCP_DRTT_MULT, drtt/(HZ+0.0)/TCP_RTT_SCALE); flags= tcp_conn->tc_flags; printf("\tflags:"); if (!flags) printf(" TCF_EMPTY"); if (flags & TCF_INUSE) flags &= ~TCF_INUSE; if (flags & TCF_FIN_RECV) { printf(" TCF_FIN_RECV"); flags &= ~TCF_FIN_RECV; } if (flags & TCF_RCV_PUSH) { printf(" TCF_RCV_PUSH"); flags &= ~TCF_RCV_PUSH; } if (flags & TCF_MORE2WRITE) { printf(" TCF_MORE2WRITE"); flags &= ~TCF_MORE2WRITE; } if (flags & TCF_SEND_ACK) { printf(" TCF_SEND_ACK"); flags &= ~TCF_SEND_ACK; } if (flags & TCF_FIN_SENT) { printf(" TCF_FIN_SENT"); flags &= ~TCF_FIN_SENT; } if (flags & TCF_BSD_URG) { printf(" TCF_BSD_URG"); flags &= ~TCF_BSD_URG; } if (flags & TCF_NO_PUSH) { printf(" TCF_NO_PUSH"); flags &= ~TCF_NO_PUSH; } if (flags & TCF_PUSH_NOW) { printf(" TCF_PUSH_NOW"); flags &= ~TCF_PUSH_NOW; } if (flags & TCF_PMTU) flags &= ~TCF_PMTU; if (flags) printf(" 0x%x", flags); printf("\n"); printf("\ttimer: ref %d, time %f, active %d\n", tcp_conn->tc_transmit_timer.tim_ref, (0.0+tcp_conn->tc_transmit_timer.tim_time-now)/HZ, tcp_conn->tc_transmit_timer.tim_active); } void usage(void) { fprintf(stderr, "Usage: %s [-anv]\n", prog_name); exit(1); } /* * $PchId: tcpstat.c,v 1.8 2005/01/30 01:04:38 philip Exp $ */