📄 inet6.c
字号:
/* $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 0static 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>#if HAVE_UNISTD_H#include <unistd.h>#endif#if HAVE_WINSOCK_H#include <winsock2.h>#include <ws2tcpip.h>#include "winstub.h"#endif#if HAVE_SYS_SOCKET_H#include <sys/socket.h>#endif#if HAVE_NETDB_H#include <netdb.h>#endif#if HAVE_SYS_TYPES_H#include <sys/types.h>#endif#if HAVE_NETINET_IN_H#include <netinet/in.h>#endif#if HAVE_ARPA_INET_H#include <arpa/inet.h>#endif#include <net-snmp/net-snmp-includes.h>#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 11voidtcp6protopr(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 %s\n", "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 %d\n", ifIndex, state ); else printf(" %4d %s\n", ifIndex, tcp6states[ state ]); } snmp_free_varbind( var );}/* * Print a summary of UDPv6 "connections" * XXX - what about "listening" services ?? */voidudp6protopr(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 Connections\n"); printf("%-5.5s %-28.28s %4s\n", "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(" %4d\n", 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. */voidip6_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. */voidicmp6_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. */voidinet6print(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, '\0'); 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 NETSNMP_ENABLE_IPV6 struct hostent *hp; char hbuf[NI_MAXHOST]; const int niflag = NI_NUMERICHOST; struct sockaddr_in6 sin6; const struct in6_addr *in6p = (const 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] = '\0'; }#ifdef NETSNMP_ENABLE_IPV6 cp = 0; if (!nflag && !IN6_IS_ADDR_UNSPECIFIED(in6p)) { hp = gethostbyaddr((const 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -