Annotation of embedaddon/quagga/ripd/rip_snmp.c, revision 1.1
1.1 ! misho 1: /* RIP SNMP support
! 2: * Copyright (C) 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
! 3: *
! 4: * This file is part of GNU Zebra.
! 5: *
! 6: * GNU Zebra is free software; you can redistribute it and/or modify it
! 7: * under the terms of the GNU General Public License as published by the
! 8: * Free Software Foundation; either version 2, or (at your option) any
! 9: * later version.
! 10: *
! 11: * GNU Zebra is distributed in the hope that it will be useful, but
! 12: * WITHOUT ANY WARRANTY; without even the implied warranty of
! 13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
! 14: * General Public License for more details.
! 15: *
! 16: * You should have received a copy of the GNU General Public License
! 17: * along with GNU Zebra; see the file COPYING. If not, write to the Free
! 18: * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
! 19: * 02111-1307, USA.
! 20: */
! 21:
! 22: #include <zebra.h>
! 23:
! 24: #ifdef HAVE_SNMP
! 25: #ifdef HAVE_NETSNMP
! 26: #include <net-snmp/net-snmp-config.h>
! 27: #include <net-snmp/net-snmp-includes.h>
! 28: #else
! 29: #include <asn1.h>
! 30: #include <snmp.h>
! 31: #include <snmp_impl.h>
! 32: #endif
! 33:
! 34: #include "if.h"
! 35: #include "log.h"
! 36: #include "prefix.h"
! 37: #include "command.h"
! 38: #include "table.h"
! 39: #include "smux.h"
! 40:
! 41: #include "ripd/ripd.h"
! 42:
! 43: /* RIPv2-MIB. */
! 44: #define RIPV2MIB 1,3,6,1,2,1,23
! 45:
! 46: /* RIPv2-MIB rip2Globals values. */
! 47: #define RIP2GLOBALROUTECHANGES 1
! 48: #define RIP2GLOBALQUERIES 2
! 49:
! 50: /* RIPv2-MIB rip2IfStatEntry. */
! 51: #define RIP2IFSTATENTRY 1
! 52:
! 53: /* RIPv2-MIB rip2IfStatTable. */
! 54: #define RIP2IFSTATADDRESS 1
! 55: #define RIP2IFSTATRCVBADPACKETS 2
! 56: #define RIP2IFSTATRCVBADROUTES 3
! 57: #define RIP2IFSTATSENTUPDATES 4
! 58: #define RIP2IFSTATSTATUS 5
! 59:
! 60: /* RIPv2-MIB rip2IfConfTable. */
! 61: #define RIP2IFCONFADDRESS 1
! 62: #define RIP2IFCONFDOMAIN 2
! 63: #define RIP2IFCONFAUTHTYPE 3
! 64: #define RIP2IFCONFAUTHKEY 4
! 65: #define RIP2IFCONFSEND 5
! 66: #define RIP2IFCONFRECEIVE 6
! 67: #define RIP2IFCONFDEFAULTMETRIC 7
! 68: #define RIP2IFCONFSTATUS 8
! 69: #define RIP2IFCONFSRCADDRESS 9
! 70:
! 71: /* RIPv2-MIB rip2PeerTable. */
! 72: #define RIP2PEERADDRESS 1
! 73: #define RIP2PEERDOMAIN 2
! 74: #define RIP2PEERLASTUPDATE 3
! 75: #define RIP2PEERVERSION 4
! 76: #define RIP2PEERRCVBADPACKETS 5
! 77: #define RIP2PEERRCVBADROUTES 6
! 78:
! 79: /* SNMP value hack. */
! 80: #define COUNTER ASN_COUNTER
! 81: #define INTEGER ASN_INTEGER
! 82: #define TIMETICKS ASN_TIMETICKS
! 83: #define IPADDRESS ASN_IPADDRESS
! 84: #define STRING ASN_OCTET_STR
! 85:
! 86: /* Define SNMP local variables. */
! 87: SNMP_LOCAL_VARIABLES
! 88:
! 89: /* RIP-MIB instances. */
! 90: oid rip_oid [] = { RIPV2MIB };
! 91:
! 92: /* Interface cache table sorted by interface's address. */
! 93: struct route_table *rip_ifaddr_table;
! 94:
! 95: /* Hook functions. */
! 96: static u_char *rip2Globals (struct variable *, oid [], size_t *,
! 97: int, size_t *, WriteMethod **);
! 98: static u_char *rip2IfStatEntry (struct variable *, oid [], size_t *,
! 99: int, size_t *, WriteMethod **);
! 100: static u_char *rip2IfConfAddress (struct variable *, oid [], size_t *,
! 101: int, size_t *, WriteMethod **);
! 102: static u_char *rip2PeerTable (struct variable *, oid [], size_t *,
! 103: int, size_t *, WriteMethod **);
! 104:
! 105: struct variable rip_variables[] =
! 106: {
! 107: /* RIP Global Counters. */
! 108: {RIP2GLOBALROUTECHANGES, COUNTER, RONLY, rip2Globals,
! 109: 2, {1, 1}},
! 110: {RIP2GLOBALQUERIES, COUNTER, RONLY, rip2Globals,
! 111: 2, {1, 2}},
! 112: /* RIP Interface Tables. */
! 113: {RIP2IFSTATADDRESS, IPADDRESS, RONLY, rip2IfStatEntry,
! 114: 3, {2, 1, 1}},
! 115: {RIP2IFSTATRCVBADPACKETS, COUNTER, RONLY, rip2IfStatEntry,
! 116: 3, {2, 1, 2}},
! 117: {RIP2IFSTATRCVBADROUTES, COUNTER, RONLY, rip2IfStatEntry,
! 118: 3, {2, 1, 3}},
! 119: {RIP2IFSTATSENTUPDATES, COUNTER, RONLY, rip2IfStatEntry,
! 120: 3, {2, 1, 4}},
! 121: {RIP2IFSTATSTATUS, COUNTER, RWRITE, rip2IfStatEntry,
! 122: 3, {2, 1, 5}},
! 123: {RIP2IFCONFADDRESS, IPADDRESS, RONLY, rip2IfConfAddress,
! 124: /* RIP Interface Configuration Table. */
! 125: 3, {3, 1, 1}},
! 126: {RIP2IFCONFDOMAIN, STRING, RONLY, rip2IfConfAddress,
! 127: 3, {3, 1, 2}},
! 128: {RIP2IFCONFAUTHTYPE, COUNTER, RONLY, rip2IfConfAddress,
! 129: 3, {3, 1, 3}},
! 130: {RIP2IFCONFAUTHKEY, STRING, RONLY, rip2IfConfAddress,
! 131: 3, {3, 1, 4}},
! 132: {RIP2IFCONFSEND, COUNTER, RONLY, rip2IfConfAddress,
! 133: 3, {3, 1, 5}},
! 134: {RIP2IFCONFRECEIVE, COUNTER, RONLY, rip2IfConfAddress,
! 135: 3, {3, 1, 6}},
! 136: {RIP2IFCONFDEFAULTMETRIC, COUNTER, RONLY, rip2IfConfAddress,
! 137: 3, {3, 1, 7}},
! 138: {RIP2IFCONFSTATUS, COUNTER, RONLY, rip2IfConfAddress,
! 139: 3, {3, 1, 8}},
! 140: {RIP2IFCONFSRCADDRESS, IPADDRESS, RONLY, rip2IfConfAddress,
! 141: 3, {3, 1, 9}},
! 142: {RIP2PEERADDRESS, IPADDRESS, RONLY, rip2PeerTable,
! 143: /* RIP Peer Table. */
! 144: 3, {4, 1, 1}},
! 145: {RIP2PEERDOMAIN, STRING, RONLY, rip2PeerTable,
! 146: 3, {4, 1, 2}},
! 147: {RIP2PEERLASTUPDATE, TIMETICKS, RONLY, rip2PeerTable,
! 148: 3, {4, 1, 3}},
! 149: {RIP2PEERVERSION, INTEGER, RONLY, rip2PeerTable,
! 150: 3, {4, 1, 4}},
! 151: {RIP2PEERRCVBADPACKETS, COUNTER, RONLY, rip2PeerTable,
! 152: 3, {4, 1, 5}},
! 153: {RIP2PEERRCVBADROUTES, COUNTER, RONLY, rip2PeerTable,
! 154: 3, {4, 1, 6}}
! 155: };
! 156:
! 157: extern struct thread_master *master;
! 158:
! 159: static u_char *
! 160: rip2Globals (struct variable *v, oid name[], size_t *length,
! 161: int exact, size_t *var_len, WriteMethod **write_method)
! 162: {
! 163: if (smux_header_generic(v, name, length, exact, var_len, write_method)
! 164: == MATCH_FAILED)
! 165: return NULL;
! 166:
! 167: /* Retrun global counter. */
! 168: switch (v->magic)
! 169: {
! 170: case RIP2GLOBALROUTECHANGES:
! 171: return SNMP_INTEGER (rip_global_route_changes);
! 172: break;
! 173: case RIP2GLOBALQUERIES:
! 174: return SNMP_INTEGER (rip_global_queries);
! 175: break;
! 176: default:
! 177: return NULL;
! 178: break;
! 179: }
! 180: return NULL;
! 181: }
! 182:
! 183: void
! 184: rip_ifaddr_add (struct interface *ifp, struct connected *ifc)
! 185: {
! 186: struct prefix *p;
! 187: struct route_node *rn;
! 188:
! 189: p = ifc->address;
! 190:
! 191: if (p->family != AF_INET)
! 192: return;
! 193:
! 194: rn = route_node_get (rip_ifaddr_table, p);
! 195: rn->info = ifp;
! 196: }
! 197:
! 198: void
! 199: rip_ifaddr_delete (struct interface *ifp, struct connected *ifc)
! 200: {
! 201: struct prefix *p;
! 202: struct route_node *rn;
! 203: struct interface *i;
! 204:
! 205: p = ifc->address;
! 206:
! 207: if (p->family != AF_INET)
! 208: return;
! 209:
! 210: rn = route_node_lookup (rip_ifaddr_table, p);
! 211: if (! rn)
! 212: return;
! 213: i = rn->info;
! 214: if (rn && !strncmp(i->name,ifp->name,INTERFACE_NAMSIZ))
! 215: {
! 216: rn->info = NULL;
! 217: route_unlock_node (rn);
! 218: route_unlock_node (rn);
! 219: }
! 220: }
! 221:
! 222: static struct interface *
! 223: rip_ifaddr_lookup_next (struct in_addr *addr)
! 224: {
! 225: struct prefix_ipv4 p;
! 226: struct route_node *rn;
! 227: struct interface *ifp;
! 228:
! 229: p.family = AF_INET;
! 230: p.prefixlen = IPV4_MAX_BITLEN;
! 231: p.prefix = *addr;
! 232:
! 233: rn = route_node_get (rip_ifaddr_table, (struct prefix *) &p);
! 234:
! 235: for (rn = route_next (rn); rn; rn = route_next (rn))
! 236: if (rn->info)
! 237: break;
! 238:
! 239: if (rn && rn->info)
! 240: {
! 241: ifp = rn->info;
! 242: *addr = rn->p.u.prefix4;
! 243: route_unlock_node (rn);
! 244: return ifp;
! 245: }
! 246: return NULL;
! 247: }
! 248:
! 249: static struct interface *
! 250: rip2IfLookup (struct variable *v, oid name[], size_t *length,
! 251: struct in_addr *addr, int exact)
! 252: {
! 253: int len;
! 254: struct interface *ifp;
! 255:
! 256: if (exact)
! 257: {
! 258: /* Check the length. */
! 259: if (*length - v->namelen != sizeof (struct in_addr))
! 260: return NULL;
! 261:
! 262: oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr);
! 263:
! 264: return if_lookup_exact_address (*addr);
! 265: }
! 266: else
! 267: {
! 268: len = *length - v->namelen;
! 269: if (len > 4) len = 4;
! 270:
! 271: oid2in_addr (name + v->namelen, len, addr);
! 272:
! 273: ifp = rip_ifaddr_lookup_next (addr);
! 274:
! 275: if (ifp == NULL)
! 276: return NULL;
! 277:
! 278: oid_copy_addr (name + v->namelen, addr, sizeof (struct in_addr));
! 279:
! 280: *length = v->namelen + sizeof (struct in_addr);
! 281:
! 282: return ifp;
! 283: }
! 284: return NULL;
! 285: }
! 286:
! 287: static struct rip_peer *
! 288: rip2PeerLookup (struct variable *v, oid name[], size_t *length,
! 289: struct in_addr *addr, int exact)
! 290: {
! 291: int len;
! 292: struct rip_peer *peer;
! 293:
! 294: if (exact)
! 295: {
! 296: /* Check the length. */
! 297: if (*length - v->namelen != sizeof (struct in_addr) + 1)
! 298: return NULL;
! 299:
! 300: oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr);
! 301:
! 302: peer = rip_peer_lookup (addr);
! 303:
! 304: if (peer->domain == name[v->namelen + sizeof (struct in_addr)])
! 305: return peer;
! 306:
! 307: return NULL;
! 308: }
! 309: else
! 310: {
! 311: len = *length - v->namelen;
! 312: if (len > 4) len = 4;
! 313:
! 314: oid2in_addr (name + v->namelen, len, addr);
! 315:
! 316: len = *length - v->namelen;
! 317: peer = rip_peer_lookup (addr);
! 318: if (peer)
! 319: {
! 320: if ((len < sizeof (struct in_addr) + 1) ||
! 321: (peer->domain > name[v->namelen + sizeof (struct in_addr)]))
! 322: {
! 323: oid_copy_addr (name + v->namelen, &peer->addr,
! 324: sizeof (struct in_addr));
! 325: name[v->namelen + sizeof (struct in_addr)] = peer->domain;
! 326: *length = sizeof (struct in_addr) + v->namelen + 1;
! 327: return peer;
! 328: }
! 329: }
! 330: peer = rip_peer_lookup_next (addr);
! 331:
! 332: if (! peer)
! 333: return NULL;
! 334:
! 335: oid_copy_addr (name + v->namelen, &peer->addr,
! 336: sizeof (struct in_addr));
! 337: name[v->namelen + sizeof (struct in_addr)] = peer->domain;
! 338: *length = sizeof (struct in_addr) + v->namelen + 1;
! 339:
! 340: return peer;
! 341: }
! 342: return NULL;
! 343: }
! 344:
! 345: static u_char *
! 346: rip2IfStatEntry (struct variable *v, oid name[], size_t *length,
! 347: int exact, size_t *var_len, WriteMethod **write_method)
! 348: {
! 349: struct interface *ifp;
! 350: struct rip_interface *ri;
! 351: static struct in_addr addr;
! 352: static long valid = SNMP_VALID;
! 353:
! 354: memset (&addr, 0, sizeof (struct in_addr));
! 355:
! 356: /* Lookup interface. */
! 357: ifp = rip2IfLookup (v, name, length, &addr, exact);
! 358: if (! ifp)
! 359: return NULL;
! 360:
! 361: /* Fetch rip_interface information. */
! 362: ri = ifp->info;
! 363:
! 364: switch (v->magic)
! 365: {
! 366: case RIP2IFSTATADDRESS:
! 367: return SNMP_IPADDRESS (addr);
! 368: break;
! 369: case RIP2IFSTATRCVBADPACKETS:
! 370: *var_len = sizeof (long);
! 371: return (u_char *) &ri->recv_badpackets;
! 372:
! 373: case RIP2IFSTATRCVBADROUTES:
! 374: *var_len = sizeof (long);
! 375: return (u_char *) &ri->recv_badroutes;
! 376:
! 377: case RIP2IFSTATSENTUPDATES:
! 378: *var_len = sizeof (long);
! 379: return (u_char *) &ri->sent_updates;
! 380:
! 381: case RIP2IFSTATSTATUS:
! 382: *var_len = sizeof (long);
! 383: v->type = ASN_INTEGER;
! 384: return (u_char *) &valid;
! 385:
! 386: default:
! 387: return NULL;
! 388:
! 389: }
! 390: return NULL;
! 391: }
! 392:
! 393: static long
! 394: rip2IfConfSend (struct rip_interface *ri)
! 395: {
! 396: #define doNotSend 1
! 397: #define ripVersion1 2
! 398: #define rip1Compatible 3
! 399: #define ripVersion2 4
! 400: #define ripV1Demand 5
! 401: #define ripV2Demand 6
! 402:
! 403: if (! ri->running)
! 404: return doNotSend;
! 405:
! 406: if (ri->ri_send & RIPv2)
! 407: return ripVersion2;
! 408: else if (ri->ri_send & RIPv1)
! 409: return ripVersion1;
! 410: else if (rip)
! 411: {
! 412: if (rip->version_send == RIPv2)
! 413: return ripVersion2;
! 414: else if (rip->version_send == RIPv1)
! 415: return ripVersion1;
! 416: }
! 417: return doNotSend;
! 418: }
! 419:
! 420: static long
! 421: rip2IfConfReceive (struct rip_interface *ri)
! 422: {
! 423: #define rip1 1
! 424: #define rip2 2
! 425: #define rip1OrRip2 3
! 426: #define doNotReceive 4
! 427:
! 428: int recvv;
! 429:
! 430: if (! ri->running)
! 431: return doNotReceive;
! 432:
! 433: recvv = (ri->ri_receive == RI_RIP_UNSPEC) ? rip->version_recv :
! 434: ri->ri_receive;
! 435: if (recvv == RI_RIP_VERSION_1_AND_2)
! 436: return rip1OrRip2;
! 437: else if (recvv & RIPv2)
! 438: return rip2;
! 439: else if (recvv & RIPv1)
! 440: return rip1;
! 441: else
! 442: return doNotReceive;
! 443: }
! 444:
! 445: static u_char *
! 446: rip2IfConfAddress (struct variable *v, oid name[], size_t *length,
! 447: int exact, size_t *val_len, WriteMethod **write_method)
! 448: {
! 449: static struct in_addr addr;
! 450: static long valid = SNMP_INVALID;
! 451: static long domain = 0;
! 452: static long config = 0;
! 453: static u_int auth = 0;
! 454: struct interface *ifp;
! 455: struct rip_interface *ri;
! 456:
! 457: memset (&addr, 0, sizeof (struct in_addr));
! 458:
! 459: /* Lookup interface. */
! 460: ifp = rip2IfLookup (v, name, length, &addr, exact);
! 461: if (! ifp)
! 462: return NULL;
! 463:
! 464: /* Fetch rip_interface information. */
! 465: ri = ifp->info;
! 466:
! 467: switch (v->magic)
! 468: {
! 469: case RIP2IFCONFADDRESS:
! 470: *val_len = sizeof (struct in_addr);
! 471: return (u_char *) &addr;
! 472:
! 473: case RIP2IFCONFDOMAIN:
! 474: *val_len = 2;
! 475: return (u_char *) &domain;
! 476:
! 477: case RIP2IFCONFAUTHTYPE:
! 478: auth = ri->auth_type;
! 479: *val_len = sizeof (long);
! 480: v->type = ASN_INTEGER;
! 481: return (u_char *)&auth;
! 482:
! 483: case RIP2IFCONFAUTHKEY:
! 484: *val_len = 0;
! 485: return (u_char *) &domain;
! 486: case RIP2IFCONFSEND:
! 487: config = rip2IfConfSend (ri);
! 488: *val_len = sizeof (long);
! 489: v->type = ASN_INTEGER;
! 490: return (u_char *) &config;
! 491: case RIP2IFCONFRECEIVE:
! 492: config = rip2IfConfReceive (ri);
! 493: *val_len = sizeof (long);
! 494: v->type = ASN_INTEGER;
! 495: return (u_char *) &config;
! 496:
! 497: case RIP2IFCONFDEFAULTMETRIC:
! 498: *val_len = sizeof (long);
! 499: v->type = ASN_INTEGER;
! 500: return (u_char *) &ifp->metric;
! 501: case RIP2IFCONFSTATUS:
! 502: *val_len = sizeof (long);
! 503: v->type = ASN_INTEGER;
! 504: return (u_char *) &valid;
! 505: case RIP2IFCONFSRCADDRESS:
! 506: *val_len = sizeof (struct in_addr);
! 507: return (u_char *) &addr;
! 508:
! 509: default:
! 510: return NULL;
! 511:
! 512: }
! 513: return NULL;
! 514: }
! 515:
! 516: static u_char *
! 517: rip2PeerTable (struct variable *v, oid name[], size_t *length,
! 518: int exact, size_t *val_len, WriteMethod **write_method)
! 519: {
! 520: static struct in_addr addr;
! 521: static int domain = 0;
! 522: static int version;
! 523: /* static time_t uptime; */
! 524:
! 525: struct rip_peer *peer;
! 526:
! 527: memset (&addr, 0, sizeof (struct in_addr));
! 528:
! 529: /* Lookup interface. */
! 530: peer = rip2PeerLookup (v, name, length, &addr, exact);
! 531: if (! peer)
! 532: return NULL;
! 533:
! 534: switch (v->magic)
! 535: {
! 536: case RIP2PEERADDRESS:
! 537: *val_len = sizeof (struct in_addr);
! 538: return (u_char *) &peer->addr;
! 539:
! 540: case RIP2PEERDOMAIN:
! 541: *val_len = 2;
! 542: return (u_char *) &domain;
! 543:
! 544: case RIP2PEERLASTUPDATE:
! 545: #if 0
! 546: /* We don't know the SNMP agent startup time. We have two choices here:
! 547: * - assume ripd startup time equals SNMP agent startup time
! 548: * - don't support this variable, at all
! 549: * Currently, we do the latter...
! 550: */
! 551: *val_len = sizeof (time_t);
! 552: uptime = peer->uptime; /* now - snmp_agent_startup - peer->uptime */
! 553: return (u_char *) &uptime;
! 554: #else
! 555: return (u_char *) NULL;
! 556: #endif
! 557:
! 558: case RIP2PEERVERSION:
! 559: *val_len = sizeof (int);
! 560: version = peer->version;
! 561: return (u_char *) &version;
! 562:
! 563: case RIP2PEERRCVBADPACKETS:
! 564: *val_len = sizeof (int);
! 565: return (u_char *) &peer->recv_badpackets;
! 566:
! 567: case RIP2PEERRCVBADROUTES:
! 568: *val_len = sizeof (int);
! 569: return (u_char *) &peer->recv_badroutes;
! 570:
! 571: default:
! 572: return NULL;
! 573:
! 574: }
! 575: return NULL;
! 576: }
! 577:
! 578: /* Register RIPv2-MIB. */
! 579: void
! 580: rip_snmp_init ()
! 581: {
! 582: rip_ifaddr_table = route_table_init ();
! 583:
! 584: smux_init (master);
! 585: REGISTER_MIB("mibII/rip", rip_variables, variable, rip_oid);
! 586: }
! 587: #endif /* HAVE_SNMP */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>