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 "$Id: inet.c,v 1.29 1998/06/09 04:13:01 imp Exp $"; 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; 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(Aflag ? 167 "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" : 168 "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n", 169 "Proto", "Recv-Q", "Send-Q", 170 "Local Address", "Foreign Address", "(state)"); 171 first = 0; 172 } 173 if (Aflag) 174 printf("%8lx ", (u_long)so->so_pcb); 175 printf("%-5.5s %6ld %6ld ", name, so->so_rcv.sb_cc, 176 so->so_snd.sb_cc); 177 if (nflag) { 178 inetprint(&inp->inp_laddr, (int)inp->inp_lport, 179 name, 1); 180 inetprint(&inp->inp_faddr, (int)inp->inp_fport, 181 name, 1); 182 } else if (inp->inp_flags & INP_ANONPORT) { 183 inetprint(&inp->inp_laddr, (int)inp->inp_lport, 184 name, 1); 185 inetprint(&inp->inp_faddr, (int)inp->inp_fport, 186 name, 0); 187 } else { 188 inetprint(&inp->inp_laddr, (int)inp->inp_lport, 189 name, 0); 190 inetprint(&inp->inp_faddr, (int)inp->inp_fport, 191 name, inp->inp_lport != inp->inp_fport); 192 } 193 if (istcp) { 194 if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES) 195 printf(" %d", tp->t_state); 196 else { 197 printf(" %s", tcpstates[tp->t_state]); 198 #if defined(TF_NEEDSYN) && defined(TF_NEEDFIN) 199 /* Show T/TCP `hidden state' */ 200 if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN)) 201 putchar('*'); 202 #endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */ 203 } 204 } 205 putchar('\n'); 206 } 207 if (xig != oxig && xig->xig_gen != oxig->xig_gen) { 208 if (oxig->xig_count > xig->xig_count) { 209 printf("Some %s sockets may have been deleted.\n", 210 name); 211 } else if (oxig->xig_count < xig->xig_count) { 212 printf("Some %s sockets may have been created.\n", 213 name); 214 } else { 215 printf("Some %s sockets may have been created or deleted", 216 name); 217 } 218 } 219 free(buf); 220 } 221 222 /* 223 * Dump TCP statistics structure. 224 */ 225 void 226 tcp_stats(off, name) 227 u_long off; 228 char *name; 229 { 230 struct tcpstat tcpstat; 231 size_t len = sizeof tcpstat; 232 233 if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len, 0, 0) < 0) { 234 warn("sysctl: net.inet.tcp.stats"); 235 return; 236 } 237 238 printf ("%s:\n", name); 239 240 #define p(f, m) if (tcpstat.f || sflag <= 1) \ 241 printf(m, tcpstat.f, plural(tcpstat.f)) 242 #define p1a(f, m) if (tcpstat.f || sflag <= 1) \ 243 printf(m, tcpstat.f) 244 #define p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \ 245 printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2)) 246 #define p2a(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \ 247 printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2) 248 #define p3(f, m) if (tcpstat.f || sflag <= 1) \ 249 printf(m, tcpstat.f, plurales(tcpstat.f)) 250 251 p(tcps_sndtotal, "\t%lu packet%s sent\n"); 252 p2(tcps_sndpack,tcps_sndbyte, 253 "\t\t%lu data packet%s (%lu byte%s)\n"); 254 p2(tcps_sndrexmitpack, tcps_sndrexmitbyte, 255 "\t\t%lu data packet%s (%lu byte%s) retransmitted\n"); 256 p(tcps_mturesent, "\t\t%lu resend%s initiated by MTU discovery\n"); 257 p2a(tcps_sndacks, tcps_delack, 258 "\t\t%lu ack-only packet%s (%lu delayed)\n"); 259 p(tcps_sndurg, "\t\t%lu URG only packet%s\n"); 260 p(tcps_sndprobe, "\t\t%lu window probe packet%s\n"); 261 p(tcps_sndwinup, "\t\t%lu window update packet%s\n"); 262 p(tcps_sndctrl, "\t\t%lu control packet%s\n"); 263 p(tcps_rcvtotal, "\t%lu packet%s received\n"); 264 p2(tcps_rcvackpack, tcps_rcvackbyte, "\t\t%lu ack%s (for %lu byte%s)\n"); 265 p(tcps_rcvdupack, "\t\t%lu duplicate ack%s\n"); 266 p(tcps_rcvacktoomuch, "\t\t%lu ack%s for unsent data\n"); 267 p2(tcps_rcvpack, tcps_rcvbyte, 268 "\t\t%lu packet%s (%lu byte%s) received in-sequence\n"); 269 p2(tcps_rcvduppack, tcps_rcvdupbyte, 270 "\t\t%lu completely duplicate packet%s (%lu byte%s)\n"); 271 p(tcps_pawsdrop, "\t\t%lu old duplicate packet%s\n"); 272 p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte, 273 "\t\t%lu packet%s with some dup. data (%lu byte%s duped)\n"); 274 p2(tcps_rcvoopack, tcps_rcvoobyte, 275 "\t\t%lu out-of-order packet%s (%lu byte%s)\n"); 276 p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin, 277 "\t\t%lu packet%s (%lu byte%s) of data after window\n"); 278 p(tcps_rcvwinprobe, "\t\t%lu window probe%s\n"); 279 p(tcps_rcvwinupd, "\t\t%lu window update packet%s\n"); 280 p(tcps_rcvafterclose, "\t\t%lu packet%s received after close\n"); 281 p(tcps_rcvbadsum, "\t\t%lu discarded for bad checksum%s\n"); 282 p(tcps_rcvbadoff, "\t\t%lu discarded for bad header offset field%s\n"); 283 p1a(tcps_rcvshort, "\t\t%lu discarded because packet too short\n"); 284 p(tcps_connattempt, "\t%lu connection request%s\n"); 285 p(tcps_accepts, "\t%lu connection accept%s\n"); 286 p(tcps_badsyn, "\t%lu bad connection attempt%s\n"); 287 p(tcps_listendrop, "\t%lu listen queue overflow%s\n"); 288 p(tcps_connects, "\t%lu connection%s established (including accepts)\n"); 289 p2(tcps_closed, tcps_drops, 290 "\t%lu connection%s closed (including %lu drop%s)\n"); 291 p(tcps_cachedrtt, "\t\t%lu connection%s updated cached RTT on close\n"); 292 p(tcps_cachedrttvar, 293 "\t\t%lu connection%s updated cached RTT variance on close\n"); 294 p(tcps_cachedssthresh, 295 "\t\t%lu connection%s updated cached ssthresh on close\n"); 296 p(tcps_conndrops, "\t%lu embryonic connection%s dropped\n"); 297 p2(tcps_rttupdated, tcps_segstimed, 298 "\t%lu segment%s updated rtt (of %lu attempt%s)\n"); 299 p(tcps_rexmttimeo, "\t%lu retransmit timeout%s\n"); 300 p(tcps_timeoutdrop, "\t\t%lu connection%s dropped by rexmit timeout\n"); 301 p(tcps_persisttimeo, "\t%lu persist timeout%s\n"); 302 p(tcps_persistdrop, "\t\t%lu connection%s dropped by persist timeout\n"); 303 p(tcps_keeptimeo, "\t%lu keepalive timeout%s\n"); 304 p(tcps_keepprobe, "\t\t%lu keepalive probe%s sent\n"); 305 p(tcps_keepdrops, "\t\t%lu connection%s dropped by keepalive\n"); 306 p(tcps_predack, "\t%lu correct ACK header prediction%s\n"); 307 p(tcps_preddat, "\t%lu correct data packet header prediction%s\n"); 308 #undef p 309 #undef p1a 310 #undef p2 311 #undef p2a 312 #undef p3 313 } 314 315 /* 316 * Dump UDP statistics structure. 317 */ 318 void 319 udp_stats(off, name) 320 u_long off; 321 char *name; 322 { 323 struct udpstat udpstat; 324 size_t len = sizeof udpstat; 325 u_long delivered; 326 327 if (sysctlbyname("net.inet.udp.stats", &udpstat, &len, 0, 0) < 0) { 328 warn("sysctl: net.inet.udp.stats"); 329 return; 330 } 331 332 printf("%s:\n", name); 333 #define p(f, m) if (udpstat.f || sflag <= 1) \ 334 printf(m, udpstat.f, plural(udpstat.f)) 335 #define p1a(f, m) if (udpstat.f || sflag <= 1) \ 336 printf(m, udpstat.f) 337 p(udps_ipackets, "\t%lu datagram%s received\n"); 338 p1a(udps_hdrops, "\t%lu with incomplete header\n"); 339 p1a(udps_badlen, "\t%lu with bad data length field\n"); 340 p1a(udps_badsum, "\t%lu with bad checksum\n"); 341 p1a(udps_noport, "\t%lu dropped due to no socket\n"); 342 p(udps_noportbcast, 343 "\t%lu broadcast/multicast datagram%s dropped due to no socket\n"); 344 p1a(udps_fullsock, "\t%lu dropped due to full socket buffers\n"); 345 p1a(udpps_pcbhashmiss, "\t%lu not for hashed pcb\n"); 346 delivered = udpstat.udps_ipackets - 347 udpstat.udps_hdrops - 348 udpstat.udps_badlen - 349 udpstat.udps_badsum - 350 udpstat.udps_noport - 351 udpstat.udps_noportbcast - 352 udpstat.udps_fullsock; 353 if (delivered || sflag <= 1) 354 printf("\t%lu delivered\n", delivered); 355 p(udps_opackets, "\t%lu datagram%s output\n"); 356 #undef p 357 #undef p1a 358 } 359 360 /* 361 * Dump IP statistics structure. 362 */ 363 void 364 ip_stats(off, name) 365 u_long off; 366 char *name; 367 { 368 struct ipstat ipstat; 369 size_t len = sizeof ipstat; 370 371 if (sysctlbyname("net.inet.ip.stats", &ipstat, &len, 0, 0) < 0) { 372 warn("sysctl: net.inet.ip.stats"); 373 return; 374 } 375 376 printf("%s:\n", name); 377 378 #define p(f, m) if (ipstat.f || sflag <= 1) \ 379 printf(m, ipstat.f, plural(ipstat.f)) 380 #define p1a(f, m) if (ipstat.f || sflag <= 1) \ 381 printf(m, ipstat.f) 382 383 p(ips_total, "\t%lu total packet%s received\n"); 384 p(ips_badsum, "\t%lu bad header checksum%s\n"); 385 p1a(ips_toosmall, "\t%lu with size smaller than minimum\n"); 386 p1a(ips_tooshort, "\t%lu with data size < data length\n"); 387 p1a(ips_badhlen, "\t%lu with header length < data size\n"); 388 p1a(ips_badlen, "\t%lu with data length < header length\n"); 389 p1a(ips_badoptions, "\t%lu with bad options\n"); 390 p1a(ips_badvers, "\t%lu with incorrect version number\n"); 391 p(ips_fragments, "\t%lu fragment%s received\n"); 392 p(ips_fragdropped, "\t%lu fragment%s dropped (dup or out of space)\n"); 393 p(ips_fragtimeout, "\t%lu fragment%s dropped after timeout\n"); 394 p(ips_reassembled, "\t%lu packet%s reassembled ok\n"); 395 p(ips_delivered, "\t%lu packet%s for this host\n"); 396 p(ips_noproto, "\t%lu packet%s for unknown/unsupported protocol\n"); 397 p(ips_forward, "\t%lu packet%s forwarded"); 398 p(ips_fastforward, " (%lu packet%s fast forwarded)"); 399 if (ipstat.ips_forward || sflag <= 1) 400 putchar('\n'); 401 p(ips_cantforward, "\t%lu packet%s not forwardable\n"); 402 p(ips_notmember, 403 "\t%lu packet%s received for unknown multicast group\n"); 404 p(ips_redirectsent, "\t%lu redirect%s sent\n"); 405 p(ips_localout, "\t%lu packet%s sent from this host\n"); 406 p(ips_rawout, "\t%lu packet%s sent with fabricated ip header\n"); 407 p(ips_odropped, 408 "\t%lu output packet%s dropped due to no bufs, etc.\n"); 409 p(ips_noroute, "\t%lu output packet%s discarded due to no route\n"); 410 p(ips_fragmented, "\t%lu output datagram%s fragmented\n"); 411 p(ips_ofragments, "\t%lu fragment%s created\n"); 412 p(ips_cantfrag, "\t%lu datagram%s that can't be fragmented\n"); 413 #undef p 414 #undef p1a 415 } 416 417 static char *icmpnames[] = { 418 "echo reply", 419 "#1", 420 "#2", 421 "destination unreachable", 422 "source quench", 423 "routing redirect", 424 "#6", 425 "#7", 426 "echo", 427 "router advertisement", 428 "router solicitation", 429 "time exceeded", 430 "parameter problem", 431 "time stamp", 432 "time stamp reply", 433 "information request", 434 "information request reply", 435 "address mask request", 436 "address mask reply", 437 }; 438 439 /* 440 * Dump ICMP statistics. 441 */ 442 void 443 icmp_stats(off, name) 444 u_long off; 445 char *name; 446 { 447 struct icmpstat icmpstat; 448 int i, first; 449 int mib[4]; /* CTL_NET + PF_INET + IPPROTO_ICMP + req */ 450 size_t len; 451 452 mib[0] = CTL_NET; 453 mib[1] = PF_INET; 454 mib[2] = IPPROTO_ICMP; 455 mib[3] = ICMPCTL_STATS; 456 457 len = sizeof icmpstat; 458 memset(&icmpstat, 0, len); 459 if (sysctl(mib, 4, &icmpstat, &len, (void *)0, 0) < 0) 460 return; /* XXX should complain, but not traditional */ 461 462 printf("%s:\n", name); 463 464 #define p(f, m) if (icmpstat.f || sflag <= 1) \ 465 printf(m, icmpstat.f, plural(icmpstat.f)) 466 #define p1a(f, m) if (icmpstat.f || sflag <= 1) \ 467 printf(m, icmpstat.f) 468 469 p(icps_error, "\t%lu call%s to icmp_error\n"); 470 p(icps_oldicmp, 471 "\t%lu error%s not generated 'cuz old message was icmp\n"); 472 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) 473 if (icmpstat.icps_outhist[i] != 0) { 474 if (first) { 475 printf("\tOutput histogram:\n"); 476 first = 0; 477 } 478 printf("\t\t%s: %lu\n", icmpnames[i], 479 icmpstat.icps_outhist[i]); 480 } 481 p(icps_badcode, "\t%lu message%s with bad code fields\n"); 482 p(icps_tooshort, "\t%lu message%s < minimum length\n"); 483 p(icps_checksum, "\t%lu bad checksum%s\n"); 484 p(icps_badlen, "\t%lu message%s with bad length\n"); 485 p1a(icps_bmcastecho, "\t%lu multicast echo requests ignored\n"); 486 p1a(icps_bmcasttstamp, "\t%lu multicast timestamp requests ignored\n"); 487 for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++) 488 if (icmpstat.icps_inhist[i] != 0) { 489 if (first) { 490 printf("\tInput histogram:\n"); 491 first = 0; 492 } 493 printf("\t\t%s: %lu\n", icmpnames[i], 494 icmpstat.icps_inhist[i]); 495 } 496 p(icps_reflect, "\t%lu message response%s generated\n"); 497 #undef p 498 #undef p1a 499 mib[3] = ICMPCTL_MASKREPL; 500 len = sizeof i; 501 if (sysctl(mib, 4, &i, &len, (void *)0, 0) < 0) 502 return; 503 printf("\tICMP address mask responses are %sabled\n", 504 i ? "en" : "dis"); 505 } 506 507 /* 508 * Dump IGMP statistics structure. 509 */ 510 void 511 igmp_stats(off, name) 512 u_long off; 513 char *name; 514 { 515 struct igmpstat igmpstat; 516 size_t len = sizeof igmpstat; 517 518 if (sysctlbyname("net.inet.igmp.stats", &igmpstat, &len, 0, 0) < 0) { 519 warn("sysctl: net.inet.igmp.stats"); 520 return; 521 } 522 523 printf("%s:\n", name); 524 525 #define p(f, m) if (igmpstat.f || sflag <= 1) \ 526 printf(m, igmpstat.f, plural(igmpstat.f)) 527 #define py(f, m) if (igmpstat.f || sflag <= 1) \ 528 printf(m, igmpstat.f, igmpstat.f != 1 ? "ies" : "y") 529 p(igps_rcv_total, "\t%u message%s received\n"); 530 p(igps_rcv_tooshort, "\t%u message%s received with too few bytes\n"); 531 p(igps_rcv_badsum, "\t%u message%s received with bad checksum\n"); 532 py(igps_rcv_queries, "\t%u membership quer%s received\n"); 533 py(igps_rcv_badqueries, "\t%u membership quer%s received with invalid field(s)\n"); 534 p(igps_rcv_reports, "\t%u membership report%s received\n"); 535 p(igps_rcv_badreports, "\t%u membership report%s received with invalid field(s)\n"); 536 p(igps_rcv_ourreports, "\t%u membership report%s received for groups to which we belong\n"); 537 p(igps_snd_reports, "\t%u membership report%s sent\n"); 538 #undef p 539 #undef py 540 } 541 542 /* 543 * Pretty print an Internet address (net address + port). 544 */ 545 void 546 inetprint(in, port, proto,numeric) 547 register struct in_addr *in; 548 int port; 549 char *proto; 550 int numeric; 551 { 552 struct servent *sp = 0; 553 char line[80], *cp; 554 int width; 555 556 sprintf(line, "%.*s.", (Aflag && !numeric) ? 12 : 16, inetname(in)); 557 cp = index(line, '\0'); 558 if (!numeric && port) 559 sp = getservbyport((int)port, proto); 560 if (sp || port == 0) 561 sprintf(cp, "%.15s", sp ? sp->s_name : "*"); 562 else 563 sprintf(cp, "%d", ntohs((u_short)port)); 564 width = Aflag ? 18 : 22; 565 printf(" %-*.*s", width, width, 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