inet.c revision 13433
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 35static char sccsid[] = "@(#)inet.c 8.5 (Berkeley) 5/24/95"; 36#endif /* not lint */ 37 38#include <sys/param.h> 39#include <sys/socket.h> 40#include <sys/socketvar.h> 41#include <sys/mbuf.h> 42#include <sys/protosw.h> 43#include <sys/queue.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 72struct inpcb inpcb; 73struct tcpcb tcpcb; 74struct socket sockb; 75 76char *inetname __P((struct in_addr *)); 77void 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 */ 85void 86protopr(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 */ 166void 167tcp_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_connects, "\t%d connection%s established (including accepts)\n"); 222 p2(tcps_closed, tcps_drops, 223 "\t%d connection%s closed (including %d drop%s)\n"); 224 p(tcps_cachedrtt, "\t\t%d connection%s updated cached RTT on close\n"); 225 p(tcps_cachedrttvar, 226 "\t\t%d connection%s updated cached RTT variance on close\n"); 227 p(tcps_cachedssthresh, 228 "\t\t%d connection%s updated cached ssthresh on close\n"); 229 p(tcps_conndrops, "\t%d embryonic connection%s dropped\n"); 230 p2(tcps_rttupdated, tcps_segstimed, 231 "\t%d segment%s updated rtt (of %d attempt%s)\n"); 232 p(tcps_rexmttimeo, "\t%d retransmit timeout%s\n"); 233 p(tcps_timeoutdrop, "\t\t%d connection%s dropped by rexmit timeout\n"); 234 p(tcps_persisttimeo, "\t%d persist timeout%s\n"); 235 p(tcps_persistdrop, "\t\t%d connection%s dropped by persist timeout\n"); 236 p(tcps_keeptimeo, "\t%d keepalive timeout%s\n"); 237 p(tcps_keepprobe, "\t\t%d keepalive probe%s sent\n"); 238 p(tcps_keepdrops, "\t\t%d connection%s dropped by keepalive\n"); 239 p(tcps_predack, "\t%d correct ACK header prediction%s\n"); 240 p(tcps_preddat, "\t%d correct data packet header prediction%s\n"); 241#undef p 242#undef p2 243#undef p3 244} 245 246/* 247 * Dump UDP statistics structure. 248 */ 249void 250udp_stats(off, name) 251 u_long off; 252 char *name; 253{ 254 struct udpstat udpstat; 255 u_long delivered; 256 257 if (off == 0) 258 return; 259 kread(off, (char *)&udpstat, sizeof (udpstat)); 260 printf("%s:\n", name); 261#define p(f, m) if (udpstat.f || sflag <= 1) \ 262 printf(m, udpstat.f, plural(udpstat.f)) 263 p(udps_ipackets, "\t%u datagram%s received\n"); 264 p(udps_hdrops, "\t%u with incomplete header\n"); 265 p(udps_badlen, "\t%u with bad data length field\n"); 266 p(udps_badsum, "\t%u with bad checksum\n"); 267 p(udps_noport, "\t%u dropped due to no socket\n"); 268 p(udps_noportbcast, "\t%u broadcast/multicast datagram%s dropped due to no socket\n"); 269 p(udps_fullsock, "\t%u dropped due to full socket buffers\n"); 270 delivered = udpstat.udps_ipackets - 271 udpstat.udps_hdrops - 272 udpstat.udps_badlen - 273 udpstat.udps_badsum - 274 udpstat.udps_noport - 275 udpstat.udps_noportbcast - 276 udpstat.udps_fullsock; 277 if (delivered || sflag <= 1) 278 printf("\t%u delivered\n", delivered); 279 p(udps_opackets, "\t%u datagram%s output\n"); 280#undef p 281} 282 283/* 284 * Dump IP statistics structure. 285 */ 286void 287ip_stats(off, name) 288 u_long off; 289 char *name; 290{ 291 struct ipstat ipstat; 292 293 if (off == 0) 294 return; 295 kread(off, (char *)&ipstat, sizeof (ipstat)); 296 printf("%s:\n", name); 297 298#define p(f, m) if (ipstat.f || sflag <= 1) \ 299 printf(m, ipstat.f, plural(ipstat.f)) 300 301 p(ips_total, "\t%u total packet%s received\n"); 302 p(ips_badsum, "\t%u bad header checksum%s\n"); 303 p(ips_toosmall, "\t%u with size smaller than minimum\n"); 304 p(ips_tooshort, "\t%u with data size < data length\n"); 305 p(ips_badhlen, "\t%u with header length < data size\n"); 306 p(ips_badlen, "\t%u with data length < header length\n"); 307 p(ips_badoptions, "\t%u with bad options\n"); 308 p(ips_badvers, "\t%u with incorrect version number\n"); 309 p(ips_fragments, "\t%u fragment%s received\n"); 310 p(ips_fragdropped, "\t%u fragment%s dropped (dup or out of space)\n"); 311 p(ips_fragtimeout, "\t%u fragment%s dropped after timeout\n"); 312 p(ips_reassembled, "\t%u packet%s reassembled ok\n"); 313 p(ips_delivered, "\t%u packet%s for this host\n"); 314 p(ips_noproto, "\t%u packet%s for unknown/unsupported protocol\n"); 315 p(ips_forward, "\t%u packet%s forwarded\n"); 316 p(ips_cantforward, "\t%u packet%s not forwardable\n"); 317 p(ips_redirectsent, "\t%u redirect%s sent\n"); 318 p(ips_localout, "\t%u packet%s sent from this host\n"); 319 p(ips_rawout, "\t%u packet%s sent with fabricated ip header\n"); 320 p(ips_odropped, "\t%u output packet%s dropped due to no bufs, etc.\n"); 321 p(ips_noroute, "\t%u output packet%s discarded due to no route\n"); 322 p(ips_fragmented, "\t%u output datagram%s fragmented\n"); 323 p(ips_ofragments, "\t%u fragment%s created\n"); 324 p(ips_cantfrag, "\t%u datagram%s that can't be fragmented\n"); 325#undef p 326} 327 328static char *icmpnames[] = { 329 "echo reply", 330 "#1", 331 "#2", 332 "destination unreachable", 333 "source quench", 334 "routing redirect", 335 "#6", 336 "#7", 337 "echo", 338 "router advertisement", 339 "router solicitation", 340 "time exceeded", 341 "parameter problem", 342 "time stamp", 343 "time stamp reply", 344 "information request", 345 "information request reply", 346 "address mask request", 347 "address mask reply", 348}; 349 350/* 351 * Dump ICMP statistics. 352 */ 353void 354icmp_stats(off, name) 355 u_long off; 356 char *name; 357{ 358 struct icmpstat icmpstat; 359 register int i, first; 360 361 if (off == 0) 362 return; 363 kread(off, (char *)&icmpstat, sizeof (icmpstat)); 364 printf("%s:\n", name); 365 366#define p(f, m) if (icmpstat.f || sflag <= 1) \ 367 printf(m, icmpstat.f, plural(icmpstat.f)) 368 369 p(icps_error, "\t%u call%s to icmp_error\n"); 370 p(icps_oldicmp, 371 "\t%u error%s not generated 'cuz old message was icmp\n"); 372 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) 373 if (icmpstat.icps_outhist[i] != 0) { 374 if (first) { 375 printf("\tOutput histogram:\n"); 376 first = 0; 377 } 378 printf("\t\t%s: %u\n", icmpnames[i], 379 icmpstat.icps_outhist[i]); 380 } 381 p(icps_badcode, "\t%u message%s with bad code fields\n"); 382 p(icps_tooshort, "\t%u message%s < minimum length\n"); 383 p(icps_checksum, "\t%u bad checksum%s\n"); 384 p(icps_badlen, "\t%u message%s with bad length\n"); 385 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) 386 if (icmpstat.icps_inhist[i] != 0) { 387 if (first) { 388 printf("\tInput histogram:\n"); 389 first = 0; 390 } 391 printf("\t\t%s: %u\n", icmpnames[i], 392 icmpstat.icps_inhist[i]); 393 } 394 p(icps_reflect, "\t%u message response%s generated\n"); 395#undef p 396} 397 398/* 399 * Dump IGMP statistics structure. 400 */ 401void 402igmp_stats(off, name) 403 u_long off; 404 char *name; 405{ 406 struct igmpstat igmpstat; 407 408 if (off == 0) 409 return; 410 kread(off, (char *)&igmpstat, sizeof (igmpstat)); 411 printf("%s:\n", name); 412 413#define p(f, m) if (igmpstat.f || sflag <= 1) \ 414 printf(m, igmpstat.f, plural(igmpstat.f)) 415#define py(f, m) if (igmpstat.f || sflag <= 1) \ 416 printf(m, igmpstat.f, igmpstat.f != 1 ? "ies" : "y") 417 p(igps_rcv_total, "\t%u message%s received\n"); 418 p(igps_rcv_tooshort, "\t%u message%s received with too few bytes\n"); 419 p(igps_rcv_badsum, "\t%u message%s received with bad checksum\n"); 420 py(igps_rcv_queries, "\t%u membership quer%s received\n"); 421 py(igps_rcv_badqueries, "\t%u membership quer%s received with invalid field(s)\n"); 422 p(igps_rcv_reports, "\t%u membership report%s received\n"); 423 p(igps_rcv_badreports, "\t%u membership report%s received with invalid field(s)\n"); 424 p(igps_rcv_ourreports, "\t%u membership report%s received for groups to which we belong\n"); 425 p(igps_snd_reports, "\t%u membership report%s sent\n"); 426#undef p 427#undef py 428} 429 430/* 431 * Pretty print an Internet address (net address + port). 432 * If the nflag was specified, use numbers instead of names. 433 */ 434void 435inetprint(in, port, proto) 436 register struct in_addr *in; 437 int port; 438 char *proto; 439{ 440 struct servent *sp = 0; 441 char line[80], *cp; 442 int width; 443 444 sprintf(line, "%.*s.", (Aflag && !nflag) ? 12 : 16, inetname(in)); 445 cp = index(line, '\0'); 446 if (!nflag && port) 447 sp = getservbyport((int)port, proto); 448 if (sp || port == 0) 449 sprintf(cp, "%.15s", sp ? sp->s_name : "*"); 450 else 451 sprintf(cp, "%d", ntohs((u_short)port)); 452 width = Aflag ? 18 : 22; 453 printf(" %-*.*s", width, width, line); 454} 455 456/* 457 * Construct an Internet address representation. 458 * If the nflag has been supplied, give 459 * numeric value, otherwise try for symbolic name. 460 */ 461char * 462inetname(inp) 463 struct in_addr *inp; 464{ 465 register char *cp; 466 static char line[50]; 467 struct hostent *hp; 468 struct netent *np; 469 470 cp = 0; 471 if (!nflag && inp->s_addr != INADDR_ANY) { 472 int net = inet_netof(*inp); 473 int lna = inet_lnaof(*inp); 474 475 if (lna == INADDR_ANY) { 476 np = getnetbyaddr(net, AF_INET); 477 if (np) 478 cp = np->n_name; 479 } 480 if (cp == 0) { 481 hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET); 482 if (hp) { 483 cp = hp->h_name; 484 trimdomain(cp); 485 } 486 } 487 } 488 if (inp->s_addr == INADDR_ANY) 489 strcpy(line, "*"); 490 else if (cp) 491 strcpy(line, cp); 492 else { 493 inp->s_addr = ntohl(inp->s_addr); 494#define C(x) ((x) & 0xff) 495 sprintf(line, "%u.%u.%u.%u", C(inp->s_addr >> 24), 496 C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr)); 497 } 498 return (line); 499} 500