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