[cleanup] Make command nodes static
[jleu-quagga.git] / ripd / rip_snmp.c
blob61c47c71d9471f90a42358406d9afe0ac1c5a135
1 /* RIP SNMP support
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
9 * later version.
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
19 * 02111-1307, USA.
22 #include <zebra.h>
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
34 #include "if.h"
35 #include "log.h"
36 #include "prefix.h"
37 #include "command.h"
38 #include "table.h"
39 #include "smux.h"
41 #include "ripd/ripd.h"
43 /* RIPv2-MIB. */
44 #define RIPV2MIB 1,3,6,1,2,1,23
46 /* RIPv2-MIB rip2Globals values. */
47 #define RIP2GLOBALROUTECHANGES 1
48 #define RIP2GLOBALQUERIES 2
50 /* RIPv2-MIB rip2IfStatEntry. */
51 #define RIP2IFSTATENTRY 1
53 /* RIPv2-MIB rip2IfStatTable. */
54 #define RIP2IFSTATADDRESS 1
55 #define RIP2IFSTATRCVBADPACKETS 2
56 #define RIP2IFSTATRCVBADROUTES 3
57 #define RIP2IFSTATSENTUPDATES 4
58 #define RIP2IFSTATSTATUS 5
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
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
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
86 /* Define SNMP local variables. */
87 SNMP_LOCAL_VARIABLES
89 /* RIP-MIB instances. */
90 oid rip_oid [] = { RIPV2MIB };
92 /* Interface cache table sorted by interface's address. */
93 struct route_table *rip_ifaddr_table;
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 **);
105 struct variable rip_variables[] =
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}}
157 extern struct thread_master *master;
159 static u_char *
160 rip2Globals (struct variable *v, oid name[], size_t *length,
161 int exact, size_t *var_len, WriteMethod **write_method)
163 if (smux_header_generic(v, name, length, exact, var_len, write_method)
164 == MATCH_FAILED)
165 return NULL;
167 /* Retrun global counter. */
168 switch (v->magic)
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;
180 return NULL;
183 void
184 rip_ifaddr_add (struct interface *ifp, struct connected *ifc)
186 struct prefix *p;
187 struct route_node *rn;
189 p = ifc->address;
191 if (p->family != AF_INET)
192 return;
194 rn = route_node_get (rip_ifaddr_table, p);
195 rn->info = ifp;
198 void
199 rip_ifaddr_delete (struct interface *ifp, struct connected *ifc)
201 struct prefix *p;
202 struct route_node *rn;
203 struct interface *i;
205 p = ifc->address;
207 if (p->family != AF_INET)
208 return;
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))
216 rn->info = NULL;
217 route_unlock_node (rn);
218 route_unlock_node (rn);
222 static struct interface *
223 rip_ifaddr_lookup_next (struct in_addr *addr)
225 struct prefix_ipv4 p;
226 struct route_node *rn;
227 struct interface *ifp;
229 p.family = AF_INET;
230 p.prefixlen = IPV4_MAX_BITLEN;
231 p.prefix = *addr;
233 rn = route_node_get (rip_ifaddr_table, (struct prefix *) &p);
235 for (rn = route_next (rn); rn; rn = route_next (rn))
236 if (rn->info)
237 break;
239 if (rn && rn->info)
241 ifp = rn->info;
242 *addr = rn->p.u.prefix4;
243 route_unlock_node (rn);
244 return ifp;
246 return NULL;
249 static struct interface *
250 rip2IfLookup (struct variable *v, oid name[], size_t *length,
251 struct in_addr *addr, int exact)
253 int len;
254 struct interface *ifp;
256 if (exact)
258 /* Check the length. */
259 if (*length - v->namelen != sizeof (struct in_addr))
260 return NULL;
262 oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr);
264 return if_lookup_exact_address (*addr);
266 else
268 len = *length - v->namelen;
269 if (len > 4) len = 4;
271 oid2in_addr (name + v->namelen, len, addr);
273 ifp = rip_ifaddr_lookup_next (addr);
275 if (ifp == NULL)
276 return NULL;
278 oid_copy_addr (name + v->namelen, addr, sizeof (struct in_addr));
280 *length = v->namelen + sizeof (struct in_addr);
282 return ifp;
284 return NULL;
287 static struct rip_peer *
288 rip2PeerLookup (struct variable *v, oid name[], size_t *length,
289 struct in_addr *addr, int exact)
291 int len;
292 struct rip_peer *peer;
294 if (exact)
296 /* Check the length. */
297 if (*length - v->namelen != sizeof (struct in_addr) + 1)
298 return NULL;
300 oid2in_addr (name + v->namelen, sizeof (struct in_addr), addr);
302 peer = rip_peer_lookup (addr);
304 if (peer->domain == name[v->namelen + sizeof (struct in_addr)])
305 return peer;
307 return NULL;
309 else
311 len = *length - v->namelen;
312 if (len > 4) len = 4;
314 oid2in_addr (name + v->namelen, len, addr);
316 len = *length - v->namelen;
317 peer = rip_peer_lookup (addr);
318 if (peer)
320 if ((len < sizeof (struct in_addr) + 1) ||
321 (peer->domain > name[v->namelen + sizeof (struct in_addr)]))
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;
330 peer = rip_peer_lookup_next (addr);
332 if (! peer)
333 return NULL;
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;
340 return peer;
342 return NULL;
345 static u_char *
346 rip2IfStatEntry (struct variable *v, oid name[], size_t *length,
347 int exact, size_t *var_len, WriteMethod **write_method)
349 struct interface *ifp;
350 struct rip_interface *ri;
351 static struct in_addr addr;
352 static long valid = SNMP_VALID;
354 memset (&addr, 0, sizeof (struct in_addr));
356 /* Lookup interface. */
357 ifp = rip2IfLookup (v, name, length, &addr, exact);
358 if (! ifp)
359 return NULL;
361 /* Fetch rip_interface information. */
362 ri = ifp->info;
364 switch (v->magic)
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;
373 case RIP2IFSTATRCVBADROUTES:
374 *var_len = sizeof (long);
375 return (u_char *) &ri->recv_badroutes;
377 case RIP2IFSTATSENTUPDATES:
378 *var_len = sizeof (long);
379 return (u_char *) &ri->sent_updates;
381 case RIP2IFSTATSTATUS:
382 *var_len = sizeof (long);
383 v->type = ASN_INTEGER;
384 return (u_char *) &valid;
386 default:
387 return NULL;
390 return NULL;
393 static long
394 rip2IfConfSend (struct rip_interface *ri)
396 #define doNotSend 1
397 #define ripVersion1 2
398 #define rip1Compatible 3
399 #define ripVersion2 4
400 #define ripV1Demand 5
401 #define ripV2Demand 6
403 if (! ri->running)
404 return doNotSend;
406 if (ri->ri_send & RIPv2)
407 return ripVersion2;
408 else if (ri->ri_send & RIPv1)
409 return ripVersion1;
410 else if (rip)
412 if (rip->version_send == RIPv2)
413 return ripVersion2;
414 else if (rip->version_send == RIPv1)
415 return ripVersion1;
417 return doNotSend;
420 static long
421 rip2IfConfReceive (struct rip_interface *ri)
423 #define rip1 1
424 #define rip2 2
425 #define rip1OrRip2 3
426 #define doNotReceive 4
428 int recvv;
430 if (! ri->running)
431 return doNotReceive;
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;
445 static u_char *
446 rip2IfConfAddress (struct variable *v, oid name[], size_t *length,
447 int exact, size_t *val_len, WriteMethod **write_method)
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;
457 memset (&addr, 0, sizeof (struct in_addr));
459 /* Lookup interface. */
460 ifp = rip2IfLookup (v, name, length, &addr, exact);
461 if (! ifp)
462 return NULL;
464 /* Fetch rip_interface information. */
465 ri = ifp->info;
467 switch (v->magic)
469 case RIP2IFCONFADDRESS:
470 *val_len = sizeof (struct in_addr);
471 return (u_char *) &addr;
473 case RIP2IFCONFDOMAIN:
474 *val_len = 2;
475 return (u_char *) &domain;
477 case RIP2IFCONFAUTHTYPE:
478 auth = ri->auth_type;
479 *val_len = sizeof (long);
480 v->type = ASN_INTEGER;
481 return (u_char *)&auth;
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;
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;
509 default:
510 return NULL;
513 return NULL;
516 static u_char *
517 rip2PeerTable (struct variable *v, oid name[], size_t *length,
518 int exact, size_t *val_len, WriteMethod **write_method)
520 static struct in_addr addr;
521 static int domain = 0;
522 static int version;
523 /* static time_t uptime; */
525 struct rip_peer *peer;
527 memset (&addr, 0, sizeof (struct in_addr));
529 /* Lookup interface. */
530 peer = rip2PeerLookup (v, name, length, &addr, exact);
531 if (! peer)
532 return NULL;
534 switch (v->magic)
536 case RIP2PEERADDRESS:
537 *val_len = sizeof (struct in_addr);
538 return (u_char *) &peer->addr;
540 case RIP2PEERDOMAIN:
541 *val_len = 2;
542 return (u_char *) &domain;
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...
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
558 case RIP2PEERVERSION:
559 *val_len = sizeof (int);
560 version = peer->version;
561 return (u_char *) &version;
563 case RIP2PEERRCVBADPACKETS:
564 *val_len = sizeof (int);
565 return (u_char *) &peer->recv_badpackets;
567 case RIP2PEERRCVBADROUTES:
568 *val_len = sizeof (int);
569 return (u_char *) &peer->recv_badroutes;
571 default:
572 return NULL;
575 return NULL;
578 /* Register RIPv2-MIB. */
579 void
580 rip_snmp_init ()
582 rip_ifaddr_table = route_table_init ();
584 smux_init (master);
585 REGISTER_MIB("mibII/rip", rip_variables, variable, rip_oid);
587 #endif /* HAVE_SNMP */