| 1 | #ifndef lint |
| 2 | static char sccsid[] = "@(#)inet.c 4.6 82/12/05"; |
| 3 | #endif |
| 4 | |
| 5 | #include <sys/types.h> |
| 6 | #include <sys/socket.h> |
| 7 | #include <sys/socketvar.h> |
| 8 | #include <sys/mbuf.h> |
| 9 | #include <sys/protosw.h> |
| 10 | |
| 11 | #include <net/route.h> |
| 12 | #include <netinet/in.h> |
| 13 | #include <netinet/in_systm.h> |
| 14 | #include <netinet/in_pcb.h> |
| 15 | #include <netinet/ip.h> |
| 16 | #include <netinet/ip_icmp.h> |
| 17 | #include <netinet/ip_var.h> |
| 18 | #include <netinet/tcp.h> |
| 19 | #include <netinet/tcpip.h> |
| 20 | #include <netinet/tcp_seq.h> |
| 21 | #define TCPSTATES |
| 22 | #include <netinet/tcp_fsm.h> |
| 23 | #include <netinet/tcp_timer.h> |
| 24 | #include <netinet/tcp_var.h> |
| 25 | #include <netinet/tcp_debug.h> |
| 26 | #include <netinet/udp.h> |
| 27 | #include <netinet/udp_var.h> |
| 28 | |
| 29 | #include <netdb.h> |
| 30 | |
| 31 | struct inpcb inpcb; |
| 32 | struct tcpcb tcpcb; |
| 33 | struct socket socket; |
| 34 | struct protosw proto; |
| 35 | extern int kmem; |
| 36 | extern int Aflag; |
| 37 | extern int aflag; |
| 38 | extern int nflag; |
| 39 | |
| 40 | static int first = 1; |
| 41 | char *inetname(); |
| 42 | |
| 43 | /* |
| 44 | * Print a summary of connections related to an Internet |
| 45 | * protocol. For TCP, also give state of connection. |
| 46 | * Listening processes (aflag) are suppressed unless the |
| 47 | * -a (all) flag is specified. |
| 48 | */ |
| 49 | protopr(off, name) |
| 50 | off_t off; |
| 51 | char *name; |
| 52 | { |
| 53 | struct inpcb cb; |
| 54 | register struct inpcb *prev, *next; |
| 55 | int istcp; |
| 56 | |
| 57 | if (off == 0) { |
| 58 | printf("%s control block: symbol not in namelist\n", name); |
| 59 | return; |
| 60 | } |
| 61 | istcp = strcmp(name, "tcp") == 0; |
| 62 | klseek(kmem, off, 0); |
| 63 | read(kmem, &cb, sizeof (struct inpcb)); |
| 64 | inpcb = cb; |
| 65 | prev = (struct inpcb *)off; |
| 66 | if (first) { |
| 67 | printf("Active connections"); |
| 68 | if (aflag) |
| 69 | printf(" (including servers)"); |
| 70 | putchar('\n'); |
| 71 | if (Aflag) |
| 72 | printf("%-8.8s ", "PCB"); |
| 73 | printf("%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n", |
| 74 | "Proto", "Recv-Q", "Send-Q", |
| 75 | "Local Address", "Foreign Address", "(state)"); |
| 76 | first = 0; |
| 77 | } |
| 78 | while (inpcb.inp_next != (struct inpcb *)off) { |
| 79 | char *cp; |
| 80 | |
| 81 | next = inpcb.inp_next; |
| 82 | klseek(kmem, (off_t)next, 0); |
| 83 | read(kmem, &inpcb, sizeof (inpcb)); |
| 84 | if (inpcb.inp_prev != prev) { |
| 85 | printf("???\n"); |
| 86 | break; |
| 87 | } |
| 88 | if (!aflag && |
| 89 | inet_lnaof(inpcb.inp_laddr.s_addr) == INADDR_ANY) { |
| 90 | prev = next; |
| 91 | continue; |
| 92 | } |
| 93 | klseek(kmem, (off_t)inpcb.inp_socket, 0); |
| 94 | read(kmem, &socket, sizeof (socket)); |
| 95 | if (istcp) { |
| 96 | klseek(kmem, (off_t)inpcb.inp_ppcb, 0); |
| 97 | read(kmem, &tcpcb, sizeof (tcpcb)); |
| 98 | } |
| 99 | if (Aflag) |
| 100 | printf("%8x ", inpcb.inp_ppcb); |
| 101 | printf("%-5.5s %6d %6d ", name, socket.so_rcv.sb_cc, |
| 102 | socket.so_snd.sb_cc); |
| 103 | inetprint(&inpcb.inp_laddr, inpcb.inp_lport, name); |
| 104 | inetprint(&inpcb.inp_faddr, inpcb.inp_fport, name); |
| 105 | if (istcp) { |
| 106 | if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES) |
| 107 | printf(" %d", tcpcb.t_state); |
| 108 | else |
| 109 | printf(" %s", tcpstates[tcpcb.t_state]); |
| 110 | } |
| 111 | putchar('\n'); |
| 112 | prev = next; |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | /* |
| 117 | * Dump TCP statistics structure. |
| 118 | */ |
| 119 | tcp_stats(off, name) |
| 120 | off_t off; |
| 121 | char *name; |
| 122 | { |
| 123 | struct tcpstat tcpstat; |
| 124 | |
| 125 | if (off == 0) { |
| 126 | printf("%sstat: symbol not in namelist\n", name); |
| 127 | return; |
| 128 | } |
| 129 | klseek(kmem, off, 0); |
| 130 | read(kmem, (char *)&tcpstat, sizeof (tcpstat)); |
| 131 | printf("%s:\n\t%d bad header checksums\n", name, tcpstat.tcps_badsum); |
| 132 | printf("\t%d bad header offset fields\n", tcpstat.tcps_badoff); |
| 133 | printf("\t%d incomplete headers\n", tcpstat.tcps_hdrops); |
| 134 | #ifdef notdef |
| 135 | printf("\t%d bad segments\n", tcpstat.tcps_badsegs); |
| 136 | printf("\t%d unacknowledged packets\n", tcpstat.tcps_unack); |
| 137 | #endif |
| 138 | } |
| 139 | |
| 140 | /* |
| 141 | * Dump UDP statistics structure. |
| 142 | */ |
| 143 | udp_stats(off, name) |
| 144 | off_t off; |
| 145 | char *name; |
| 146 | { |
| 147 | struct udpstat udpstat; |
| 148 | |
| 149 | if (off == 0) { |
| 150 | printf("%sstat: symbol not in namelist\n", name); |
| 151 | return; |
| 152 | } |
| 153 | klseek(kmem, off, 0); |
| 154 | read(kmem, (char *)&udpstat, sizeof (udpstat)); |
| 155 | printf("%s:\n\t%d bad header checksums\n", name, udpstat.udps_badsum); |
| 156 | printf("\t%d incomplete headers\n", udpstat.udps_hdrops); |
| 157 | printf("\t%d bad data length fields\n", udpstat.udps_badlen); |
| 158 | } |
| 159 | |
| 160 | /* |
| 161 | * Dump IP statistics structure. |
| 162 | */ |
| 163 | ip_stats(off, name) |
| 164 | off_t off; |
| 165 | char *name; |
| 166 | { |
| 167 | struct ipstat ipstat; |
| 168 | |
| 169 | if (off == 0) { |
| 170 | printf("%sstat: symbol not in namelist\n", name); |
| 171 | return; |
| 172 | } |
| 173 | klseek(kmem, off, 0); |
| 174 | read(kmem, (char *)&ipstat, sizeof (ipstat)); |
| 175 | printf("%s:\n\t%d bad header checksums\n", name, ipstat.ips_badsum); |
| 176 | printf("\t%d incomplete packets\n", ipstat.ips_tooshort); |
| 177 | } |
| 178 | |
| 179 | /* |
| 180 | * Pretty print an Internet address (net address + port). |
| 181 | * If the nflag was specified, use numbers instead of names. |
| 182 | */ |
| 183 | inetprint(in, port, proto) |
| 184 | register struct in_addr *in; |
| 185 | int port; |
| 186 | char *proto; |
| 187 | { |
| 188 | struct servent *sp = 0; |
| 189 | char line[80], *cp, *index(); |
| 190 | |
| 191 | sprintf(line, "%.10s.", inetname(*in)); |
| 192 | cp = index(line, '\0'); |
| 193 | #if vax || pdp11 |
| 194 | port = ntohs((u_short)port); |
| 195 | #endif |
| 196 | if (!nflag && port) |
| 197 | sp = getservbyport(port, proto); |
| 198 | if (sp || port == 0) |
| 199 | sprintf(cp, "%.8s", sp ? sp->s_name : "*"); |
| 200 | else |
| 201 | sprintf(cp, "%d", port); |
| 202 | printf(" %-18.18s", line); |
| 203 | } |
| 204 | |
| 205 | /* |
| 206 | * Construct an Internet address representation. |
| 207 | * If the nflag has been supplied, give |
| 208 | * numeric value, otherwise try for symbolic name. |
| 209 | */ |
| 210 | char * |
| 211 | inetname(in) |
| 212 | struct in_addr in; |
| 213 | { |
| 214 | char *cp = 0; |
| 215 | static char line[50]; |
| 216 | |
| 217 | if (!nflag) { |
| 218 | if (inet_lnaof(in) == INADDR_ANY) { |
| 219 | struct netent *np; |
| 220 | |
| 221 | np = getnetbyaddr(inet_netof(in), AF_INET); |
| 222 | if (np) |
| 223 | cp = np->n_name; |
| 224 | } else { |
| 225 | struct hostent *hp; |
| 226 | |
| 227 | hp = gethostbyaddr(&in, sizeof (struct in_addr), |
| 228 | AF_INET); |
| 229 | if (hp) |
| 230 | cp = hp->h_name; |
| 231 | } |
| 232 | } |
| 233 | if (in.s_addr == INADDR_ANY) |
| 234 | strcpy(line, "*"); |
| 235 | else if (cp) |
| 236 | strcpy(line, cp); |
| 237 | else { |
| 238 | u_char *ucp = (u_char *)∈ |
| 239 | sprintf(line, "%u.%u.%u.%u", ucp[0], ucp[1], ucp[2], ucp[3]); |
| 240 | } |
| 241 | return (line); |
| 242 | } |