source: trunk/minix/commands/simple/tcpstat.c@ 9

Last change on this file since 9 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

File size: 6.6 KB
Line 
1/*
2tcpstat.c
3
4Created: June 1995 by Philip Homburg <philip@f-mnx.phicoh.com>
5*/
6
7#define _MINIX_SOURCE
8#define _POSIX_C_SOURCE 2
9
10#include <inet/inet.h>
11#undef printf
12
13#include <fcntl.h>
14#include <stdio.h>
15#include <time.h>
16#include <unistd.h>
17#include <sys/svrctl.h>
18#ifndef __minix_vmd
19#include <sys/times.h>
20#endif
21#include <net/netlib.h>
22#include <net/gen/inet.h>
23#include <net/gen/netdb.h>
24#include <net/gen/socket.h>
25#include <minix/queryparam.h>
26
27#include <inet/generic/buf.h>
28#include <inet/generic/clock.h>
29#include <inet/generic/event.h>
30#include <inet/generic/type.h>
31#include <inet/generic/tcp.h>
32#include <inet/generic/tcp_int.h>
33
34char *prog_name;
35tcp_conn_t tcp_conn_table[TCP_CONN_NR];
36char values[2 * sizeof(tcp_conn_table) + 1];
37int inclListen, numerical, verbose;
38
39void print_conn(int i, clock_t now);
40void usage(void);
41
42int main(int argc, char*argv[])
43{
44 char *tcp_device;
45 int fd, i;
46 struct svrqueryparam qpar;
47 char *pval;
48 struct timeval uptime;
49 clock_t now;
50 int fl;
51 int a_flag, n_flag, v_flag;
52
53 (prog_name=strrchr(argv[0], '/')) ? prog_name++ : (prog_name=argv[0]);
54
55 a_flag= 0;
56 n_flag= 0;
57 v_flag= 0;
58 while ((fl= getopt(argc, argv, "?anv")) != -1)
59 {
60 switch(fl)
61 {
62 case '?':
63 usage();
64 case 'a':
65 a_flag= 1;
66 break;
67 case 'n':
68 n_flag= 1;
69 break;
70 case 'v':
71 v_flag= 1;
72 break;
73 default:
74 fprintf(stderr, "%s: getopt failed: '%c'\n",
75 prog_name, fl);
76 exit(1);
77 }
78 }
79 inclListen= !!a_flag;
80 numerical= !!n_flag;
81 verbose= !!v_flag;
82
83 tcp_device= TCP_DEVICE;
84 if ((fd= open(tcp_device, O_RDWR)) == -1)
85 {
86 fprintf(stderr, "%s: unable to open '%s': %s\n", prog_name,
87 tcp_device, strerror(errno));
88 exit(1);
89 }
90
91 qpar.param = "tcp_conn_table";
92 qpar.psize = strlen(qpar.param);
93 qpar.value = values;
94 qpar.vsize = sizeof(values);
95 if (ioctl(fd, NWIOQUERYPARAM, &qpar) == -1)
96 {
97 fprintf(stderr, "%s: queryparam failed: %s\n", prog_name,
98 strerror(errno));
99 exit(1);
100 }
101 pval= values;
102 if (paramvalue(&pval, tcp_conn_table, sizeof(tcp_conn_table)) !=
103 sizeof(tcp_conn_table))
104 {
105 fprintf(stderr,
106 "%s: unable to decode the results from queryparam\n",
107 prog_name);
108 exit(1);
109 }
110
111#ifdef __minix_vmd
112 /* Get the uptime in clock ticks. */
113 if (sysutime(UTIME_UPTIME, &uptime) == -1)
114 {
115 fprintf(stderr, "%s: sysutime failed: %s\n", prog_name,
116 strerror(errno));
117 exit(1);
118 }
119 now= uptime.tv_sec * HZ + (uptime.tv_usec*HZ/1000000);
120#else /* Minix 3 */
121 now= times(NULL);
122#endif
123
124 for (i= 0; i<TCP_CONN_NR; i++)
125 print_conn(i, now);
126 exit(0);
127}
128
129void print_conn(int i, clock_t now)
130{
131 tcp_conn_t *tcp_conn;
132 char *addr_str;
133 struct hostent *hostent;
134 struct servent *servent;
135 ipaddr_t a1, a2;
136 tcpport_t p1, p2;
137 unsigned flags;
138 int no_verbose;
139 clock_t rtt, artt, drtt;
140
141 tcp_conn= &tcp_conn_table[i];
142 if (!(tcp_conn->tc_flags & TCF_INUSE))
143 return;
144 if (tcp_conn->tc_state == TCS_LISTEN && !inclListen)
145 return;
146 if (tcp_conn->tc_state == TCS_CLOSED && tcp_conn->tc_fd == NULL &&
147 tcp_conn->tc_senddis < now)
148 {
149 return;
150 }
151
152 printf("%3d", i);
153
154 a1= tcp_conn->tc_locaddr;
155 p1= tcp_conn->tc_locport;
156 a2= tcp_conn->tc_remaddr;
157 p2= tcp_conn->tc_remport;
158
159 if (a1 == 0)
160 addr_str= "*";
161 else if (!numerical &&
162 (hostent= gethostbyaddr((char *)&a1,
163 sizeof(a1), AF_INET)) != NULL)
164 {
165 addr_str= hostent->h_name;
166 }
167 else
168 addr_str= inet_ntoa(a1);
169 printf(" %s:", addr_str);
170
171 if (p1 == 0)
172 printf("*");
173 else if ((servent= getservbyport(p1, "tcp")) != NULL)
174 {
175 printf("%s", servent->s_name);
176 }
177 else
178 printf("%u", ntohs(p1));
179
180 if (tcp_conn->tc_orglisten)
181 printf(" <- ");
182 else
183 printf(" -> ");
184
185 if (a2 == 0)
186 addr_str= "*";
187 else if (!numerical &&
188 (hostent= gethostbyaddr((char *)&a2,
189 sizeof(a2), AF_INET)) != NULL)
190 {
191 addr_str= hostent->h_name;
192 }
193 else
194 addr_str= inet_ntoa(a2);
195 printf("%s:", addr_str);
196
197 if (p2 == 0)
198 printf("*");
199 else if ((servent= getservbyport(p2, "tcp")) !=
200 NULL)
201 {
202 printf("%s", servent->s_name);
203 }
204 else
205 printf("%u", ntohs(p2));
206
207 printf(" ");
208 no_verbose= 0;
209 switch(tcp_conn->tc_state)
210 {
211 case TCS_CLOSED: printf("CLOSED");
212 if (tcp_conn->tc_senddis >= now)
213 {
214 printf("(time wait %ld s)",
215 (tcp_conn->tc_senddis-now)/HZ);
216 }
217 no_verbose= 1;
218 break;
219 case TCS_LISTEN: printf("LISTEN"); no_verbose= 1; break;
220 case TCS_SYN_RECEIVED: printf("SYN_RECEIVED"); break;
221 case TCS_SYN_SENT: printf("SYN_SENT"); break;
222 case TCS_ESTABLISHED: printf("ESTABLISHED"); break;
223 case TCS_CLOSING: printf("CLOSING"); break;
224 default: printf("state(%d)", tcp_conn->tc_state);
225 break;
226 }
227
228 if (tcp_conn->tc_flags & TCF_FIN_RECV)
229 printf(" F<");
230 if (tcp_conn->tc_flags & TCF_FIN_SENT)
231 {
232 printf(" F>");
233 if (tcp_conn->tc_SND_UNA == tcp_conn->tc_SND_NXT)
234 printf("+");
235 }
236 if (tcp_conn->tc_state != TCS_CLOSED &&
237 tcp_conn->tc_state != TCS_LISTEN)
238 {
239 printf("\n\t");
240 printf("RQ: %lu, SQ: %lu, RWnd: %u, SWnd: %lu, SWThresh: %lu",
241 tcp_conn->tc_RCV_NXT - tcp_conn->tc_RCV_LO,
242 tcp_conn->tc_SND_NXT - tcp_conn->tc_SND_UNA,
243 tcp_conn->tc_rcv_wnd,
244 tcp_conn->tc_snd_cwnd - tcp_conn->tc_SND_UNA,
245 tcp_conn->tc_snd_cthresh);
246 }
247
248 printf("\n");
249
250 if (!verbose || no_verbose)
251 return;
252 rtt= tcp_conn->tc_rtt;
253 artt= tcp_conn->tc_artt;
254 drtt= tcp_conn->tc_drtt;
255 printf("\tmss %u, mtu %u%s, rtt %.3f (%.3f+%d*%.3f) s\n",
256 tcp_conn->tc_max_mtu-IP_TCP_MIN_HDR_SIZE,
257 tcp_conn->tc_mtu,
258 (tcp_conn->tc_flags & TCF_PMTU) ? "" : " (no PMTU)",
259 rtt/(HZ+0.0),
260 artt/(HZ+0.0)/TCP_RTT_SCALE, TCP_DRTT_MULT,
261 drtt/(HZ+0.0)/TCP_RTT_SCALE);
262 flags= tcp_conn->tc_flags;
263 printf("\tflags:");
264 if (!flags)
265 printf(" TCF_EMPTY");
266 if (flags & TCF_INUSE)
267 flags &= ~TCF_INUSE;
268 if (flags & TCF_FIN_RECV)
269 {
270 printf(" TCF_FIN_RECV");
271 flags &= ~TCF_FIN_RECV;
272 }
273 if (flags & TCF_RCV_PUSH)
274 {
275 printf(" TCF_RCV_PUSH");
276 flags &= ~TCF_RCV_PUSH;
277 }
278 if (flags & TCF_MORE2WRITE)
279 {
280 printf(" TCF_MORE2WRITE");
281 flags &= ~TCF_MORE2WRITE;
282 }
283 if (flags & TCF_SEND_ACK)
284 {
285 printf(" TCF_SEND_ACK");
286 flags &= ~TCF_SEND_ACK;
287 }
288 if (flags & TCF_FIN_SENT)
289 {
290 printf(" TCF_FIN_SENT");
291 flags &= ~TCF_FIN_SENT;
292 }
293 if (flags & TCF_BSD_URG)
294 {
295 printf(" TCF_BSD_URG");
296 flags &= ~TCF_BSD_URG;
297 }
298 if (flags & TCF_NO_PUSH)
299 {
300 printf(" TCF_NO_PUSH");
301 flags &= ~TCF_NO_PUSH;
302 }
303 if (flags & TCF_PUSH_NOW)
304 {
305 printf(" TCF_PUSH_NOW");
306 flags &= ~TCF_PUSH_NOW;
307 }
308 if (flags & TCF_PMTU)
309 flags &= ~TCF_PMTU;
310 if (flags)
311 printf(" 0x%x", flags);
312 printf("\n");
313 printf("\ttimer: ref %d, time %f, active %d\n",
314 tcp_conn->tc_transmit_timer.tim_ref,
315 (0.0+tcp_conn->tc_transmit_timer.tim_time-now)/HZ,
316 tcp_conn->tc_transmit_timer.tim_active);
317}
318
319void usage(void)
320{
321 fprintf(stderr, "Usage: %s [-anv]\n", prog_name);
322 exit(1);
323}
324
325/*
326 * $PchId: tcpstat.c,v 1.8 2005/01/30 01:04:38 philip Exp $
327 */
Note: See TracBrowser for help on using the repository browser.