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