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