1 /* 2 * Copyright (c) 1983, 1988, 1993, 1995 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 /* 36 static char sccsid[] = "@(#)inet.c 8.5 (Berkeley) 5/24/95"; 37 */ 38 static const char rcsid[] = 39 "$Id$"; 40 #endif /* not lint */ 41 42 #include <sys/param.h> 43 #include <sys/queue.h> 44 #include <sys/socket.h> 45 #include <sys/socketvar.h> 46 #include <sys/protosw.h> 47 48 #include <net/route.h> 49 #include <netinet/in.h> 50 #include <netinet/in_systm.h> 51 #include <netinet/ip.h> 52 #include <netinet/in_pcb.h> 53 #include <netinet/ip_icmp.h> 54 #include <netinet/icmp_var.h> 55 #include <netinet/igmp_var.h> 56 #include <netinet/ip_var.h> 57 #include <netinet/tcp.h> 58 #include <netinet/tcpip.h> 59 #include <netinet/tcp_seq.h> 60 #define TCPSTATES 61 #include <netinet/tcp_fsm.h> 62 #include <netinet/tcp_timer.h> 63 #include <netinet/tcp_var.h> 64 #include <netinet/tcp_debug.h> 65 #include <netinet/udp.h> 66 #include <netinet/udp_var.h> 67 68 #include <arpa/inet.h> 69 #include <netdb.h> 70 #include <stdio.h> 71 #include <string.h> 72 #include <unistd.h> 73 #include "netstat.h" 74 75 struct inpcb inpcb; 76 struct tcpcb tcpcb; 77 struct socket sockb; 78 79 char *inetname __P((struct in_addr *)); 80 void inetprint __P((struct in_addr *, int, char *, int)); 81 82 /* 83 * Print a summary of connections related to an Internet 84 * protocol. For TCP, also give state of connection. 85 * Listening processes (aflag) are suppressed unless the 86 * -a (all) flag is specified. 87 */ 88 void 89 protopr(off, name) 90 u_long off; 91 char *name; 92 { 93 struct inpcbhead head; 94 register struct inpcb *prev, *next; 95 int istcp; 96 static int first = 1; 97 98 if (off == 0) 99 return; 100 101 istcp = strcmp(name, "tcp") == 0; 102 kread(off, (char *)&head, sizeof (struct inpcbhead)); 103 prev = (struct inpcb *)off; 104 105 for (next = head.lh_first; next != NULL; next = inpcb.inp_list.le_next) { 106 if (kread((u_long)next, (char *)&inpcb, sizeof (inpcb))) { 107 printf("???\n"); 108 break; 109 } 110 if (!aflag && 111 inet_lnaof(inpcb.inp_laddr) == INADDR_ANY) { 112 prev = next; 113 continue; 114 } 115 if (kread((u_long)inpcb.inp_socket, (char *)&sockb, sizeof (sockb))) { 116 printf("???\n"); 117 break; 118 }; 119 if (istcp) { 120 if (kread((u_long)inpcb.inp_ppcb, 121 (char *)&tcpcb, sizeof (tcpcb))) { 122 printf("???\n"); 123 break; 124 }; 125 } 126 if (first) { 127 printf("Active Internet connections"); 128 if (aflag) 129 printf(" (including servers)"); 130 putchar('\n'); 131 if (Aflag) 132 printf("%-8.8s ", "PCB"); 133 printf(Aflag ? 134 "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" : 135 "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n", 136 "Proto", "Recv-Q", "Send-Q", 137 "Local Address", "Foreign Address", "(state)"); 138 first = 0; 139 } 140 if (Aflag) 141 if (istcp) 142 printf("%8x ", (int)inpcb.inp_ppcb); 143 else 144 printf("%8x ", (int)next); 145 printf("%-5.5s %6ld %6ld ", name, sockb.so_rcv.sb_cc, 146 sockb.so_snd.sb_cc); 147 if (nflag) { 148 inetprint(&inpcb.inp_laddr, (int)inpcb.inp_lport, 149 name, 1); 150 inetprint(&inpcb.inp_faddr, (int)inpcb.inp_fport, 151 name, 1); 152 } else if (inpcb.inp_flags & INP_ANONPORT) { 153 inetprint(&inpcb.inp_laddr, (int)inpcb.inp_lport, 154 name, 1); 155 inetprint(&inpcb.inp_faddr, (int)inpcb.inp_fport, 156 name, 0); 157 } else { 158 inetprint(&inpcb.inp_laddr, (int)inpcb.inp_lport, 159 name, 0); 160 inetprint(&inpcb.inp_faddr, (int)inpcb.inp_fport, 161 name, inpcb.inp_lport != inpcb.inp_fport); 162 } 163 if (istcp) { 164 if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES) 165 printf(" %d", tcpcb.t_state); 166 else { 167 printf(" %s", tcpstates[tcpcb.t_state]); 168 #if defined(TF_NEEDSYN) && defined(TF_NEEDFIN) 169 /* Show T/TCP `hidden state' */ 170 if (tcpcb.t_flags & (TF_NEEDSYN|TF_NEEDFIN)) 171 putchar('*'); 172 #endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */ 173 } 174 } 175 putchar('\n'); 176 prev = next; 177 } 178 } 179 180 /* 181 * Dump TCP statistics structure. 182 */ 183 void 184 tcp_stats(off, name) 185 u_long off; 186 char *name; 187 { 188 struct tcpstat tcpstat; 189 190 if (off == 0) 191 return; 192 printf ("%s:\n", name); 193 kread(off, (char *)&tcpstat, sizeof (tcpstat)); 194 195 #define p(f, m) if (tcpstat.f || sflag <= 1) \ 196 printf(m, tcpstat.f, plural(tcpstat.f)) 197 #define p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \ 198 printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2)) 199 #define p3(f, m) if (tcpstat.f || sflag <= 1) \ 200 printf(m, tcpstat.f, plurales(tcpstat.f)) 201 202 p(tcps_sndtotal, "\t%ld packet%s sent\n"); 203 p2(tcps_sndpack,tcps_sndbyte, 204 "\t\t%ld data packet%s (%ld byte%s)\n"); 205 p2(tcps_sndrexmitpack, tcps_sndrexmitbyte, 206 "\t\t%ld data packet%s (%ld byte%s) retransmitted\n"); 207 p(tcps_mturesent, "\t\t%ld resend%s initiated by MTU discovery\n"); 208 p2(tcps_sndacks, tcps_delack, 209 "\t\t%ld ack-only packet%s (%ld delayed)\n"); 210 p(tcps_sndurg, "\t\t%ld URG only packet%s\n"); 211 p(tcps_sndprobe, "\t\t%ld window probe packet%s\n"); 212 p(tcps_sndwinup, "\t\t%ld window update packet%s\n"); 213 p(tcps_sndctrl, "\t\t%ld control packet%s\n"); 214 p(tcps_rcvtotal, "\t%ld packet%s received\n"); 215 p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%ld ack%s (for %ld byte%s)\n"); 216 p(tcps_rcvdupack, "\t\t%ld duplicate ack%s\n"); 217 p(tcps_rcvacktoomuch, "\t\t%ld ack%s for unsent data\n"); 218 p2(tcps_rcvpack, tcps_rcvbyte, 219 "\t\t%ld packet%s (%ld byte%s) received in-sequence\n"); 220 p2(tcps_rcvduppack, tcps_rcvdupbyte, 221 "\t\t%ld completely duplicate packet%s (%ld byte%s)\n"); 222 p(tcps_pawsdrop, "\t\t%ld old duplicate packet%s\n"); 223 p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte, 224 "\t\t%ld packet%s with some dup. data (%ld byte%s duped)\n"); 225 p2(tcps_rcvoopack, tcps_rcvoobyte, 226 "\t\t%ld out-of-order packet%s (%ld byte%s)\n"); 227 p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin, 228 "\t\t%ld packet%s (%ld byte%s) of data after window\n"); 229 p(tcps_rcvwinprobe, "\t\t%ld window probe%s\n"); 230 p(tcps_rcvwinupd, "\t\t%ld window update packet%s\n"); 231 p(tcps_rcvafterclose, "\t\t%ld packet%s received after close\n"); 232 p(tcps_rcvbadsum, "\t\t%ld discarded for bad checksum%s\n"); 233 p(tcps_rcvbadoff, "\t\t%ld discarded for bad header offset field%s\n"); 234 p(tcps_rcvshort, "\t\t%ld discarded because packet too short\n"); 235 p(tcps_connattempt, "\t%ld connection request%s\n"); 236 p(tcps_accepts, "\t%ld connection accept%s\n"); 237 p(tcps_badsyn, "\t%ld bad connection attempt%s\n"); 238 p(tcps_listendrop, "\t%ld listen queue overflow%s\n"); 239 p(tcps_connects, "\t%ld connection%s established (including accepts)\n"); 240 p2(tcps_closed, tcps_drops, 241 "\t%ld connection%s closed (including %ld drop%s)\n"); 242 p(tcps_cachedrtt, "\t\t%ld connection%s updated cached RTT on close\n"); 243 p(tcps_cachedrttvar, 244 "\t\t%ld connection%s updated cached RTT variance on close\n"); 245 p(tcps_cachedssthresh, 246 "\t\t%ld connection%s updated cached ssthresh on close\n"); 247 p(tcps_conndrops, "\t%ld embryonic connection%s dropped\n"); 248 p2(tcps_rttupdated, tcps_segstimed, 249 "\t%ld segment%s updated rtt (of %ld attempt%s)\n"); 250 p(tcps_rexmttimeo, "\t%ld retransmit timeout%s\n"); 251 p(tcps_timeoutdrop, "\t\t%ld connection%s dropped by rexmit timeout\n"); 252 p(tcps_persisttimeo, "\t%ld persist timeout%s\n"); 253 p(tcps_persistdrop, "\t\t%ld connection%s dropped by persist timeout\n"); 254 p(tcps_keeptimeo, "\t%ld keepalive timeout%s\n"); 255 p(tcps_keepprobe, "\t\t%ld keepalive probe%s sent\n"); 256 p(tcps_keepdrops, "\t\t%ld connection%s dropped by keepalive\n"); 257 p(tcps_predack, "\t%ld correct ACK header prediction%s\n"); 258 p(tcps_preddat, "\t%ld correct data packet header prediction%s\n"); 259 #undef p 260 #undef p2 261 #undef p3 262 } 263 264 /* 265 * Dump UDP statistics structure. 266 */ 267 void 268 udp_stats(off, name) 269 u_long off; 270 char *name; 271 { 272 struct udpstat udpstat; 273 u_long delivered; 274 275 if (off == 0) 276 return; 277 kread(off, (char *)&udpstat, sizeof (udpstat)); 278 printf("%s:\n", name); 279 #define p(f, m) if (udpstat.f || sflag <= 1) \ 280 printf(m, udpstat.f, plural(udpstat.f)) 281 p(udps_ipackets, "\t%lu datagram%s received\n"); 282 p(udps_hdrops, "\t%lu with incomplete header\n"); 283 p(udps_badlen, "\t%lu with bad data length field\n"); 284 p(udps_badsum, "\t%lu with bad checksum\n"); 285 p(udps_noport, "\t%lu dropped due to no socket\n"); 286 p(udps_noportbcast, "\t%lu broadcast/multicast datagram%s dropped due to no socket\n"); 287 p(udps_fullsock, "\t%lu dropped due to full socket buffers\n"); 288 p(udpps_pcbhashmiss, "\t%lu not for hashed pcb\n"); 289 delivered = udpstat.udps_ipackets - 290 udpstat.udps_hdrops - 291 udpstat.udps_badlen - 292 udpstat.udps_badsum - 293 udpstat.udps_noport - 294 udpstat.udps_noportbcast - 295 udpstat.udps_fullsock; 296 if (delivered || sflag <= 1) 297 printf("\t%lu delivered\n", delivered); 298 p(udps_opackets, "\t%lu datagram%s output\n"); 299 #undef p 300 } 301 302 /* 303 * Dump IP statistics structure. 304 */ 305 void 306 ip_stats(off, name) 307 u_long off; 308 char *name; 309 { 310 struct ipstat ipstat; 311 312 if (off == 0) 313 return; 314 kread(off, (char *)&ipstat, sizeof (ipstat)); 315 printf("%s:\n", name); 316 317 #define p(f, m) if (ipstat.f || sflag <= 1) \ 318 printf(m, ipstat.f, plural(ipstat.f)) 319 320 p(ips_total, "\t%lu total packet%s received\n"); 321 p(ips_badsum, "\t%lu bad header checksum%s\n"); 322 p(ips_toosmall, "\t%lu with size smaller than minimum\n"); 323 p(ips_tooshort, "\t%lu with data size < data length\n"); 324 p(ips_badhlen, "\t%lu with header length < data size\n"); 325 p(ips_badlen, "\t%lu with data length < header length\n"); 326 p(ips_badoptions, "\t%lu with bad options\n"); 327 p(ips_badvers, "\t%lu with incorrect version number\n"); 328 p(ips_fragments, "\t%lu fragment%s received\n"); 329 p(ips_fragdropped, "\t%lu fragment%s dropped (dup or out of space)\n"); 330 p(ips_fragtimeout, "\t%lu fragment%s dropped after timeout\n"); 331 p(ips_reassembled, "\t%lu packet%s reassembled ok\n"); 332 p(ips_delivered, "\t%lu packet%s for this host\n"); 333 p(ips_noproto, "\t%lu packet%s for unknown/unsupported protocol\n"); 334 p(ips_forward, "\t%lu packet%s forwarded\n"); 335 p(ips_cantforward, "\t%lu packet%s not forwardable\n"); 336 p(ips_redirectsent, "\t%lu redirect%s sent\n"); 337 p(ips_localout, "\t%lu packet%s sent from this host\n"); 338 p(ips_rawout, "\t%lu packet%s sent with fabricated ip header\n"); 339 p(ips_odropped, "\t%lu output packet%s dropped due to no bufs, etc.\n"); 340 p(ips_noroute, "\t%lu output packet%s discarded due to no route\n"); 341 p(ips_fragmented, "\t%lu output datagram%s fragmented\n"); 342 p(ips_ofragments, "\t%lu fragment%s created\n"); 343 p(ips_cantfrag, "\t%lu datagram%s that can't be fragmented\n"); 344 #undef p 345 } 346 347 static char *icmpnames[] = { 348 "echo reply", 349 "#1", 350 "#2", 351 "destination unreachable", 352 "source quench", 353 "routing redirect", 354 "#6", 355 "#7", 356 "echo", 357 "router advertisement", 358 "router solicitation", 359 "time exceeded", 360 "parameter problem", 361 "time stamp", 362 "time stamp reply", 363 "information request", 364 "information request reply", 365 "address mask request", 366 "address mask reply", 367 }; 368 369 /* 370 * Dump ICMP statistics. 371 */ 372 void 373 icmp_stats(off, name) 374 u_long off; 375 char *name; 376 { 377 struct icmpstat icmpstat; 378 register int i, first; 379 380 if (off == 0) 381 return; 382 kread(off, (char *)&icmpstat, sizeof (icmpstat)); 383 printf("%s:\n", name); 384 385 #define p(f, m) if (icmpstat.f || sflag <= 1) \ 386 printf(m, icmpstat.f, plural(icmpstat.f)) 387 388 p(icps_error, "\t%lu call%s to icmp_error\n"); 389 p(icps_oldicmp, 390 "\t%lu error%s not generated 'cuz old message was icmp\n"); 391 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) 392 if (icmpstat.icps_outhist[i] != 0) { 393 if (first) { 394 printf("\tOutput histogram:\n"); 395 first = 0; 396 } 397 printf("\t\t%s: %lu\n", icmpnames[i], 398 icmpstat.icps_outhist[i]); 399 } 400 p(icps_badcode, "\t%lu message%s with bad code fields\n"); 401 p(icps_tooshort, "\t%lu message%s < minimum length\n"); 402 p(icps_checksum, "\t%lu bad checksum%s\n"); 403 p(icps_badlen, "\t%lu message%s with bad length\n"); 404 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) 405 if (icmpstat.icps_inhist[i] != 0) { 406 if (first) { 407 printf("\tInput histogram:\n"); 408 first = 0; 409 } 410 printf("\t\t%s: %lu\n", icmpnames[i], 411 icmpstat.icps_inhist[i]); 412 } 413 p(icps_reflect, "\t%lu message response%s generated\n"); 414 #undef p 415 } 416 417 /* 418 * Dump IGMP statistics structure. 419 */ 420 void 421 igmp_stats(off, name) 422 u_long off; 423 char *name; 424 { 425 struct igmpstat igmpstat; 426 427 if (off == 0) 428 return; 429 kread(off, (char *)&igmpstat, sizeof (igmpstat)); 430 printf("%s:\n", name); 431 432 #define p(f, m) if (igmpstat.f || sflag <= 1) \ 433 printf(m, igmpstat.f, plural(igmpstat.f)) 434 #define py(f, m) if (igmpstat.f || sflag <= 1) \ 435 printf(m, igmpstat.f, igmpstat.f != 1 ? "ies" : "y") 436 p(igps_rcv_total, "\t%u message%s received\n"); 437 p(igps_rcv_tooshort, "\t%u message%s received with too few bytes\n"); 438 p(igps_rcv_badsum, "\t%u message%s received with bad checksum\n"); 439 py(igps_rcv_queries, "\t%u membership quer%s received\n"); 440 py(igps_rcv_badqueries, "\t%u membership quer%s received with invalid field(s)\n"); 441 p(igps_rcv_reports, "\t%u membership report%s received\n"); 442 p(igps_rcv_badreports, "\t%u membership report%s received with invalid field(s)\n"); 443 p(igps_rcv_ourreports, "\t%u membership report%s received for groups to which we belong\n"); 444 p(igps_snd_reports, "\t%u membership report%s sent\n"); 445 #undef p 446 #undef py 447 } 448 449 /* 450 * Pretty print an Internet address (net address + port). 451 */ 452 void 453 inetprint(in, port, proto,numeric) 454 register struct in_addr *in; 455 int port; 456 char *proto; 457 int numeric; 458 { 459 struct servent *sp = 0; 460 char line[80], *cp; 461 int width; 462 463 sprintf(line, "%.*s.", (Aflag && !numeric) ? 12 : 16, inetname(in)); 464 cp = index(line, '\0'); 465 if (!numeric && port) 466 sp = getservbyport((int)port, proto); 467 if (sp || port == 0) 468 sprintf(cp, "%.15s", sp ? sp->s_name : "*"); 469 else 470 sprintf(cp, "%d", ntohs((u_short)port)); 471 width = Aflag ? 18 : 22; 472 printf(" %-*.*s", width, width, line); 473 } 474 475 /* 476 * Construct an Internet address representation. 477 * If the nflag has been supplied, give 478 * numeric value, otherwise try for symbolic name. 479 */ 480 char * 481 inetname(inp) 482 struct in_addr *inp; 483 { 484 register char *cp; 485 static char line[50]; 486 struct hostent *hp; 487 struct netent *np; 488 489 cp = 0; 490 if (!nflag && inp->s_addr != INADDR_ANY) { 491 int net = inet_netof(*inp); 492 int lna = inet_lnaof(*inp); 493 494 if (lna == INADDR_ANY) { 495 np = getnetbyaddr(net, AF_INET); 496 if (np) 497 cp = np->n_name; 498 } 499 if (cp == 0) { 500 hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET); 501 if (hp) { 502 cp = hp->h_name; 503 trimdomain(cp); 504 } 505 } 506 } 507 if (inp->s_addr == INADDR_ANY) 508 strcpy(line, "*"); 509 else if (cp) 510 strcpy(line, cp); 511 else { 512 inp->s_addr = ntohl(inp->s_addr); 513 #define C(x) ((x) & 0xff) 514 sprintf(line, "%lu.%lu.%lu.%lu", C(inp->s_addr >> 24), 515 C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr)); 516 } 517 return (line); 518 } 519