+++ /dev/null
-/****************************************************************
- Copyright 1989, 1991, 1992 by Carnegie Mellon University
-
- All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of CMU not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-******************************************************************/
-/*
- * Copyright (c) 1983,1988 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms are permitted
- * provided that this notice is preserved and that due credit is given
- * to the University of California at Berkeley. The name of the University
- * may not be used to endorse or promote products derived from this
- * software without specific prior written permission. This software
- * is provided ``as is'' without express or implied warranty.
- */
-
-#include <net-snmp/net-snmp-config.h>
-
-#ifdef INET6
-
-#if HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#if HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#if HAVE_STRING_H
-#include <string.h>
-#else
-#include <strings.h>
-#endif
-
-#include <stdio.h>
-
-#if HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#if HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-#if HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#if HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#if HAVE_WINSOCK_H
-#include <winsock.h>
-#include "winstub.h"
-#else
-#include <sys/socket.h>
-#include <netdb.h>
-#endif
-
-#include "main.h"
-#include <net-snmp/net-snmp-includes.h>
-#include "netstat.h"
-
-static char *inet6name(struct in6_addr *);
-
-struct stat_table {
- int entry; /* entry number in table */
- /*
- * format string to printf(description, value, plural(value));
- */
- /*
- * warning: the %d must be before the %s
- */
- char description[80];
-};
-
-#if DEBUGGING_INFORMATION
- /*
- * The following tables provide useful debugging information.
- * This isn't normally needed or easily accessible,
- * but could potentially be very useful.
- * Rather than delete it totally, it's commented out
- */
-static oid oid_ipstats[] = { 1, 3, 6, 1, 2, 1, 4, 0, 0 };
-struct stat_table ip_stattab[] = {
- {3, "%d total datagram%s received"},
- {4, "%d datagram%s with header errors"},
- {5, "%d datagram%s with an invalid destination address"},
- {6, "%d datagram%s forwarded"},
- {7, "%d datagram%s with unknown protocol"},
- {8, "%d datagram%s discarded"},
- {9, "%d datagram%s delivered"},
- {10, "%d output datagram request%s"},
- {11, "%d output datagram%s discarded"},
- {12, "%d datagram%s with no route"},
- {14, "%d fragment%s received"},
- {15, "%d datagram%s reassembled"},
- {16, "%d reassembly failure%s"},
- {17, "%d datagram%s fragmented"},
- {18, "%d fragmentation failure%s"},
- {19, "%d fragment%s created"}
-};
-
-static oid oid_udpstats[] = { 1, 3, 6, 1, 2, 1, 7, 0, 0 };
-struct stat_table udp_stattab[] = {
- {1, "%d total datagram%s received"},
- {2, "%d datagram%s to invalid port"},
- {3, "%d datagram%s dropped due to errors"},
- {4, "%d output datagram request%s"}
-};
-
-static oid oid_tcpstats[] = { 1, 3, 6, 1, 2, 1, 6, 0, 0 };
-struct stat_table tcp_stattab[] = {
- {5, "%d active open%s"},
- {6, "%d passive open%s"},
- {7, "%d failed attempt%s"},
- {8, "%d reset%s of established connections"},
- {9, "%d current established connection%s"},
- {10, "%d segment%s received"},
- {11, "%d segment%s sent"},
- {12, "%d segment%s retransmitted"}
-};
-
-static oid oid_icmpstats[] = { 1, 3, 6, 1, 2, 1, 5, 0, 0 };
-struct stat_table icmp_stattab[] = {
- {1, "%d total message%s received"},
- {2, "%d message%s dropped due to errors"},
- {14, "%d ouput message request%s"},
- {15, "%d output message%s discarded"}
-};
-
-struct stat_table icmp_inhistogram[] = {
- {3, "Destination unreachable: %d"},
- {4, "Time Exceeded: %d"},
- {5, "Parameter Problem: %d"},
- {6, "Source Quench: %d"},
- {7, "Redirect: %d"},
- {8, "Echo Request: %d"},
- {9, "Echo Reply: %d"},
- {10, "Timestamp Request: %d"},
- {11, "Timestamp Reply: %d"},
- {12, "Address Mask Request: %d"},
- {13, "Addrss Mask Reply:%d"},
-};
-
-struct stat_table icmp_outhistogram[] = {
- {16, "Destination unreachable: %d"},
- {17, "Time Exceeded: %d"},
- {18, "Parameter Problem: %d"},
- {19, "Source Quench: %d"},
- {20, "Redirect: %d"},
- {21, "Echo Request: %d"},
- {22, "Echo Reply: %d"},
- {23, "Timestamp Request: %d"},
- {24, "Timestamp Reply: %d"},
- {25, "Address Mask Request: %d"},
- {26, "Addrss Mask Reply:%d"},
-};
-#endif
-
-struct tcpconn_entry {
- oid instance[16 + 1 + 16 + 1 + 1];
- struct in6_addr localAddress;
- int locAddrSet;
- u_short localPort;
- int locPortSet;
- struct in6_addr remoteAddress;
- int remAddrSet;
- u_short remotePort;
- int remPortSet;
- int state;
- int stateSet;
- struct tcpconn_entry *next;
-};
-
-struct udp_entry {
- oid instance[16 + 1 + 1];
- struct in6_addr localAddress;
- int locAddrSet;
- u_short localPort;
- int locPortSet;
- struct udp_entry *next;
-};
-
-#define TCPCONN_LOCADDR 1
-#define TCPCONN_LOCPORT 2
-#define TCPCONN_REMADDR 3
-#define TCPCONN_REMPORT 4
-#define TCPCONN_IFINDEX 5
-#define TCPCONN_STATE 6
-
-static oid oid_tcpconntable[] = { 1, 3, 6, 1, 3, 86, 1, 16, 1 };
-#define TCP_ENTRY 9
-
-#define UDP_LOCADDR 1
-#define UDP_LOCPORT 2
-#define UDP_IFINDEX 3
-
-static oid oid_udptable[] = { 1, 3, 6, 1, 3, 87, 1, 1, 1 };
-#define UDP_ENTRY 9
-
-static const char *tcpstates[] = {
- "",
- "CLOSED",
- "LISTEN",
- "SYNSENT",
- "SYNRECEIVED",
- "ESTABLISHED",
- "FINWAIT1",
- "FINWAIT2",
- "CLOSEWAIT",
- "LASTACK",
- "CLOSING",
- "TIMEWAIT"
-};
-#define TCP_NSTATES 11
-
-static int validUShortAssign(unsigned short *, int, const char *);
-
-/*
- * Print a summary of connections related to an Internet
- * protocol (currently only TCP). For TCP, also give state of connection.
- */
-void
-protopr6(const char *name)
-{
- struct tcpconn_entry *tcpconn = NULL, *tcplast = NULL, *tp, *newtp;
- struct udp_entry *udpconn = NULL, *udplast = NULL, *up, *newup;
- netsnmp_pdu *request = NULL, *response = NULL;
- netsnmp_variable_list *vp;
- oid *instance;
- int first, status;
-
- response = NULL;
- if (strncmp(name, "tcp", 3) == 0) {
- request = snmp_pdu_create(SNMP_MSG_GETNEXT);
- snmp_add_null_var(request, oid_tcpconntable,
- sizeof(oid_tcpconntable) / sizeof(oid));
- status = STAT_SUCCESS;
- } else
- status = STAT_TIMEOUT;
- while (status == STAT_SUCCESS) {
- if (response)
- snmp_free_pdu(response);
- response = NULL;
- status = snmp_synch_response(Session, request, &response);
- if (status != STAT_SUCCESS
- || response->errstat != SNMP_ERR_NOERROR) {
- snmp_perror("SNMP request failed");
- break;
- }
- vp = response->variables;
- if (!vp)
- break;
- if (vp->name_length != 46 ||
- memcmp(vp->name, oid_tcpconntable, sizeof(oid_tcpconntable))) {
- break;
- }
-
- request = snmp_pdu_create(SNMP_MSG_GETNEXT);
- snmp_add_null_var(request, vp->name, vp->name_length);
-
- instance = vp->name + 10;
- for (tp = tcpconn; tp != NULL; tp = tp->next) {
- if (!memcmp(instance, tp->instance, sizeof(tp->instance)))
- break;
- }
- if (tp == NULL) {
- tp = (struct tcpconn_entry *) calloc(1,
- sizeof(struct
- tcpconn_entry));
- if (tp == NULL)
- break;
- if (tcplast != NULL)
- tcplast->next = tp;
- tcplast = tp;
- if (tcpconn == NULL)
- tcpconn = tp;
- memmove(tp->instance, instance, sizeof(tp->instance));
- }
-
- if (vp->name[TCP_ENTRY] == TCPCONN_STATE) {
- tp->state = *vp->val.integer;
- tp->stateSet = 1;
- }
-
- if (vp->name[TCP_ENTRY] == TCPCONN_LOCADDR) {
- memmove(&tp->localAddress, vp->val.string,
- sizeof(struct in6_addr));
- tp->locAddrSet = 1;
- }
-
- if (vp->name[TCP_ENTRY] == TCPCONN_LOCPORT) {
- if (validUShortAssign(&tp->localPort, *vp->val.integer,
- "TCPCONN_LOCPORT"))
- tp->locPortSet = 1;
- }
-
- if (vp->name[TCP_ENTRY] == TCPCONN_REMADDR) {
- memmove(&tp->remoteAddress, vp->val.string,
- sizeof(struct in6_addr));
- tp->remAddrSet = 1;
- }
-
- if (vp->name[TCP_ENTRY] == TCPCONN_REMPORT) {
- if (validUShortAssign(&tp->remotePort, *vp->val.integer,
- "TCPCONN_REMPORT"))
- tp->remPortSet = 1;
- }
- }
- if (response)
- snmp_free_pdu(response);
- response = NULL;
-
- for (first = 1, tp = tcpconn, newtp = NULL; tp != NULL; tp = tp->next) {
- if (newtp)
- free(newtp);
- newtp = tp;
- if (!(tp->stateSet && tp->locAddrSet
- && tp->locPortSet && tp->remAddrSet && tp->remPortSet)) {
- printf("incomplete entry\n");
- continue;
- }
- if (!aflag && tp->state == MIB_TCPCONNSTATE_LISTEN)
- continue;
- if (first) {
- printf("Active Internet (%s) Connections", name);
- if (aflag)
- printf(" (including servers)");
- putchar('\n');
- printf("%-5.5s %-28.28s %-28.28s %s\n",
- "Proto", "Local Address", "Foreign Address", "(state)");
- first = 0;
- }
- printf("%-5.5s ", name);
- inet6print(&tp->localAddress, tp->localPort, name);
- inet6print(&tp->remoteAddress, tp->remotePort, name);
- if (tp->state < 1 || tp->state > TCP_NSTATES)
- printf(" %d", tp->state);
- else
- printf(" %s", tcpstates[tp->state]);
- putchar('\n');
- }
- if (newtp)
- free(newtp);
-
- response = NULL;
- if (strncmp(name, "udp", 3) == 0) {
- request = snmp_pdu_create(SNMP_MSG_GETNEXT);
- snmp_add_null_var(request, oid_udptable,
- sizeof(oid_udptable) / sizeof(oid));
- status = STAT_SUCCESS;
- } else
- status = STAT_TIMEOUT;
- while (status == STAT_SUCCESS) {
- if (response)
- snmp_free_pdu(response);
- response = NULL;
- status = snmp_synch_response(Session, request, &response);
- if (status != STAT_SUCCESS
- || response->errstat != SNMP_ERR_NOERROR) {
- fprintf(stderr, "SNMP request failed\n");
- break;
- }
- vp = response->variables;
- if (!vp)
- break;
- if (vp->name_length != 28 ||
- memcmp(vp->name, oid_udptable, sizeof(oid_udptable))) {
- break;
- }
-
- request = snmp_pdu_create(SNMP_MSG_GETNEXT);
- snmp_add_null_var(request, vp->name, vp->name_length);
-
- instance = vp->name + 10;
- for (up = udpconn; up != NULL; up = up->next) {
- if (!memcmp(instance, up->instance, sizeof(up->instance)))
- break;
- }
- if (up == NULL) {
- up = (struct udp_entry *) calloc(1, sizeof(struct udp_entry));
- if (up == NULL)
- break;
- if (udplast != NULL)
- udplast->next = up;
- udplast = up;
- if (udpconn == NULL)
- udpconn = up;
- memmove(up->instance, instance, sizeof(up->instance));
- }
-
- if (vp->name[UDP_ENTRY] == UDP_LOCADDR) {
- memmove(&up->localAddress, vp->val.string,
- sizeof(struct in6_addr));
- up->locAddrSet = 1;
- }
-
- if (vp->name[UDP_ENTRY] == UDP_LOCPORT) {
- if (validUShortAssign(&up->localPort, *vp->val.integer,
- "UDP_LOCPORT"))
- up->locPortSet = 1;
- }
- }
- if (response)
- snmp_free_pdu(response);
- response = NULL;
-
- for (first = 1, up = udpconn, newup = NULL; up != NULL; up = up->next) {
- if (newup)
- free(newup);
- newup = up;
- if (!(up->locAddrSet && up->locPortSet)) {
- printf("incomplete entry\n");
- continue;
- }
- if (first) {
- printf("Active Internet (%s) Connections", name);
- putchar('\n');
- printf("%-5.5s %-28.28s\n", "Proto", "Local Address");
- first = 0;
- }
- printf("%-5.5s ", name);
- inet6print(&up->localAddress, up->localPort, name);
- putchar('\n');
- }
- if (newup)
- free(newup);
-
-}
-
-static int
-validUShortAssign(unsigned short *pushort, int ival, const char *errstr)
-{
- u_long ulval = (u_long) ival;
- if (ival > 65535) {
- printf("Warning: %s value %ld (0x%lx) is not a port address\n",
- errstr, ulval, ulval);
- return 0;
- }
- *pushort = (unsigned short) ulval;
- return 1;
-}
-
-
-#if DEBUGGING_INFORMATION
- /*
- * The following routines print out useful debugging information.
- * This isn't normally needed or easily accessible,
- * but could potentially be very useful.
- * Rather than delete it totally, it's commented out
- */
-/*
- * Dump UDP statistics structure.
- */
-void
-udp_stats(void)
-{
- oid varname[MAX_OID_LEN], *udpentry;
- int varname_len;
- netsnmp_variable_list *var;
- int count;
- struct stat_table *sp = udp_stattab;
-
- memmove(varname, oid_udpstats, sizeof(oid_udpstats));
- varname_len = sizeof(oid_udpstats) / sizeof(oid);
- udpentry = varname + 7;
- printf("udp:\n");
- count = sizeof(udp_stattab) / sizeof(struct stat_table);
- while (count--) {
- *udpentry = sp->entry;
- var = getvarbyname(Session, varname, varname_len);
- if (var && var->val.integer) {
- putchar('\t');
- printf(sp->description, *var->val.integer,
- plural((int) *var->val.integer));
- putchar('\n');
- }
- if (var)
- snmp_free_var(var);
- sp++;
- }
-
-}
-
-/*
- * Dump TCP statistics structure.
- */
-void
-tcp_stats(void)
-{
- oid varname[MAX_OID_LEN], *tcpentry;
- int varname_len;
- netsnmp_variable_list *var;
- int count;
- struct stat_table *sp = tcp_stattab;
-
- memmove(varname, oid_tcpstats, sizeof(oid_tcpstats));
- varname_len = sizeof(oid_tcpstats) / sizeof(oid);
- tcpentry = varname + 7;
- printf("tcp:\n");
- count = sizeof(tcp_stattab) / sizeof(struct stat_table);
- while (count--) {
- *tcpentry = sp->entry;
- var = getvarbyname(Session, varname, varname_len);
- if (var && var->val.integer) {
- putchar('\t');
- printf(sp->description, *var->val.integer,
- plural((int) *var->val.integer));
- putchar('\n');
- }
- if (var)
- snmp_free_var(var);
- sp++;
- }
-
-}
-
-/*
- * Dump IP statistics structure.
- */
-void
-ip_stats(void)
-{
- oid varname[MAX_OID_LEN], *ipentry;
- int varname_len;
- netsnmp_variable_list *var;
- int count;
- struct stat_table *sp = ip_stattab;
-
- memmove(varname, oid_ipstats, sizeof(oid_ipstats));
- varname_len = sizeof(oid_ipstats) / sizeof(oid);
- ipentry = varname + 7;
- printf("ip:\n");
- count = sizeof(ip_stattab) / sizeof(struct stat_table);
- while (count--) {
- *ipentry = sp->entry;
- var = getvarbyname(Session, varname, varname_len);
- if (var && var->val.integer) {
- putchar('\t');
- printf(sp->description, *var->val.integer,
- plural((int) *var->val.integer));
- putchar('\n');
- }
- if (var)
- snmp_free_var(var);
- sp++;
- }
-
-}
-
-/*
- * Dump ICMP statistics.
- */
-void
-icmp_stats(void)
-{
- oid varname[MAX_OID_LEN], *icmpentry;
- int varname_len;
- netsnmp_variable_list *var;
- int count, first;
- struct stat_table *sp;
-
- memmove(varname, oid_icmpstats, sizeof(oid_icmpstats));
- varname_len = sizeof(oid_icmpstats) / sizeof(oid);
- icmpentry = varname + 7;
- printf("icmp:\n");
- sp = icmp_stattab;
- count = sizeof(icmp_stattab) / sizeof(struct stat_table);
- while (count--) {
- *icmpentry = sp->entry;
- var = getvarbyname(Session, varname, varname_len);
- if (var && var->val.integer) {
- putchar('\t');
- printf(sp->description, *var->val.integer,
- plural((int) *var->val.integer));
- putchar('\n');
- }
- if (var)
- snmp_free_var(var);
- sp++;
- }
-
- sp = icmp_outhistogram;
- first = 1;
- count = sizeof(icmp_outhistogram) / sizeof(struct stat_table);
- while (count--) {
- *icmpentry = sp->entry;
- var = getvarbyname(Session, varname, varname_len);
- if (var && var->val.integer && *var->val.integer != 0) {
- if (first) {
- printf("\tOutput Histogram:\n");
- first = 0;
- }
- printf("\t\t");
- printf(sp->description, *var->val.integer,
- plural((int) *var->val.integer));
- putchar('\n');
- }
- if (var)
- snmp_free_var(var);
- sp++;
- }
-
- sp = icmp_inhistogram;
- first = 1;
- count = sizeof(icmp_inhistogram) / sizeof(struct stat_table);
- while (count--) {
- *icmpentry = sp->entry;
- var = getvarbyname(Session, varname, varname_len);
- if (var && var->val.integer && *var->val.integer != 0) {
- if (first) {
- printf("\tInput Histogram:\n");
- first = 0;
- }
- printf("\t\t");
- printf(sp->description, *var->val.integer,
- plural((int) *var->val.integer));
- putchar('\n');
- }
- if (var)
- snmp_free_var(var);
- sp++;
- }
-}
-#endif
-
-/*
- * Pretty print an Internet address (net address + port).
- * If the nflag was specified, use numbers instead of names.
- */
-void
-inet6print(struct in6_addr *in, u_short port, const char *proto)
-{
- struct servent *sp = 0;
- char line[80], *cp;
- int width;
-
- sprintf(line, "%.*s.", 22, inet6name(in));
- cp = strchr(line, '\0');
- if (!nflag && port)
- sp = getservbyport(htons(port), proto);
- if (sp || port == 0)
- sprintf(cp, "%.8s", sp ? sp->s_name : "*");
- else
- sprintf(cp, "%d", port);
- width = 28;
- printf(" %-*.*s", width, width, line);
-}
-
-/*
- * Construct an Internet address representation.
- * If the nflag has been supplied, give
- * numeric value, otherwise try for symbolic name.
- */
-static char *
-inet6name(struct in6_addr *in)
-{
- register char *cp;
- static char line[50];
- struct hostent *hp;
- static char domain[MAXHOSTNAMELEN + 1];
- static int first = 1;
-
- if (first && !nflag) {
- first = 0;
- if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
- (cp = strchr(domain, '.')))
- (void) strcpy(domain, cp + 1);
- else
- domain[0] = 0;
- }
- cp = 0;
- if (!nflag && !IN6_IS_ADDR_UNSPECIFIED(in)) {
- hp = gethostbyaddr((char *) in, sizeof(*in), 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(in))
- strcpy(line, "*");
- else if (cp) {
- strncpy(line, cp, sizeof(line));
- line[ sizeof(line)-1 ] = 0;
- } else
- inet_ntop(AF_INET6, in, line, sizeof(line));
- return (line);
-}
-
-#endif /* INET6 */