2 * Copyright (C) 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
4 * This file is part of GNU Zebra.
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
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.
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
25 #include <net-snmp/net-snmp-config.h>
26 #include <net-snmp/net-snmp-includes.h>
35 #include "ripd/ripd.h"
38 #define RIPV2MIB 1,3,6,1,2,1,23
40 /* RIPv2-MIB rip2Globals values. */
41 #define RIP2GLOBALROUTECHANGES 1
42 #define RIP2GLOBALQUERIES 2
44 /* RIPv2-MIB rip2IfStatEntry. */
45 #define RIP2IFSTATENTRY 1
47 /* RIPv2-MIB rip2IfStatTable. */
48 #define RIP2IFSTATADDRESS 1
49 #define RIP2IFSTATRCVBADPACKETS 2
50 #define RIP2IFSTATRCVBADROUTES 3
51 #define RIP2IFSTATSENTUPDATES 4
52 #define RIP2IFSTATSTATUS 5
54 /* RIPv2-MIB rip2IfConfTable. */
55 #define RIP2IFCONFADDRESS 1
56 #define RIP2IFCONFDOMAIN 2
57 #define RIP2IFCONFAUTHTYPE 3
58 #define RIP2IFCONFAUTHKEY 4
59 #define RIP2IFCONFSEND 5
60 #define RIP2IFCONFRECEIVE 6
61 #define RIP2IFCONFDEFAULTMETRIC 7
62 #define RIP2IFCONFSTATUS 8
63 #define RIP2IFCONFSRCADDRESS 9
65 /* RIPv2-MIB rip2PeerTable. */
66 #define RIP2PEERADDRESS 1
67 #define RIP2PEERDOMAIN 2
68 #define RIP2PEERLASTUPDATE 3
69 #define RIP2PEERVERSION 4
70 #define RIP2PEERRCVBADPACKETS 5
71 #define RIP2PEERRCVBADROUTES 6
73 /* SNMP value hack. */
74 #define COUNTER ASN_COUNTER
75 #define INTEGER ASN_INTEGER
76 #define TIMETICKS ASN_TIMETICKS
77 #define IPADDRESS ASN_IPADDRESS
78 #define STRING ASN_OCTET_STR
80 /* Define SNMP local variables. */
83 /* RIP-MIB instances. */
84 oid rip_oid [] = { RIPV2MIB };
86 /* Interface cache table sorted by interface's address. */
87 struct route_table *rip_ifaddr_table;
90 static u_char *rip2Globals (struct variable *, oid [], size_t *,
91 int, size_t *, WriteMethod **);
92 static u_char *rip2IfStatEntry (struct variable *, oid [], size_t *,
93 int, size_t *, WriteMethod **);
94 static u_char *rip2IfConfAddress (struct variable *, oid [], size_t *,
95 int, size_t *, WriteMethod **);
96 static u_char *rip2PeerTable (struct variable *, oid [], size_t *,
97 int, size_t *, WriteMethod **);
99 struct variable rip_variables[] =
101 /* RIP Global Counters. */
102 {RIP2GLOBALROUTECHANGES, COUNTER, RONLY, rip2Globals,
104 {RIP2GLOBALQUERIES, COUNTER, RONLY, rip2Globals,
106 /* RIP Interface Tables. */
107 {RIP2IFSTATADDRESS, IPADDRESS, RONLY, rip2IfStatEntry,
109 {RIP2IFSTATRCVBADPACKETS, COUNTER, RONLY, rip2IfStatEntry,
111 {RIP2IFSTATRCVBADROUTES, COUNTER, RONLY, rip2IfStatEntry,
113 {RIP2IFSTATSENTUPDATES, COUNTER, RONLY, rip2IfStatEntry,
115 {RIP2IFSTATSTATUS, COUNTER, RWRITE, rip2IfStatEntry,
117 {RIP2IFCONFADDRESS, IPADDRESS, RONLY, rip2IfConfAddress,
118 /* RIP Interface Configuration Table. */
120 {RIP2IFCONFDOMAIN, STRING, RONLY, rip2IfConfAddress,
122 {RIP2IFCONFAUTHTYPE, COUNTER, RONLY, rip2IfConfAddress,
124 {RIP2IFCONFAUTHKEY, STRING, RONLY, rip2IfConfAddress,
126 {RIP2IFCONFSEND, COUNTER, RONLY, rip2IfConfAddress,
128 {RIP2IFCONFRECEIVE, COUNTER, RONLY, rip2IfConfAddress,
130 {RIP2IFCONFDEFAULTMETRIC, COUNTER, RONLY, rip2IfConfAddress,
132 {RIP2IFCONFSTATUS, COUNTER, RONLY, rip2IfConfAddress,
134 {RIP2IFCONFSRCADDRESS, IPADDRESS, RONLY, rip2IfConfAddress,
136 {RIP2PEERADDRESS, IPADDRESS, RONLY, rip2PeerTable,
137 /* RIP Peer Table. */
139 {RIP2PEERDOMAIN, STRING, RONLY, rip2PeerTable,
141 {RIP2PEERLASTUPDATE, TIMETICKS, RONLY, rip2PeerTable,
143 {RIP2PEERVERSION, INTEGER, RONLY, rip2PeerTable,
145 {RIP2PEERRCVBADPACKETS, COUNTER, RONLY, rip2PeerTable,
147 {RIP2PEERRCVBADROUTES, COUNTER, RONLY, rip2PeerTable,
151 extern struct thread_master *master;
154 rip2Globals (struct variable *v, oid name[], size_t *length,
155 int exact, size_t *var_len, WriteMethod **write_method)
157 if (smux_header_generic(v, name, length, exact, var_len, write_method)
161 /* Retrun global counter. */
164 case RIP2GLOBALROUTECHANGES:
165 return SNMP_INTEGER (rip_global_route_changes);
167 case RIP2GLOBALQUERIES:
168 return SNMP_INTEGER (rip_global_queries);
178 rip_ifaddr_add (struct interface *ifp, struct connected *ifc)
181 struct route_node *rn;
185 if (p->family != AF_INET)
188 rn = route_node_get (rip_ifaddr_table, p);
193 rip_ifaddr_delete (struct interface *ifp, struct connected *ifc)
196 struct route_node *rn;
201 if (p->family != AF_INET)
204 rn = route_node_lookup (rip_ifaddr_table, p);
208 if (rn && !strncmp(i->name,ifp->name,INTERFACE_NAMSIZ))
211 route_unlock_node (rn);
212 route_unlock_node (rn);
216 static struct interface *
217 rip_ifaddr_lookup_next (struct in_addr *addr)
219 struct prefix_ipv4 p;
220 struct route_node *rn;
221 struct interface *ifp;
224 p.prefixlen = IPV4_MAX_BITLEN;
227 rn = route_node_get (rip_ifaddr_table, (struct prefix *) &p);
229 for (rn = route_next (rn); rn; rn = route_next (rn))
236 *addr = rn->p.u.prefix4;
237 route_unlock_node (rn);
243 static struct interface *
244 rip2IfLookup (struct variable *v, oid name[], size_t *length,
245 struct in_addr *addr, int exact)
248 struct interface *ifp;
252 /* Check the length. */
253 if (*length - v->namelen != sizeof (struct in_addr))
256 oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr);
258 return if_lookup_exact_address (*addr);
262 len = *length - v->namelen;
263 if (len > 4) len = 4;
265 oid2in_addr (name + v->namelen, len, addr);
267 ifp = rip_ifaddr_lookup_next (addr);
272 oid_copy_addr (name + v->namelen, addr, sizeof (struct in_addr));
274 *length = v->namelen + sizeof (struct in_addr);
281 static struct rip_peer *
282 rip2PeerLookup (struct variable *v, oid name[], size_t *length,
283 struct in_addr *addr, int exact)
286 struct rip_peer *peer;
290 /* Check the length. */
291 if (*length - v->namelen != sizeof (struct in_addr) + 1)
294 oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr);
296 peer = rip_peer_lookup (addr);
298 if (peer->domain == (int)name[v->namelen + sizeof (struct in_addr)])
305 len = *length - v->namelen;
306 if (len > 4) len = 4;
308 oid2in_addr (name + v->namelen, len, addr);
310 len = *length - v->namelen;
311 peer = rip_peer_lookup (addr);
314 if ((len < (int)sizeof (struct in_addr) + 1) ||
315 (peer->domain > (int)name[v->namelen + sizeof (struct in_addr)]))
317 oid_copy_addr (name + v->namelen, &peer->addr,
318 sizeof (struct in_addr));
319 name[v->namelen + sizeof (struct in_addr)] = peer->domain;
320 *length = sizeof (struct in_addr) + v->namelen + 1;
324 peer = rip_peer_lookup_next (addr);
329 oid_copy_addr (name + v->namelen, &peer->addr,
330 sizeof (struct in_addr));
331 name[v->namelen + sizeof (struct in_addr)] = peer->domain;
332 *length = sizeof (struct in_addr) + v->namelen + 1;
340 rip2IfStatEntry (struct variable *v, oid name[], size_t *length,
341 int exact, size_t *var_len, WriteMethod **write_method)
343 struct interface *ifp;
344 struct rip_interface *ri;
345 static struct in_addr addr;
346 static long valid = SNMP_VALID;
348 if (smux_header_table(v, name, length, exact, var_len, write_method)
352 memset (&addr, 0, sizeof (struct in_addr));
354 /* Lookup interface. */
355 ifp = rip2IfLookup (v, name, length, &addr, exact);
359 /* Fetch rip_interface information. */
364 case RIP2IFSTATADDRESS:
365 return SNMP_IPADDRESS (addr);
367 case RIP2IFSTATRCVBADPACKETS:
368 *var_len = sizeof (long);
369 return (u_char *) &ri->recv_badpackets;
371 case RIP2IFSTATRCVBADROUTES:
372 *var_len = sizeof (long);
373 return (u_char *) &ri->recv_badroutes;
375 case RIP2IFSTATSENTUPDATES:
376 *var_len = sizeof (long);
377 return (u_char *) &ri->sent_updates;
379 case RIP2IFSTATSTATUS:
380 *var_len = sizeof (long);
381 v->type = ASN_INTEGER;
382 return (u_char *) &valid;
392 rip2IfConfSend (struct rip_interface *ri)
395 #define ripVersion1 2
396 #define rip1Compatible 3
397 #define ripVersion2 4
398 #define ripV1Demand 5
399 #define ripV2Demand 6
404 if (ri->ri_send & RIPv2)
406 else if (ri->ri_send & RIPv1)
410 if (rip->version_send == RIPv2)
412 else if (rip->version_send == RIPv1)
419 rip2IfConfReceive (struct rip_interface *ri)
424 #define doNotReceive 4
431 recvv = (ri->ri_receive == RI_RIP_UNSPEC) ? rip->version_recv :
433 if (recvv == RI_RIP_VERSION_1_AND_2)
435 else if (recvv & RIPv2)
437 else if (recvv & RIPv1)
444 rip2IfConfAddress (struct variable *v, oid name[], size_t *length,
445 int exact, size_t *val_len, WriteMethod **write_method)
447 static struct in_addr addr;
448 static long valid = SNMP_INVALID;
449 static long domain = 0;
450 static long config = 0;
451 static u_int auth = 0;
452 struct interface *ifp;
453 struct rip_interface *ri;
455 if (smux_header_table(v, name, length, exact, val_len, write_method)
459 memset (&addr, 0, sizeof (struct in_addr));
461 /* Lookup interface. */
462 ifp = rip2IfLookup (v, name, length, &addr, exact);
466 /* Fetch rip_interface information. */
471 case RIP2IFCONFADDRESS:
472 *val_len = sizeof (struct in_addr);
473 return (u_char *) &addr;
475 case RIP2IFCONFDOMAIN:
477 return (u_char *) &domain;
479 case RIP2IFCONFAUTHTYPE:
480 auth = ri->auth_type;
481 *val_len = sizeof (long);
482 v->type = ASN_INTEGER;
483 return (u_char *)&auth;
485 case RIP2IFCONFAUTHKEY:
487 return (u_char *) &domain;
489 config = rip2IfConfSend (ri);
490 *val_len = sizeof (long);
491 v->type = ASN_INTEGER;
492 return (u_char *) &config;
493 case RIP2IFCONFRECEIVE:
494 config = rip2IfConfReceive (ri);
495 *val_len = sizeof (long);
496 v->type = ASN_INTEGER;
497 return (u_char *) &config;
499 case RIP2IFCONFDEFAULTMETRIC:
500 *val_len = sizeof (long);
501 v->type = ASN_INTEGER;
502 return (u_char *) &ifp->metric;
503 case RIP2IFCONFSTATUS:
504 *val_len = sizeof (long);
505 v->type = ASN_INTEGER;
506 return (u_char *) &valid;
507 case RIP2IFCONFSRCADDRESS:
508 *val_len = sizeof (struct in_addr);
509 return (u_char *) &addr;
519 rip2PeerTable (struct variable *v, oid name[], size_t *length,
520 int exact, size_t *val_len, WriteMethod **write_method)
522 static struct in_addr addr;
523 static int domain = 0;
525 /* static time_t uptime; */
527 struct rip_peer *peer;
529 if (smux_header_table(v, name, length, exact, val_len, write_method)
533 memset (&addr, 0, sizeof (struct in_addr));
535 /* Lookup interface. */
536 peer = rip2PeerLookup (v, name, length, &addr, exact);
542 case RIP2PEERADDRESS:
543 *val_len = sizeof (struct in_addr);
544 return (u_char *) &peer->addr;
548 return (u_char *) &domain;
550 case RIP2PEERLASTUPDATE:
552 /* We don't know the SNMP agent startup time. We have two choices here:
553 * - assume ripd startup time equals SNMP agent startup time
554 * - don't support this variable, at all
555 * Currently, we do the latter...
557 *val_len = sizeof (time_t);
558 uptime = peer->uptime; /* now - snmp_agent_startup - peer->uptime */
559 return (u_char *) &uptime;
561 return (u_char *) NULL;
564 case RIP2PEERVERSION:
565 *val_len = sizeof (int);
566 version = peer->version;
567 return (u_char *) &version;
569 case RIP2PEERRCVBADPACKETS:
570 *val_len = sizeof (int);
571 return (u_char *) &peer->recv_badpackets;
573 case RIP2PEERRCVBADROUTES:
574 *val_len = sizeof (int);
575 return (u_char *) &peer->recv_badroutes;
584 /* Register RIPv2-MIB. */
588 rip_ifaddr_table = route_table_init ();
591 REGISTER_MIB("mibII/rip", rip_variables, variable, rip_oid);
593 #endif /* HAVE_SNMP */