Annotation of embedaddon/quagga/ripd/rip_snmp.c, revision 1.1.1.1
1.1 misho 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:
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:
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 (struct variable *, oid [], size_t *,
97: int, size_t *, WriteMethod **);
98: static u_char *rip2IfStatEntry (struct variable *, oid [], size_t *,
99: int, size_t *, WriteMethod **);
100: static u_char *rip2IfConfAddress (struct variable *, oid [], size_t *,
101: int, size_t *, WriteMethod **);
102: static u_char *rip2PeerTable (struct variable *, oid [], size_t *,
103: int, size_t *, WriteMethod **);
104:
105: struct variable rip_variables[] =
106: {
107: /* RIP Global Counters. */
108: {RIP2GLOBALROUTECHANGES, COUNTER, RONLY, rip2Globals,
109: 2, {1, 1}},
110: {RIP2GLOBALQUERIES, COUNTER, RONLY, rip2Globals,
111: 2, {1, 2}},
112: /* RIP Interface Tables. */
113: {RIP2IFSTATADDRESS, IPADDRESS, RONLY, rip2IfStatEntry,
114: 3, {2, 1, 1}},
115: {RIP2IFSTATRCVBADPACKETS, COUNTER, RONLY, rip2IfStatEntry,
116: 3, {2, 1, 2}},
117: {RIP2IFSTATRCVBADROUTES, COUNTER, RONLY, rip2IfStatEntry,
118: 3, {2, 1, 3}},
119: {RIP2IFSTATSENTUPDATES, COUNTER, RONLY, rip2IfStatEntry,
120: 3, {2, 1, 4}},
121: {RIP2IFSTATSTATUS, COUNTER, RWRITE, rip2IfStatEntry,
122: 3, {2, 1, 5}},
123: {RIP2IFCONFADDRESS, IPADDRESS, RONLY, rip2IfConfAddress,
124: /* RIP Interface Configuration Table. */
125: 3, {3, 1, 1}},
126: {RIP2IFCONFDOMAIN, STRING, RONLY, rip2IfConfAddress,
127: 3, {3, 1, 2}},
128: {RIP2IFCONFAUTHTYPE, COUNTER, RONLY, rip2IfConfAddress,
129: 3, {3, 1, 3}},
130: {RIP2IFCONFAUTHKEY, STRING, RONLY, rip2IfConfAddress,
131: 3, {3, 1, 4}},
132: {RIP2IFCONFSEND, COUNTER, RONLY, rip2IfConfAddress,
133: 3, {3, 1, 5}},
134: {RIP2IFCONFRECEIVE, COUNTER, RONLY, rip2IfConfAddress,
135: 3, {3, 1, 6}},
136: {RIP2IFCONFDEFAULTMETRIC, COUNTER, RONLY, rip2IfConfAddress,
137: 3, {3, 1, 7}},
138: {RIP2IFCONFSTATUS, COUNTER, RONLY, rip2IfConfAddress,
139: 3, {3, 1, 8}},
140: {RIP2IFCONFSRCADDRESS, IPADDRESS, RONLY, rip2IfConfAddress,
141: 3, {3, 1, 9}},
142: {RIP2PEERADDRESS, IPADDRESS, RONLY, rip2PeerTable,
143: /* RIP Peer Table. */
144: 3, {4, 1, 1}},
145: {RIP2PEERDOMAIN, STRING, RONLY, rip2PeerTable,
146: 3, {4, 1, 2}},
147: {RIP2PEERLASTUPDATE, TIMETICKS, RONLY, rip2PeerTable,
148: 3, {4, 1, 3}},
149: {RIP2PEERVERSION, INTEGER, RONLY, rip2PeerTable,
150: 3, {4, 1, 4}},
151: {RIP2PEERRCVBADPACKETS, COUNTER, RONLY, rip2PeerTable,
152: 3, {4, 1, 5}},
153: {RIP2PEERRCVBADROUTES, COUNTER, RONLY, rip2PeerTable,
154: 3, {4, 1, 6}}
155: };
156:
157: extern struct thread_master *master;
158:
159: static u_char *
160: rip2Globals (struct variable *v, oid name[], size_t *length,
161: int exact, size_t *var_len, WriteMethod **write_method)
162: {
163: if (smux_header_generic(v, name, length, exact, var_len, write_method)
164: == MATCH_FAILED)
165: return NULL;
166:
167: /* Retrun global counter. */
168: switch (v->magic)
169: {
170: case RIP2GLOBALROUTECHANGES:
171: return SNMP_INTEGER (rip_global_route_changes);
172: break;
173: case RIP2GLOBALQUERIES:
174: return SNMP_INTEGER (rip_global_queries);
175: break;
176: default:
177: return NULL;
178: break;
179: }
180: return NULL;
181: }
182:
183: void
184: rip_ifaddr_add (struct interface *ifp, struct connected *ifc)
185: {
186: struct prefix *p;
187: struct route_node *rn;
188:
189: p = ifc->address;
190:
191: if (p->family != AF_INET)
192: return;
193:
194: rn = route_node_get (rip_ifaddr_table, p);
195: rn->info = ifp;
196: }
197:
198: void
199: rip_ifaddr_delete (struct interface *ifp, struct connected *ifc)
200: {
201: struct prefix *p;
202: struct route_node *rn;
203: struct interface *i;
204:
205: p = ifc->address;
206:
207: if (p->family != AF_INET)
208: return;
209:
210: rn = route_node_lookup (rip_ifaddr_table, p);
211: if (! rn)
212: return;
213: i = rn->info;
214: if (rn && !strncmp(i->name,ifp->name,INTERFACE_NAMSIZ))
215: {
216: rn->info = NULL;
217: route_unlock_node (rn);
218: route_unlock_node (rn);
219: }
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 (*addr);
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 == 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 < sizeof (struct in_addr) + 1) ||
321: (peer->domain > 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: memset (&addr, 0, sizeof (struct in_addr));
355:
356: /* Lookup interface. */
357: ifp = rip2IfLookup (v, name, length, &addr, exact);
358: if (! ifp)
359: return NULL;
360:
361: /* Fetch rip_interface information. */
362: ri = ifp->info;
363:
364: switch (v->magic)
365: {
366: case RIP2IFSTATADDRESS:
367: return SNMP_IPADDRESS (addr);
368: break;
369: case RIP2IFSTATRCVBADPACKETS:
370: *var_len = sizeof (long);
371: return (u_char *) &ri->recv_badpackets;
372:
373: case RIP2IFSTATRCVBADROUTES:
374: *var_len = sizeof (long);
375: return (u_char *) &ri->recv_badroutes;
376:
377: case RIP2IFSTATSENTUPDATES:
378: *var_len = sizeof (long);
379: return (u_char *) &ri->sent_updates;
380:
381: case RIP2IFSTATSTATUS:
382: *var_len = sizeof (long);
383: v->type = ASN_INTEGER;
384: return (u_char *) &valid;
385:
386: default:
387: return NULL;
388:
389: }
390: return NULL;
391: }
392:
393: static long
394: rip2IfConfSend (struct rip_interface *ri)
395: {
396: #define doNotSend 1
397: #define ripVersion1 2
398: #define rip1Compatible 3
399: #define ripVersion2 4
400: #define ripV1Demand 5
401: #define ripV2Demand 6
402:
403: if (! ri->running)
404: return doNotSend;
405:
406: if (ri->ri_send & RIPv2)
407: return ripVersion2;
408: else if (ri->ri_send & RIPv1)
409: return ripVersion1;
410: else if (rip)
411: {
412: if (rip->version_send == RIPv2)
413: return ripVersion2;
414: else if (rip->version_send == RIPv1)
415: return ripVersion1;
416: }
417: return doNotSend;
418: }
419:
420: static long
421: rip2IfConfReceive (struct rip_interface *ri)
422: {
423: #define rip1 1
424: #define rip2 2
425: #define rip1OrRip2 3
426: #define doNotReceive 4
427:
428: int recvv;
429:
430: if (! ri->running)
431: return doNotReceive;
432:
433: recvv = (ri->ri_receive == RI_RIP_UNSPEC) ? rip->version_recv :
434: ri->ri_receive;
435: if (recvv == RI_RIP_VERSION_1_AND_2)
436: return rip1OrRip2;
437: else if (recvv & RIPv2)
438: return rip2;
439: else if (recvv & RIPv1)
440: return rip1;
441: else
442: return doNotReceive;
443: }
444:
445: static u_char *
446: rip2IfConfAddress (struct variable *v, oid name[], size_t *length,
447: int exact, size_t *val_len, WriteMethod **write_method)
448: {
449: static struct in_addr addr;
450: static long valid = SNMP_INVALID;
451: static long domain = 0;
452: static long config = 0;
453: static u_int auth = 0;
454: struct interface *ifp;
455: struct rip_interface *ri;
456:
457: memset (&addr, 0, sizeof (struct in_addr));
458:
459: /* Lookup interface. */
460: ifp = rip2IfLookup (v, name, length, &addr, exact);
461: if (! ifp)
462: return NULL;
463:
464: /* Fetch rip_interface information. */
465: ri = ifp->info;
466:
467: switch (v->magic)
468: {
469: case RIP2IFCONFADDRESS:
470: *val_len = sizeof (struct in_addr);
471: return (u_char *) &addr;
472:
473: case RIP2IFCONFDOMAIN:
474: *val_len = 2;
475: return (u_char *) &domain;
476:
477: case RIP2IFCONFAUTHTYPE:
478: auth = ri->auth_type;
479: *val_len = sizeof (long);
480: v->type = ASN_INTEGER;
481: return (u_char *)&auth;
482:
483: case RIP2IFCONFAUTHKEY:
484: *val_len = 0;
485: return (u_char *) &domain;
486: case RIP2IFCONFSEND:
487: config = rip2IfConfSend (ri);
488: *val_len = sizeof (long);
489: v->type = ASN_INTEGER;
490: return (u_char *) &config;
491: case RIP2IFCONFRECEIVE:
492: config = rip2IfConfReceive (ri);
493: *val_len = sizeof (long);
494: v->type = ASN_INTEGER;
495: return (u_char *) &config;
496:
497: case RIP2IFCONFDEFAULTMETRIC:
498: *val_len = sizeof (long);
499: v->type = ASN_INTEGER;
500: return (u_char *) &ifp->metric;
501: case RIP2IFCONFSTATUS:
502: *val_len = sizeof (long);
503: v->type = ASN_INTEGER;
504: return (u_char *) &valid;
505: case RIP2IFCONFSRCADDRESS:
506: *val_len = sizeof (struct in_addr);
507: return (u_char *) &addr;
508:
509: default:
510: return NULL;
511:
512: }
513: return NULL;
514: }
515:
516: static u_char *
517: rip2PeerTable (struct variable *v, oid name[], size_t *length,
518: int exact, size_t *val_len, WriteMethod **write_method)
519: {
520: static struct in_addr addr;
521: static int domain = 0;
522: static int version;
523: /* static time_t uptime; */
524:
525: struct rip_peer *peer;
526:
527: memset (&addr, 0, sizeof (struct in_addr));
528:
529: /* Lookup interface. */
530: peer = rip2PeerLookup (v, name, length, &addr, exact);
531: if (! peer)
532: return NULL;
533:
534: switch (v->magic)
535: {
536: case RIP2PEERADDRESS:
537: *val_len = sizeof (struct in_addr);
538: return (u_char *) &peer->addr;
539:
540: case RIP2PEERDOMAIN:
541: *val_len = 2;
542: return (u_char *) &domain;
543:
544: case RIP2PEERLASTUPDATE:
545: #if 0
546: /* We don't know the SNMP agent startup time. We have two choices here:
547: * - assume ripd startup time equals SNMP agent startup time
548: * - don't support this variable, at all
549: * Currently, we do the latter...
550: */
551: *val_len = sizeof (time_t);
552: uptime = peer->uptime; /* now - snmp_agent_startup - peer->uptime */
553: return (u_char *) &uptime;
554: #else
555: return (u_char *) NULL;
556: #endif
557:
558: case RIP2PEERVERSION:
559: *val_len = sizeof (int);
560: version = peer->version;
561: return (u_char *) &version;
562:
563: case RIP2PEERRCVBADPACKETS:
564: *val_len = sizeof (int);
565: return (u_char *) &peer->recv_badpackets;
566:
567: case RIP2PEERRCVBADROUTES:
568: *val_len = sizeof (int);
569: return (u_char *) &peer->recv_badroutes;
570:
571: default:
572: return NULL;
573:
574: }
575: return NULL;
576: }
577:
578: /* Register RIPv2-MIB. */
579: void
580: rip_snmp_init ()
581: {
582: rip_ifaddr_table = route_table_init ();
583:
584: smux_init (master);
585: REGISTER_MIB("mibII/rip", rip_variables, variable, rip_oid);
586: }
587: #endif /* HAVE_SNMP */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>