inet6.c
上传用户:wxp200602
上传日期:2007-10-30
资源大小:4028k
文件大小:15k
- /* $OpenBSD: inet6.c,v 1.31 2004/11/17 01:47:20 itojun Exp $ */
- /* BSDI inet.c,v 2.3 1995/10/24 02:19:29 prb Exp */
- /*
- * Copyright (c) 1983, 1988, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
- #ifdef INHERITED_CODE
- #ifndef lint
- #if 0
- static char sccsid[] = "@(#)inet.c 8.4 (Berkeley) 4/20/94";
- #else
- /*__RCSID("$OpenBSD: inet6.c,v 1.31 2004/11/17 01:47:20 itojun Exp $");*/
- /*__RCSID("KAME Id: inet6.c,v 1.10 2000/02/09 10:49:31 itojun Exp");*/
- #endif
- #endif /* not lint */
- #endif
- #include <net-snmp/net-snmp-config.h>
- /*
- * hack-o-matic for Cygwin to use winsock2
- */
- #if defined(cygwin)
- #undef HAVE_UNISTD_H
- #undef HAVE_NETINET_IN_H
- #undef HAVE_ARPA_INET_H
- #undef HAVE_SYS_PARAM_H
- #undef HAVE_SYS_SELECT_H
- #undef HAVE_SYS_SOCKET_H
- #undef HAVE_IN_ADDR_T
- #endif
- #if defined(HAVE_WINSOCK_H) || defined(cygwin)
- #include <winsock2.h>
- #include <ws2tcpip.h>
- #include "winstub.h"
- extern const char *inet_ntop(int, const void*, char*, size_t);
- #ifdef cygwin
- extern int WSAAPI getnameinfo(const struct sockaddr*,socklen_t,char*,DWORD, char*,DWORD,int);
- #endif
- #else /* WIN32 */
- #if HAVE_NETDB_H
- #include <netdb.h>
- #endif
- #endif /* WIN32 */
- #include <net-snmp/net-snmp-includes.h>
- #if HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #include "main.h"
- #include "netstat.h"
- struct stat_table {
- int entry; /* entry number in table */
- /*
- * format string to printf(description, value)
- * warning: the %d must be before the %s
- */
- char description[80];
- };
- char *inet6name(const unsigned char *);
- void inet6print(unsigned char *, int, const char *, int);
- /*
- * Print a summary of TCPv6 connections
- * Listening processes are suppressed unless the
- * -a (all) flag is specified.
- */
- const char *tcp6states[] = {
- "",
- "CLOSED",
- "LISTEN",
- "SYNSENT",
- "SYNRECEIVED",
- "ESTABLISHED",
- "FINWAIT1",
- "FINWAIT2",
- "CLOSEWAIT",
- "LASTACK",
- "CLOSING",
- "TIMEWAIT"
- };
- #define TCP_NSTATES 11
- void
- tcp6protopr(const char *name)
- {
- netsnmp_variable_list *var, *vp;
- oid ipv6TcpConnState_oid[] = { 1,3,6,1,2,1,6,16,1,6 };
- size_t ipv6TcpConnState_len = OID_LENGTH( ipv6TcpConnState_oid );
- int state, i;
- unsigned char localAddr[16], remoteAddr[16];
- int localPort, remotePort, ifIndex;
- int first = 1;
- /*
- * Walking the v6 tcpConnState column will provide all
- * the necessary information.
- */
- var = NULL;
- snmp_varlist_add_variable( &var, ipv6TcpConnState_oid,
- ipv6TcpConnState_len,
- ASN_NULL, NULL, 0);
- if (netsnmp_query_walk( var, ss ) != SNMP_ERR_NOERROR)
- return;
- if (var->type == ASN_NULL) /* No entries */
- return;
- for (vp = var; vp ; vp=vp->next_variable) {
- state = *var->val.integer;
- if (!aflag && state == MIB_TCPCONNSTATE_LISTEN)
- continue;
- if (first) {
- printf("Active Internet Connections");
- if (aflag)
- printf(" (including servers)");
- putchar('n');
- printf("%-5.5s %-28.28s %-28.28s %4s %sn",
- "Proto", "Local Address", "Remote Address", "I/F", "(state)");
- first = 0;
- }
-
- /* Extract the local/remote information from the index values */
- for (i=0; i<16; i++)
- localAddr[i] = var->name[ 10+i ];
- localPort = var->name[ 26 ];
- for (i=0; i<16; i++)
- remoteAddr[i] = var->name[ 27+i ];
- remotePort = var->name[ 43 ];
- ifIndex = var->name[ 44 ];
- printf("%-5.5s", name);
- inet6print(localAddr, localPort, name, 1);
- inet6print(remoteAddr, remotePort, name, 0);
- if ( state < 1 || state > TCP_NSTATES )
- printf(" %4d %dn", ifIndex, state );
- else
- printf(" %4d %sn", ifIndex, tcp6states[ state ]);
- }
- snmp_free_varbind( var );
- }
- /*
- * Print a summary of UDPv6 "connections"
- * XXX - what about "listening" services ??
- */
- void
- udp6protopr(const char *name)
- {
- netsnmp_variable_list *var, *vp;
- oid ipv6UdpLocalAddress_oid[] = { 1,3,6,1,2,1,7,6,1,1 };
- size_t ipv6UdpLocalAddress_len = OID_LENGTH( ipv6UdpLocalAddress_oid );
- int localPort, ifIndex;
- /*
- * Walking a single column of the udpTable will provide
- * all the necessary information from the index values.
- */
- var = NULL;
- snmp_varlist_add_variable( &var, ipv6UdpLocalAddress_oid,
- ipv6UdpLocalAddress_len,
- ASN_NULL, NULL, 0);
- if (netsnmp_query_walk( var, ss ) != SNMP_ERR_NOERROR)
- return;
- if (var->type == ASN_NULL) /* No entries */
- return;
- printf("Active Internet Connectionsn");
- printf("%-5.5s %-28.28s %4sn", "Proto", "Local Address", "I/F");
- for (vp = var; vp ; vp=vp->next_variable) {
- printf("%-5.5s", name);
- /*
- * Extract the local port from the index values, but take
- * the IP address from the varbind value, (which is why
- * we walked udpLocalAddress rather than udpLocalPort)
- */
- localPort = var->name[ var->name_length-2 ];
- ifIndex = var->name[ var->name_length-1 ];
- inet6print(var->val.string, localPort, name, 1);
- printf(" %4dn", ifIndex );
- }
- snmp_free_varbind( var );
- }
- /*********************
- *
- * IPv6 statistics
- *
- *********************/
- /*
- * Unlike the equivalent IPv4 statistics display routine,
- * the IPv6 version must walk the columns of a table
- * and total the statistics for each column (rather
- * than simply retrieving individual scalar values)
- */
- void
- _dump_v6stats( const char *name, oid *oid_buf, size_t buf_len,
- struct stat_table *stable )
- {
- netsnmp_variable_list *var, *vp;
- struct stat_table *sp;
- oid *stats, stat;
- int max_stat = 0;
- int active = 0;
- var = NULL;
- for (sp=stable; sp->entry; sp++) {
- oid_buf[buf_len-1] = sp->entry;
- if (sp->entry>max_stat)
- max_stat = sp->entry;
- snmp_varlist_add_variable( &var, oid_buf, buf_len,
- ASN_NULL, NULL, 0);
- }
- oid_buf[buf_len-1] = stable[0].entry;
- stats = (oid *)calloc(max_stat+1, sizeof(oid));
-
- /*
- * Walk the specified column(s), and total the individual statistics
- */
- while (1) {
- if (netsnmp_query_getnext( var, ss ) != SNMP_ERR_NOERROR)
- break;
- if ( snmp_oid_compare( oid_buf, buf_len-1,
- var->name, buf_len-1) != 0 )
- break; /* End of Table */
-
- for ( vp=var; vp; vp=vp->next_variable ) {
- stat = var->name[ buf_len-1 ];
- stats[stat] += *vp->val.integer;
- }
- active=1;
- }
- if (!active) {
- free( stats );
- snmp_free_varbind( var );
- return; /* No statistics to display */
- }
- /*
- * Display the results
- */
- printf("%s:n", name);
- for (sp=stable; sp->entry; sp++) {
- /*
- * If '-Cs' was specified twice,
- * then only display non-zero stats.
- */
- if ( stats[sp->entry] > 0 || sflag == 1 ) {
- putchar('t');
- printf(sp->description, stats[sp->entry],
- plural(stats[sp->entry]));
- putchar('n');
- }
- }
- free( stats );
- snmp_free_varbind( var );
- }
- /*
- * Dump IP6 statistics.
- */
- void
- ip6_stats(const char *name)
- {
- oid ip6stats_oid[] = { 1, 3, 6, 1, 2, 1, 55, 1, 6, 1, 0 };
- size_t ip6stats_len = OID_LENGTH( ip6stats_oid );
- struct stat_table ip6stats_tbl[] = {
- {1, "%d total datagram%s received"},
- {2, "%d datagram%s with header errors"},
- {3, "%d oversized datagram%s"},
- {4, "%d datagram%s with no route"},
- {5, "%d datagram%s with an invalid destination address"},
- {6, "%d datagram%s with unknown protocol"},
- {7, "%d short datagram%s discarded"},
- {8, "%d datagram%s discarded"},
- {9, "%d datagram%s delivered"},
- {10, "%d datagram%s forwarded"},
- {11, "%d output datagram request%s"},
- {12, "%d output datagram%s discarded"},
- {13, "%d datagram%s fragmented"},
- {14, "%d fragmentation failure%s"},
- {15, "%d fragment%s created"},
- {16, "%d fragment%s received"},
- {17, "%d datagram%s reassembled"},
- {18, "%d reassembly failure%s"},
- {19, "%d multicast datagram%s received"},
- {20, "%d multicast datagram%s transmitted"},
- {0, ""}
- };
- _dump_v6stats( name, ip6stats_oid, ip6stats_len, ip6stats_tbl );
- }
- /*
- * Dump IPv6 per-interface statistics - Omitted
- */
- /*
- * Dump ICMP6 statistics.
- */
- void
- icmp6_stats(const char *name)
- {
- oid icmp6stats_oid[] = { 1, 3, 6, 1, 2, 1, 56, 1, 1, 1, 0 };
- size_t icmp6stats_len = OID_LENGTH( icmp6stats_oid );
- struct stat_table icmp6stats_tbl[] = {
- {1, "%d total message%s received"},
- {2, "%d message%s dropped due to errors"},
- {18, "%d ouput message request%s"},
- {19, "%d output message%s discarded"},
- {0, ""}
- };
- struct stat_table icmp6_inhistogram[] = {
- {3, "Destination unreachable: %d"},
- {4, "Admin Prohibit: %d"},
- {5, "Time Exceeded: %d"},
- {6, "Parameter Problem: %d"},
- {7, "Too Big: %d"},
- {8, "Echo Request: %d"},
- {9, "Echo Reply: %d"},
- {10, "Router Solicit: %d"},
- {11, "Router Advert: %d"},
- {12, "Neighbor Solicit: %d"},
- {13, "Neighbor Advert: %d"},
- {14, "Redirect: %d"},
- {15, "Group Member Request: %d"},
- {16, "Group Member Reply:%d"},
- {17, "Group Member Reduce:%d"},
- {0, ""}
- };
- struct stat_table icmp6_outhistogram[] = {
- {20, "Destination unreachable: %d"},
- {21, "Admin Prohibit: %d"},
- {22, "Time Exceeded: %d"},
- {23, "Parameter Problem: %d"},
- {24, "Too Big: %d"},
- {25, "Echo Request: %d"},
- {26, "Echo Reply: %d"},
- {27, "Router Solicit: %d"},
- {28, "Router Advert: %d"},
- {29, "Neighbor Solicit: %d"},
- {30, "Neighbor Advert: %d"},
- {31, "Redirect: %d"},
- {32, "Group Member Request: %d"},
- {33, "Group Member Reply:%d"},
- {34, "Group Member Reduce:%d"},
- {0, ""}
- };
- _dump_v6stats( name, icmp6stats_oid, icmp6stats_len, icmp6stats_tbl );
- _dump_v6stats( " Input Histogram",
- icmp6stats_oid, icmp6stats_len, icmp6_inhistogram );
- _dump_v6stats( " Output Histogram",
- icmp6stats_oid, icmp6stats_len, icmp6_outhistogram );
- }
- /*
- * Dump ICMPv6 per-interface statistics - Omitted
- */
- /*
- * Ommitted:
- * Dump PIM statistics
- * Dump raw ip6 statistics
- */
- /*
- * Pretty print an Internet address (net address + port).
- * If the nflag was specified, use numbers instead of names.
- */
- void
- inet6print(unsigned char *in6, int port, const char *proto, int local)
- {
- #define GETSERVBYPORT6(port, proto, ret) do {
- if (strcmp((proto), "tcp6") == 0)
- (ret) = getservbyport((int)(port), "tcp");
- else if (strcmp((proto), "udp6") == 0)
- (ret) = getservbyport((int)(port), "udp");
- else
- (ret) = getservbyport((int)(port), (proto));
- } while (0)
- struct servent *sp = 0;
- char line[80], *cp;
- int width;
- int len = sizeof line;
- width = Aflag ? 12 : 16;
- if (vflag && width < strlen(inet6name(in6)))
- width = strlen(inet6name(in6));
- snprintf(line, len, "%.*s.", width, inet6name(in6));
- len -= strlen(line);
- if (len <= 0)
- goto bail;
- cp = strchr(line, ' ');
- if (!nflag && port && local)
- GETSERVBYPORT6(port, proto, sp);
- if (sp || port == 0)
- snprintf(cp, len, "%.8s", sp ? sp->s_name : "*");
- else
- snprintf(cp, len, "%d", ntohs((u_short)port));
- width = Aflag ? 18 : 22;
- if (vflag && width < strlen(line))
- width = strlen(line);
- bail:
- printf(" %-*.*s", width, width, line);
- }
- /*
- * Construct an Internet address representation.
- * If the nflag has been supplied, give
- * numeric value, otherwise try for symbolic name.
- */
- char *
- inet6name(const unsigned char *in6)
- {
- char *cp;
- static char line[NI_MAXHOST];
- static char domain[MAXHOSTNAMELEN];
- static int first = 1;
- #ifdef INET6
- struct hostent *hp;
- char hbuf[NI_MAXHOST];
- const int niflag = NI_NUMERICHOST;
- struct sockaddr_in6 sin6;
- struct in6_addr *in6p = (struct in6_addr *)in6;
- #endif
- if (first && !nflag) {
- first = 0;
- if (gethostname(domain, sizeof(domain)) == 0 &&
- (cp = strchr(domain, '.')))
- (void) strlcpy(domain, cp + 1, sizeof domain);
- else
- domain[0] = ' ';
- }
- #ifdef INET6
- cp = 0;
- if (!nflag && !IN6_IS_ADDR_UNSPECIFIED(in6p)) {
- hp = gethostbyaddr((char *)in6p, sizeof(*in6p), AF_INET6);
- if (hp) {
- if ((cp = strchr(hp->h_name, '.')) &&
- !strcmp(cp + 1, domain))
- *cp = 0;
- cp = hp->h_name;
- }
- }
- if (IN6_IS_ADDR_UNSPECIFIED(in6p))
- strlcpy(line, "*", sizeof(line));
- else if (cp)
- strlcpy(line, cp, sizeof(line));
- else {
- memset(&sin6, 0, sizeof(sin6));
- /* sin6.sin6_len = sizeof(sin6); */
- sin6.sin6_family = AF_INET6;
- sin6.sin6_addr = *in6p;
- #ifdef __KAME__
- if (IN6_IS_ADDR_LINKLOCAL(in6p) ||
- IN6_IS_ADDR_MC_LINKLOCAL(in6p)) {
- sin6.sin6_scope_id =
- ntohs(*(u_int16_t *)&in6p->s6_addr[2]);
- sin6.sin6_addr.s6_addr[2] = 0;
- sin6.sin6_addr.s6_addr[3] = 0;
- }
- #endif
- if (getnameinfo((struct sockaddr *)&sin6, sizeof(sin6),
- hbuf, sizeof(hbuf), NULL, 0, niflag) != 0)
- strlcpy(hbuf, "?", sizeof hbuf);
- strlcpy(line, hbuf, sizeof(line));
- }
- #else
- strlcpy(line, "[[XXX - inet6 address]]", sizeof(line));
- #endif
- return (line);
- }
- #ifdef TCP6
- /*
- * Dump the contents of a TCP6 PCB - Omitted
- */
- #endif