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