]> git.proxmox.com Git - mirror_frr.git/blob - ripd/rip_snmp.c
Merge branch stable/2.0 into 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
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 #include <net-snmp/net-snmp-config.h>
25 #include <net-snmp/net-snmp-includes.h>
26
27 #include "if.h"
28 #include "vrf.h"
29 #include "log.h"
30 #include "prefix.h"
31 #include "command.h"
32 #include "table.h"
33 #include "smux.h"
34 #include "libfrr.h"
35 #include "version.h"
36
37 #include "ripd/ripd.h"
38
39 /* RIPv2-MIB. */
40 #define RIPV2MIB 1,3,6,1,2,1,23
41
42 /* RIPv2-MIB rip2Globals values. */
43 #define RIP2GLOBALROUTECHANGES 1
44 #define RIP2GLOBALQUERIES 2
45
46 /* RIPv2-MIB rip2IfStatEntry. */
47 #define RIP2IFSTATENTRY 1
48
49 /* RIPv2-MIB rip2IfStatTable. */
50 #define RIP2IFSTATADDRESS 1
51 #define RIP2IFSTATRCVBADPACKETS 2
52 #define RIP2IFSTATRCVBADROUTES 3
53 #define RIP2IFSTATSENTUPDATES 4
54 #define RIP2IFSTATSTATUS 5
55
56 /* RIPv2-MIB rip2IfConfTable. */
57 #define RIP2IFCONFADDRESS 1
58 #define RIP2IFCONFDOMAIN 2
59 #define RIP2IFCONFAUTHTYPE 3
60 #define RIP2IFCONFAUTHKEY 4
61 #define RIP2IFCONFSEND 5
62 #define RIP2IFCONFRECEIVE 6
63 #define RIP2IFCONFDEFAULTMETRIC 7
64 #define RIP2IFCONFSTATUS 8
65 #define RIP2IFCONFSRCADDRESS 9
66
67 /* RIPv2-MIB rip2PeerTable. */
68 #define RIP2PEERADDRESS 1
69 #define RIP2PEERDOMAIN 2
70 #define RIP2PEERLASTUPDATE 3
71 #define RIP2PEERVERSION 4
72 #define RIP2PEERRCVBADPACKETS 5
73 #define RIP2PEERRCVBADROUTES 6
74
75 /* SNMP value hack. */
76 #define COUNTER ASN_COUNTER
77 #define INTEGER ASN_INTEGER
78 #define TIMETICKS ASN_TIMETICKS
79 #define IPADDRESS ASN_IPADDRESS
80 #define STRING ASN_OCTET_STR
81
82 /* Define SNMP local variables. */
83 SNMP_LOCAL_VARIABLES
84
85 /* RIP-MIB instances. */
86 static oid rip_oid [] = { RIPV2MIB };
87
88 /* Interface cache table sorted by interface's address. */
89 static struct route_table *rip_ifaddr_table;
90
91 /* Hook functions. */
92 static u_char *rip2Globals (struct variable *, oid [], size_t *,
93 int, size_t *, WriteMethod **);
94 static u_char *rip2IfStatEntry (struct variable *, oid [], size_t *,
95 int, size_t *, WriteMethod **);
96 static u_char *rip2IfConfAddress (struct variable *, oid [], size_t *,
97 int, size_t *, WriteMethod **);
98 static u_char *rip2PeerTable (struct variable *, oid [], size_t *,
99 int, size_t *, WriteMethod **);
100
101 static struct variable rip_variables[] =
102 {
103 /* RIP Global Counters. */
104 {RIP2GLOBALROUTECHANGES, COUNTER, RONLY, rip2Globals,
105 2, {1, 1}},
106 {RIP2GLOBALQUERIES, COUNTER, RONLY, rip2Globals,
107 2, {1, 2}},
108 /* RIP Interface Tables. */
109 {RIP2IFSTATADDRESS, IPADDRESS, RONLY, rip2IfStatEntry,
110 3, {2, 1, 1}},
111 {RIP2IFSTATRCVBADPACKETS, COUNTER, RONLY, rip2IfStatEntry,
112 3, {2, 1, 2}},
113 {RIP2IFSTATRCVBADROUTES, COUNTER, RONLY, rip2IfStatEntry,
114 3, {2, 1, 3}},
115 {RIP2IFSTATSENTUPDATES, COUNTER, RONLY, rip2IfStatEntry,
116 3, {2, 1, 4}},
117 {RIP2IFSTATSTATUS, COUNTER, RWRITE, rip2IfStatEntry,
118 3, {2, 1, 5}},
119 {RIP2IFCONFADDRESS, IPADDRESS, RONLY, rip2IfConfAddress,
120 /* RIP Interface Configuration Table. */
121 3, {3, 1, 1}},
122 {RIP2IFCONFDOMAIN, STRING, RONLY, rip2IfConfAddress,
123 3, {3, 1, 2}},
124 {RIP2IFCONFAUTHTYPE, COUNTER, RONLY, rip2IfConfAddress,
125 3, {3, 1, 3}},
126 {RIP2IFCONFAUTHKEY, STRING, RONLY, rip2IfConfAddress,
127 3, {3, 1, 4}},
128 {RIP2IFCONFSEND, COUNTER, RONLY, rip2IfConfAddress,
129 3, {3, 1, 5}},
130 {RIP2IFCONFRECEIVE, COUNTER, RONLY, rip2IfConfAddress,
131 3, {3, 1, 6}},
132 {RIP2IFCONFDEFAULTMETRIC, COUNTER, RONLY, rip2IfConfAddress,
133 3, {3, 1, 7}},
134 {RIP2IFCONFSTATUS, COUNTER, RONLY, rip2IfConfAddress,
135 3, {3, 1, 8}},
136 {RIP2IFCONFSRCADDRESS, IPADDRESS, RONLY, rip2IfConfAddress,
137 3, {3, 1, 9}},
138 {RIP2PEERADDRESS, IPADDRESS, RONLY, rip2PeerTable,
139 /* RIP Peer Table. */
140 3, {4, 1, 1}},
141 {RIP2PEERDOMAIN, STRING, RONLY, rip2PeerTable,
142 3, {4, 1, 2}},
143 {RIP2PEERLASTUPDATE, TIMETICKS, RONLY, rip2PeerTable,
144 3, {4, 1, 3}},
145 {RIP2PEERVERSION, INTEGER, RONLY, rip2PeerTable,
146 3, {4, 1, 4}},
147 {RIP2PEERRCVBADPACKETS, COUNTER, RONLY, rip2PeerTable,
148 3, {4, 1, 5}},
149 {RIP2PEERRCVBADROUTES, COUNTER, RONLY, rip2PeerTable,
150 3, {4, 1, 6}}
151 };
152
153 extern struct thread_master *master;
154
155 static u_char *
156 rip2Globals (struct variable *v, oid name[], size_t *length,
157 int exact, size_t *var_len, WriteMethod **write_method)
158 {
159 if (smux_header_generic(v, name, length, exact, var_len, write_method)
160 == MATCH_FAILED)
161 return NULL;
162
163 /* Retrun global counter. */
164 switch (v->magic)
165 {
166 case RIP2GLOBALROUTECHANGES:
167 return SNMP_INTEGER (rip_global_route_changes);
168 break;
169 case RIP2GLOBALQUERIES:
170 return SNMP_INTEGER (rip_global_queries);
171 break;
172 default:
173 return NULL;
174 break;
175 }
176 return NULL;
177 }
178
179 static int
180 rip_snmp_ifaddr_add (struct connected *ifc)
181 {
182 struct interface *ifp = ifc->ifp;
183 struct prefix *p;
184 struct route_node *rn;
185
186 p = ifc->address;
187
188 if (p->family != AF_INET)
189 return 0;
190
191 rn = route_node_get (rip_ifaddr_table, p);
192 rn->info = ifp;
193 return 0;
194 }
195
196 static int
197 rip_snmp_ifaddr_del (struct connected *ifc)
198 {
199 struct interface *ifp = ifc->ifp;
200 struct prefix *p;
201 struct route_node *rn;
202 struct interface *i;
203
204 p = ifc->address;
205
206 if (p->family != AF_INET)
207 return 0;
208
209 rn = route_node_lookup (rip_ifaddr_table, p);
210 if (! rn)
211 return 0;
212 i = rn->info;
213 if (rn && !strncmp(i->name,ifp->name,INTERFACE_NAMSIZ))
214 {
215 rn->info = NULL;
216 route_unlock_node (rn);
217 route_unlock_node (rn);
218 }
219 return 0;
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 ((void *)addr, AF_INET, VRF_DEFAULT);
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 == (int)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 < (int)sizeof (struct in_addr) + 1) ||
321 (peer->domain > (int)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 if (smux_header_table(v, name, length, exact, var_len, write_method)
355 == MATCH_FAILED)
356 return NULL;
357
358 memset (&addr, 0, sizeof (struct in_addr));
359
360 /* Lookup interface. */
361 ifp = rip2IfLookup (v, name, length, &addr, exact);
362 if (! ifp)
363 return NULL;
364
365 /* Fetch rip_interface information. */
366 ri = ifp->info;
367
368 switch (v->magic)
369 {
370 case RIP2IFSTATADDRESS:
371 return SNMP_IPADDRESS (addr);
372 break;
373 case RIP2IFSTATRCVBADPACKETS:
374 *var_len = sizeof (long);
375 return (u_char *) &ri->recv_badpackets;
376
377 case RIP2IFSTATRCVBADROUTES:
378 *var_len = sizeof (long);
379 return (u_char *) &ri->recv_badroutes;
380
381 case RIP2IFSTATSENTUPDATES:
382 *var_len = sizeof (long);
383 return (u_char *) &ri->sent_updates;
384
385 case RIP2IFSTATSTATUS:
386 *var_len = sizeof (long);
387 v->type = ASN_INTEGER;
388 return (u_char *) &valid;
389
390 default:
391 return NULL;
392
393 }
394 return NULL;
395 }
396
397 static long
398 rip2IfConfSend (struct rip_interface *ri)
399 {
400 #define doNotSend 1
401 #define ripVersion1 2
402 #define rip1Compatible 3
403 #define ripVersion2 4
404 #define ripV1Demand 5
405 #define ripV2Demand 6
406
407 if (! ri->running)
408 return doNotSend;
409
410 if (ri->ri_send & RIPv2)
411 return ripVersion2;
412 else if (ri->ri_send & RIPv1)
413 return ripVersion1;
414 else if (rip)
415 {
416 if (rip->version_send == RIPv2)
417 return ripVersion2;
418 else if (rip->version_send == RIPv1)
419 return ripVersion1;
420 }
421 return doNotSend;
422 }
423
424 static long
425 rip2IfConfReceive (struct rip_interface *ri)
426 {
427 #define rip1 1
428 #define rip2 2
429 #define rip1OrRip2 3
430 #define doNotReceive 4
431
432 int recvv;
433
434 if (! ri->running)
435 return doNotReceive;
436
437 recvv = (ri->ri_receive == RI_RIP_UNSPEC) ? rip->version_recv :
438 ri->ri_receive;
439 if (recvv == RI_RIP_VERSION_1_AND_2)
440 return rip1OrRip2;
441 else if (recvv & RIPv2)
442 return rip2;
443 else if (recvv & RIPv1)
444 return rip1;
445 else
446 return doNotReceive;
447 }
448
449 static u_char *
450 rip2IfConfAddress (struct variable *v, oid name[], size_t *length,
451 int exact, size_t *val_len, WriteMethod **write_method)
452 {
453 static struct in_addr addr;
454 static long valid = SNMP_INVALID;
455 static long domain = 0;
456 static long config = 0;
457 static u_int auth = 0;
458 struct interface *ifp;
459 struct rip_interface *ri;
460
461 if (smux_header_table(v, name, length, exact, val_len, write_method)
462 == MATCH_FAILED)
463 return NULL;
464
465 memset (&addr, 0, sizeof (struct in_addr));
466
467 /* Lookup interface. */
468 ifp = rip2IfLookup (v, name, length, &addr, exact);
469 if (! ifp)
470 return NULL;
471
472 /* Fetch rip_interface information. */
473 ri = ifp->info;
474
475 switch (v->magic)
476 {
477 case RIP2IFCONFADDRESS:
478 *val_len = sizeof (struct in_addr);
479 return (u_char *) &addr;
480
481 case RIP2IFCONFDOMAIN:
482 *val_len = 2;
483 return (u_char *) &domain;
484
485 case RIP2IFCONFAUTHTYPE:
486 auth = ri->auth_type;
487 *val_len = sizeof (long);
488 v->type = ASN_INTEGER;
489 return (u_char *)&auth;
490
491 case RIP2IFCONFAUTHKEY:
492 *val_len = 0;
493 return (u_char *) &domain;
494 case RIP2IFCONFSEND:
495 config = rip2IfConfSend (ri);
496 *val_len = sizeof (long);
497 v->type = ASN_INTEGER;
498 return (u_char *) &config;
499 case RIP2IFCONFRECEIVE:
500 config = rip2IfConfReceive (ri);
501 *val_len = sizeof (long);
502 v->type = ASN_INTEGER;
503 return (u_char *) &config;
504
505 case RIP2IFCONFDEFAULTMETRIC:
506 *val_len = sizeof (long);
507 v->type = ASN_INTEGER;
508 return (u_char *) &ifp->metric;
509 case RIP2IFCONFSTATUS:
510 *val_len = sizeof (long);
511 v->type = ASN_INTEGER;
512 return (u_char *) &valid;
513 case RIP2IFCONFSRCADDRESS:
514 *val_len = sizeof (struct in_addr);
515 return (u_char *) &addr;
516
517 default:
518 return NULL;
519
520 }
521 return NULL;
522 }
523
524 static u_char *
525 rip2PeerTable (struct variable *v, oid name[], size_t *length,
526 int exact, size_t *val_len, WriteMethod **write_method)
527 {
528 static struct in_addr addr;
529 static int domain = 0;
530 static int version;
531 /* static time_t uptime; */
532
533 struct rip_peer *peer;
534
535 if (smux_header_table(v, name, length, exact, val_len, write_method)
536 == MATCH_FAILED)
537 return NULL;
538
539 memset (&addr, 0, sizeof (struct in_addr));
540
541 /* Lookup interface. */
542 peer = rip2PeerLookup (v, name, length, &addr, exact);
543 if (! peer)
544 return NULL;
545
546 switch (v->magic)
547 {
548 case RIP2PEERADDRESS:
549 *val_len = sizeof (struct in_addr);
550 return (u_char *) &peer->addr;
551
552 case RIP2PEERDOMAIN:
553 *val_len = 2;
554 return (u_char *) &domain;
555
556 case RIP2PEERLASTUPDATE:
557 #if 0
558 /* We don't know the SNMP agent startup time. We have two choices here:
559 * - assume ripd startup time equals SNMP agent startup time
560 * - don't support this variable, at all
561 * Currently, we do the latter...
562 */
563 *val_len = sizeof (time_t);
564 uptime = peer->uptime; /* now - snmp_agent_startup - peer->uptime */
565 return (u_char *) &uptime;
566 #else
567 return (u_char *) NULL;
568 #endif
569
570 case RIP2PEERVERSION:
571 *val_len = sizeof (int);
572 version = peer->version;
573 return (u_char *) &version;
574
575 case RIP2PEERRCVBADPACKETS:
576 *val_len = sizeof (int);
577 return (u_char *) &peer->recv_badpackets;
578
579 case RIP2PEERRCVBADROUTES:
580 *val_len = sizeof (int);
581 return (u_char *) &peer->recv_badroutes;
582
583 default:
584 return NULL;
585
586 }
587 return NULL;
588 }
589
590 /* Register RIPv2-MIB. */
591 static int
592 rip_snmp_init (struct thread_master *master)
593 {
594 rip_ifaddr_table = route_table_init ();
595
596 smux_init (master);
597 REGISTER_MIB("mibII/rip", rip_variables, variable, rip_oid);
598 return 0;
599 }
600
601 static int
602 rip_snmp_module_init (void)
603 {
604 hook_register(rip_ifaddr_add, rip_snmp_ifaddr_add);
605 hook_register(rip_ifaddr_del, rip_snmp_ifaddr_del);
606
607 hook_register(frr_late_init, rip_snmp_init);
608 return 0;
609 }
610
611 FRR_MODULE_SETUP(
612 .name = "ripd_snmp",
613 .version = FRR_VERSION,
614 .description = "ripd AgentX SNMP module",
615 .init = rip_snmp_module_init,
616 )