inet.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:15k
源码类别:

SNMP编程

开发平台:

Unix_Linux

  1. /* $OpenBSD: inet.c,v 1.92 2005/02/10 14:25:08 itojun Exp $ */
  2. /* $NetBSD: inet.c,v 1.14 1995/10/03 21:42:37 thorpej Exp $ */
  3. /*
  4.  * Copyright (c) 1983, 1988, 1993
  5.  * The Regents of the University of California.  All rights reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  * 1. Redistributions of source code must retain the above copyright
  11.  *    notice, this list of conditions and the following disclaimer.
  12.  * 2. Redistributions in binary form must reproduce the above copyright
  13.  *    notice, this list of conditions and the following disclaimer in the
  14.  *    documentation and/or other materials provided with the distribution.
  15.  * 3. Neither the name of the University nor the names of its contributors
  16.  *    may be used to endorse or promote products derived from this software
  17.  *    without specific prior written permission.
  18.  *
  19.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  20.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  21.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  22.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  23.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  24.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  25.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  26.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  27.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  28.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  29.  * SUCH DAMAGE.
  30.  */
  31. #ifdef  INHERITED_CODE
  32. #ifndef lint
  33. #if 0
  34. static char sccsid[] = "from: @(#)inet.c 8.4 (Berkeley) 4/20/94";
  35. #else
  36. static const char *rcsid = "$OpenBSD: inet.c,v 1.92 2005/02/10 14:25:08 itojun Exp $";
  37. #endif
  38. #endif /* not lint */
  39. #endif
  40. #include <net-snmp/net-snmp-config.h>
  41. #if HAVE_UNISTD_H
  42. #include <unistd.h>
  43. #endif
  44. #if HAVE_WINSOCK_H
  45. #include <winsock2.h>
  46. #include <ws2tcpip.h>
  47. #include "winstub.h"
  48. #endif
  49. #if HAVE_SYS_SOCKET_H
  50. #include <sys/socket.h>
  51. #endif
  52. #if HAVE_NETDB_H
  53. #include <netdb.h>
  54. #endif
  55. #if HAVE_NETINET_IN_H
  56. #include <netinet/in.h>
  57. #endif
  58. #if HAVE_ARPA_INET_H
  59. #include <arpa/inet.h>
  60. #endif
  61. #include <net-snmp/net-snmp-includes.h>
  62. #include "main.h"
  63. #include "netstat.h"
  64. struct stat_table {
  65.     int             entry;      /* entry number in table */
  66.     /*
  67.      * format string to printf(description, value) 
  68.      * warning: the %d must be before the %s 
  69.      */
  70.     char            description[80];
  71. };
  72. char *inetname(struct in_addr *);
  73. void inetprint(struct in_addr *, int, const char *, int);
  74. /*
  75.  * Print a summary of connections related to
  76.  *   an Internet protocol (kread-based) - Omitted
  77.  */
  78. /*
  79.  * Print a summary of TCP connections
  80.  * Listening processes are suppressed unless the
  81.  *   -a (all) flag is specified.
  82.  */
  83. const char     *tcpstates[] = {
  84.     "",
  85.     "CLOSED",
  86.     "LISTEN",
  87.     "SYNSENT",
  88.     "SYNRECEIVED",
  89.     "ESTABLISHED",
  90.     "FINWAIT1",
  91.     "FINWAIT2",
  92.     "CLOSEWAIT",
  93.     "LASTACK",
  94.     "CLOSING",
  95.     "TIMEWAIT"
  96. };
  97. #define TCP_NSTATES 11
  98. void
  99. tcpprotopr(const char *name)
  100. {
  101.     netsnmp_variable_list *var, *vp;
  102.     oid    tcpConnState_oid[] = { 1,3,6,1,2,1,6,13,1,1 };
  103.     size_t tcpConnState_len   = OID_LENGTH( tcpConnState_oid );
  104.     int    state, width;
  105.     union {
  106.         struct in_addr addr;
  107.         char      data[4];
  108.     } tmpAddr;
  109.     oid    localPort, remotePort;
  110.     struct in_addr localAddr, remoteAddr;
  111.     char  *cp;
  112.     int    first = 1;
  113.     /*
  114.      * Walking the tcpConnState column will provide all
  115.      *   the necessary information.
  116.      */
  117.     var = NULL;
  118.     snmp_varlist_add_variable( &var, tcpConnState_oid, tcpConnState_len,
  119.                                    ASN_NULL, NULL,  0);
  120.     if (!var)
  121.         return;
  122.     if (netsnmp_query_walk( var, ss ) != SNMP_ERR_NOERROR)
  123.         return;
  124.     for (vp = var; vp ; vp=vp->next_variable) {
  125.         state = *vp->val.integer;
  126.         if (!aflag && state == MIB_TCPCONNSTATE_LISTEN)
  127.             continue;
  128.         if (first) {
  129.             printf("Active Internet (%s) Connections", name);
  130.             if (aflag)
  131.                 printf(" (including servers)");
  132.             putchar('n');
  133.             width = Aflag ? 18 : 22;
  134.             printf("%-5.5s %*.*s %*.*s %sn",
  135.                    "Proto", -width, width, "Local Address",
  136.                             -width, width, "Remote Address", "(state)");
  137.             first=0;
  138.         }
  139.         
  140.         /* Extract the local/remote information from the index values */
  141.         cp = tmpAddr.data;
  142.         cp[0] = vp->name[ 10 ] & 0xff;
  143.         cp[1] = vp->name[ 11 ] & 0xff;
  144.         cp[2] = vp->name[ 12 ] & 0xff;
  145.         cp[3] = vp->name[ 13 ] & 0xff;
  146.         localAddr.s_addr = tmpAddr.addr.s_addr;
  147.         localPort        = ntohs(vp->name[ 14 ]);
  148.         cp = tmpAddr.data;
  149.         cp[0] = vp->name[ 15 ] & 0xff;
  150.         cp[1] = vp->name[ 16 ] & 0xff;
  151.         cp[2] = vp->name[ 17 ] & 0xff;
  152.         cp[3] = vp->name[ 18 ] & 0xff;
  153.         remoteAddr.s_addr = tmpAddr.addr.s_addr;
  154.         remotePort        = ntohs(vp->name[ 19 ]);
  155.         printf("%-5.5s", name);
  156.         inetprint(&localAddr,  localPort,  name, 1);
  157.         inetprint(&remoteAddr, remotePort, name, 0);
  158.         if ( state < 1 || state > TCP_NSTATES )
  159.             printf("%dn", state );
  160.         else
  161.             printf("%sn", tcpstates[ state ]);
  162.     }
  163.     snmp_free_varbind( var );
  164. }
  165. /*
  166.  * Print a summary of UDP "connections"
  167.  *    XXX - what about "listening" services ??
  168.  */
  169. void
  170. udpprotopr(const char *name)
  171. {
  172.     netsnmp_variable_list *var, *vp;
  173.     oid    udpLocalAddress_oid[] = { 1,3,6,1,2,1,7,5,1,1 };
  174.     size_t udpLocalAddress_len   = OID_LENGTH( udpLocalAddress_oid );
  175.     union {
  176.         struct in_addr addr;
  177.         char      data[4];
  178.     } tmpAddr;
  179.     struct in_addr localAddr;
  180.     oid    localPort;
  181.     char  *cp;
  182.     /*
  183.      * Walking a single column of the udpTable will provide
  184.      *   all the necessary information from the index values.
  185.      */
  186.     var = NULL;
  187.     snmp_varlist_add_variable( &var, udpLocalAddress_oid, udpLocalAddress_len,
  188.                                    ASN_NULL, NULL,  0);
  189.     if (!var)
  190.         return;
  191.     if (netsnmp_query_walk( var, ss ) != SNMP_ERR_NOERROR)
  192.         return;
  193.     printf("Active Internet (%s) Connectionsn", name);
  194.     printf("%-5.5s %-28.28sn", "Proto", "Local Address");
  195.     for (vp = var; vp ; vp=vp->next_variable) {
  196.         printf("%-5.5s", name);
  197.         /*
  198.          * Extract the local port from the index values, but take
  199.          *   the IP address from the varbind value, (which is why
  200.          *   we walked udpLocalAddress rather than udpLocalPort)
  201.          */
  202.         cp = tmpAddr.data;
  203.         cp[0] = vp->name[ 10 ] & 0xff;
  204.         cp[1] = vp->name[ 11 ] & 0xff;
  205.         cp[2] = vp->name[ 12 ] & 0xff;
  206.         cp[3] = vp->name[ 13 ] & 0xff;
  207.         localAddr.s_addr = tmpAddr.addr.s_addr;
  208.         localPort        = ntohs( vp->name[ 14 ]);
  209.         inetprint(&localAddr, localPort, name, 1);
  210.         putchar('n');
  211.     }
  212.     snmp_free_varbind( var );
  213. }
  214. /*********************
  215.  *
  216.  *  Internet-protocol statistics
  217.  *
  218.  *********************/
  219. void
  220. _dump_stats( const char *name, oid *oid_buf, size_t buf_len,
  221.              struct stat_table *stable )
  222. {
  223.     netsnmp_variable_list *var, *vp;
  224.     struct stat_table     *sp;
  225.     oid    stat;
  226.     var = NULL;
  227.     for (sp=stable; sp->entry; sp++) {
  228.         oid_buf[buf_len-2] = sp->entry;
  229.         snmp_varlist_add_variable( &var, oid_buf, buf_len,
  230.                                    ASN_NULL, NULL,  0);
  231.     }
  232.  
  233.     if (netsnmp_query_get( var, ss ) != SNMP_ERR_NOERROR) {
  234.         snmp_free_var( var );
  235.         return;
  236.     }
  237.     printf("%s:n", name);
  238.     for (vp=var, sp=stable; vp; vp=vp->next_variable, sp++) {
  239.         stat =  vp->name[buf_len-2];
  240.         /* XXX - Check that  sp->entry == stat  */
  241.         /*
  242.          * If '-Cs' was specified twice,
  243.          *   then only display non-zero stats.
  244.          */
  245.         if ( *vp->val.integer > 0 || sflag == 1 ) {
  246.             putchar('t');
  247.             printf(sp->description, *vp->val.integer,
  248.                              plural(*vp->val.integer));
  249.             putchar('n');
  250.         }
  251.     }
  252.     snmp_free_varbind( var );
  253. }
  254. /*
  255.  * Dump IP statistics.
  256.  */
  257. void
  258. ip_stats(const char *name)
  259. {
  260.     oid               ipstats_oid[] = { 1, 3, 6, 1, 2, 1, 4, 0, 0 };
  261.     size_t            ipstats_len   = OID_LENGTH( ipstats_oid );
  262.     struct stat_table ipstats_tbl[] = {
  263.         {3, "%d total datagram%s received"},
  264.         {4, "%d datagram%s with header errors"},
  265.         {5, "%d datagram%s with an invalid destination address"},
  266.         {6, "%d datagram%s forwarded"},
  267.         {7, "%d datagram%s with unknown protocol"},
  268.         {8, "%d datagram%s discarded"},
  269.         {9, "%d datagram%s delivered"},
  270.         {10, "%d output datagram request%s"},
  271.         {11, "%d output datagram%s discarded"},
  272.         {12, "%d datagram%s with no route"},
  273.         {14, "%d fragment%s received"},
  274.         {15, "%d datagram%s reassembled"},
  275.         {16, "%d reassembly failure%s"},
  276.         {17, "%d datagram%s fragmented"},
  277.         {18, "%d fragmentation failure%s"},
  278.         {19, "%d fragment%s created"},
  279.         {23, "%d route%s discarded"},
  280.         {0, ""}
  281.     };
  282.     _dump_stats( name, ipstats_oid, ipstats_len, ipstats_tbl );
  283. }
  284. /*
  285.  * Dump ICMP statistics.
  286.  */
  287. void
  288. icmp_stats(const char *name)
  289. {
  290.     oid               icmpstats_oid[] = { 1, 3, 6, 1, 2, 1, 5, 0, 0 };
  291.     size_t            icmpstats_len   = OID_LENGTH( icmpstats_oid );
  292.     struct stat_table icmpstats_tbl[] = {
  293.         {1, "%d total message%s received"},
  294.         {2, "%d message%s dropped due to errors"},
  295.         {14, "%d ouput message request%s"},
  296.         {15, "%d output message%s discarded"},
  297.         {0, ""}
  298.     };
  299.     struct stat_table icmp_inhistogram[] = {
  300.         {3, "Destination unreachable: %d"},
  301.         {4, "Time Exceeded: %d"},
  302.         {5, "Parameter Problem: %d"},
  303.         {6, "Source Quench: %d"},
  304.         {7, "Redirect: %d"},
  305.         {8, "Echo Request: %d"},
  306.         {9, "Echo Reply: %d"},
  307.         {10, "Timestamp Request: %d"},
  308.         {11, "Timestamp Reply: %d"},
  309.         {12, "Address Mask Request: %d"},
  310.         {13, "Addrss Mask Reply:%d"},
  311.         {0, ""}
  312.     };
  313.     struct stat_table icmp_outhistogram[] = {
  314.         {16, "Destination unreachable: %d"},
  315.         {17, "Time Exceeded: %d"},
  316.         {18, "Parameter Problem: %d"},
  317.         {19, "Source Quench: %d"},
  318.         {20, "Redirect: %d"},
  319.         {21, "Echo Request: %d"},
  320.         {22, "Echo Reply: %d"},
  321.         {23, "Timestamp Request: %d"},
  322.         {24, "Timestamp Reply: %d"},
  323.         {25, "Address Mask Request: %d"},
  324.         {26, "Addrss Mask Reply:%d"},
  325.         {0, ""}
  326.     };
  327.     _dump_stats( name, icmpstats_oid, icmpstats_len, icmpstats_tbl );
  328.     _dump_stats( "    Input Histogram",
  329.                        icmpstats_oid, icmpstats_len, icmp_inhistogram );
  330.     _dump_stats( "    Output Histogram",
  331.                        icmpstats_oid, icmpstats_len, icmp_outhistogram );
  332. }
  333. /*
  334.  * Dump TCP statistics.
  335.  */
  336. void
  337. tcp_stats(const char *name)
  338. {
  339.     oid               tcpstats_oid[] = { 1, 3, 6, 1, 2, 1, 6, 0, 0 };
  340.     size_t            tcpstats_len   = OID_LENGTH( tcpstats_oid );
  341.     struct stat_table tcpstats_tbl[] = {
  342.         {5, "%d active open%s"},
  343.         {6, "%d passive open%s"},
  344.         {7, "%d failed attempt%s"},
  345.         {8, "%d reset%s of established connections"},
  346.         {9, "%d current established connection%s"},
  347.         {10, "%d segment%s received"},
  348.         {11, "%d segment%s sent"},
  349.         {12, "%d segment%s retransmitted"},
  350.         {14, "%d invalid segment%s received"},
  351.         {15, "%d reset%s sent"},
  352.         {0, ""}
  353.     };
  354.     _dump_stats( name, tcpstats_oid, tcpstats_len, tcpstats_tbl );
  355. }
  356. /*
  357.  * Dump UDP statistics.
  358.  */
  359. void
  360. udp_stats(const char *name)
  361. {
  362.     oid               udpstats_oid[] = { 1, 3, 6, 1, 2, 1, 7, 0, 0 };
  363.     size_t            udpstats_len   = OID_LENGTH( udpstats_oid );
  364.     struct stat_table udpstats_tbl[] = {
  365.         {1, "%d total datagram%s received"},
  366.         {2, "%d datagram%s to invalid port"},
  367.         {3, "%d datagram%s dropped due to errors"},
  368.         {4, "%d output datagram request%s"},
  369.         {0, ""}
  370.     };
  371.     _dump_stats( name, udpstats_oid, udpstats_len, udpstats_tbl );
  372. }
  373. /*
  374.  * Omitted:
  375.  *     Dump IGMP     statistics
  376.  *     Dump PIM      statistics
  377.  *     Dump AH       statistics
  378.  *     Dump etherip  statistics
  379.  *     Dump ESP      statistics
  380.  *     Dump IP-in-IP statistics
  381.  *     Dump CARP     statistics
  382.  *     Dump pfsync   statistics
  383.  *     Dump IPCOMP   statistics
  384.  */
  385. /*
  386.  * Utility routines
  387.  */
  388. /*
  389.  * Translation of RPC service names - Omitted
  390.  */
  391. /*
  392.  * Pretty print an Internet address (net address + port).
  393.  * If the nflag was specified, use numbers instead of names.
  394.  */
  395. void
  396. inetprint(struct in_addr *in, int port, const char *proto, int local)
  397. {
  398. struct servent *sp = 0;
  399. char line[80], *cp;
  400. int width;
  401. snprintf(line, sizeof line, "%.*s.", (Aflag && !nflag) ? 12 : 16,
  402.     inetname(in));
  403. cp = strchr(line, '');
  404. if (!nflag && port)
  405. sp = getservbyport((int)port, proto);
  406. if (sp || port == 0)
  407. snprintf(cp, line + sizeof line - cp, "%.8s",
  408.     sp ? sp->s_name : "*");
  409.      /*
  410.       * Translation of RPC service names - Omitted
  411.       */
  412. else
  413. snprintf(cp, line + sizeof line - cp, "%d", ntohs(port));
  414. width = Aflag ? 18 : 22;
  415. printf(" %-*.*s", width, width, line);
  416. }
  417. /*
  418.  * Construct an Internet address representation.
  419.  * If the nflag has been supplied, give
  420.  * numeric value, otherwise try for symbolic name.
  421.  */
  422. char *
  423. inetname(struct in_addr *inp)
  424. {
  425. char *cp;
  426. static char line[50];
  427. struct hostent *hp;
  428. struct netent *np;
  429. static char domain[MAXHOSTNAMELEN];
  430. static int first = 1;
  431. #if defined (WIN32) || defined (cygwin)
  432.         char host_temp[] = "localhost";
  433. #endif
  434. if (first && !nflag) {
  435. first = 0;
  436. if (gethostname(domain, sizeof(domain)) == 0 &&
  437.     (cp = strchr(domain, '.')))
  438. (void) strlcpy(domain, cp + 1, sizeof domain);
  439. else
  440. domain[0] = '';
  441. }
  442. cp = NULL;
  443. if (!nflag && inp->s_addr != INADDR_ANY) {
  444. int net = inet_netof(*inp);
  445. int lna = inet_lnaof(*inp);
  446. if (lna == INADDR_ANY) {
  447. np = getnetbyaddr(net, AF_INET);
  448. if (np)
  449. cp = np->n_name;
  450. }
  451. if (cp == NULL) {
  452. hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
  453. if (hp) {
  454. if ((cp = strchr(hp->h_name, '.')) &&
  455.     !strcmp(cp + 1, domain))
  456. *cp = '';
  457. #if defined (WIN32) || defined (cygwin)
  458.                                         /* Windows insists on returning the computer name for 127.0.0.1
  459.                                          * even if the hosts file lists something else such as 'localhost'.
  460.                                          * If we are trying to look up 127.0.0.1, just return 'localhost'   */
  461.                                         if (!strcmp(inet_ntoa(*inp),"127.0.0.1"))
  462.                                              cp = host_temp;
  463.                                         else
  464. #endif                                                                          
  465. cp = hp->h_name;
  466. }
  467. }
  468. }
  469. if (inp->s_addr == INADDR_ANY)
  470. snprintf(line, sizeof line, "*");
  471. else if (cp)
  472. snprintf(line, sizeof line, "%s", cp);
  473. else {
  474. inp->s_addr = ntohl(inp->s_addr);
  475. #define C(x) ((x) & 0xff)
  476. snprintf(line, sizeof line, "%u.%u.%u.%u",
  477.     C(inp->s_addr >> 24), C(inp->s_addr >> 16),
  478.     C(inp->s_addr >> 8), C(inp->s_addr));
  479. }
  480. return (line);
  481. }