1 /* 2 * Copyright (c) 1983, 1988, 1993, 1995 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 /* 36 static char sccsid[] = "@(#)inet.c 8.5 (Berkeley) 5/24/95"; 37 */ 38 static const char rcsid[] = 39 "$FreeBSD$"; 40 #endif /* not lint */ 41 42 #include <sys/param.h> 43 #include <sys/queue.h> 44 #include <sys/socket.h> 45 #include <sys/socketvar.h> 46 #include <sys/sysctl.h> 47 #include <sys/protosw.h> 48 49 #include <net/route.h> 50 #include <netinet/in.h> 51 #include <netinet/in_systm.h> 52 #include <netinet/ip.h> 53 #include <netinet/in_pcb.h> 54 #include <netinet/ip_icmp.h> 55 #include <netinet/icmp_var.h> 56 #include <netinet/igmp_var.h> 57 #include <netinet/ip_var.h> 58 #include <netinet/tcp.h> 59 #include <netinet/tcpip.h> 60 #include <netinet/tcp_seq.h> 61 #define TCPSTATES 62 #include <netinet/tcp_fsm.h> 63 #include <netinet/tcp_timer.h> 64 #include <netinet/tcp_var.h> 65 #include <netinet/tcp_debug.h> 66 #include <netinet/udp.h> 67 #include <netinet/udp_var.h> 68 69 #include <arpa/inet.h> 70 #include <err.h> 71 #include <errno.h> 72 #include <netdb.h> 73 #include <stdio.h> 74 #include <stdlib.h> 75 #include <string.h> 76 #include <unistd.h> 77 #include "netstat.h" 78 79 char *inetname __P((struct in_addr *)); 80 void inetprint __P((struct in_addr *, int, char *, int)); 81 82 /* 83 * Print a summary of connections related to an Internet 84 * protocol. For TCP, also give state of connection. 85 * Listening processes (aflag) are suppressed unless the 86 * -a (all) flag is specified. 87 */ 88 void 89 protopr(proto, name) 90 u_long proto; /* for sysctl version we pass proto # */ 91 char *name; 92 { 93 int istcp; 94 static int first = 1; 95 char *buf; 96 const char *mibvar; 97 struct tcpcb *tp = NULL; 98 struct inpcb *inp; 99 struct xinpgen *xig, *oxig; 100 struct xsocket *so; 101 size_t len; 102 103 istcp = 0; 104 switch (proto) { 105 case IPPROTO_TCP: 106 istcp = 1; 107 mibvar = "net.inet.tcp.pcblist"; 108 break; 109 case IPPROTO_UDP: 110 mibvar = "net.inet.udp.pcblist"; 111 break; 112 case IPPROTO_DIVERT: 113 mibvar = "net.inet.divert.pcblist"; 114 break; 115 default: 116 mibvar = "net.inet.raw.pcblist"; 117 break; 118 } 119 len = 0; 120 if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) { 121 if (errno != ENOENT) 122 warn("sysctl: %s", mibvar); 123 return; 124 } 125 if ((buf = malloc(len)) == 0) { 126 warn("malloc %lu bytes", (u_long)len); 127 return; 128 } 129 if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) { 130 warn("sysctl: %s", mibvar); 131 free(buf); 132 return; 133 } 134 135 oxig = xig = (struct xinpgen *)buf; 136 for (xig = (struct xinpgen *)((char *)xig + xig->xig_len); 137 xig->xig_len > sizeof(struct xinpgen); 138 xig = (struct xinpgen *)((char *)xig + xig->xig_len)) { 139 if (istcp) { 140 tp = &((struct xtcpcb *)xig)->xt_tp; 141 inp = &((struct xtcpcb *)xig)->xt_inp; 142 so = &((struct xtcpcb *)xig)->xt_socket; 143 } else { 144 inp = &((struct xinpcb *)xig)->xi_inp; 145 so = &((struct xinpcb *)xig)->xi_socket; 146 } 147 148 /* Ignore sockets for protocols other than the desired one. */ 149 if (so->xso_protocol != proto) 150 continue; 151 152 /* Ignore PCBs which were freed during copyout. */ 153 if (inp->inp_gencnt > oxig->xig_gen) 154 continue; 155 156 if (!aflag && inet_lnaof(inp->inp_laddr) == INADDR_ANY) 157 continue; 158 159 if (first) { 160 printf("Active Internet connections"); 161 if (aflag) 162 printf(" (including servers)"); 163 putchar('\n'); 164 if (Aflag) 165 printf("%-8.8s ", "Socket"); 166 printf("%-5.5s %-6.6s %-6.6s %-21.21s %-21.21s %s\n", 167 "Proto", "Recv-Q", "Send-Q", 168 "Local Address", "Foreign Address", "(state)"); 169 first = 0; 170 } 171 if (Aflag) { 172 if (istcp) 173 printf("%8lx ", (u_long)inp->inp_ppcb); 174 else 175 printf("%8lx ", (u_long)so->so_pcb); 176 } 177 printf("%-5.5s %6ld %6ld ", name, so->so_rcv.sb_cc, 178 so->so_snd.sb_cc); 179 if (nflag) { 180 inetprint(&inp->inp_laddr, (int)inp->inp_lport, 181 name, 1); 182 inetprint(&inp->inp_faddr, (int)inp->inp_fport, 183 name, 1); 184 } else if (inp->inp_flags & INP_ANONPORT) { 185 inetprint(&inp->inp_laddr, (int)inp->inp_lport, 186 name, 1); 187 inetprint(&inp->inp_faddr, (int)inp->inp_fport, 188 name, 0); 189 } else { 190 inetprint(&inp->inp_laddr, (int)inp->inp_lport, 191 name, 0); 192 inetprint(&inp->inp_faddr, (int)inp->inp_fport, 193 name, inp->inp_lport != inp->inp_fport); 194 } 195 if (istcp) { 196 if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES) 197 printf("%d", tp->t_state); 198 else { 199 printf("%s", tcpstates[tp->t_state]); 200 #if defined(TF_NEEDSYN) && defined(TF_NEEDFIN) 201 /* Show T/TCP `hidden state' */ 202 if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN)) 203 putchar('*'); 204 #endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */ 205 } 206 } 207 putchar('\n'); 208 } 209 if (xig != oxig && xig->xig_gen != oxig->xig_gen) { 210 if (oxig->xig_count > xig->xig_count) { 211 printf("Some %s sockets may have been deleted.\n", 212 name); 213 } else if (oxig->xig_count < xig->xig_count) { 214 printf("Some %s sockets may have been created.\n", 215 name); 216 } else { 217 printf("Some %s sockets may have been created or deleted", 218 name); 219 } 220 } 221 free(buf); 222 } 223 224 /* 225 * Dump TCP statistics structure. 226 */ 227 void 228 tcp_stats(off, name) 229 u_long off; 230 char *name; 231 { 232 struct tcpstat tcpstat; 233 size_t len = sizeof tcpstat; 234 235 if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len, 0, 0) < 0) { 236 warn("sysctl: net.inet.tcp.stats"); 237 return; 238 } 239 240 printf ("%s:\n", name); 241 242 #define p(f, m) if (tcpstat.f || sflag <= 1) \ 243 printf(m, tcpstat.f, plural(tcpstat.f)) 244 #define p1a(f, m) if (tcpstat.f || sflag <= 1) \ 245 printf(m, tcpstat.f) 246 #define p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \ 247 printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2)) 248 #define p2a(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \ 249 printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2) 250 #define p3(f, m) if (tcpstat.f || sflag <= 1) \ 251 printf(m, tcpstat.f, plurales(tcpstat.f)) 252 253 p(tcps_sndtotal, "\t%lu packet%s sent\n"); 254 p2(tcps_sndpack,tcps_sndbyte, 255 "\t\t%lu data packet%s (%lu byte%s)\n"); 256 p2(tcps_sndrexmitpack, tcps_sndrexmitbyte, 257 "\t\t%lu data packet%s (%lu byte%s) retransmitted\n"); 258 p(tcps_mturesent, "\t\t%lu resend%s initiated by MTU discovery\n"); 259 p2a(tcps_sndacks, tcps_delack, 260 "\t\t%lu ack-only packet%s (%lu delayed)\n"); 261 p(tcps_sndurg, "\t\t%lu URG only packet%s\n"); 262 p(tcps_sndprobe, "\t\t%lu window probe packet%s\n"); 263 p(tcps_sndwinup, "\t\t%lu window update packet%s\n"); 264 p(tcps_sndctrl, "\t\t%lu control packet%s\n"); 265 p(tcps_rcvtotal, "\t%lu packet%s received\n"); 266 p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%lu ack%s (for %lu byte%s)\n"); 267 p(tcps_rcvdupack, "\t\t%lu duplicate ack%s\n"); 268 p(tcps_rcvacktoomuch, "\t\t%lu ack%s for unsent data\n"); 269 p2(tcps_rcvpack, tcps_rcvbyte, 270 "\t\t%lu packet%s (%lu byte%s) received in-sequence\n"); 271 p2(tcps_rcvduppack, tcps_rcvdupbyte, 272 "\t\t%lu completely duplicate packet%s (%lu byte%s)\n"); 273 p(tcps_pawsdrop, "\t\t%lu old duplicate packet%s\n"); 274 p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte, 275 "\t\t%lu packet%s with some dup. data (%lu byte%s duped)\n"); 276 p2(tcps_rcvoopack, tcps_rcvoobyte, 277 "\t\t%lu out-of-order packet%s (%lu byte%s)\n"); 278 p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin, 279 "\t\t%lu packet%s (%lu byte%s) of data after window\n"); 280 p(tcps_rcvwinprobe, "\t\t%lu window probe%s\n"); 281 p(tcps_rcvwinupd, "\t\t%lu window update packet%s\n"); 282 p(tcps_rcvafterclose, "\t\t%lu packet%s received after close\n"); 283 p(tcps_rcvbadsum, "\t\t%lu discarded for bad checksum%s\n"); 284 p(tcps_rcvbadoff, "\t\t%lu discarded for bad header offset field%s\n"); 285 p1a(tcps_rcvshort, "\t\t%lu discarded because packet too short\n"); 286 p(tcps_connattempt, "\t%lu connection request%s\n"); 287 p(tcps_accepts, "\t%lu connection accept%s\n"); 288 p(tcps_badsyn, "\t%lu bad connection attempt%s\n"); 289 p(tcps_listendrop, "\t%lu listen queue overflow%s\n"); 290 p(tcps_connects, "\t%lu connection%s established (including accepts)\n"); 291 p2(tcps_closed, tcps_drops, 292 "\t%lu connection%s closed (including %lu drop%s)\n"); 293 p(tcps_cachedrtt, "\t\t%lu connection%s updated cached RTT on close\n"); 294 p(tcps_cachedrttvar, 295 "\t\t%lu connection%s updated cached RTT variance on close\n"); 296 p(tcps_cachedssthresh, 297 "\t\t%lu connection%s updated cached ssthresh on close\n"); 298 p(tcps_conndrops, "\t%lu embryonic connection%s dropped\n"); 299 p2(tcps_rttupdated, tcps_segstimed, 300 "\t%lu segment%s updated rtt (of %lu attempt%s)\n"); 301 p(tcps_rexmttimeo, "\t%lu retransmit timeout%s\n"); 302 p(tcps_timeoutdrop, "\t\t%lu connection%s dropped by rexmit timeout\n"); 303 p(tcps_persisttimeo, "\t%lu persist timeout%s\n"); 304 p(tcps_persistdrop, "\t\t%lu connection%s dropped by persist timeout\n"); 305 p(tcps_keeptimeo, "\t%lu keepalive timeout%s\n"); 306 p(tcps_keepprobe, "\t\t%lu keepalive probe%s sent\n"); 307 p(tcps_keepdrops, "\t\t%lu connection%s dropped by keepalive\n"); 308 p(tcps_predack, "\t%lu correct ACK header prediction%s\n"); 309 p(tcps_preddat, "\t%lu correct data packet header prediction%s\n"); 310 #undef p 311 #undef p1a 312 #undef p2 313 #undef p2a 314 #undef p3 315 } 316 317 /* 318 * Dump UDP statistics structure. 319 */ 320 void 321 udp_stats(off, name) 322 u_long off; 323 char *name; 324 { 325 struct udpstat udpstat; 326 size_t len = sizeof udpstat; 327 u_long delivered; 328 329 if (sysctlbyname("net.inet.udp.stats", &udpstat, &len, 0, 0) < 0) { 330 warn("sysctl: net.inet.udp.stats"); 331 return; 332 } 333 334 printf("%s:\n", name); 335 #define p(f, m) if (udpstat.f || sflag <= 1) \ 336 printf(m, udpstat.f, plural(udpstat.f)) 337 #define p1a(f, m) if (udpstat.f || sflag <= 1) \ 338 printf(m, udpstat.f) 339 p(udps_ipackets, "\t%lu datagram%s received\n"); 340 p1a(udps_hdrops, "\t%lu with incomplete header\n"); 341 p1a(udps_badlen, "\t%lu with bad data length field\n"); 342 p1a(udps_badsum, "\t%lu with bad checksum\n"); 343 p1a(udps_noport, "\t%lu dropped due to no socket\n"); 344 p(udps_noportbcast, 345 "\t%lu broadcast/multicast datagram%s dropped due to no socket\n"); 346 p1a(udps_fullsock, "\t%lu dropped due to full socket buffers\n"); 347 p1a(udpps_pcbhashmiss, "\t%lu not for hashed pcb\n"); 348 delivered = udpstat.udps_ipackets - 349 udpstat.udps_hdrops - 350 udpstat.udps_badlen - 351 udpstat.udps_badsum - 352 udpstat.udps_noport - 353 udpstat.udps_noportbcast - 354 udpstat.udps_fullsock; 355 if (delivered || sflag <= 1) 356 printf("\t%lu delivered\n", delivered); 357 p(udps_opackets, "\t%lu datagram%s output\n"); 358 #undef p 359 #undef p1a 360 } 361 362 /* 363 * Dump IP statistics structure. 364 */ 365 void 366 ip_stats(off, name) 367 u_long off; 368 char *name; 369 { 370 struct ipstat ipstat; 371 size_t len = sizeof ipstat; 372 373 if (sysctlbyname("net.inet.ip.stats", &ipstat, &len, 0, 0) < 0) { 374 warn("sysctl: net.inet.ip.stats"); 375 return; 376 } 377 378 printf("%s:\n", name); 379 380 #define p(f, m) if (ipstat.f || sflag <= 1) \ 381 printf(m, ipstat.f, plural(ipstat.f)) 382 #define p1a(f, m) if (ipstat.f || sflag <= 1) \ 383 printf(m, ipstat.f) 384 385 p(ips_total, "\t%lu total packet%s received\n"); 386 p(ips_badsum, "\t%lu bad header checksum%s\n"); 387 p1a(ips_toosmall, "\t%lu with size smaller than minimum\n"); 388 p1a(ips_tooshort, "\t%lu with data size < data length\n"); 389 p1a(ips_badhlen, "\t%lu with header length < data size\n"); 390 p1a(ips_badlen, "\t%lu with data length < header length\n"); 391 p1a(ips_badoptions, "\t%lu with bad options\n"); 392 p1a(ips_badvers, "\t%lu with incorrect version number\n"); 393 p(ips_fragments, "\t%lu fragment%s received\n"); 394 p(ips_fragdropped, "\t%lu fragment%s dropped (dup or out of space)\n"); 395 p(ips_fragtimeout, "\t%lu fragment%s dropped after timeout\n"); 396 p(ips_reassembled, "\t%lu packet%s reassembled ok\n"); 397 p(ips_delivered, "\t%lu packet%s for this host\n"); 398 p(ips_noproto, "\t%lu packet%s for unknown/unsupported protocol\n"); 399 p(ips_forward, "\t%lu packet%s forwarded"); 400 p(ips_fastforward, " (%lu packet%s fast forwarded)"); 401 if (ipstat.ips_forward || sflag <= 1) 402 putchar('\n'); 403 p(ips_cantforward, "\t%lu packet%s not forwardable\n"); 404 p(ips_notmember, 405 "\t%lu packet%s received for unknown multicast group\n"); 406 p(ips_redirectsent, "\t%lu redirect%s sent\n"); 407 p(ips_localout, "\t%lu packet%s sent from this host\n"); 408 p(ips_rawout, "\t%lu packet%s sent with fabricated ip header\n"); 409 p(ips_odropped, 410 "\t%lu output packet%s dropped due to no bufs, etc.\n"); 411 p(ips_noroute, "\t%lu output packet%s discarded due to no route\n"); 412 p(ips_fragmented, "\t%lu output datagram%s fragmented\n"); 413 p(ips_ofragments, "\t%lu fragment%s created\n"); 414 p(ips_cantfrag, "\t%lu datagram%s that can't be fragmented\n"); 415 #undef p 416 #undef p1a 417 } 418 419 static char *icmpnames[] = { 420 "echo reply", 421 "#1", 422 "#2", 423 "destination unreachable", 424 "source quench", 425 "routing redirect", 426 "#6", 427 "#7", 428 "echo", 429 "router advertisement", 430 "router solicitation", 431 "time exceeded", 432 "parameter problem", 433 "time stamp", 434 "time stamp reply", 435 "information request", 436 "information request reply", 437 "address mask request", 438 "address mask reply", 439 }; 440 441 /* 442 * Dump ICMP statistics. 443 */ 444 void 445 icmp_stats(off, name) 446 u_long off; 447 char *name; 448 { 449 struct icmpstat icmpstat; 450 int i, first; 451 int mib[4]; /* CTL_NET + PF_INET + IPPROTO_ICMP + req */ 452 size_t len; 453 454 mib[0] = CTL_NET; 455 mib[1] = PF_INET; 456 mib[2] = IPPROTO_ICMP; 457 mib[3] = ICMPCTL_STATS; 458 459 len = sizeof icmpstat; 460 memset(&icmpstat, 0, len); 461 if (sysctl(mib, 4, &icmpstat, &len, (void *)0, 0) < 0) 462 return; /* XXX should complain, but not traditional */ 463 464 printf("%s:\n", name); 465 466 #define p(f, m) if (icmpstat.f || sflag <= 1) \ 467 printf(m, icmpstat.f, plural(icmpstat.f)) 468 #define p1a(f, m) if (icmpstat.f || sflag <= 1) \ 469 printf(m, icmpstat.f) 470 471 p(icps_error, "\t%lu call%s to icmp_error\n"); 472 p(icps_oldicmp, 473 "\t%lu error%s not generated 'cuz old message was icmp\n"); 474 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) 475 if (icmpstat.icps_outhist[i] != 0) { 476 if (first) { 477 printf("\tOutput histogram:\n"); 478 first = 0; 479 } 480 printf("\t\t%s: %lu\n", icmpnames[i], 481 icmpstat.icps_outhist[i]); 482 } 483 p(icps_badcode, "\t%lu message%s with bad code fields\n"); 484 p(icps_tooshort, "\t%lu message%s < minimum length\n"); 485 p(icps_checksum, "\t%lu bad checksum%s\n"); 486 p(icps_badlen, "\t%lu message%s with bad length\n"); 487 p1a(icps_bmcastecho, "\t%lu multicast echo requests ignored\n"); 488 p1a(icps_bmcasttstamp, "\t%lu multicast timestamp requests ignored\n"); 489 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) 490 if (icmpstat.icps_inhist[i] != 0) { 491 if (first) { 492 printf("\tInput histogram:\n"); 493 first = 0; 494 } 495 printf("\t\t%s: %lu\n", icmpnames[i], 496 icmpstat.icps_inhist[i]); 497 } 498 p(icps_reflect, "\t%lu message response%s generated\n"); 499 #undef p 500 #undef p1a 501 mib[3] = ICMPCTL_MASKREPL; 502 len = sizeof i; 503 if (sysctl(mib, 4, &i, &len, (void *)0, 0) < 0) 504 return; 505 printf("\tICMP address mask responses are %sabled\n", 506 i ? "en" : "dis"); 507 } 508 509 /* 510 * Dump IGMP statistics structure. 511 */ 512 void 513 igmp_stats(off, name) 514 u_long off; 515 char *name; 516 { 517 struct igmpstat igmpstat; 518 size_t len = sizeof igmpstat; 519 520 if (sysctlbyname("net.inet.igmp.stats", &igmpstat, &len, 0, 0) < 0) { 521 warn("sysctl: net.inet.igmp.stats"); 522 return; 523 } 524 525 printf("%s:\n", name); 526 527 #define p(f, m) if (igmpstat.f || sflag <= 1) \ 528 printf(m, igmpstat.f, plural(igmpstat.f)) 529 #define py(f, m) if (igmpstat.f || sflag <= 1) \ 530 printf(m, igmpstat.f, igmpstat.f != 1 ? "ies" : "y") 531 p(igps_rcv_total, "\t%u message%s received\n"); 532 p(igps_rcv_tooshort, "\t%u message%s received with too few bytes\n"); 533 p(igps_rcv_badsum, "\t%u message%s received with bad checksum\n"); 534 py(igps_rcv_queries, "\t%u membership quer%s received\n"); 535 py(igps_rcv_badqueries, "\t%u membership quer%s received with invalid field(s)\n"); 536 p(igps_rcv_reports, "\t%u membership report%s received\n"); 537 p(igps_rcv_badreports, "\t%u membership report%s received with invalid field(s)\n"); 538 p(igps_rcv_ourreports, "\t%u membership report%s received for groups to which we belong\n"); 539 p(igps_snd_reports, "\t%u membership report%s sent\n"); 540 #undef p 541 #undef py 542 } 543 544 /* 545 * Pretty print an Internet address (net address + port). 546 */ 547 void 548 inetprint(in, port, proto,numeric) 549 register struct in_addr *in; 550 int port; 551 char *proto; 552 int numeric; 553 { 554 struct servent *sp = 0; 555 char line[80], *cp; 556 557 sprintf(line, "%.*s.", (Aflag && !numeric) ? 12 : 16, inetname(in)); 558 cp = index(line, '\0'); 559 if (!numeric && port) 560 sp = getservbyport((int)port, proto); 561 if (sp || port == 0) 562 sprintf(cp, "%.15s", sp ? sp->s_name : "*"); 563 else 564 sprintf(cp, "%d", ntohs((u_short)port)); 565 printf("%-21.21s ", line); 566 } 567 568 /* 569 * Construct an Internet address representation. 570 * If the nflag has been supplied, give 571 * numeric value, otherwise try for symbolic name. 572 */ 573 char * 574 inetname(inp) 575 struct in_addr *inp; 576 { 577 register char *cp; 578 static char line[MAXHOSTNAMELEN + 1]; 579 struct hostent *hp; 580 struct netent *np; 581 582 cp = 0; 583 if (!nflag && inp->s_addr != INADDR_ANY) { 584 int net = inet_netof(*inp); 585 int lna = inet_lnaof(*inp); 586 587 if (lna == INADDR_ANY) { 588 np = getnetbyaddr(net, AF_INET); 589 if (np) 590 cp = np->n_name; 591 } 592 if (cp == 0) { 593 hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET); 594 if (hp) { 595 cp = hp->h_name; 596 trimdomain(cp); 597 } 598 } 599 } 600 if (inp->s_addr == INADDR_ANY) 601 strcpy(line, "*"); 602 else if (cp) { 603 strncpy(line, cp, sizeof(line) - 1); 604 line[sizeof(line) - 1] = '\0'; 605 } else { 606 inp->s_addr = ntohl(inp->s_addr); 607 #define C(x) ((u_int)((x) & 0xff)) 608 sprintf(line, "%u.%u.%u.%u", C(inp->s_addr >> 24), 609 C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr)); 610 } 611 return (line); 612 } 613