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