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>
52 #include <sys/param.h>
56 #include <sys/select.h>
59 #include <netinet/in.h>
62 #include <arpa/inet.h>
64 #define LOOPBACKNET 127
71 #include <sys/socket.h>
78 #include <net-snmp/net-snmp-includes.h>
83 struct in_addr destination;
87 struct in_addr gateway;
106 static oid oid_rttable[] = { 1, 3, 6, 1, 2, 1, 4, 21, 1 };
107 static oid oid_rtdest[] = { 1, 3, 6, 1, 2, 1, 4, 21, 1, 1 };
108 static oid oid_rtifindex[] = { 1, 3, 6, 1, 2, 1, 4, 21, 1, 2 };
109 static oid oid_rtnexthop[] = { 1, 3, 6, 1, 2, 1, 4, 21, 1, 7 };
110 static oid oid_rttype[] = { 1, 3, 6, 1, 2, 1, 4, 21, 1, 8 };
111 static oid oid_rtproto[] = { 1, 3, 6, 1, 2, 1, 4, 21, 1, 9 };
112 static oid oid_rtmask[] = { 1, 3, 6, 1, 2, 1, 4, 21, 1, 11 };
113 static oid oid_ifdescr[] = { 1, 3, 6, 1, 2, 1, 2, 2, 1, 2 };
114 static oid oid_ipnoroutes[] = { 1, 3, 6, 1, 2, 1, 4, 12, 0 };
118 * Print routing tables.
123 struct route_entry route, *rp = &route;
124 netsnmp_pdu *request, *response;
125 netsnmp_variable_list *vp;
126 char name[16], *flags;
128 int toloopback, status;
131 printf("Routing tables\n");
132 printf("%-26.26s %-18.18s %-6.6s %s\n",
133 "Destination", "Gateway", "Flags", "Interface");
136 request = snmp_pdu_create(SNMP_MSG_GETNEXT);
138 snmp_add_null_var(request, oid_rtdest,
139 sizeof(oid_rtdest) / sizeof(oid));
140 snmp_add_null_var(request, oid_rtmask,
141 sizeof(oid_rtmask) / sizeof(oid));
142 snmp_add_null_var(request, oid_rtifindex,
143 sizeof(oid_rtifindex) / sizeof(oid));
144 snmp_add_null_var(request, oid_rtnexthop,
145 sizeof(oid_rtnexthop) / sizeof(oid));
146 snmp_add_null_var(request, oid_rttype,
147 sizeof(oid_rttype) / sizeof(oid));
148 snmp_add_null_var(request, oid_rtproto,
149 sizeof(oid_rtproto) / sizeof(oid));
152 status = snmp_synch_response(Session, request, &response);
153 if (status != STAT_SUCCESS
154 || response->errstat != SNMP_ERR_NOERROR) {
155 fprintf(stderr, "SNMP request failed\n");
160 rp->set_destination = 0;
162 rp->set_ifNumber = 0;
166 for (vp = response->variables; vp; vp = vp->next_variable) {
167 if (vp->name_length != 14 ||
168 memcmp(vp->name, oid_rttable, sizeof(oid_rttable))) {
169 continue; /* if it isn't in this subtree, just continue */
172 if (instance != NULL) {
178 for (count = 0; count < 4; count++) {
183 continue; /* not the right instance, ignore */
185 instance = vp->name + 10;
188 * At this point, this variable is known to be in the routing table
189 * subtree, and is of the right instance for this transaction.
193 request = snmp_pdu_create(SNMP_MSG_GETNEXT);
194 snmp_add_null_var(request, vp->name, vp->name_length);
197 switch ((char) type) {
199 memmove(&rp->destination, vp->val.string, sizeof(u_long));
200 rp->set_destination = 1;
203 memmove(&rp->mask, vp->val.string, sizeof(u_long));
207 rp->ifNumber = *vp->val.integer;
208 rp->set_ifNumber = 1;
211 memmove(&rp->gateway, vp->val.string, sizeof(u_long));
215 rp->type = *vp->val.integer;
219 rp->proto = *vp->val.integer;
224 snmp_free_pdu(response);
225 if (!(rp->set_destination && rp->set_gateway
226 && rp->set_type && rp->set_ifNumber)) {
228 snmp_free_pdu(request);
232 toloopback = *(char *) &rp->gateway == LOOPBACKNET;
234 (rp->destination.s_addr == INADDR_ANY) ? "default" :
235 (toloopback) ? routename(rp->destination) :
236 rp->set_mask ? netname(rp->destination, rp->mask.s_addr) :
237 netname(rp->destination, 0L));
238 printf("%-18.18s ", routename(rp->gateway));
240 *flags++ = 'U'; /* route is in use */
242 * this !toloopback shouldnt be necessary
244 if (!toloopback && rp->type == MIB_IPROUTETYPE_REMOTE)
248 if (rp->proto == MIB_IPROUTEPROTO_ICMP)
249 *flags++ = 'D'; /* redirect */
251 printf("%-6.6s ", name);
252 get_ifname(rp->ifname, rp->ifNumber);
253 ch = rp->ifname[strlen(rp->ifname) - 1];
254 ch = '5'; /* force the if statement */
256 printf(" %.32s\n", rp->ifname);
258 printf(" %.32s%d\n", rp->ifname, rp->ifNumber);
270 get_ifname(char *name, int ifIndex)
272 netsnmp_pdu *pdu, *response;
273 netsnmp_variable_list *vp;
275 oid varname[MAX_OID_LEN];
278 for (ip = Iflist; ip; ip = ip->next) {
279 if (ip->index == ifIndex)
283 strcpy(name, ip->name);
286 ip = (struct iflist *) malloc(sizeof(struct iflist));
292 pdu = snmp_pdu_create(SNMP_MSG_GET);
293 memmove(varname, oid_ifdescr, sizeof(oid_ifdescr));
294 varname[10] = (oid) ifIndex;
295 snmp_add_null_var(pdu, varname, sizeof(oid_ifdescr) / sizeof(oid) + 1);
296 status = snmp_synch_response(Session, pdu, &response);
297 if (status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR) {
298 vp = response->variables;
299 if (vp->val_len >= sizeof(ip->name))
300 vp->val_len = sizeof(ip->name) - 1;
301 memmove(ip->name, vp->val.string, vp->val_len);
302 ip->name[vp->val_len] = '\0';
303 snmp_free_pdu(response);
305 sprintf(ip->name, "if%d", ifIndex);
307 strcpy(name, ip->name);
316 else if (IN_CLASSB(a))
324 domask(char *dst, u_long addr, u_long mask)
327 if (!mask || forgemask(addr) == mask) {
332 for (b = 0; b < 32; b++)
333 if (mask & (1 << b)) {
336 for (bb = b + 1; bb < 32; bb++)
337 if (!(mask & (1 << bb))) {
338 i = -1; /* non-contig */
344 sprintf(dst, "&0x%lx", mask);
346 sprintf(dst, "/%d", 32 - i);
350 routename(struct in_addr in)
353 static char line[MAXHOSTNAMELEN + 1];
355 static char domain[MAXHOSTNAMELEN + 1];
356 static int first = 1;
360 if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
361 (cp = (char *) strchr(domain, '.')))
362 (void) strcpy(domain, cp + 1);
368 hp = gethostbyaddr((char *) &in, sizeof(struct in_addr), AF_INET);
370 if ((cp = (char *) strchr(hp->h_name, '.')) &&
371 !strcmp(cp + 1, domain))
373 cp = (char *) hp->h_name;
377 strncpy(line, cp, sizeof(line) - 1);
379 #define C(x) (unsigned)((x) & 0xff)
380 in.s_addr = ntohl(in.s_addr);
381 sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
382 C(in.s_addr >> 16), C(in.s_addr >> 8), C(in.s_addr));
388 * Return the name of the network whose address is given.
389 * The address is assumed to be that of a net or subnet, not a host.
392 netname(struct in_addr in, u_long mask)
395 static char line[MAXHOSTNAMELEN + 1];
396 struct netent *np = 0;
401 i = ntohl(in.s_addr);
402 omask = mask = ntohl(mask);
403 if (!nflag && i != INADDR_ANY) {
404 if (mask == INADDR_ANY) {
406 mask = IN_CLASSA_NET;
408 } else if (IN_CLASSB(i)) {
409 mask = IN_CLASSB_NET;
412 mask = IN_CLASSC_NET;
416 * If there are more bits than the standard mask
417 * would suggest, subnets must be in use.
418 * Guess at the subnet mask, assuming reasonable
419 * width subnet fields.
422 mask = (long) mask >> subnetshift;
425 while ((mask & 1) == 0)
426 mask >>= 1, net >>= 1;
427 np = getnetbyaddr(net, AF_INET);
432 strncpy(line, cp, sizeof(line) - 1);
433 else if ((i & 0xffffff) == 0)
434 sprintf(line, "%u", C(i >> 24));
435 else if ((i & 0xffff) == 0)
436 sprintf(line, "%u.%u", C(i >> 24), C(i >> 16));
437 else if ((i & 0xff) == 0)
438 sprintf(line, "%u.%u.%u", C(i >> 24), C(i >> 16), C(i >> 8));
440 sprintf(line, "%u.%u.%u.%u", C(i >> 24),
441 C(i >> 16), C(i >> 8), C(i));
442 domask(line + strlen(line), i, omask);
447 * Print routing statistics
452 netsnmp_variable_list *var;
454 printf("routing:\n");
456 getvarbyname(Session, oid_ipnoroutes,
457 sizeof(oid_ipnoroutes) / sizeof(oid));
459 printf("\t%lu destination%s found unreachable\n",
460 *var->val.integer, plural((int) *var->val.integer));
463 printf("\tCouldn't get ipOutNoRoutes variable\n");
468 * Request a variable with a GET REQUEST message on the given
469 * session. If the variable is found, a
470 * pointer to a netsnmp_variable_list object will be returned.
471 * Otherwise, NULL is returned. The caller must free the returned
472 * variable_list object when done with it.
474 netsnmp_variable_list *
475 getvarbyname(netsnmp_session * sp, oid * name, size_t len)
477 netsnmp_pdu *request, *response;
478 netsnmp_variable_list *var = NULL, *vp;
481 request = snmp_pdu_create(SNMP_MSG_GET);
483 snmp_add_null_var(request, name, len);
485 status = snmp_synch_response(sp, request, &response);
487 if (status == STAT_SUCCESS) {
488 if (response->errstat == SNMP_ERR_NOERROR) {
489 for (var = response->variables; var; var = var->next_variable) {
490 if (var->name_length == len
491 && !memcmp(name, var->name, len * sizeof(oid)))
492 break; /* found our match */
496 * Now unlink this var from pdu chain so it doesn't get freed.
497 * The caller will free the var.
499 if (response->variables == var) {
500 response->variables = var->next_variable;
502 for (vp = response->variables; vp;
503 vp = vp->next_variable) {
504 if (vp->next_variable == var) {
505 vp->next_variable = var->next_variable;
510 if (var->type == SNMP_NOSUCHOBJECT ||
511 var->type == SNMP_NOSUCHINSTANCE ||
512 var->type == SNMP_ENDOFMIBVIEW) {
518 } else if (status != STAT_TIMEOUT)
519 snmp_sess_perror("snmpnetstat", sp);
521 snmp_free_pdu(response);