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