]> git.proxmox.com Git - mirror_frr.git/blame - ripd/rip_snmp.c
Merge pull request #10071 from donaldsharp/valgrind_supp_change
[mirror_frr.git] / ripd / rip_snmp.c
CommitLineData
718e3744 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 *
896014f4
DL
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
718e3744 19 */
20
21#include <zebra.h>
22
07661cb5 23#include <net-snmp/net-snmp-config.h>
fb62a3ce 24#include <net-snmp/net-snmp-includes.h>
718e3744 25
26#include "if.h"
d6b1bfba 27#include "vrf.h"
718e3744 28#include "log.h"
29#include "prefix.h"
30#include "command.h"
31#include "table.h"
32#include "smux.h"
5986b66b 33#include "libfrr.h"
09781197 34#include "lib/version.h"
718e3744 35
36#include "ripd/ripd.h"
6b0655a2 37
718e3744 38/* RIPv2-MIB. */
39#define RIPV2MIB 1,3,6,1,2,1,23
40
718e3744 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
6b0655a2 80
718e3744 81/* Define SNMP local variables. */
82SNMP_LOCAL_VARIABLES
83
84/* RIP-MIB instances. */
d62a17ae 85static oid rip_oid[] = {RIPV2MIB};
718e3744 86
87/* Interface cache table sorted by interface's address. */
1c6f50bf 88static struct route_table *rip_ifaddr_table;
718e3744 89
90/* Hook functions. */
d7c0a89a
QY
91static uint8_t *rip2Globals(struct variable *, oid[], size_t *, int, size_t *,
92 WriteMethod **);
93static uint8_t *rip2IfStatEntry(struct variable *, oid[], size_t *, int,
94 size_t *, WriteMethod **);
95static uint8_t *rip2IfConfAddress(struct variable *, oid[], size_t *, int,
96 size_t *, WriteMethod **);
97static uint8_t *rip2PeerTable(struct variable *, oid[], size_t *, int, size_t *,
98 WriteMethod **);
d62a17ae 99
100static struct variable rip_variables[] = {
101 /* RIP Global Counters. */
102 {RIP2GLOBALROUTECHANGES, COUNTER, RONLY, rip2Globals, 2, {1, 1}},
103 {RIP2GLOBALQUERIES, COUNTER, RONLY, rip2Globals, 2, {1, 2}},
104 /* RIP Interface Tables. */
105 {RIP2IFSTATADDRESS, IPADDRESS, RONLY, rip2IfStatEntry, 3, {2, 1, 1}},
106 {RIP2IFSTATRCVBADPACKETS,
107 COUNTER,
108 RONLY,
109 rip2IfStatEntry,
110 3,
111 {2, 1, 2}},
112 {RIP2IFSTATRCVBADROUTES, COUNTER, RONLY, rip2IfStatEntry, 3, {2, 1, 3}},
113 {RIP2IFSTATSENTUPDATES, COUNTER, RONLY, rip2IfStatEntry, 3, {2, 1, 4}},
114 {RIP2IFSTATSTATUS, COUNTER, RWRITE, rip2IfStatEntry, 3, {2, 1, 5}},
115 {RIP2IFCONFADDRESS,
116 IPADDRESS,
117 RONLY,
118 rip2IfConfAddress,
119 /* RIP Interface Configuration Table. */
120 3,
121 {3, 1, 1}},
122 {RIP2IFCONFDOMAIN, STRING, RONLY, rip2IfConfAddress, 3, {3, 1, 2}},
123 {RIP2IFCONFAUTHTYPE, COUNTER, RONLY, rip2IfConfAddress, 3, {3, 1, 3}},
124 {RIP2IFCONFAUTHKEY, STRING, RONLY, rip2IfConfAddress, 3, {3, 1, 4}},
125 {RIP2IFCONFSEND, COUNTER, RONLY, rip2IfConfAddress, 3, {3, 1, 5}},
126 {RIP2IFCONFRECEIVE, COUNTER, RONLY, rip2IfConfAddress, 3, {3, 1, 6}},
127 {RIP2IFCONFDEFAULTMETRIC,
128 COUNTER,
129 RONLY,
130 rip2IfConfAddress,
131 3,
132 {3, 1, 7}},
133 {RIP2IFCONFSTATUS, COUNTER, RONLY, rip2IfConfAddress, 3, {3, 1, 8}},
134 {RIP2IFCONFSRCADDRESS,
135 IPADDRESS,
136 RONLY,
137 rip2IfConfAddress,
138 3,
139 {3, 1, 9}},
140 {RIP2PEERADDRESS,
141 IPADDRESS,
142 RONLY,
143 rip2PeerTable,
144 /* RIP Peer Table. */
145 3,
146 {4, 1, 1}},
147 {RIP2PEERDOMAIN, STRING, RONLY, rip2PeerTable, 3, {4, 1, 2}},
148 {RIP2PEERLASTUPDATE, TIMETICKS, RONLY, rip2PeerTable, 3, {4, 1, 3}},
149 {RIP2PEERVERSION, INTEGER, RONLY, rip2PeerTable, 3, {4, 1, 4}},
150 {RIP2PEERRCVBADPACKETS, COUNTER, RONLY, rip2PeerTable, 3, {4, 1, 5}},
151 {RIP2PEERRCVBADROUTES, COUNTER, RONLY, rip2PeerTable, 3, {4, 1, 6}}};
dd488a78 152
153extern struct thread_master *master;
6b0655a2 154
d7c0a89a
QY
155static uint8_t *rip2Globals(struct variable *v, oid name[], size_t *length,
156 int exact, size_t *var_len,
157 WriteMethod **write_method)
718e3744 158{
045c5389
RW
159 struct rip *rip;
160
d62a17ae 161 if (smux_header_generic(v, name, length, exact, var_len, write_method)
162 == MATCH_FAILED)
163 return NULL;
164
045c5389 165 rip = rip_lookup_by_vrf_id(VRF_DEFAULT);
c08a2107
RW
166 if (!rip)
167 return NULL;
168
639caccf 169 /* Return global counter. */
d62a17ae 170 switch (v->magic) {
171 case RIP2GLOBALROUTECHANGES:
c08a2107 172 return SNMP_INTEGER(rip->counters.route_changes);
d62a17ae 173 case RIP2GLOBALQUERIES:
c08a2107 174 return SNMP_INTEGER(rip->counters.queries);
d62a17ae 175 default:
176 return NULL;
d62a17ae 177 }
178 return NULL;
718e3744 179}
180
d62a17ae 181static int rip_snmp_ifaddr_add(struct connected *ifc)
718e3744 182{
d62a17ae 183 struct interface *ifp = ifc->ifp;
184 struct prefix *p;
185 struct route_node *rn;
718e3744 186
d62a17ae 187 p = ifc->address;
718e3744 188
d62a17ae 189 if (p->family != AF_INET)
190 return 0;
718e3744 191
d62a17ae 192 rn = route_node_get(rip_ifaddr_table, p);
193 rn->info = ifp;
194 return 0;
718e3744 195}
196
d62a17ae 197static int rip_snmp_ifaddr_del(struct connected *ifc)
718e3744 198{
d62a17ae 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;
47e5a60f 213 if (!strncmp(i->name, ifp->name, INTERFACE_NAMSIZ)) {
d62a17ae 214 rn->info = NULL;
215 route_unlock_node(rn);
216 route_unlock_node(rn);
217 }
218 return 0;
718e3744 219}
220
d62a17ae 221static struct interface *rip_ifaddr_lookup_next(struct in_addr *addr)
718e3744 222{
d62a17ae 223 struct prefix_ipv4 p;
224 struct route_node *rn;
225 struct interface *ifp;
226
227 p.family = AF_INET;
228 p.prefixlen = IPV4_MAX_BITLEN;
229 p.prefix = *addr;
230
231 rn = route_node_get(rip_ifaddr_table, (struct prefix *)&p);
232
233 for (rn = route_next(rn); rn; rn = route_next(rn))
234 if (rn->info)
235 break;
236
237 if (rn && rn->info) {
238 ifp = rn->info;
239 *addr = rn->p.u.prefix4;
240 route_unlock_node(rn);
241 return ifp;
242 }
243 return NULL;
718e3744 244}
245
d62a17ae 246static struct interface *rip2IfLookup(struct variable *v, oid name[],
247 size_t *length, struct in_addr *addr,
248 int exact)
718e3744 249{
d62a17ae 250 int len;
251 struct interface *ifp;
718e3744 252
d62a17ae 253 if (exact) {
254 /* Check the length. */
255 if (*length - v->namelen != sizeof(struct in_addr))
256 return NULL;
718e3744 257
d62a17ae 258 oid2in_addr(name + v->namelen, sizeof(struct in_addr), addr);
718e3744 259
d62a17ae 260 return if_lookup_exact_address((void *)addr, AF_INET,
261 VRF_DEFAULT);
262 } else {
263 len = *length - v->namelen;
264 if (len > 4)
265 len = 4;
718e3744 266
d62a17ae 267 oid2in_addr(name + v->namelen, len, addr);
718e3744 268
d62a17ae 269 ifp = rip_ifaddr_lookup_next(addr);
718e3744 270
d62a17ae 271 if (ifp == NULL)
272 return NULL;
718e3744 273
9e263221 274 oid_copy_in_addr(name + v->namelen, addr);
718e3744 275
d62a17ae 276 *length = v->namelen + sizeof(struct in_addr);
718e3744 277
d62a17ae 278 return ifp;
279 }
718e3744 280 return NULL;
d62a17ae 281}
718e3744 282
d62a17ae 283static struct rip_peer *rip2PeerLookup(struct variable *v, oid name[],
284 size_t *length, struct in_addr *addr,
285 int exact)
286{
045c5389 287 struct rip *rip;
d62a17ae 288 int len;
289 struct rip_peer *peer;
290
045c5389 291 rip = rip_lookup_by_vrf_id(VRF_DEFAULT);
29e897ad
RW
292 if (!rip)
293 return NULL;
294
d62a17ae 295 if (exact) {
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
045c5389 302 peer = rip_peer_lookup(rip, addr);
d62a17ae 303
304 if (peer->domain
305 == (int)name[v->namelen + sizeof(struct in_addr)])
306 return peer;
307
308 return NULL;
309 } else {
310 len = *length - v->namelen;
311 if (len > 4)
312 len = 4;
313
314 oid2in_addr(name + v->namelen, len, addr);
315
316 len = *length - v->namelen;
045c5389 317 peer = rip_peer_lookup(rip, addr);
d62a17ae 318 if (peer) {
319 if ((len < (int)sizeof(struct in_addr) + 1)
320 || (peer->domain
321 > (int)name[v->namelen
322 + sizeof(struct in_addr)])) {
9e263221
PR
323 oid_copy_in_addr(name + v->namelen,
324 &peer->addr);
d62a17ae 325 name[v->namelen + sizeof(struct in_addr)] =
326 peer->domain;
327 *length =
328 sizeof(struct in_addr) + v->namelen + 1;
329 return peer;
330 }
331 }
045c5389 332 peer = rip_peer_lookup_next(rip, addr);
d62a17ae 333
334 if (!peer)
335 return NULL;
336
9e263221 337 oid_copy_in_addr(name + v->namelen, &peer->addr);
d62a17ae 338 name[v->namelen + sizeof(struct in_addr)] = peer->domain;
339 *length = sizeof(struct in_addr) + v->namelen + 1;
340
341 return peer;
342 }
718e3744 343 return NULL;
718e3744 344}
345
d7c0a89a
QY
346static uint8_t *rip2IfStatEntry(struct variable *v, oid name[], size_t *length,
347 int exact, size_t *var_len,
348 WriteMethod **write_method)
718e3744 349{
d62a17ae 350 struct interface *ifp;
351 struct rip_interface *ri;
352 static struct in_addr addr;
353 static long valid = SNMP_VALID;
354
355 if (smux_header_table(v, name, length, exact, var_len, write_method)
356 == MATCH_FAILED)
357 return NULL;
358
359 memset(&addr, 0, sizeof(struct in_addr));
360
361 /* Lookup interface. */
362 ifp = rip2IfLookup(v, name, length, &addr, exact);
363 if (!ifp)
364 return NULL;
365
366 /* Fetch rip_interface information. */
367 ri = ifp->info;
368
369 switch (v->magic) {
370 case RIP2IFSTATADDRESS:
371 return SNMP_IPADDRESS(addr);
d62a17ae 372 case RIP2IFSTATRCVBADPACKETS:
373 *var_len = sizeof(long);
d7c0a89a 374 return (uint8_t *)&ri->recv_badpackets;
d62a17ae 375
376 case RIP2IFSTATRCVBADROUTES:
377 *var_len = sizeof(long);
d7c0a89a 378 return (uint8_t *)&ri->recv_badroutes;
d62a17ae 379
380 case RIP2IFSTATSENTUPDATES:
381 *var_len = sizeof(long);
d7c0a89a 382 return (uint8_t *)&ri->sent_updates;
d62a17ae 383
384 case RIP2IFSTATSTATUS:
385 *var_len = sizeof(long);
386 v->type = ASN_INTEGER;
d7c0a89a 387 return (uint8_t *)&valid;
d62a17ae 388
389 default:
390 return NULL;
391 }
392 return NULL;
718e3744 393}
394
d62a17ae 395static long rip2IfConfSend(struct rip_interface *ri)
718e3744 396{
397#define doNotSend 1
398#define ripVersion1 2
399#define rip1Compatible 3
400#define ripVersion2 4
401#define ripV1Demand 5
402#define ripV2Demand 6
403
d62a17ae 404 if (!ri->running)
405 return doNotSend;
406
407 if (ri->ri_send & RIPv2)
408 return ripVersion2;
409 else if (ri->ri_send & RIPv1)
410 return ripVersion1;
045c5389
RW
411 else if (ri->rip) {
412 if (ri->rip->version_send == RIPv2)
d62a17ae 413 return ripVersion2;
045c5389 414 else if (ri->rip->version_send == RIPv1)
d62a17ae 415 return ripVersion1;
416 }
417 return doNotSend;
718e3744 418}
419
d62a17ae 420static long rip2IfConfReceive(struct rip_interface *ri)
718e3744 421{
422#define rip1 1
423#define rip2 2
424#define rip1OrRip2 3
425#define doNotReceive 4
426
d62a17ae 427 int recvv;
428
429 if (!ri->running)
430 return doNotReceive;
431
045c5389 432 recvv = (ri->ri_receive == RI_RIP_UNSPEC) ? ri->rip->version_recv
d62a17ae 433 : ri->ri_receive;
434 if (recvv == RI_RIP_VERSION_1_AND_2)
435 return rip1OrRip2;
436 else if (recvv & RIPv2)
437 return rip2;
438 else if (recvv & RIPv1)
439 return rip1;
440 else
441 return doNotReceive;
718e3744 442}
443
d7c0a89a
QY
444static uint8_t *rip2IfConfAddress(struct variable *v, oid name[],
445 size_t *length, int exact, size_t *val_len,
446 WriteMethod **write_method)
718e3744 447{
d62a17ae 448 static struct in_addr addr;
449 static long valid = SNMP_INVALID;
450 static long domain = 0;
451 static long config = 0;
d7c0a89a 452 static unsigned int auth = 0;
d62a17ae 453 struct interface *ifp;
454 struct rip_interface *ri;
455
456 if (smux_header_table(v, name, length, exact, val_len, write_method)
457 == MATCH_FAILED)
458 return NULL;
459
460 memset(&addr, 0, sizeof(struct in_addr));
461
462 /* Lookup interface. */
463 ifp = rip2IfLookup(v, name, length, &addr, exact);
464 if (!ifp)
465 return NULL;
466
467 /* Fetch rip_interface information. */
468 ri = ifp->info;
469
470 switch (v->magic) {
471 case RIP2IFCONFADDRESS:
472 *val_len = sizeof(struct in_addr);
d7c0a89a 473 return (uint8_t *)&addr;
d62a17ae 474
475 case RIP2IFCONFDOMAIN:
476 *val_len = 2;
d7c0a89a 477 return (uint8_t *)&domain;
d62a17ae 478
479 case RIP2IFCONFAUTHTYPE:
480 auth = ri->auth_type;
481 *val_len = sizeof(long);
482 v->type = ASN_INTEGER;
d7c0a89a 483 return (uint8_t *)&auth;
d62a17ae 484
485 case RIP2IFCONFAUTHKEY:
486 *val_len = 0;
d7c0a89a 487 return (uint8_t *)&domain;
d62a17ae 488 case RIP2IFCONFSEND:
489 config = rip2IfConfSend(ri);
490 *val_len = sizeof(long);
491 v->type = ASN_INTEGER;
d7c0a89a 492 return (uint8_t *)&config;
d62a17ae 493 case RIP2IFCONFRECEIVE:
494 config = rip2IfConfReceive(ri);
495 *val_len = sizeof(long);
496 v->type = ASN_INTEGER;
d7c0a89a 497 return (uint8_t *)&config;
d62a17ae 498
499 case RIP2IFCONFDEFAULTMETRIC:
500 *val_len = sizeof(long);
501 v->type = ASN_INTEGER;
d7c0a89a 502 return (uint8_t *)&ifp->metric;
d62a17ae 503 case RIP2IFCONFSTATUS:
504 *val_len = sizeof(long);
505 v->type = ASN_INTEGER;
d7c0a89a 506 return (uint8_t *)&valid;
d62a17ae 507 case RIP2IFCONFSRCADDRESS:
508 *val_len = sizeof(struct in_addr);
d7c0a89a 509 return (uint8_t *)&addr;
d62a17ae 510
511 default:
512 return NULL;
513 }
514 return NULL;
718e3744 515}
516
d7c0a89a
QY
517static uint8_t *rip2PeerTable(struct variable *v, oid name[], size_t *length,
518 int exact, size_t *val_len,
519 WriteMethod **write_method)
718e3744 520{
d62a17ae 521 static struct in_addr addr;
522 static int domain = 0;
523 static int version;
524 /* static time_t uptime; */
525
526 struct rip_peer *peer;
527
528 if (smux_header_table(v, name, length, exact, val_len, write_method)
529 == MATCH_FAILED)
530 return NULL;
531
532 memset(&addr, 0, sizeof(struct in_addr));
533
534 /* Lookup interface. */
535 peer = rip2PeerLookup(v, name, length, &addr, exact);
536 if (!peer)
537 return NULL;
538
539 switch (v->magic) {
540 case RIP2PEERADDRESS:
541 *val_len = sizeof(struct in_addr);
d7c0a89a 542 return (uint8_t *)&peer->addr;
d62a17ae 543
544 case RIP2PEERDOMAIN:
545 *val_len = 2;
d7c0a89a 546 return (uint8_t *)&domain;
d62a17ae 547
548 case RIP2PEERLASTUPDATE:
d7c0a89a 549 return (uint8_t *)NULL;
718e3744 550
d62a17ae 551 case RIP2PEERVERSION:
552 *val_len = sizeof(int);
553 version = peer->version;
d7c0a89a 554 return (uint8_t *)&version;
718e3744 555
d62a17ae 556 case RIP2PEERRCVBADPACKETS:
557 *val_len = sizeof(int);
d7c0a89a 558 return (uint8_t *)&peer->recv_badpackets;
718e3744 559
d62a17ae 560 case RIP2PEERRCVBADROUTES:
561 *val_len = sizeof(int);
d7c0a89a 562 return (uint8_t *)&peer->recv_badroutes;
718e3744 563
d62a17ae 564 default:
565 return NULL;
566 }
567 return NULL;
718e3744 568}
569
570/* Register RIPv2-MIB. */
d62a17ae 571static int rip_snmp_init(struct thread_master *master)
718e3744 572{
d62a17ae 573 rip_ifaddr_table = route_table_init();
718e3744 574
d62a17ae 575 smux_init(master);
576 REGISTER_MIB("mibII/rip", rip_variables, variable, rip_oid);
577 return 0;
718e3744 578}
5986b66b 579
d62a17ae 580static int rip_snmp_module_init(void)
5986b66b 581{
d62a17ae 582 hook_register(rip_ifaddr_add, rip_snmp_ifaddr_add);
583 hook_register(rip_ifaddr_del, rip_snmp_ifaddr_del);
5986b66b 584
d62a17ae 585 hook_register(frr_late_init, rip_snmp_init);
586 return 0;
5986b66b
DL
587}
588
d62a17ae 589FRR_MODULE_SETUP(.name = "ripd_snmp", .version = FRR_VERSION,
590 .description = "ripd AgentX SNMP module",
80413c20
DL
591 .init = rip_snmp_module_init,
592);