1 /****************************************************************
2 Copyright 1989, 1991, 1992 by Carnegie Mellon University
6 Permission to use, copy, modify, and distribute this software and its
7 documentation for any purpose and without fee is hereby granted,
8 provided that the above copyright notice appear in all copies and that
9 both that copyright notice and this permission notice appear in
10 supporting documentation, and that the name of CMU not be
11 used in advertising or publicity pertaining to distribution of the
12 software without specific, written prior permission.
14 CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16 CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21 ******************************************************************/
23 * Copyright (c) 1983,1988 Regents of the University of California.
24 * All rights reserved.
26 * Redistribution and use in source and binary forms are permitted
27 * provided that this notice is preserved and that due credit is given
28 * to the University of California at Berkeley. The name of the University
29 * may not be used to endorse or promote products derived from this
30 * software without specific prior written permission. This software
31 * is provided ``as is'' without express or implied warranty.
34 #include <net-snmp/net-snmp-config.h>
51 #include <sys/param.h>
54 #include <sys/select.h>
57 #include <netinet/in.h>
60 #include <arpa/inet.h>
67 #include <sys/socket.h>
74 #include <net-snmp/net-snmp-includes.h>
77 static char *inetname(struct in_addr);
80 int entry; /* entry number in table */
82 * format string to printf(description, value, plural(value));
85 * warning: the %d must be before the %s
90 static oid oid_ipstats[] = { 1, 3, 6, 1, 2, 1, 4, 0, 0 };
91 struct stat_table ip_stattab[] = {
92 {3, "%d total datagram%s received"},
93 {4, "%d datagram%s with header errors"},
94 {5, "%d datagram%s with an invalid destination address"},
95 {6, "%d datagram%s forwarded"},
96 {7, "%d datagram%s with unknown protocol"},
97 {8, "%d datagram%s discarded"},
98 {9, "%d datagram%s delivered"},
99 {10, "%d output datagram request%s"},
100 {11, "%d output datagram%s discarded"},
101 {12, "%d datagram%s with no route"},
102 {14, "%d fragment%s received"},
103 {15, "%d datagram%s reassembled"},
104 {16, "%d reassembly failure%s"},
105 {17, "%d datagram%s fragmented"},
106 {18, "%d fragmentation failure%s"},
107 {19, "%d fragment%s created"}
110 static oid oid_udpstats[] = { 1, 3, 6, 1, 2, 1, 7, 0, 0 };
111 struct stat_table udp_stattab[] = {
112 {1, "%d total datagram%s received"},
113 {2, "%d datagram%s to invalid port"},
114 {3, "%d datagram%s dropped due to errors"},
115 {4, "%d output datagram request%s"}
118 static oid oid_tcpstats[] = { 1, 3, 6, 1, 2, 1, 6, 0, 0 };
119 struct stat_table tcp_stattab[] = {
120 {5, "%d active open%s"},
121 {6, "%d passive open%s"},
122 {7, "%d failed attempt%s"},
123 {8, "%d reset%s of established connections"},
124 {9, "%d current established connection%s"},
125 {10, "%d segment%s received"},
126 {11, "%d segment%s sent"},
127 {12, "%d segment%s retransmitted"}
130 static oid oid_icmpstats[] = { 1, 3, 6, 1, 2, 1, 5, 0, 0 };
131 struct stat_table icmp_stattab[] = {
132 {1, "%d total message%s received"},
133 {2, "%d message%s dropped due to errors"},
134 {14, "%d ouput message request%s"},
135 {15, "%d output message%s discarded"}
138 struct stat_table icmp_inhistogram[] = {
139 {3, "Destination unreachable: %d"},
140 {4, "Time Exceeded: %d"},
141 {5, "Parameter Problem: %d"},
142 {6, "Source Quench: %d"},
144 {8, "Echo Request: %d"},
145 {9, "Echo Reply: %d"},
146 {10, "Timestamp Request: %d"},
147 {11, "Timestamp Reply: %d"},
148 {12, "Address Mask Request: %d"},
149 {13, "Addrss Mask Reply:%d"},
152 struct stat_table icmp_outhistogram[] = {
153 {16, "Destination unreachable: %d"},
154 {17, "Time Exceeded: %d"},
155 {18, "Parameter Problem: %d"},
156 {19, "Source Quench: %d"},
157 {20, "Redirect: %d"},
158 {21, "Echo Request: %d"},
159 {22, "Echo Reply: %d"},
160 {23, "Timestamp Request: %d"},
161 {24, "Timestamp Reply: %d"},
162 {25, "Address Mask Request: %d"},
163 {26, "Addrss Mask Reply:%d"},
166 struct tcpconn_entry {
168 struct in_addr localAddress;
172 struct in_addr remoteAddress;
178 struct tcpconn_entry *next;
183 struct in_addr localAddress;
187 struct udp_entry *next;
190 #define TCPCONN_STATE 1
191 #define TCPCONN_LOCADDR 2
192 #define TCPCONN_LOCPORT 3
193 #define TCPCONN_REMADDR 4
194 #define TCPCONN_REMPORT 5
196 static oid oid_tcpconntable[] = { 1, 3, 6, 1, 2, 1, 6, 13, 1 };
199 #define UDP_LOCADDR 1
200 #define UDP_LOCPORT 2
202 static oid oid_udptable[] = { 1, 3, 6, 1, 2, 1, 7, 5, 1 };
205 const char *tcpstates[] = {
219 #define TCP_NSTATES 11
221 int validUShortAssign(unsigned short *, int, const char *);
224 * Print a summary of connections related to an Internet
225 * protocol (currently only TCP). For TCP, also give state of connection.
228 protopr(const char *name)
230 struct tcpconn_entry *tcpconn = NULL, *tcplast = NULL, *tp, *newtp;
231 struct udp_entry *udpconn = NULL, *udplast = NULL, *up, *newup;
232 netsnmp_pdu *request = NULL, *response = NULL;
233 netsnmp_variable_list *vp;
239 if (strcmp(name, "tcp") == 0) {
240 request = snmp_pdu_create(SNMP_MSG_GETNEXT);
241 snmp_add_null_var(request, oid_tcpconntable,
242 sizeof(oid_tcpconntable) / sizeof(oid));
243 status = STAT_SUCCESS;
245 status = STAT_TIMEOUT;
246 while (status == STAT_SUCCESS) {
248 snmp_free_pdu(response);
250 status = snmp_synch_response(Session, request, &response);
251 if (status != STAT_SUCCESS
252 || response->errstat != SNMP_ERR_NOERROR) {
253 snmp_sess_perror("SNMP request failed", Session);
256 vp = response->variables;
259 if (vp->name_length != 20 ||
260 memcmp(vp->name, oid_tcpconntable, sizeof(oid_tcpconntable))) {
264 request = snmp_pdu_create(SNMP_MSG_GETNEXT);
265 snmp_add_null_var(request, vp->name, vp->name_length);
267 instance = vp->name + 10;
268 for (tp = tcpconn; tp != NULL; tp = tp->next) {
269 if (!memcmp(instance, tp->instance, sizeof(tp->instance)))
273 tp = (struct tcpconn_entry *) calloc(1,
283 memmove(tp->instance, instance, sizeof(tp->instance));
286 if (vp->name[TCP_ENTRY] == TCPCONN_STATE) {
287 tp->state = *vp->val.integer;
291 if (vp->name[TCP_ENTRY] == TCPCONN_LOCADDR) {
292 memmove(&tp->localAddress, vp->val.string, sizeof(u_long));
296 if (vp->name[TCP_ENTRY] == TCPCONN_LOCPORT) {
297 if (validUShortAssign(&tp->localPort, *vp->val.integer,
302 if (vp->name[TCP_ENTRY] == TCPCONN_REMADDR) {
303 memmove(&tp->remoteAddress, vp->val.string, sizeof(u_long));
307 if (vp->name[TCP_ENTRY] == TCPCONN_REMPORT) {
308 if (validUShortAssign(&tp->remotePort, *vp->val.integer,
314 snmp_free_pdu(response);
317 for (first = 1, tp = tcpconn, newtp = NULL; tp != NULL; tp = tp->next) {
321 if (!(tp->stateSet && tp->locAddrSet
322 && tp->locPortSet && tp->remAddrSet && tp->remPortSet)) {
323 printf("incomplete entry\n");
326 if (!aflag && tp->state == MIB_TCPCONNSTATE_LISTEN)
329 printf("Active Internet (%s) Connections", name);
331 printf(" (including servers)");
333 printf("%-5.5s %-28.28s %-28.28s %s\n",
334 "Proto", "Local Address", "Foreign Address", "(state)");
337 printf("%-5.5s ", "tcp");
338 inetprint(&tp->localAddress, tp->localPort, "tcp");
339 inetprint(&tp->remoteAddress, tp->remotePort, "tcp");
340 if (tp->state < 1 || tp->state > TCP_NSTATES)
341 printf(" %d", tp->state);
343 printf(" %s", tcpstates[tp->state]);
351 if (strcmp(name, "udp") == 0) {
352 request = snmp_pdu_create(SNMP_MSG_GETNEXT);
353 snmp_add_null_var(request, oid_udptable,
354 sizeof(oid_udptable) / sizeof(oid));
355 status = STAT_SUCCESS;
357 status = STAT_TIMEOUT;
358 while (status == STAT_SUCCESS) {
360 snmp_free_pdu(response);
362 status = snmp_synch_response(Session, request, &response);
363 if (status != STAT_SUCCESS
364 || response->errstat != SNMP_ERR_NOERROR) {
365 fprintf(stderr, "SNMP request failed\n");
368 vp = response->variables;
371 if (vp->name_length != 15 ||
372 memcmp(vp->name, oid_udptable, sizeof(oid_udptable))) {
376 request = snmp_pdu_create(SNMP_MSG_GETNEXT);
377 snmp_add_null_var(request, vp->name, vp->name_length);
379 instance = vp->name + 10;
380 for (up = udpconn; up != NULL; up = up->next) {
381 if (!memcmp(instance, up->instance, sizeof(up->instance)))
385 up = (struct udp_entry *) calloc(1, sizeof(struct udp_entry));
393 memmove(up->instance, instance, sizeof(up->instance));
396 if (vp->name[UDP_ENTRY] == UDP_LOCADDR) {
397 memmove(&up->localAddress, vp->val.string, sizeof(u_long));
401 if (vp->name[UDP_ENTRY] == UDP_LOCPORT) {
402 if (validUShortAssign(&up->localPort, *vp->val.integer,
408 snmp_free_pdu(response);
411 for (first = 1, up = udpconn, newup = NULL; up != NULL; up = up->next) {
415 if (!(up->locAddrSet && up->locPortSet)) {
416 printf("incomplete entry\n");
420 printf("Active Internet (%s) Connections", name);
422 printf("%-5.5s %-28.28s\n", "Proto", "Local Address");
425 printf("%-5.5s ", "udp");
426 inetprint(&up->localAddress, up->localPort, "udp");
435 validUShortAssign(unsigned short *pushort, int ival, const char *errstr)
437 u_long ulval = (u_long) ival;
439 printf("Warning: %s value %ld (0x%lx) is not a port address\n",
440 errstr, ulval, ulval);
443 *pushort = (unsigned short) ulval;
449 * Dump UDP statistics structure.
454 oid varname[MAX_OID_LEN], *udpentry;
456 netsnmp_variable_list *var;
458 struct stat_table *sp = udp_stattab;
460 memmove(varname, oid_udpstats, sizeof(oid_udpstats));
461 varname_len = sizeof(oid_udpstats) / sizeof(oid);
462 udpentry = varname + 7;
464 count = sizeof(udp_stattab) / sizeof(struct stat_table);
466 *udpentry = sp->entry;
467 var = getvarbyname(Session, varname, varname_len);
468 if (var && var->val.integer) {
470 printf(sp->description, *var->val.integer,
471 plural((int) *var->val.integer));
482 * Dump TCP statistics structure.
487 oid varname[MAX_OID_LEN], *tcpentry;
489 netsnmp_variable_list *var;
491 struct stat_table *sp = tcp_stattab;
493 memmove(varname, oid_tcpstats, sizeof(oid_tcpstats));
494 varname_len = sizeof(oid_tcpstats) / sizeof(oid);
495 tcpentry = varname + 7;
497 count = sizeof(tcp_stattab) / sizeof(struct stat_table);
499 *tcpentry = sp->entry;
500 var = getvarbyname(Session, varname, varname_len);
501 if (var && var->val.integer) {
503 printf(sp->description, *var->val.integer,
504 plural((int) *var->val.integer));
515 * Dump IP statistics structure.
520 oid varname[MAX_OID_LEN], *ipentry;
522 netsnmp_variable_list *var;
524 struct stat_table *sp = ip_stattab;
526 memmove(varname, oid_ipstats, sizeof(oid_ipstats));
527 varname_len = sizeof(oid_ipstats) / sizeof(oid);
528 ipentry = varname + 7;
530 count = sizeof(ip_stattab) / sizeof(struct stat_table);
532 *ipentry = sp->entry;
533 var = getvarbyname(Session, varname, varname_len);
534 if (var && var->val.integer) {
536 printf(sp->description, *var->val.integer,
537 plural((int) *var->val.integer));
548 * Dump ICMP statistics.
553 oid varname[MAX_OID_LEN], *icmpentry;
555 netsnmp_variable_list *var;
557 struct stat_table *sp;
559 memmove(varname, oid_icmpstats, sizeof(oid_icmpstats));
560 varname_len = sizeof(oid_icmpstats) / sizeof(oid);
561 icmpentry = varname + 7;
564 count = sizeof(icmp_stattab) / sizeof(struct stat_table);
566 *icmpentry = sp->entry;
567 var = getvarbyname(Session, varname, varname_len);
568 if (var && var->val.integer) {
570 printf(sp->description, *var->val.integer,
571 plural((int) *var->val.integer));
579 sp = icmp_outhistogram;
581 count = sizeof(icmp_outhistogram) / sizeof(struct stat_table);
583 *icmpentry = sp->entry;
584 var = getvarbyname(Session, varname, varname_len);
585 if (var && var->val.integer && *var->val.integer != 0) {
587 printf("\tOutput Histogram:\n");
591 printf(sp->description, *var->val.integer,
592 plural((int) *var->val.integer));
600 sp = icmp_inhistogram;
602 count = sizeof(icmp_inhistogram) / sizeof(struct stat_table);
604 *icmpentry = sp->entry;
605 var = getvarbyname(Session, varname, varname_len);
606 if (var && var->val.integer && *var->val.integer != 0) {
608 printf("\tInput Histogram:\n");
612 printf(sp->description, *var->val.integer,
613 plural((int) *var->val.integer));
623 * Pretty print an Internet address (net address + port).
624 * If the nflag was specified, use numbers instead of names.
627 inetprint(struct in_addr *in, u_short port, const char *proto)
629 struct servent *sp = 0;
633 sprintf(line, "%.*s.", 22, inetname(*in));
634 cp = (char *) strchr(line, '\0');
636 sp = getservbyport(htons(port), proto);
638 sprintf(cp, "%.8s", sp ? sp->s_name : "*");
640 sprintf(cp, "%d", port);
642 printf(" %-*.*s", width, width, line);
646 * Construct an Internet address representation.
647 * If the nflag has been supplied, give
648 * numeric value, otherwise try for symbolic name.
651 inetname(struct in_addr in)
654 static char line[50];
657 static char domain[MAXHOSTNAMELEN + 1];
658 static int first = 1;
660 if (first && !nflag) {
662 if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
663 (cp = (char *) strchr(domain, '.')))
664 (void) strcpy(domain, cp + 1);
669 if (!nflag && in.s_addr != INADDR_ANY) {
670 u_long net = inet_netof(in);
671 u_long lna = inet_lnaof(in);
673 if (lna == INADDR_ANY) {
674 np = getnetbyaddr(net, AF_INET);
679 hp = gethostbyaddr((char *) &in, sizeof(in), AF_INET);
681 if ((cp = (char *) strchr(hp->h_name, '.')) &&
682 !strcmp(cp + 1, domain))
684 cp = (char *) hp->h_name;
688 if (in.s_addr == INADDR_ANY)
691 strncpy(line, cp, sizeof(line));
692 line[ sizeof(line)-1 ] = 0;
694 in.s_addr = ntohl(in.s_addr);
695 #define C(x) (unsigned)((x) & 0xff)
696 sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
697 C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));