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 "$FreeBSD$"; 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%lu packet%s sent\n"); 203 p2(tcps_sndpack,tcps_sndbyte, 204 "\t\t%lu data packet%s (%lu byte%s)\n"); 205 p2(tcps_sndrexmitpack, tcps_sndrexmitbyte, 206 "\t\t%lu data packet%s (%lu byte%s) retransmitted\n"); 207 p(tcps_mturesent, "\t\t%lu resend%s initiated by MTU discovery\n"); 208 p2(tcps_sndacks, tcps_delack, 209 "\t\t%lu ack-only packet%s (%lu delayed)\n"); 210 p(tcps_sndurg, "\t\t%lu URG only packet%s\n"); 211 p(tcps_sndprobe, "\t\t%lu window probe packet%s\n"); 212 p(tcps_sndwinup, "\t\t%lu window update packet%s\n"); 213 p(tcps_sndctrl, "\t\t%lu control packet%s\n"); 214 p(tcps_rcvtotal, "\t%lu packet%s received\n"); 215 p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%lu ack%s (for %lu byte%s)\n"); 216 p(tcps_rcvdupack, "\t\t%lu duplicate ack%s\n"); 217 p(tcps_rcvacktoomuch, "\t\t%lu ack%s for unsent data\n"); 218 p2(tcps_rcvpack, tcps_rcvbyte, 219 "\t\t%lu packet%s (%lu byte%s) received in-sequence\n"); 220 p2(tcps_rcvduppack, tcps_rcvdupbyte, 221 "\t\t%lu completely duplicate packet%s (%lu byte%s)\n"); 222 p(tcps_pawsdrop, "\t\t%lu old duplicate packet%s\n"); 223 p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte, 224 "\t\t%lu packet%s with some dup. data (%lu byte%s duped)\n"); 225 p2(tcps_rcvoopack, tcps_rcvoobyte, 226 "\t\t%lu out-of-order packet%s (%lu byte%s)\n"); 227 p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin, 228 "\t\t%lu packet%s (%lu byte%s) of data after window\n"); 229 p(tcps_rcvwinprobe, "\t\t%lu window probe%s\n"); 230 p(tcps_rcvwinupd, "\t\t%lu window update packet%s\n"); 231 p(tcps_rcvafterclose, "\t\t%lu packet%s received after close\n"); 232 p(tcps_rcvbadsum, "\t\t%lu discarded for bad checksum%s\n"); 233 p(tcps_rcvbadoff, "\t\t%lu discarded for bad header offset field%s\n"); 234 p(tcps_rcvshort, "\t\t%lu discarded because packet too short\n"); 235 p(tcps_connattempt, "\t%lu connection request%s\n"); 236 p(tcps_accepts, "\t%lu connection accept%s\n"); 237 p(tcps_badsyn, "\t%lu bad connection attempt%s\n"); 238 p(tcps_listendrop, "\t%lu listen queue overflow%s\n"); 239 p(tcps_connects, "\t%lu connection%s established (including accepts)\n"); 240 p2(tcps_closed, tcps_drops, 241 "\t%lu connection%s closed (including %lu drop%s)\n"); 242 p(tcps_cachedrtt, "\t\t%lu connection%s updated cached RTT on close\n"); 243 p(tcps_cachedrttvar, 244 "\t\t%lu connection%s updated cached RTT variance on close\n"); 245 p(tcps_cachedssthresh, 246 "\t\t%lu connection%s updated cached ssthresh on close\n"); 247 p(tcps_conndrops, "\t%lu embryonic connection%s dropped\n"); 248 p2(tcps_rttupdated, tcps_segstimed, 249 "\t%lu segment%s updated rtt (of %lu attempt%s)\n"); 250 p(tcps_rexmttimeo, "\t%lu retransmit timeout%s\n"); 251 p(tcps_timeoutdrop, "\t\t%lu connection%s dropped by rexmit timeout\n"); 252 p(tcps_persisttimeo, "\t%lu persist timeout%s\n"); 253 p(tcps_persistdrop, "\t\t%lu connection%s dropped by persist timeout\n"); 254 p(tcps_keeptimeo, "\t%lu keepalive timeout%s\n"); 255 p(tcps_keepprobe, "\t\t%lu keepalive probe%s sent\n"); 256 p(tcps_keepdrops, "\t\t%lu connection%s dropped by keepalive\n"); 257 p(tcps_predack, "\t%lu correct ACK header prediction%s\n"); 258 p(tcps_preddat, "\t%lu 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_notmember, 337 "\t%lu packet%s received for unknown multicast group\n"); 338 p(ips_redirectsent, "\t%lu redirect%s sent\n"); 339 p(ips_localout, "\t%lu packet%s sent from this host\n"); 340 p(ips_rawout, "\t%lu packet%s sent with fabricated ip header\n"); 341 p(ips_odropped, 342 "\t%lu output packet%s dropped due to no bufs, etc.\n"); 343 p(ips_noroute, "\t%lu output packet%s discarded due to no route\n"); 344 p(ips_fragmented, "\t%lu output datagram%s fragmented\n"); 345 p(ips_ofragments, "\t%lu fragment%s created\n"); 346 p(ips_cantfrag, "\t%lu datagram%s that can't be fragmented\n"); 347 #undef p 348 } 349 350 static char *icmpnames[] = { 351 "echo reply", 352 "#1", 353 "#2", 354 "destination unreachable", 355 "source quench", 356 "routing redirect", 357 "#6", 358 "#7", 359 "echo", 360 "router advertisement", 361 "router solicitation", 362 "time exceeded", 363 "parameter problem", 364 "time stamp", 365 "time stamp reply", 366 "information request", 367 "information request reply", 368 "address mask request", 369 "address mask reply", 370 }; 371 372 /* 373 * Dump ICMP statistics. 374 */ 375 void 376 icmp_stats(off, name) 377 u_long off; 378 char *name; 379 { 380 struct icmpstat icmpstat; 381 register int i, first; 382 383 if (off == 0) 384 return; 385 kread(off, (char *)&icmpstat, sizeof (icmpstat)); 386 printf("%s:\n", name); 387 388 #define p(f, m) if (icmpstat.f || sflag <= 1) \ 389 printf(m, icmpstat.f, plural(icmpstat.f)) 390 391 p(icps_error, "\t%lu call%s to icmp_error\n"); 392 p(icps_oldicmp, 393 "\t%lu error%s not generated 'cuz old message was icmp\n"); 394 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) 395 if (icmpstat.icps_outhist[i] != 0) { 396 if (first) { 397 printf("\tOutput histogram:\n"); 398 first = 0; 399 } 400 printf("\t\t%s: %lu\n", icmpnames[i], 401 icmpstat.icps_outhist[i]); 402 } 403 p(icps_badcode, "\t%lu message%s with bad code fields\n"); 404 p(icps_tooshort, "\t%lu message%s < minimum length\n"); 405 p(icps_checksum, "\t%lu bad checksum%s\n"); 406 p(icps_badlen, "\t%lu message%s with bad length\n"); 407 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) 408 if (icmpstat.icps_inhist[i] != 0) { 409 if (first) { 410 printf("\tInput histogram:\n"); 411 first = 0; 412 } 413 printf("\t\t%s: %lu\n", icmpnames[i], 414 icmpstat.icps_inhist[i]); 415 } 416 p(icps_reflect, "\t%lu message response%s generated\n"); 417 #undef p 418 } 419 420 /* 421 * Dump IGMP statistics structure. 422 */ 423 void 424 igmp_stats(off, name) 425 u_long off; 426 char *name; 427 { 428 struct igmpstat igmpstat; 429 430 if (off == 0) 431 return; 432 kread(off, (char *)&igmpstat, sizeof (igmpstat)); 433 printf("%s:\n", name); 434 435 #define p(f, m) if (igmpstat.f || sflag <= 1) \ 436 printf(m, igmpstat.f, plural(igmpstat.f)) 437 #define py(f, m) if (igmpstat.f || sflag <= 1) \ 438 printf(m, igmpstat.f, igmpstat.f != 1 ? "ies" : "y") 439 p(igps_rcv_total, "\t%u message%s received\n"); 440 p(igps_rcv_tooshort, "\t%u message%s received with too few bytes\n"); 441 p(igps_rcv_badsum, "\t%u message%s received with bad checksum\n"); 442 py(igps_rcv_queries, "\t%u membership quer%s received\n"); 443 py(igps_rcv_badqueries, "\t%u membership quer%s received with invalid field(s)\n"); 444 p(igps_rcv_reports, "\t%u membership report%s received\n"); 445 p(igps_rcv_badreports, "\t%u membership report%s received with invalid field(s)\n"); 446 p(igps_rcv_ourreports, "\t%u membership report%s received for groups to which we belong\n"); 447 p(igps_snd_reports, "\t%u membership report%s sent\n"); 448 #undef p 449 #undef py 450 } 451 452 /* 453 * Pretty print an Internet address (net address + port). 454 */ 455 void 456 inetprint(in, port, proto,numeric) 457 register struct in_addr *in; 458 int port; 459 char *proto; 460 int numeric; 461 { 462 struct servent *sp = 0; 463 char line[80], *cp; 464 int width; 465 466 sprintf(line, "%.*s.", (Aflag && !numeric) ? 12 : 16, inetname(in)); 467 cp = index(line, '\0'); 468 if (!numeric && port) 469 sp = getservbyport((int)port, proto); 470 if (sp || port == 0) 471 sprintf(cp, "%.15s", sp ? sp->s_name : "*"); 472 else 473 sprintf(cp, "%d", ntohs((u_short)port)); 474 width = Aflag ? 18 : 22; 475 printf(" %-*.*s", width, width, line); 476 } 477 478 /* 479 * Construct an Internet address representation. 480 * If the nflag has been supplied, give 481 * numeric value, otherwise try for symbolic name. 482 */ 483 char * 484 inetname(inp) 485 struct in_addr *inp; 486 { 487 register char *cp; 488 static char line[50]; 489 struct hostent *hp; 490 struct netent *np; 491 492 cp = 0; 493 if (!nflag && inp->s_addr != INADDR_ANY) { 494 int net = inet_netof(*inp); 495 int lna = inet_lnaof(*inp); 496 497 if (lna == INADDR_ANY) { 498 np = getnetbyaddr(net, AF_INET); 499 if (np) 500 cp = np->n_name; 501 } 502 if (cp == 0) { 503 hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET); 504 if (hp) { 505 cp = hp->h_name; 506 trimdomain(cp); 507 } 508 } 509 } 510 if (inp->s_addr == INADDR_ANY) 511 strcpy(line, "*"); 512 else if (cp) 513 strcpy(line, cp); 514 else { 515 inp->s_addr = ntohl(inp->s_addr); 516 #define C(x) ((x) & 0xff) 517 sprintf(line, "%lu.%lu.%lu.%lu", C(inp->s_addr >> 24), 518 C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr)); 519 } 520 return (line); 521 } 522