1: /* 2: * Copyright (c) 1983,1988 Regents of the University of California. 3: * All rights reserved. 4: * 5: * Redistribution and use in source and binary forms are permitted 6: * provided that this notice is preserved and that due credit is given 7: * to the University of California at Berkeley. The name of the University 8: * may not be used to endorse or promote products derived from this 9: * software without specific prior written permission. This software 10: * is provided ``as is'' without express or implied warranty. 11: */ 12: 13: #if defined(DOSCCS) && !defined(lint) 14: static char sccsid[] = "@(#)inet.c 5.9.3 (2.11BSD GTE) 8/28/94"; 15: #endif 16: 17: #include <strings.h> 18: #include <stdio.h> 19: 20: #include <sys/param.h> 21: #include <sys/socket.h> 22: #include <sys/socketvar.h> 23: #include <sys/mbuf.h> 24: #include <sys/protosw.h> 25: 26: #include <arpa/inet.h> 27: 28: #include <net/route.h> 29: #include <netinet/in.h> 30: #include <netinet/in_systm.h> 31: #include <netinet/in_pcb.h> 32: #include <netinet/ip.h> 33: #include <netinet/ip_icmp.h> 34: #include <netinet/icmp_var.h> 35: #include <netinet/ip_var.h> 36: #include <netinet/tcp.h> 37: #include <netinet/tcpip.h> 38: #include <netinet/tcp_seq.h> 39: #define TCPSTATES 40: #include <netinet/tcp_fsm.h> 41: #include <netinet/tcp_timer.h> 42: #include <netinet/tcp_var.h> 43: #include <netinet/tcp_debug.h> 44: #include <netinet/udp.h> 45: #include <netinet/udp_var.h> 46: 47: #include <netdb.h> 48: 49: struct inpcb inpcb; 50: struct tcpcb tcpcb; 51: struct socket sockb; 52: extern int kmem; 53: extern int Aflag; 54: extern int aflag; 55: extern int nflag; 56: extern int sflag; 57: extern char *plural(); 58: 59: #ifdef pdp11 60: #define klseek slseek 61: #endif 62: 63: char *inetname(); 64: 65: /* 66: * Print a summary of connections related to an Internet 67: * protocol. For TCP, also give state of connection. 68: * Listening processes (aflag) are suppressed unless the 69: * -a (all) flag is specified. 70: */ 71: protopr(off, name) 72: off_t off; 73: char *name; 74: { 75: struct inpcb cb; 76: register struct inpcb *prev, *next; 77: int istcp; 78: static int first = 1; 79: 80: if (off == 0) 81: return; 82: istcp = strcmp(name, "tcp") == 0; 83: klseek(kmem, off, 0); 84: read(kmem, (char *)&cb, sizeof (struct inpcb)); 85: inpcb = cb; 86: prev = (struct inpcb *)off; 87: if (inpcb.inp_next == (struct inpcb *)off) 88: return; 89: while (inpcb.inp_next != (struct inpcb *)off) { 90: 91: next = inpcb.inp_next; 92: klseek(kmem, (off_t)next, 0); 93: read(kmem, (char *)&inpcb, sizeof (inpcb)); 94: if (inpcb.inp_prev != prev) { 95: printf("???\n"); 96: break; 97: } 98: if (!aflag && 99: inet_lnaof(inpcb.inp_laddr.s_addr) == INADDR_ANY) { 100: prev = next; 101: continue; 102: } 103: klseek(kmem, (off_t)inpcb.inp_socket, 0); 104: read(kmem, (char *)&sockb, sizeof (sockb)); 105: if (istcp) { 106: klseek(kmem, (off_t)inpcb.inp_ppcb, 0); 107: read(kmem, (char *)&tcpcb, sizeof (tcpcb)); 108: } 109: if (first) { 110: printf("Active Internet connections"); 111: if (aflag) 112: printf(" (including servers)"); 113: putchar('\n'); 114: if (Aflag) 115: printf("%-8.8s ", "PCB"); 116: printf(Aflag ? 117: "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" : 118: "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n", 119: "Proto", "Recv-Q", "Send-Q", 120: "Local Address", "Foreign Address", "(state)"); 121: first = 0; 122: } 123: if (Aflag) 124: if (istcp) 125: printf("%8x ", inpcb.inp_ppcb); 126: else 127: printf("%8x ", next); 128: printf("%-5.5s %6d %6d ", name, sockb.so_rcv.sb_cc, 129: sockb.so_snd.sb_cc); 130: inetprint(&inpcb.inp_laddr, inpcb.inp_lport, name); 131: inetprint(&inpcb.inp_faddr, inpcb.inp_fport, name); 132: if (istcp) { 133: if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES) 134: printf(" %d", tcpcb.t_state); 135: else 136: printf(" %s", tcpstates[tcpcb.t_state]); 137: } 138: putchar('\n'); 139: prev = next; 140: } 141: } 142: 143: /* 144: * Dump TCP statistics structure. 145: */ 146: tcp_stats(off, name) 147: off_t off; 148: char *name; 149: { 150: struct tcpstat tcpstat; 151: 152: if (off == 0) 153: return; 154: printf ("%s:\n", name); 155: klseek(kmem, off, 0); 156: read(kmem, (char *)&tcpstat, sizeof (tcpstat)); 157: 158: #define p(f, m) printf(m, tcpstat.f, plural(tcpstat.f)) 159: #define p2(f1, f2, m) printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2)) 160: 161: p(tcps_sndtotal, "\t%ld packet%s sent\n"); 162: p2(tcps_sndpack,tcps_sndbyte, 163: "\t\t%ld data packet%s (%ld byte%s)\n"); 164: p2(tcps_sndrexmitpack, tcps_sndrexmitbyte, 165: "\t\t%ld data packet%s (%ld byte%s) retransmitted\n"); 166: p2(tcps_sndacks, tcps_delack, 167: "\t\t%ld ack-only packet%s (%ld delayed)\n"); 168: p(tcps_sndurg, "\t\t%ld URG only packet%s\n"); 169: p(tcps_sndprobe, "\t\t%ld window probe packet%s\n"); 170: p(tcps_sndwinup, "\t\t%ld window update packet%s\n"); 171: p(tcps_sndctrl, "\t\t%ld control packet%s\n"); 172: p(tcps_rcvtotal, "\t%ld packet%s received\n"); 173: p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%ld ack%s (for %D byte%s)\n"); 174: p(tcps_rcvdupack, "\t\t%ld duplicate ack%s\n"); 175: p(tcps_rcvacktoomuch, "\t\t%ld ack%s for unsent data\n"); 176: p2(tcps_rcvpack, tcps_rcvbyte, 177: "\t\t%ld packet%s (%ld byte%s) received in-sequence\n"); 178: p2(tcps_rcvduppack, tcps_rcvdupbyte, 179: "\t\t%ld completely duplicate packet%s (%ld byte%s)\n"); 180: p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte, 181: "\t\t%ld packet%s with some dup. data (%ld byte%s duped)\n"); 182: p2(tcps_rcvoopack, tcps_rcvoobyte, 183: "\t\t%ld out-of-order packet%s (%ld byte%s)\n"); 184: p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin, 185: "\t\t%ld packet%s (%ld byte%s) of data after window\n"); 186: p(tcps_rcvwinprobe, "\t\t%ld window probe%s\n"); 187: p(tcps_rcvwinupd, "\t\t%ld window update packet%s\n"); 188: p(tcps_rcvafterclose, "\t\t%ld packet%s received after close\n"); 189: p(tcps_rcvbadsum, "\t\t%ld discarded for bad checksum%s\n"); 190: p(tcps_rcvbadoff, "\t\t%ld discarded for bad header offset field%s\n"); 191: p(tcps_rcvshort, "\t\t%ld discarded because packet too short\n"); 192: p(tcps_connattempt, "\t%ld connection request%s\n"); 193: p(tcps_accepts, "\t%ld connection accept%s\n"); 194: p(tcps_connects, "\t%D connection%s established (including accepts)\n"); 195: p2(tcps_closed, tcps_drops, 196: "\t%ld connection%s closed (including %ld drop%s)\n"); 197: p(tcps_conndrops, "\t%ld embryonic connection%s dropped\n"); 198: p2(tcps_rttupdated, tcps_segstimed, 199: "\t%ld segment%s updated rtt (of %ld attempt%s)\n"); 200: p(tcps_rexmttimeo, "\t%ld retransmit timeout%s\n"); 201: p(tcps_timeoutdrop, "\t\t%ld connection%s dropped by rexmit timeout\n"); 202: p(tcps_persisttimeo, "\t%ld persist timeout%s\n"); 203: p(tcps_keeptimeo, "\t%ld keepalive timeout%s\n"); 204: p(tcps_keepprobe, "\t\t%ld keepalive probe%s sent\n"); 205: p(tcps_keepdrops, "\t\t%ld connection%s dropped by keepalive\n"); 206: #undef p 207: #undef p2 208: } 209: 210: /* 211: * Dump UDP statistics structure. 212: */ 213: udp_stats(off, name) 214: off_t off; 215: char *name; 216: { 217: struct udpstat udpstat; 218: 219: if (off == 0) 220: return; 221: klseek(kmem, off, 0); 222: read(kmem, (char *)&udpstat, sizeof (udpstat)); 223: printf("%s:\n", name); 224: #define p(f, m) printf(m, udpstat.f, plural(udpstat.f)) 225: p(udps_hdrops, "\t%lu incomplete header%s\n"); 226: p(udps_badlen, "\t%lu bad data length field%s\n"); 227: p(udps_badsum, "\t%lu bad checksum%s\n"); 228: p(udps_noport, "\t%lu no port%s\n"); 229: p(udps_noportbcast, "\t%lu (arrived as bcast) no port%s\n"); 230: #undef p 231: } 232: 233: /* 234: * Dump IP statistics structure. 235: */ 236: ip_stats(off, name) 237: off_t off; 238: char *name; 239: { 240: struct ipstat ipstat; 241: 242: if (off == 0) 243: return; 244: klseek(kmem, off, 0); 245: read(kmem, (char *)&ipstat, sizeof (ipstat)); 246: #if BSD>=43 247: printf("%s:\n\t%lu total packets received\n", name, 248: ipstat.ips_total); 249: #endif 250: printf("\t%lu bad header checksum%s\n", 251: ipstat.ips_badsum, plural(ipstat.ips_badsum)); 252: printf("\t%lu with size smaller than minimum\n", ipstat.ips_toosmall); 253: printf("\t%lu with data size < data length\n", ipstat.ips_tooshort); 254: printf("\t%lu with header length < data size\n", ipstat.ips_badhlen); 255: printf("\t%lu with data length < header length\n", ipstat.ips_badlen); 256: #if BSD>=43 257: printf("\t%lu fragment%s received\n", 258: ipstat.ips_fragments, plural(ipstat.ips_fragments)); 259: printf("\t%lu fragment%s dropped (dup or out of space)\n", 260: ipstat.ips_fragdropped, plural(ipstat.ips_fragdropped)); 261: printf("\t%lu fragment%s dropped after timeout\n", 262: ipstat.ips_fragtimeout, plural(ipstat.ips_fragtimeout)); 263: printf("\t%lu packet%s forwarded\n", 264: ipstat.ips_forward, plural(ipstat.ips_forward)); 265: printf("\t%lu packet%s not forwardable\n", 266: ipstat.ips_cantforward, plural(ipstat.ips_cantforward)); 267: printf("\t%lu redirect%s sent\n", 268: ipstat.ips_redirectsent, plural(ipstat.ips_redirectsent)); 269: #endif 270: } 271: 272: static char *icmpnames[] = { 273: "echo reply", 274: "#1", 275: "#2", 276: "destination unreachable", 277: "source quench", 278: "routing redirect", 279: "#6", 280: "#7", 281: "echo", 282: "#9", 283: "#10", 284: "time exceeded", 285: "parameter problem", 286: "time stamp", 287: "time stamp reply", 288: "information request", 289: "information request reply", 290: "address mask request", 291: "address mask reply", 292: }; 293: 294: /* 295: * Dump ICMP statistics. 296: */ 297: icmp_stats(off, name) 298: off_t off; 299: char *name; 300: { 301: struct icmpstat icmpstat; 302: register int i, first; 303: 304: if (off == 0) 305: return; 306: klseek(kmem, off, 0); 307: read(kmem, (char *)&icmpstat, sizeof (icmpstat)); 308: printf("%s:\n\t%lu call%s to icmp_error\n", name, 309: icmpstat.icps_error, plural(icmpstat.icps_error)); 310: printf("\t%lu error%s not generated 'cuz old message was icmp\n", 311: icmpstat.icps_oldicmp, plural(icmpstat.icps_oldicmp)); 312: for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) 313: if (icmpstat.icps_outhist[i] != 0) { 314: if (first) { 315: printf("\tOutput histogram:\n"); 316: first = 0; 317: } 318: printf("\t\t%s: %lu\n", icmpnames[i], 319: icmpstat.icps_outhist[i]); 320: } 321: printf("\t%lu message%s with bad code fields\n", 322: icmpstat.icps_badcode, plural(icmpstat.icps_badcode)); 323: printf("\t%lu message%s < minimum length\n", 324: icmpstat.icps_tooshort, plural(icmpstat.icps_tooshort)); 325: printf("\t%lu bad checksum%s\n", 326: icmpstat.icps_checksum, plural(icmpstat.icps_checksum)); 327: printf("\t%lu message%s with bad length\n", 328: icmpstat.icps_badlen, plural(icmpstat.icps_badlen)); 329: for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) 330: if (icmpstat.icps_inhist[i] != 0) { 331: if (first) { 332: printf("\tInput histogram:\n"); 333: first = 0; 334: } 335: printf("\t\t%s: %lu\n", icmpnames[i], 336: icmpstat.icps_inhist[i]); 337: } 338: printf("\t%lu message response%s generated\n", 339: icmpstat.icps_reflect, plural(icmpstat.icps_reflect)); 340: } 341: 342: /* 343: * Pretty print an Internet address (net address + port). 344: * If the nflag was specified, use numbers instead of names. 345: */ 346: inetprint(in, port, proto) 347: register struct in_addr *in; 348: u_short port; 349: char *proto; 350: { 351: struct servent *sp = 0; 352: char line[80], *cp, *index(); 353: int width; 354: 355: sprintf(line, "%.*s.", (Aflag && !nflag) ? 12 : 16, inetname(*in)); 356: cp = index(line, '\0'); 357: if (!nflag && port) 358: sp = getservbyport((int)port, proto); 359: if (sp || port == 0) 360: sprintf(cp, "%.8s", sp ? sp->s_name : "*"); 361: else 362: sprintf(cp, "%u", ntohs((u_short)port)); 363: width = Aflag ? 18 : 22; 364: printf(" %-*.*s", width, width, line); 365: } 366: 367: /* 368: * Construct an Internet address representation. 369: * If the nflag has been supplied, give 370: * numeric value, otherwise try for symbolic name. 371: */ 372: char * 373: inetname(in) 374: struct in_addr in; 375: { 376: register char *cp; 377: static char line[50]; 378: struct hostent *hp; 379: struct netent *np; 380: static char domain[MAXHOSTNAMELEN + 1]; 381: static int first = 1; 382: 383: if (first && !nflag) { 384: first = 0; 385: if (gethostname(domain, MAXHOSTNAMELEN) == 0 && 386: (cp = index(domain, '.'))) 387: (void) strcpy(domain, cp + 1); 388: else 389: domain[0] = 0; 390: } 391: cp = 0; 392: if (!nflag && in.s_addr != INADDR_ANY) { 393: u_long net = inet_netof(in); 394: u_long lna = inet_lnaof(in); 395: 396: if (lna == INADDR_ANY) { 397: np = getnetbyaddr(net, AF_INET); 398: if (np) 399: cp = np->n_name; 400: } 401: if (cp == 0) { 402: hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET); 403: if (hp) { 404: if ((cp = index(hp->h_name, '.')) && 405: !strcmp(cp + 1, domain)) 406: *cp = 0; 407: cp = hp->h_name; 408: } 409: } 410: } 411: if (in.s_addr == INADDR_ANY) 412: strcpy(line, "*"); 413: else if (cp) 414: strcpy(line, cp); 415: else { 416: in.s_addr = ntohl(in.s_addr); 417: #define C(x) (u_char)((x) & 0xff) 418: sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24), 419: C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr)); 420: } 421: return (line); 422: }