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