1*21987Sdist /* 2*21987Sdist * Copyright (c) 1983 Regents of the University of California. 3*21987Sdist * All rights reserved. The Berkeley software License Agreement 4*21987Sdist * specifies the terms and conditions for redistribution. 5*21987Sdist */ 6*21987Sdist 77906Ssam #ifndef lint 8*21987Sdist static char sccsid[] = "@(#)inet.c 5.1 (Berkeley) 06/04/85"; 9*21987Sdist #endif not lint 107906Ssam 117906Ssam #include <sys/types.h> 127906Ssam #include <sys/socket.h> 137906Ssam #include <sys/socketvar.h> 147906Ssam #include <sys/mbuf.h> 157906Ssam #include <sys/protosw.h> 169204Ssam 177906Ssam #include <net/route.h> 189204Ssam #include <netinet/in.h> 199204Ssam #include <netinet/in_systm.h> 209204Ssam #include <netinet/in_pcb.h> 219204Ssam #include <netinet/ip.h> 229204Ssam #include <netinet/ip_icmp.h> 2311536Ssam #include <netinet/icmp_var.h> 249204Ssam #include <netinet/ip_var.h> 259204Ssam #include <netinet/tcp.h> 269204Ssam #include <netinet/tcpip.h> 279204Ssam #include <netinet/tcp_seq.h> 287906Ssam #define TCPSTATES 299204Ssam #include <netinet/tcp_fsm.h> 309204Ssam #include <netinet/tcp_timer.h> 319204Ssam #include <netinet/tcp_var.h> 329204Ssam #include <netinet/tcp_debug.h> 339204Ssam #include <netinet/udp.h> 349204Ssam #include <netinet/udp_var.h> 359204Ssam 367906Ssam #include <netdb.h> 377906Ssam 387906Ssam struct inpcb inpcb; 397906Ssam struct tcpcb tcpcb; 4021907Skarels struct socket sockb; 417906Ssam struct protosw proto; 427906Ssam extern int kmem; 437906Ssam extern int Aflag; 447906Ssam extern int aflag; 457906Ssam extern int nflag; 467906Ssam 477906Ssam static int first = 1; 487906Ssam char *inetname(); 497906Ssam 507906Ssam /* 517906Ssam * Print a summary of connections related to an Internet 527906Ssam * protocol. For TCP, also give state of connection. 537906Ssam * Listening processes (aflag) are suppressed unless the 547906Ssam * -a (all) flag is specified. 557906Ssam */ 567906Ssam protopr(off, name) 577906Ssam off_t off; 587906Ssam char *name; 597906Ssam { 607906Ssam struct inpcb cb; 617906Ssam register struct inpcb *prev, *next; 627906Ssam int istcp; 637906Ssam 647906Ssam if (off == 0) { 657906Ssam printf("%s control block: symbol not in namelist\n", name); 667906Ssam return; 677906Ssam } 687906Ssam istcp = strcmp(name, "tcp") == 0; 697906Ssam klseek(kmem, off, 0); 707906Ssam read(kmem, &cb, sizeof (struct inpcb)); 717906Ssam inpcb = cb; 727906Ssam prev = (struct inpcb *)off; 737906Ssam if (first) { 747906Ssam printf("Active connections"); 757906Ssam if (aflag) 767906Ssam printf(" (including servers)"); 777906Ssam putchar('\n'); 787906Ssam if (Aflag) 797906Ssam printf("%-8.8s ", "PCB"); 8017312Skarels printf(Aflag ? "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" : 8117312Skarels "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n", 827906Ssam "Proto", "Recv-Q", "Send-Q", 837906Ssam "Local Address", "Foreign Address", "(state)"); 847906Ssam first = 0; 857906Ssam } 867906Ssam while (inpcb.inp_next != (struct inpcb *)off) { 877906Ssam char *cp; 887906Ssam 897906Ssam next = inpcb.inp_next; 907906Ssam klseek(kmem, (off_t)next, 0); 917906Ssam read(kmem, &inpcb, sizeof (inpcb)); 927906Ssam if (inpcb.inp_prev != prev) { 937906Ssam printf("???\n"); 947906Ssam break; 957906Ssam } 967906Ssam if (!aflag && 978366Ssam inet_lnaof(inpcb.inp_laddr.s_addr) == INADDR_ANY) { 987906Ssam prev = next; 997906Ssam continue; 1007906Ssam } 1017906Ssam klseek(kmem, (off_t)inpcb.inp_socket, 0); 10221907Skarels read(kmem, &sockb, sizeof (sockb)); 1037906Ssam if (istcp) { 1047906Ssam klseek(kmem, (off_t)inpcb.inp_ppcb, 0); 1057906Ssam read(kmem, &tcpcb, sizeof (tcpcb)); 1067906Ssam } 1077906Ssam if (Aflag) 1087906Ssam printf("%8x ", inpcb.inp_ppcb); 10921907Skarels printf("%-5.5s %6d %6d ", name, sockb.so_rcv.sb_cc, 11021907Skarels sockb.so_snd.sb_cc); 1117906Ssam inetprint(&inpcb.inp_laddr, inpcb.inp_lport, name); 1127906Ssam inetprint(&inpcb.inp_faddr, inpcb.inp_fport, name); 1137906Ssam if (istcp) { 1147906Ssam if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES) 1157906Ssam printf(" %d", tcpcb.t_state); 1167906Ssam else 1177906Ssam printf(" %s", tcpstates[tcpcb.t_state]); 1187906Ssam } 1197906Ssam putchar('\n'); 1207906Ssam prev = next; 1217906Ssam } 1227906Ssam } 1237906Ssam 1247906Ssam /* 1259569Ssam * Dump TCP statistics structure. 1269569Ssam */ 1279569Ssam tcp_stats(off, name) 1289569Ssam off_t off; 1299569Ssam char *name; 1309569Ssam { 1319569Ssam struct tcpstat tcpstat; 1329569Ssam 1339569Ssam if (off == 0) { 1349569Ssam printf("%sstat: symbol not in namelist\n", name); 1359569Ssam return; 1369569Ssam } 1379569Ssam klseek(kmem, off, 0); 1389569Ssam read(kmem, (char *)&tcpstat, sizeof (tcpstat)); 13912838Ssam printf("%s:\n\t%d bad header checksum%s\n", name, 14012838Ssam tcpstat.tcps_badsum, plural(tcpstat.tcps_badsum)); 14112838Ssam printf("\t%d bad header offset field%s\n", 14212838Ssam tcpstat.tcps_badoff, plural(tcpstat.tcps_badoff)); 14312838Ssam printf("\t%d incomplete header%s\n", 14412838Ssam tcpstat.tcps_hdrops, plural(tcpstat.tcps_hdrops)); 1459569Ssam #ifdef notdef 14612838Ssam printf("\t%d bad segment%s\n", 14712838Ssam tcpstat.tcps_badsegs, plural(tcpstat.badsegs)); 14812838Ssam printf("\t%d unacknowledged packet%s\n", 14912838Ssam tcpstat.tcps_unack, plural(tcpstat.tcps_unack)); 1509569Ssam #endif 1519569Ssam } 1529569Ssam 1539569Ssam /* 1549569Ssam * Dump UDP statistics structure. 1559569Ssam */ 1569569Ssam udp_stats(off, name) 1579569Ssam off_t off; 1589569Ssam char *name; 1599569Ssam { 1609569Ssam struct udpstat udpstat; 1619569Ssam 1629569Ssam if (off == 0) { 1639569Ssam printf("%sstat: symbol not in namelist\n", name); 1649569Ssam return; 1659569Ssam } 1669569Ssam klseek(kmem, off, 0); 1679569Ssam read(kmem, (char *)&udpstat, sizeof (udpstat)); 16812838Ssam printf("%s:\n\t%d bad header checksum%s\n", name, 16912838Ssam udpstat.udps_badsum, plural(udpstat.udps_badsum)); 17012838Ssam printf("\t%d incomplete header%s\n", 17112838Ssam udpstat.udps_hdrops, plural(udpstat.udps_hdrops)); 17212838Ssam printf("\t%d bad data length field%s\n", 17312838Ssam udpstat.udps_badlen, plural(udpstat.udps_badlen)); 1749569Ssam } 1759569Ssam 1769569Ssam /* 1779569Ssam * Dump IP statistics structure. 1789569Ssam */ 1799569Ssam ip_stats(off, name) 1809569Ssam off_t off; 1819569Ssam char *name; 1829569Ssam { 1839569Ssam struct ipstat ipstat; 1849569Ssam 1859569Ssam if (off == 0) { 1869569Ssam printf("%sstat: symbol not in namelist\n", name); 1879569Ssam return; 1889569Ssam } 1899569Ssam klseek(kmem, off, 0); 1909569Ssam read(kmem, (char *)&ipstat, sizeof (ipstat)); 19112838Ssam printf("%s:\n\t%d bad header checksum%s\n", name, 19212838Ssam ipstat.ips_badsum, plural(ipstat.ips_badsum)); 19312838Ssam printf("\t%d with size smaller than minimum\n", ipstat.ips_tooshort); 19412838Ssam printf("\t%d with data size < data length\n", ipstat.ips_toosmall); 19512838Ssam printf("\t%d with header length < data size\n", ipstat.ips_badhlen); 19612838Ssam printf("\t%d with data length < header length\n", ipstat.ips_badlen); 1979569Ssam } 1989569Ssam 19911536Ssam static char *icmpnames[] = { 20011536Ssam "echo reply", 20111536Ssam "#1", 20211536Ssam "#2", 20311536Ssam "destination unreachable", 20411536Ssam "source quench", 20511536Ssam "routing redirect", 20611536Ssam "#6", 20711536Ssam "#7", 20811536Ssam "echo", 20911536Ssam "#9", 21011536Ssam "#10", 21111536Ssam "time exceeded", 21211536Ssam "parameter problem", 21311536Ssam "time stamp", 21411536Ssam "time stamp reply", 21511536Ssam "information request", 21611536Ssam "information request reply" 21711536Ssam }; 21811536Ssam 2199569Ssam /* 22011536Ssam * Dump ICMP statistics. 22111536Ssam */ 22211536Ssam icmp_stats(off, name) 22311536Ssam off_t off; 22411536Ssam char *name; 22511536Ssam { 22611536Ssam struct icmpstat icmpstat; 22711536Ssam register int i, first; 22811536Ssam 22911536Ssam if (off == 0) { 23011536Ssam printf("%sstat: symbol not in namelist\n", name); 23111536Ssam return; 23211536Ssam } 23311536Ssam klseek(kmem, off, 0); 23411536Ssam read(kmem, (char *)&icmpstat, sizeof (icmpstat)); 23512838Ssam printf("%s:\n\t%d call%s to icmp_error\n", name, 23612838Ssam icmpstat.icps_error, plural(icmpstat.icps_error)); 23712838Ssam printf("\t%d error%s not generated 'cuz old message too short\n", 23812838Ssam icmpstat.icps_oldshort, plural(icmpstat.icps_oldshort)); 23912838Ssam printf("\t%d error%s not generated 'cuz old message was icmp\n", 24012838Ssam icmpstat.icps_oldicmp, plural(icmpstat.icps_oldicmp)); 24111537Ssam for (first = 1, i = 0; i < ICMP_IREQREPLY + 1; i++) 24211536Ssam if (icmpstat.icps_outhist[i] != 0) { 24311536Ssam if (first) { 24411536Ssam printf("\tOutput histogram:\n"); 24511536Ssam first = 0; 24611536Ssam } 24711536Ssam printf("\t\t%s: %d\n", icmpnames[i], 24811536Ssam icmpstat.icps_outhist[i]); 24911536Ssam } 25015043Ssam printf("\t%d message%s with bad code fields\n", 25115043Ssam icmpstat.icps_badcode, plural(icmpstat.icps_badcode)); 25212838Ssam printf("\t%d message%s < minimum length\n", 25312838Ssam icmpstat.icps_tooshort, plural(icmpstat.icps_tooshort)); 25415000Ssam printf("\t%d bad checksum%s\n", 25515000Ssam icmpstat.icps_checksum, plural(icmpstat.icps_checksum)); 25612838Ssam printf("\t%d message%s with bad length\n", 25712838Ssam icmpstat.icps_badlen, plural(icmpstat.icps_badlen)); 25812838Ssam printf("\t%d message response%s generated\n", 25912838Ssam icmpstat.icps_reflect, plural(icmpstat.icps_reflect)); 26011537Ssam for (first = 1, i = 0; i < ICMP_IREQREPLY + 1; i++) 26111536Ssam if (icmpstat.icps_inhist[i] != 0) { 26211536Ssam if (first) { 26311536Ssam printf("\tInput histogram:\n"); 26411536Ssam first = 0; 26511536Ssam } 26611536Ssam printf("\t\t%s: %d\n", icmpnames[i], 26711536Ssam icmpstat.icps_inhist[i]); 26811536Ssam } 26911536Ssam } 27011536Ssam 27111536Ssam /* 2727906Ssam * Pretty print an Internet address (net address + port). 2737906Ssam * If the nflag was specified, use numbers instead of names. 2747906Ssam */ 2757906Ssam inetprint(in, port, proto) 2767906Ssam register struct in_addr *in; 2777906Ssam int port; 2787906Ssam char *proto; 2797906Ssam { 2807906Ssam struct servent *sp = 0; 2817906Ssam char line[80], *cp, *index(); 28217312Skarels int width; 2837906Ssam 28417312Skarels sprintf(line, "%.*s.", Aflag ? 10 : 16, inetname(*in)); 2857906Ssam cp = index(line, '\0'); 2867906Ssam if (!nflag && port) 2878323Ssam sp = getservbyport(port, proto); 2887906Ssam if (sp || port == 0) 2897906Ssam sprintf(cp, "%.8s", sp ? sp->s_name : "*"); 2907906Ssam else 2919835Ssam sprintf(cp, "%d", ntohs((u_short)port)); 29217312Skarels width = Aflag ? 18 : 22; 29317312Skarels printf(" %-*.*s", width, width, line); 2947906Ssam } 2957906Ssam 2967906Ssam /* 2977906Ssam * Construct an Internet address representation. 2987906Ssam * If the nflag has been supplied, give 2997906Ssam * numeric value, otherwise try for symbolic name. 3007906Ssam */ 3017906Ssam char * 3027906Ssam inetname(in) 3037906Ssam struct in_addr in; 3047906Ssam { 3057906Ssam char *cp = 0; 3067906Ssam static char line[50]; 30716501Skarels struct hostent *hp; 30816501Skarels struct netent *np; 3097906Ssam 31016662Ssam if (!nflag && in.s_addr != INADDR_ANY) { 31121907Skarels int net = inet_netof(in); 31216501Skarels int lna = inet_lnaof(in); 31316662Ssam 31416501Skarels if (lna == INADDR_ANY) { 31516462Skarels np = getnetbyaddr(net, AF_INET); 3167906Ssam if (np) 3177906Ssam cp = np->n_name; 31821907Skarels } 31921907Skarels if (cp == 0) { 32016662Ssam hp = gethostbyaddr(&in, sizeof (in), AF_INET); 3217906Ssam if (hp) 3227906Ssam cp = hp->h_name; 3237906Ssam } 3247906Ssam } 3257906Ssam if (in.s_addr == INADDR_ANY) 3267906Ssam strcpy(line, "*"); 3277906Ssam else if (cp) 3287906Ssam strcpy(line, cp); 3297906Ssam else { 33021907Skarels in.s_addr = ntohl(in.s_addr); 33121907Skarels #define C(x) ((x) & 0xff) 33221907Skarels sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24), 33321907Skarels C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr)); 3347906Ssam } 3357906Ssam return (line); 3367906Ssam } 337