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

SNMP编程

开发平台:

Unix_Linux

  1. /* $OpenBSD: inet6.c,v 1.31 2004/11/17 01:47:20 itojun Exp $ */
  2. /* BSDI inet.c,v 2.3 1995/10/24 02:19:29 prb 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[] = "@(#)inet.c 8.4 (Berkeley) 4/20/94";
  35. #else
  36. /*__RCSID("$OpenBSD: inet6.c,v 1.31 2004/11/17 01:47:20 itojun Exp $");*/
  37. /*__RCSID("KAME Id: inet6.c,v 1.10 2000/02/09 10:49:31 itojun Exp");*/
  38. #endif
  39. #endif /* not lint */
  40. #endif
  41. #include <net-snmp/net-snmp-config.h>
  42. /*
  43.  * hack-o-matic for Cygwin to use winsock2
  44. */
  45. #if defined(cygwin)
  46. #undef HAVE_UNISTD_H
  47. #undef HAVE_NETINET_IN_H
  48. #undef HAVE_ARPA_INET_H
  49. #undef HAVE_SYS_PARAM_H
  50. #undef HAVE_SYS_SELECT_H
  51. #undef HAVE_SYS_SOCKET_H
  52. #undef HAVE_IN_ADDR_T
  53. #endif
  54. #if defined(HAVE_WINSOCK_H) || defined(cygwin)
  55. #include <winsock2.h>
  56. #include <ws2tcpip.h>
  57. #include "winstub.h"
  58. extern const char *inet_ntop(int, const void*, char*, size_t);
  59. #ifdef cygwin
  60. extern int WSAAPI getnameinfo(const struct sockaddr*,socklen_t,char*,DWORD, char*,DWORD,int);
  61. #endif
  62. #else                  /* WIN32 */
  63. #if HAVE_NETDB_H
  64. #include <netdb.h>
  65. #endif
  66. #endif                  /* WIN32 */
  67. #include <net-snmp/net-snmp-includes.h>
  68. #if HAVE_UNISTD_H
  69. #include <unistd.h>
  70. #endif
  71. #include "main.h"
  72. #include "netstat.h"
  73. struct stat_table {
  74.     int             entry;      /* entry number in table */
  75.     /*
  76.      * format string to printf(description, value) 
  77.      * warning: the %d must be before the %s 
  78.      */
  79.     char            description[80];
  80. };
  81. char *inet6name(const unsigned char *);
  82. void inet6print(unsigned char *, int, const char *, int);
  83. /*
  84.  * Print a summary of TCPv6 connections
  85.  * Listening processes are suppressed unless the
  86.  *   -a (all) flag is specified.
  87.  */
  88. const char     *tcp6states[] = {
  89.     "",
  90.     "CLOSED",
  91.     "LISTEN",
  92.     "SYNSENT",
  93.     "SYNRECEIVED",
  94.     "ESTABLISHED",
  95.     "FINWAIT1",
  96.     "FINWAIT2",
  97.     "CLOSEWAIT",
  98.     "LASTACK",
  99.     "CLOSING",
  100.     "TIMEWAIT"
  101. };
  102. #define TCP_NSTATES 11
  103. void
  104. tcp6protopr(const char *name)
  105. {
  106.     netsnmp_variable_list *var, *vp;
  107.     oid    ipv6TcpConnState_oid[] = { 1,3,6,1,2,1,6,16,1,6 };
  108.     size_t ipv6TcpConnState_len   = OID_LENGTH( ipv6TcpConnState_oid );
  109.     int    state, i;
  110.     unsigned char   localAddr[16], remoteAddr[16];
  111.     int    localPort,     remotePort,  ifIndex;
  112.     int    first = 1;
  113.     /*
  114.      * Walking the v6 tcpConnState column will provide all
  115.      *   the necessary information.
  116.      */
  117.     var = NULL;
  118.     snmp_varlist_add_variable( &var, ipv6TcpConnState_oid,
  119.                                      ipv6TcpConnState_len,
  120.                                      ASN_NULL, NULL,  0);
  121.     if (netsnmp_query_walk( var, ss ) != SNMP_ERR_NOERROR)
  122.         return;
  123.     if (var->type == ASN_NULL)    /* No entries */
  124.         return;
  125.     for (vp = var; vp ; vp=vp->next_variable) {
  126.         state = *var->val.integer;
  127.         if (!aflag && state == MIB_TCPCONNSTATE_LISTEN)
  128.             continue;
  129.         if (first) {
  130.             printf("Active Internet Connections");
  131.             if (aflag)
  132.                 printf(" (including servers)");
  133.             putchar('n');
  134.             printf("%-5.5s %-28.28s %-28.28s %4s %sn",
  135.                    "Proto", "Local Address", "Remote Address", "I/F", "(state)");
  136.             first = 0;
  137.         }
  138.         
  139.         /* Extract the local/remote information from the index values */
  140.         for (i=0; i<16; i++)
  141.             localAddr[i]  = var->name[ 10+i ];
  142.         localPort    = var->name[ 26 ];
  143.         for (i=0; i<16; i++)
  144.             remoteAddr[i] = var->name[ 27+i ];
  145.         remotePort   = var->name[ 43 ];
  146.         ifIndex      = var->name[ 44 ];
  147.         printf("%-5.5s", name);
  148.         inet6print(localAddr,  localPort,  name, 1);
  149.         inet6print(remoteAddr, remotePort, name, 0);
  150.         if ( state < 1 || state > TCP_NSTATES )
  151.             printf(" %4d %dn", ifIndex, state );
  152.         else
  153.             printf(" %4d %sn", ifIndex, tcp6states[ state ]);
  154.     }
  155.     snmp_free_varbind( var );
  156. }
  157. /*
  158.  * Print a summary of UDPv6 "connections"
  159.  *    XXX - what about "listening" services ??
  160.  */
  161. void
  162. udp6protopr(const char *name)
  163. {
  164.     netsnmp_variable_list *var, *vp;
  165.     oid    ipv6UdpLocalAddress_oid[] = { 1,3,6,1,2,1,7,6,1,1 };
  166.     size_t ipv6UdpLocalAddress_len   = OID_LENGTH( ipv6UdpLocalAddress_oid );
  167.     int    localPort, ifIndex;
  168.     /*
  169.      * Walking a single column of the udpTable will provide
  170.      *   all the necessary information from the index values.
  171.      */
  172.     var = NULL;
  173.     snmp_varlist_add_variable( &var, ipv6UdpLocalAddress_oid,
  174.                                      ipv6UdpLocalAddress_len,
  175.                                      ASN_NULL, NULL,  0);
  176.     if (netsnmp_query_walk( var, ss ) != SNMP_ERR_NOERROR)
  177.         return;
  178.     if (var->type == ASN_NULL)    /* No entries */
  179.         return;
  180.     printf("Active Internet Connectionsn");
  181.     printf("%-5.5s %-28.28s %4sn", "Proto", "Local Address", "I/F");
  182.     for (vp = var; vp ; vp=vp->next_variable) {
  183.         printf("%-5.5s", name);
  184.         /*
  185.          * Extract the local port from the index values, but take
  186.          *   the IP address from the varbind value, (which is why
  187.          *   we walked udpLocalAddress rather than udpLocalPort)
  188.          */
  189.         localPort = var->name[ var->name_length-2 ];
  190.         ifIndex   = var->name[ var->name_length-1 ];
  191.         inet6print(var->val.string, localPort, name, 1);
  192.         printf(" %4dn", ifIndex );
  193.     }
  194.     snmp_free_varbind( var );
  195. }
  196. /*********************
  197.  *
  198.  *  IPv6 statistics
  199.  *
  200.  *********************/
  201. /*
  202.  *  Unlike the equivalent IPv4 statistics display routine,
  203.  *    the IPv6 version must walk the columns of a table
  204.  *    and total the statistics for each column (rather
  205.  *    than simply retrieving individual scalar values)
  206.  */
  207. void
  208. _dump_v6stats( const char *name, oid *oid_buf, size_t buf_len,
  209.                struct stat_table *stable )
  210. {
  211.     netsnmp_variable_list *var, *vp;
  212.     struct stat_table     *sp;
  213.     oid   *stats, stat;
  214.     int    max_stat = 0;
  215.     int    active   = 0;
  216.     var = NULL;
  217.     for (sp=stable; sp->entry; sp++) {
  218.         oid_buf[buf_len-1] = sp->entry;
  219.         if (sp->entry>max_stat)
  220.             max_stat = sp->entry;
  221.         snmp_varlist_add_variable( &var, oid_buf, buf_len,
  222.                                    ASN_NULL, NULL,  0);
  223.     }
  224.     oid_buf[buf_len-1] = stable[0].entry;
  225.     stats = (oid *)calloc(max_stat+1, sizeof(oid));
  226.     
  227.     /*
  228.      * Walk the specified column(s), and total the individual statistics
  229.      */
  230.     while (1) {
  231.         if (netsnmp_query_getnext( var, ss ) != SNMP_ERR_NOERROR)
  232.             break;
  233.         if ( snmp_oid_compare( oid_buf,   buf_len-1,
  234.                                var->name, buf_len-1) != 0 )
  235.             break;    /* End of Table */
  236.             
  237.         for ( vp=var; vp; vp=vp->next_variable ) {
  238.             stat = var->name[ buf_len-1 ];
  239.             stats[stat] += *vp->val.integer;
  240.         }
  241.         active=1;
  242.     }
  243.     if (!active) {
  244.         free( stats );
  245.         snmp_free_varbind( var );
  246.         return;     /* No statistics to display */
  247.     }
  248.     /*
  249.      * Display the results
  250.      */
  251.     printf("%s:n", name);
  252.     for (sp=stable; sp->entry; sp++) {
  253.         /*
  254.          * If '-Cs' was specified twice,
  255.          *   then only display non-zero stats.
  256.          */
  257.         if ( stats[sp->entry] > 0 || sflag == 1 ) {
  258.             putchar('t');
  259.             printf(sp->description, stats[sp->entry],
  260.                              plural(stats[sp->entry]));
  261.             putchar('n');
  262.         }
  263.     }
  264.     free( stats );
  265.     snmp_free_varbind( var );
  266. }
  267. /*
  268.  * Dump IP6 statistics.
  269.  */
  270. void
  271. ip6_stats(const char *name)
  272. {
  273.     oid               ip6stats_oid[] = { 1, 3, 6, 1, 2, 1, 55, 1, 6, 1, 0 };
  274.     size_t            ip6stats_len   = OID_LENGTH( ip6stats_oid );
  275.     struct stat_table ip6stats_tbl[] = {
  276.         {1, "%d total datagram%s received"},
  277.         {2, "%d datagram%s with header errors"},
  278.         {3, "%d oversized datagram%s"},
  279.         {4, "%d datagram%s with no route"},
  280.         {5, "%d datagram%s with an invalid destination address"},
  281.         {6, "%d datagram%s with unknown protocol"},
  282.         {7, "%d short datagram%s discarded"},
  283.         {8, "%d datagram%s discarded"},
  284.         {9, "%d datagram%s delivered"},
  285.         {10, "%d datagram%s forwarded"},
  286.         {11, "%d output datagram request%s"},
  287.         {12, "%d output datagram%s discarded"},
  288.         {13, "%d datagram%s fragmented"},
  289.         {14, "%d fragmentation failure%s"},
  290.         {15, "%d fragment%s created"},
  291.         {16, "%d fragment%s received"},
  292.         {17, "%d datagram%s reassembled"},
  293.         {18, "%d reassembly failure%s"},
  294.         {19, "%d multicast datagram%s received"},
  295.         {20, "%d multicast datagram%s transmitted"},
  296.         {0, ""}
  297.     };
  298.     _dump_v6stats( name, ip6stats_oid, ip6stats_len, ip6stats_tbl );
  299. }
  300. /*
  301.  * Dump IPv6 per-interface statistics - Omitted
  302.  */
  303. /*
  304.  * Dump ICMP6 statistics.
  305.  */
  306. void
  307. icmp6_stats(const char *name)
  308. {
  309.     oid               icmp6stats_oid[] = { 1, 3, 6, 1, 2, 1, 56, 1, 1, 1, 0 };
  310.     size_t            icmp6stats_len   = OID_LENGTH( icmp6stats_oid );
  311.     struct stat_table icmp6stats_tbl[] = {
  312.         {1, "%d total message%s received"},
  313.         {2, "%d message%s dropped due to errors"},
  314.         {18, "%d ouput message request%s"},
  315.         {19, "%d output message%s discarded"},
  316.         {0, ""}
  317.     };
  318.     struct stat_table icmp6_inhistogram[] = {
  319.         {3, "Destination unreachable: %d"},
  320.         {4, "Admin Prohibit: %d"},
  321.         {5, "Time Exceeded: %d"},
  322.         {6, "Parameter Problem: %d"},
  323.         {7, "Too Big: %d"},
  324.         {8, "Echo Request: %d"},
  325.         {9, "Echo Reply: %d"},
  326.         {10, "Router Solicit: %d"},
  327.         {11, "Router Advert: %d"},
  328.         {12, "Neighbor Solicit: %d"},
  329.         {13, "Neighbor Advert: %d"},
  330.         {14, "Redirect: %d"},
  331.         {15, "Group Member Request: %d"},
  332.         {16, "Group Member Reply:%d"},
  333.         {17, "Group Member Reduce:%d"},
  334.         {0, ""}
  335.     };
  336.     struct stat_table icmp6_outhistogram[] = {
  337.         {20, "Destination unreachable: %d"},
  338.         {21, "Admin Prohibit: %d"},
  339.         {22, "Time Exceeded: %d"},
  340.         {23, "Parameter Problem: %d"},
  341.         {24, "Too Big: %d"},
  342.         {25, "Echo Request: %d"},
  343.         {26, "Echo Reply: %d"},
  344.         {27, "Router Solicit: %d"},
  345.         {28, "Router Advert: %d"},
  346.         {29, "Neighbor Solicit: %d"},
  347.         {30, "Neighbor Advert: %d"},
  348.         {31, "Redirect: %d"},
  349.         {32, "Group Member Request: %d"},
  350.         {33, "Group Member Reply:%d"},
  351.         {34, "Group Member Reduce:%d"},
  352.         {0, ""}
  353.     };
  354.     _dump_v6stats( name, icmp6stats_oid, icmp6stats_len, icmp6stats_tbl );
  355.     _dump_v6stats( "    Input Histogram",
  356.                          icmp6stats_oid, icmp6stats_len, icmp6_inhistogram );
  357.     _dump_v6stats( "    Output Histogram",
  358.                          icmp6stats_oid, icmp6stats_len, icmp6_outhistogram );
  359. }
  360. /*
  361.  * Dump ICMPv6 per-interface statistics - Omitted
  362.  */
  363. /*
  364.  * Ommitted:
  365.  *     Dump PIM statistics
  366.  *     Dump raw ip6 statistics
  367.  */
  368. /*
  369.  * Pretty print an Internet address (net address + port).
  370.  * If the nflag was specified, use numbers instead of names.
  371.  */
  372. void
  373. inet6print(unsigned char *in6, int port, const char *proto, int local)
  374. {
  375. #define GETSERVBYPORT6(port, proto, ret) do { 
  376. if (strcmp((proto), "tcp6") == 0) 
  377. (ret) = getservbyport((int)(port), "tcp"); 
  378. else if (strcmp((proto), "udp6") == 0) 
  379. (ret) = getservbyport((int)(port), "udp"); 
  380. else 
  381. (ret) = getservbyport((int)(port), (proto)); 
  382. } while (0)
  383. struct servent *sp = 0;
  384. char line[80], *cp;
  385. int width;
  386. int len = sizeof line;
  387. width = Aflag ? 12 : 16;
  388. if (vflag && width < strlen(inet6name(in6)))
  389. width = strlen(inet6name(in6));
  390. snprintf(line, len, "%.*s.", width, inet6name(in6));
  391. len -= strlen(line);
  392. if (len <= 0)
  393. goto bail;
  394. cp = strchr(line, '');
  395. if (!nflag && port && local)
  396. GETSERVBYPORT6(port, proto, sp);
  397. if (sp || port == 0)
  398. snprintf(cp, len, "%.8s", sp ? sp->s_name : "*");
  399. else
  400. snprintf(cp, len, "%d", ntohs((u_short)port));
  401. width = Aflag ? 18 : 22;
  402. if (vflag && width < strlen(line))
  403. width = strlen(line);
  404. bail:
  405. printf(" %-*.*s", width, width, line);
  406. }
  407. /*
  408.  * Construct an Internet address representation.
  409.  * If the nflag has been supplied, give
  410.  * numeric value, otherwise try for symbolic name.
  411.  */
  412. char *
  413. inet6name(const unsigned char *in6)
  414. {
  415. char *cp;
  416. static char line[NI_MAXHOST];
  417. static char domain[MAXHOSTNAMELEN];
  418. static int first = 1;
  419. #ifdef INET6
  420. struct hostent *hp;
  421. char hbuf[NI_MAXHOST];
  422. const int niflag = NI_NUMERICHOST;
  423. struct sockaddr_in6 sin6;
  424. struct in6_addr *in6p = (struct in6_addr *)in6;
  425. #endif
  426. if (first && !nflag) {
  427. first = 0;
  428. if (gethostname(domain, sizeof(domain)) == 0 &&
  429.     (cp = strchr(domain, '.')))
  430. (void) strlcpy(domain, cp + 1, sizeof domain);
  431. else
  432. domain[0] = '';
  433. }
  434. #ifdef INET6
  435. cp = 0;
  436. if (!nflag && !IN6_IS_ADDR_UNSPECIFIED(in6p)) {
  437. hp = gethostbyaddr((char *)in6p, sizeof(*in6p), AF_INET6);
  438. if (hp) {
  439. if ((cp = strchr(hp->h_name, '.')) &&
  440.     !strcmp(cp + 1, domain))
  441. *cp = 0;
  442. cp = hp->h_name;
  443. }
  444. }
  445. if (IN6_IS_ADDR_UNSPECIFIED(in6p))
  446. strlcpy(line, "*", sizeof(line));
  447. else if (cp)
  448. strlcpy(line, cp, sizeof(line));
  449. else {
  450. memset(&sin6, 0, sizeof(sin6));
  451. /* sin6.sin6_len = sizeof(sin6);   */
  452. sin6.sin6_family = AF_INET6;
  453. sin6.sin6_addr = *in6p;
  454. #ifdef __KAME__
  455. if (IN6_IS_ADDR_LINKLOCAL(in6p) ||
  456.     IN6_IS_ADDR_MC_LINKLOCAL(in6p)) {
  457. sin6.sin6_scope_id =
  458.     ntohs(*(u_int16_t *)&in6p->s6_addr[2]);
  459. sin6.sin6_addr.s6_addr[2] = 0;
  460. sin6.sin6_addr.s6_addr[3] = 0;
  461. }
  462. #endif
  463. if (getnameinfo((struct sockaddr *)&sin6, sizeof(sin6),
  464.     hbuf, sizeof(hbuf), NULL, 0, niflag) != 0)
  465. strlcpy(hbuf, "?", sizeof hbuf);
  466. strlcpy(line, hbuf, sizeof(line));
  467. }
  468. #else
  469. strlcpy(line, "[[XXX - inet6 address]]", sizeof(line));
  470. #endif
  471. return (line);
  472. }
  473. #ifdef TCP6
  474. /*
  475.  * Dump the contents of a TCP6 PCB - Omitted
  476.  */
  477. #endif