1 /* $OpenBSD: inet.c,v 1.33 1999/04/11 19:41:40 niklas Exp $ */ 2 /* $NetBSD: inet.c,v 1.14 1995/10/03 21:42:37 thorpej Exp $ */ 3 4 /* 5 * Copyright (c) 1983, 1988, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #ifndef lint 38 #if 0 39 static char sccsid[] = "from: @(#)inet.c 8.4 (Berkeley) 4/20/94"; 40 #else 41 static char *rcsid = "$OpenBSD: inet.c,v 1.33 1999/04/11 19:41:40 niklas Exp $"; 42 #endif 43 #endif /* not lint */ 44 45 #include <sys/param.h> 46 #include <sys/queue.h> 47 #include <sys/socket.h> 48 #include <sys/socketvar.h> 49 #include <sys/mbuf.h> 50 #include <sys/protosw.h> 51 52 #include <net/route.h> 53 #include <netinet/in.h> 54 #include <netinet/in_systm.h> 55 #include <netinet/ip.h> 56 #include <netinet/in_pcb.h> 57 #include <netinet/ip_icmp.h> 58 #include <netinet/icmp_var.h> 59 #include <netinet/igmp_var.h> 60 #include <netinet/ip_var.h> 61 #include <netinet/tcp.h> 62 #include <netinet/tcpip.h> 63 #include <netinet/tcp_seq.h> 64 #define TCPSTATES 65 #include <netinet/tcp_fsm.h> 66 #include <netinet/tcp_timer.h> 67 #include <netinet/tcp_var.h> 68 #include <netinet/tcp_debug.h> 69 #include <netinet/udp.h> 70 #include <netinet/udp_var.h> 71 #include <netinet/ip_ipsp.h> 72 #include <netinet/ip_ah.h> 73 #include <netinet/ip_esp.h> 74 #include <netinet/ip_ip4.h> 75 76 #include <arpa/inet.h> 77 #include <limits.h> 78 #include <netdb.h> 79 #include <stdio.h> 80 #include <string.h> 81 #include <unistd.h> 82 #include <stdlib.h> 83 #include "netstat.h" 84 85 #include <rpc/rpc.h> 86 #include <rpc/pmap_prot.h> 87 #include <rpc/pmap_clnt.h> 88 89 struct inpcb inpcb; 90 struct tcpcb tcpcb; 91 struct socket sockb; 92 93 char *inetname __P((struct in_addr *)); 94 void inetprint __P((struct in_addr *, int, char *, int)); 95 96 /* 97 * Print a summary of connections related to an Internet 98 * protocol. For TCP, also give state of connection. 99 * Listening processes (aflag) are suppressed unless the 100 * -a (all) flag is specified. 101 */ 102 void 103 protopr(off, name) 104 u_long off; 105 char *name; 106 { 107 struct inpcbtable table; 108 register struct inpcb *head, *next, *prev; 109 struct inpcb inpcb; 110 int istcp; 111 static int first = 1; 112 113 if (off == 0) 114 return; 115 istcp = strcmp(name, "tcp") == 0; 116 kread(off, (char *)&table, sizeof table); 117 prev = head = 118 (struct inpcb *)&((struct inpcbtable *)off)->inpt_queue.cqh_first; 119 next = table.inpt_queue.cqh_first; 120 121 while (next != head) { 122 kread((u_long)next, (char *)&inpcb, sizeof inpcb); 123 if (inpcb.inp_queue.cqe_prev != prev) { 124 printf("???\n"); 125 break; 126 } 127 prev = next; 128 next = inpcb.inp_queue.cqe_next; 129 130 if (!aflag && 131 inet_lnaof(inpcb.inp_laddr) == INADDR_ANY) 132 continue; 133 kread((u_long)inpcb.inp_socket, (char *)&sockb, sizeof (sockb)); 134 if (istcp) { 135 kread((u_long)inpcb.inp_ppcb, 136 (char *)&tcpcb, sizeof (tcpcb)); 137 } 138 if (first) { 139 printf("Active Internet connections"); 140 if (aflag) 141 printf(" (including servers)"); 142 putchar('\n'); 143 if (Aflag) 144 printf("%-*.*s %-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n", 145 PLEN, PLEN, "PCB", "Proto", "Recv-Q", 146 "Send-Q", "Local Address", 147 "Foreign Address", "(state)"); 148 else 149 printf("%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n", 150 "Proto", "Recv-Q", "Send-Q", 151 "Local Address", "Foreign Address", 152 "(state)"); 153 first = 0; 154 } 155 if (Aflag) 156 if (istcp) 157 printf("%*p ", PLEN, inpcb.inp_ppcb); 158 else 159 printf("%*p ", PLEN, prev); 160 printf("%-5.5s %6ld %6ld ", name, sockb.so_rcv.sb_cc, 161 sockb.so_snd.sb_cc); 162 inetprint(&inpcb.inp_laddr, (int)inpcb.inp_lport, name, 1); 163 inetprint(&inpcb.inp_faddr, (int)inpcb.inp_fport, name, 0); 164 if (istcp) { 165 if (tcpcb.t_state < 0 || tcpcb.t_state >= TCP_NSTATES) 166 printf(" %d", tcpcb.t_state); 167 else 168 printf(" %s", tcpstates[tcpcb.t_state]); 169 } 170 putchar('\n'); 171 } 172 } 173 174 /* 175 * Dump TCP statistics structure. 176 */ 177 void 178 tcp_stats(off, name) 179 u_long off; 180 char *name; 181 { 182 struct tcpstat tcpstat; 183 184 if (off == 0) 185 return; 186 printf ("%s:\n", name); 187 kread(off, (char *)&tcpstat, sizeof (tcpstat)); 188 189 #define p(f, m) if (tcpstat.f || sflag <= 1) \ 190 printf(m, tcpstat.f, plural(tcpstat.f)) 191 #define p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \ 192 printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2)) 193 #define p3(f, m) if (tcpstat.f || sflag <= 1) \ 194 printf(m, tcpstat.f, plurales(tcpstat.f)) 195 196 p(tcps_sndtotal, "\t%ld packet%s sent\n"); 197 p2(tcps_sndpack,tcps_sndbyte, 198 "\t\t%ld data packet%s (%qd byte%s)\n"); 199 p2(tcps_sndrexmitpack, tcps_sndrexmitbyte, 200 "\t\t%ld data packet%s (%qd byte%s) retransmitted\n"); 201 p(tcps_sndrexmitfast, "\t\t%qd fast retransmitted packet%s\n"); 202 p2(tcps_sndacks, tcps_delack, 203 "\t\t%ld ack-only packet%s (%ld delayed)\n"); 204 p(tcps_sndurg, "\t\t%ld URG only packet%s\n"); 205 p(tcps_sndprobe, "\t\t%ld window probe packet%s\n"); 206 p(tcps_sndwinup, "\t\t%ld window update packet%s\n"); 207 p(tcps_sndctrl, "\t\t%ld control packet%s\n"); 208 p(tcps_rcvtotal, "\t%ld packet%s received\n"); 209 p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%ld ack%s (for %qd byte%s)\n"); 210 p(tcps_rcvdupack, "\t\t%ld duplicate ack%s\n"); 211 p(tcps_rcvacktoomuch, "\t\t%ld ack%s for unsent data\n"); 212 p2(tcps_rcvpack, tcps_rcvbyte, 213 "\t\t%ld packet%s (%qd byte%s) received in-sequence\n"); 214 p2(tcps_rcvduppack, tcps_rcvdupbyte, 215 "\t\t%ld completely duplicate packet%s (%qd byte%s)\n"); 216 p(tcps_pawsdrop, "\t\t%ld old duplicate packet%s\n"); 217 p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte, 218 "\t\t%ld packet%s with some dup. data (%qd byte%s duped)\n"); 219 p2(tcps_rcvoopack, tcps_rcvoobyte, 220 "\t\t%ld out-of-order packet%s (%qd byte%s)\n"); 221 p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin, 222 "\t\t%ld packet%s (%qd byte%s) of data after window\n"); 223 p(tcps_rcvwinprobe, "\t\t%ld window probe%s\n"); 224 p(tcps_rcvwinupd, "\t\t%ld window update packet%s\n"); 225 p(tcps_rcvafterclose, "\t\t%ld packet%s received after close\n"); 226 p(tcps_rcvbadsum, "\t\t%ld discarded for bad checksum%s\n"); 227 p(tcps_rcvbadoff, "\t\t%ld discarded for bad header offset field%s\n"); 228 p(tcps_rcvshort, "\t\t%ld discarded because packet too short\n"); 229 p(tcps_rcvnosec, "\t\t%ld discarded for missing IPSec protection\n"); 230 p(tcps_connattempt, "\t%ld connection request%s\n"); 231 p(tcps_accepts, "\t%ld connection accept%s\n"); 232 p(tcps_connects, "\t%ld connection%s established (including accepts)\n"); 233 p2(tcps_closed, tcps_drops, 234 "\t%ld connection%s closed (including %ld drop%s)\n"); 235 p(tcps_conndrops, "\t%ld embryonic connection%s dropped\n"); 236 p2(tcps_rttupdated, tcps_segstimed, 237 "\t%ld segment%s updated rtt (of %ld attempt%s)\n"); 238 p(tcps_rexmttimeo, "\t%ld retransmit timeout%s\n"); 239 p(tcps_timeoutdrop, "\t\t%ld connection%s dropped by rexmit timeout\n"); 240 p(tcps_persisttimeo, "\t%ld persist timeout%s\n"); 241 p(tcps_keeptimeo, "\t%ld keepalive timeout%s\n"); 242 p(tcps_keepprobe, "\t\t%ld keepalive probe%s sent\n"); 243 p(tcps_keepdrops, "\t\t%ld connection%s dropped by keepalive\n"); 244 p(tcps_predack, "\t%ld correct ACK header prediction%s\n"); 245 p(tcps_preddat, "\t%ld correct data packet header prediction%s\n"); 246 p3(tcps_pcbhashmiss, "\t%ld PCB cache miss%s\n"); 247 p(tcps_badsyn, "\t%ld SYN packet%s received with same src/dst address/port\n"); 248 #undef p 249 #undef p2 250 #undef p3 251 } 252 253 /* 254 * Dump UDP statistics structure. 255 */ 256 void 257 udp_stats(off, name) 258 u_long off; 259 char *name; 260 { 261 struct udpstat udpstat; 262 u_long delivered; 263 264 if (off == 0) 265 return; 266 kread(off, (char *)&udpstat, sizeof (udpstat)); 267 printf("%s:\n", name); 268 #define p(f, m) if (udpstat.f || sflag <= 1) \ 269 printf(m, udpstat.f, plural(udpstat.f)) 270 p(udps_ipackets, "\t%lu datagram%s received\n"); 271 p(udps_hdrops, "\t%lu with incomplete header\n"); 272 p(udps_badlen, "\t%lu with bad data length field\n"); 273 p(udps_badsum, "\t%lu with bad checksum\n"); 274 p(udps_nosum, "\t%lu with no checksum\n"); 275 p(udps_noport, "\t%lu dropped due to no socket\n"); 276 p(udps_noportbcast, "\t%lu broadcast/multicast datagram%s dropped due to no socket\n"); 277 p(udps_nosec, "\t%lu dropped due to missing IPSec protection\n"); 278 p(udps_fullsock, "\t%lu dropped due to full socket buffers\n"); 279 delivered = udpstat.udps_ipackets - 280 udpstat.udps_hdrops - 281 udpstat.udps_badlen - 282 udpstat.udps_badsum - 283 udpstat.udps_noport - 284 udpstat.udps_noportbcast - 285 udpstat.udps_fullsock; 286 if (delivered || sflag <= 1) 287 printf("\t%lu delivered\n", delivered); 288 p(udps_opackets, "\t%lu datagram%s output\n"); 289 p(udps_pcbhashmiss, "\t%lu missed PCB cache\n"); 290 #undef p 291 } 292 293 /* 294 * Dump IP statistics structure. 295 */ 296 void 297 ip_stats(off, name) 298 u_long off; 299 char *name; 300 { 301 struct ipstat ipstat; 302 303 if (off == 0) 304 return; 305 kread(off, (char *)&ipstat, sizeof (ipstat)); 306 printf("%s:\n", name); 307 308 #define p(f, m) if (ipstat.f || sflag <= 1) \ 309 printf(m, ipstat.f, plural(ipstat.f)) 310 311 p(ips_total, "\t%lu total packet%s received\n"); 312 p(ips_badsum, "\t%lu bad header checksum%s\n"); 313 p(ips_toosmall, "\t%lu with size smaller than minimum\n"); 314 p(ips_tooshort, "\t%lu with data size < data length\n"); 315 p(ips_badhlen, "\t%lu with header length < data size\n"); 316 p(ips_badlen, "\t%lu with data length < header length\n"); 317 p(ips_badoptions, "\t%lu with bad options\n"); 318 p(ips_badvers, "\t%lu with incorrect version number\n"); 319 p(ips_fragments, "\t%lu fragment%s received\n"); 320 p(ips_fragdropped, "\t%lu fragment%s dropped (dup or out of space)\n"); 321 p(ips_badfrags, "\t%lu malformed fragment%s dropped\n"); 322 p(ips_fragtimeout, "\t%lu fragment%s dropped after timeout\n"); 323 p(ips_reassembled, "\t%lu packet%s reassembled ok\n"); 324 p(ips_delivered, "\t%lu packet%s for this host\n"); 325 p(ips_noproto, "\t%lu packet%s for unknown/unsupported protocol\n"); 326 p(ips_forward, "\t%lu packet%s forwarded\n"); 327 p(ips_cantforward, "\t%lu packet%s not forwardable\n"); 328 p(ips_redirectsent, "\t%lu redirect%s sent\n"); 329 p(ips_localout, "\t%lu packet%s sent from this host\n"); 330 p(ips_rawout, "\t%lu packet%s sent with fabricated ip header\n"); 331 p(ips_odropped, "\t%lu output packet%s dropped due to no bufs, etc.\n"); 332 p(ips_noroute, "\t%lu output packet%s discarded due to no route\n"); 333 p(ips_fragmented, "\t%lu output datagram%s fragmented\n"); 334 p(ips_ofragments, "\t%lu fragment%s created\n"); 335 p(ips_cantfrag, "\t%lu datagram%s that can't be fragmented\n"); 336 p(ips_rcvmemdrop, "\t%lu fragment floods\n"); 337 #undef p 338 } 339 340 static char *icmpnames[] = { 341 "echo reply", 342 "#1", 343 "#2", 344 "destination unreachable", 345 "source quench", 346 "routing redirect", 347 "#6", 348 "#7", 349 "echo", 350 "router advertisement", 351 "router solicitation", 352 "time exceeded", 353 "parameter problem", 354 "time stamp", 355 "time stamp reply", 356 "information request", 357 "information request reply", 358 "address mask request", 359 "address mask reply", 360 }; 361 362 /* 363 * Dump ICMP statistics. 364 */ 365 void 366 icmp_stats(off, name) 367 u_long off; 368 char *name; 369 { 370 struct icmpstat icmpstat; 371 register int i, first; 372 373 if (off == 0) 374 return; 375 kread(off, (char *)&icmpstat, sizeof (icmpstat)); 376 printf("%s:\n", name); 377 378 #define p(f, m) if (icmpstat.f || sflag <= 1) \ 379 printf(m, icmpstat.f, plural(icmpstat.f)) 380 381 p(icps_error, "\t%lu call%s to icmp_error\n"); 382 p(icps_oldicmp, 383 "\t%lu error%s not generated 'cuz old message was icmp\n"); 384 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) 385 if (icmpstat.icps_outhist[i] != 0) { 386 if (first) { 387 printf("\tOutput histogram:\n"); 388 first = 0; 389 } 390 printf("\t\t%s: %lu\n", icmpnames[i], 391 icmpstat.icps_outhist[i]); 392 } 393 p(icps_badcode, "\t%lu message%s with bad code fields\n"); 394 p(icps_tooshort, "\t%lu message%s < minimum length\n"); 395 p(icps_checksum, "\t%lu bad checksum%s\n"); 396 p(icps_badlen, "\t%lu message%s with bad length\n"); 397 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) 398 if (icmpstat.icps_inhist[i] != 0) { 399 if (first) { 400 printf("\tInput histogram:\n"); 401 first = 0; 402 } 403 printf("\t\t%s: %lu\n", icmpnames[i], 404 icmpstat.icps_inhist[i]); 405 } 406 p(icps_reflect, "\t%lu message response%s generated\n"); 407 #undef p 408 } 409 410 /* 411 * Dump IGMP statistics structure. 412 */ 413 void 414 igmp_stats(off, name) 415 u_long off; 416 char *name; 417 { 418 struct igmpstat igmpstat; 419 420 if (off == 0) 421 return; 422 kread(off, (char *)&igmpstat, sizeof (igmpstat)); 423 printf("%s:\n", name); 424 425 #define p(f, m) if (igmpstat.f || sflag <= 1) \ 426 printf(m, igmpstat.f, plural(igmpstat.f)) 427 #define py(f, m) if (igmpstat.f || sflag <= 1) \ 428 printf(m, igmpstat.f, igmpstat.f != 1 ? "ies" : "y") 429 p(igps_rcv_total, "\t%lu message%s received\n"); 430 p(igps_rcv_tooshort, "\t%lu message%s received with too few bytes\n"); 431 p(igps_rcv_badsum, "\t%lu message%s received with bad checksum\n"); 432 py(igps_rcv_queries, "\t%lu membership quer%s received\n"); 433 py(igps_rcv_badqueries, "\t%lu membership quer%s received with invalid field(s)\n"); 434 p(igps_rcv_reports, "\t%lu membership report%s received\n"); 435 p(igps_rcv_badreports, "\t%lu membership report%s received with invalid field(s)\n"); 436 p(igps_rcv_ourreports, "\t%lu membership report%s received for groups to which we belong\n"); 437 p(igps_snd_reports, "\t%lu membership report%s sent\n"); 438 #undef p 439 #undef py 440 } 441 442 struct rpcnams { 443 struct rpcnams *next; 444 in_port_t port; 445 int proto; 446 char *rpcname; 447 }; 448 449 char * 450 getrpcportnam(port, proto) 451 in_port_t port; 452 int proto; 453 { 454 struct sockaddr_in server_addr; 455 register struct hostent *hp; 456 static struct pmaplist *head; 457 int socket = RPC_ANYSOCK; 458 struct timeval minutetimeout; 459 register CLIENT *client; 460 struct rpcent *rpc; 461 static int first; 462 static struct rpcnams *rpcn; 463 struct rpcnams *n; 464 char num[20]; 465 466 if (first == 0) { 467 first = 1; 468 memset((char *)&server_addr, 0, sizeof server_addr); 469 server_addr.sin_family = AF_INET; 470 if ((hp = gethostbyname("localhost")) != NULL) 471 memmove((caddr_t)&server_addr.sin_addr, hp->h_addr, 472 hp->h_length); 473 else 474 (void) inet_aton("0.0.0.0", &server_addr.sin_addr); 475 476 minutetimeout.tv_sec = 60; 477 minutetimeout.tv_usec = 0; 478 server_addr.sin_port = htons(PMAPPORT); 479 if ((client = clnttcp_create(&server_addr, PMAPPROG, 480 PMAPVERS, &socket, 50, 500)) == NULL) 481 return (NULL); 482 if (clnt_call(client, PMAPPROC_DUMP, xdr_void, NULL, 483 xdr_pmaplist, &head, minutetimeout) != RPC_SUCCESS) { 484 clnt_destroy(client); 485 return (NULL); 486 } 487 for (; head != NULL; head = head->pml_next) { 488 n = (struct rpcnams *)malloc(sizeof(struct rpcnams)); 489 if (n == NULL) 490 continue; 491 n->next = rpcn; 492 rpcn = n; 493 n->port = head->pml_map.pm_port; 494 n->proto = head->pml_map.pm_prot; 495 496 rpc = getrpcbynumber(head->pml_map.pm_prog); 497 if (rpc) 498 n->rpcname = strdup(rpc->r_name); 499 else { 500 snprintf(num, sizeof num, "%ld", 501 head->pml_map.pm_prog); 502 n->rpcname = strdup(num); 503 } 504 } 505 clnt_destroy(client); 506 } 507 508 for (n = rpcn; n; n = n->next) 509 if (n->port == port && n->proto == proto) 510 return (n->rpcname); 511 return (NULL); 512 } 513 514 /* 515 * Pretty print an Internet address (net address + port). 516 * If the nflag was specified, use numbers instead of names. 517 */ 518 void 519 inetprint(in, port, proto, local) 520 register struct in_addr *in; 521 in_port_t port; 522 char *proto; 523 int local; 524 { 525 struct servent *sp = 0; 526 char line[80], *cp, *nam; 527 int proton; 528 int width; 529 530 snprintf(line, sizeof line, "%.*s.", (Aflag && !nflag) ? 12 : 16, 531 inetname(in)); 532 cp = strchr(line, '\0'); 533 if (!nflag && port) 534 sp = getservbyport((int)port, proto); 535 if (sp || port == 0) 536 snprintf(cp, line + sizeof line - cp, "%.8s", 537 sp ? sp->s_name : "*"); 538 else if (local && !nflag && (nam = getrpcportnam(ntohs(port), 539 (strcmp(proto, "tcp") == 0 ? IPPROTO_TCP : IPPROTO_UDP)))) 540 snprintf(cp, line + sizeof line - cp, "%d[%.8s]", 541 ntohs(port), nam); 542 else 543 snprintf(cp, line + sizeof line - cp, "%d", ntohs(port)); 544 width = Aflag ? 18 : 22; 545 printf(" %-*.*s", width, width, line); 546 } 547 548 /* 549 * Construct an Internet address representation. 550 * If the nflag has been supplied, give 551 * numeric value, otherwise try for symbolic name. 552 */ 553 char * 554 inetname(inp) 555 struct in_addr *inp; 556 { 557 register char *cp; 558 static char line[50]; 559 struct hostent *hp; 560 struct netent *np; 561 static char domain[MAXHOSTNAMELEN + 1]; 562 static int first = 1; 563 564 if (first && !nflag) { 565 first = 0; 566 if (gethostname(domain, MAXHOSTNAMELEN) == 0 && 567 (cp = strchr(domain, '.'))) 568 (void) strcpy(domain, cp + 1); 569 else 570 domain[0] = 0; 571 } 572 cp = 0; 573 if (!nflag && inp->s_addr != INADDR_ANY) { 574 int net = inet_netof(*inp); 575 int lna = inet_lnaof(*inp); 576 577 if (lna == INADDR_ANY) { 578 np = getnetbyaddr(net, AF_INET); 579 if (np) 580 cp = np->n_name; 581 } 582 if (cp == 0) { 583 hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET); 584 if (hp) { 585 if ((cp = strchr(hp->h_name, '.')) && 586 !strcmp(cp + 1, domain)) 587 *cp = 0; 588 cp = hp->h_name; 589 } 590 } 591 } 592 if (inp->s_addr == INADDR_ANY) 593 snprintf(line, sizeof line, "*"); 594 else if (cp) 595 snprintf(line, sizeof line, "%s", cp); 596 else { 597 inp->s_addr = ntohl(inp->s_addr); 598 #define C(x) ((x) & 0xff) 599 snprintf(line, sizeof line, "%u.%u.%u.%u", 600 C(inp->s_addr >> 24), C(inp->s_addr >> 16), 601 C(inp->s_addr >> 8), C(inp->s_addr)); 602 } 603 return (line); 604 } 605 606 /* 607 * Dump AH statistics structure. 608 */ 609 void 610 ah_stats(off, name) 611 u_long off; 612 char *name; 613 { 614 struct ahstat ahstat; 615 616 if (off == 0) 617 return; 618 kread(off, (char *)&ahstat, sizeof (ahstat)); 619 printf("%s:\n", name); 620 621 #define p(f, m) if (ahstat.f || sflag <= 1) \ 622 printf(m, ahstat.f, plural(ahstat.f)) 623 624 p(ahs_input, "\t%u input AH packets\n"); 625 p(ahs_output, "\t%u output AH packets\n"); 626 p(ahs_hdrops, "\t%u packet%s shorter than header shows\n"); 627 p(ahs_pdrops, "\t%u packet%s dropped due to policy\n"); 628 p(ahs_notdb, "\t%u packet%s for which no TDB was found\n"); 629 p(ahs_badkcr, "\t%u input packet%s that failed to be processed\n"); 630 p(ahs_badauth, "\t%u packet%s that failed verification received\n"); 631 p(ahs_noxform, "\t%u packet%s for which no XFORM was set in TDB received\n"); 632 p(ahs_qfull, "\t%u packet%s were dropped due to full output queue\n"); 633 p(ahs_wrap, "\t%u packet%s where counter wrapping was detected\n"); 634 p(ahs_replay, "\t%u possibly replayed packet%s received\n"); 635 p(ahs_badauthl, "\t%u packet%s with bad authenticator length received\n"); 636 p(ahs_invalid, "\t%u packet%s attempted to use an invalid tdb\n"); 637 p(ahs_toobig, "\t%u packet%s got larger than max IP packet size\n"); 638 p(ahs_ibytes, "\t%qu input byte%s\n"); 639 p(ahs_obytes, "\t%qu output byte%s\n"); 640 641 #undef p 642 } 643 644 /* 645 * Dump ESP statistics structure. 646 */ 647 void 648 esp_stats(off, name) 649 u_long off; 650 char *name; 651 { 652 struct espstat espstat; 653 654 655 if (off == 0) 656 return; 657 kread(off, (char *)&espstat, sizeof (espstat)); 658 printf("%s:\n", name); 659 660 #define p(f, m) if (espstat.f || sflag <= 1) \ 661 printf(m, espstat.f, plural(espstat.f)) 662 663 p(esps_input, "\t%u input ESP packets\n"); 664 p(esps_output, "\t%u output ESP packets\n"); 665 p(esps_hdrops, "\t%u packet%s shorter than header shows\n"); 666 p(esps_pdrops, "\t%u packet%s dropped due to policy\n"); 667 p(esps_notdb, "\t%u packet%s for which no TDB was found\n"); 668 p(esps_badkcr, "\t%u input packet%s that failed to be processed\n"); 669 p(esps_badauth, "\t%u packet%s that failed verification received\n"); 670 p(esps_noxform, "\t%u packet%s for which no XFORM was set in TDB received\n"); 671 p(esps_qfull, "\t%u packet%s were dropped due to full output queue\n"); 672 p(esps_wrap, "\t%u packet%s where counter wrapping was detected\n"); 673 p(esps_replay, "\t%u possibly replayed packet%s received\n"); 674 p(esps_badilen, "\t%u packet%s with payload not a multiple of 8 received\n"); 675 p(esps_invalid, "\t%u packet%s attempted to use an invalid tdb\n"); 676 p(esps_toobig, "\t%u packet%s got larger than max IP packet size\n"); 677 p(esps_ibytes, "\t%qu input byte%s\n"); 678 p(esps_obytes, "\t%qu output byte%s\n"); 679 680 #undef p 681 } 682 683 /* 684 * Dump ESP statistics structure. 685 */ 686 void 687 ip4_stats(off, name) 688 u_long off; 689 char *name; 690 { 691 struct ip4stat ip4stat; 692 693 if (off == 0) 694 return; 695 kread(off, (char *)&ip4stat, sizeof (ip4stat)); 696 printf("%s:\n", name); 697 698 #define p(f, m) if (ip4stat.f || sflag <= 1) \ 699 printf(m, ip4stat.f, plural(ip4stat.f)) 700 701 p(ip4s_ipackets, "\t%u total input packet%s\n"); 702 p(ip4s_opackets, "\t%u total output packet%s\n"); 703 p(ip4s_hdrops, "\t%u packet%s shorter than header shows\n"); 704 p(ip4s_pdrops, "\t%u packet%s dropped due to policy\n"); 705 p(ip4s_spoof, "\t%u packet%s with possibly spoofed local addresses\n"); 706 p(ip4s_notip4, "\t%u packet%s with internal header not IPv4 received\n"); 707 p(ip4s_qfull, "\t%u packet%s were dropped due to full output queue\n"); 708 p(ip4s_ibytes, "\t%qu input byte%s\n"); 709 p(ip4s_obytes, "\t%qu output byte%s\n"); 710 711 #undef p 712 } 713