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