Annotation of embedaddon/quagga/zebra/zebra_snmp.c, revision 1.1.1.1
1.1 misho 1: /* FIB SNMP.
2: * Copyright (C) 1999 Kunihiro Ishiguro
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 "smux.h"
39: #include "table.h"
40:
41: #include "zebra/rib.h"
42: #include "zebra/zserv.h"
43:
44: #define IPFWMIB 1,3,6,1,2,1,4,24
45:
46: /* ipForwardTable */
47: #define IPFORWARDDEST 1
48: #define IPFORWARDMASK 2
49: #define IPFORWARDPOLICY 3
50: #define IPFORWARDNEXTHOP 4
51: #define IPFORWARDIFINDEX 5
52: #define IPFORWARDTYPE 6
53: #define IPFORWARDPROTO 7
54: #define IPFORWARDAGE 8
55: #define IPFORWARDINFO 9
56: #define IPFORWARDNEXTHOPAS 10
57: #define IPFORWARDMETRIC1 11
58: #define IPFORWARDMETRIC2 12
59: #define IPFORWARDMETRIC3 13
60: #define IPFORWARDMETRIC4 14
61: #define IPFORWARDMETRIC5 15
62:
63: /* ipCidrRouteTable */
64: #define IPCIDRROUTEDEST 1
65: #define IPCIDRROUTEMASK 2
66: #define IPCIDRROUTETOS 3
67: #define IPCIDRROUTENEXTHOP 4
68: #define IPCIDRROUTEIFINDEX 5
69: #define IPCIDRROUTETYPE 6
70: #define IPCIDRROUTEPROTO 7
71: #define IPCIDRROUTEAGE 8
72: #define IPCIDRROUTEINFO 9
73: #define IPCIDRROUTENEXTHOPAS 10
74: #define IPCIDRROUTEMETRIC1 11
75: #define IPCIDRROUTEMETRIC2 12
76: #define IPCIDRROUTEMETRIC3 13
77: #define IPCIDRROUTEMETRIC4 14
78: #define IPCIDRROUTEMETRIC5 15
79: #define IPCIDRROUTESTATUS 16
80:
81: #define INTEGER32 ASN_INTEGER
82: #define GAUGE32 ASN_GAUGE
83: #define ENUMERATION ASN_INTEGER
84: #define ROWSTATUS ASN_INTEGER
85: #define IPADDRESS ASN_IPADDRESS
86: #define OBJECTIDENTIFIER ASN_OBJECT_ID
87:
88: extern struct zebra_t zebrad;
89:
90: oid ipfw_oid [] = { IPFWMIB };
91:
92: /* Hook functions. */
93: static u_char * ipFwNumber (struct variable *, oid [], size_t *,
94: int, size_t *, WriteMethod **);
95: static u_char * ipFwTable (struct variable *, oid [], size_t *,
96: int, size_t *, WriteMethod **);
97: static u_char * ipCidrNumber (struct variable *, oid [], size_t *,
98: int, size_t *, WriteMethod **);
99: static u_char * ipCidrTable (struct variable *, oid [], size_t *,
100: int, size_t *, WriteMethod **);
101:
102: struct variable zebra_variables[] =
103: {
104: {0, GAUGE32, RONLY, ipFwNumber, 1, {1}},
105: {IPFORWARDDEST, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 1}},
106: {IPFORWARDMASK, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 2}},
107: {IPFORWARDPOLICY, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 3}},
108: {IPFORWARDNEXTHOP, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 4}},
109: {IPFORWARDIFINDEX, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 5}},
110: {IPFORWARDTYPE, ENUMERATION, RONLY, ipFwTable, 3, {2, 1, 6}},
111: {IPFORWARDPROTO, ENUMERATION, RONLY, ipFwTable, 3, {2, 1, 7}},
112: {IPFORWARDAGE, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 8}},
113: {IPFORWARDINFO, OBJECTIDENTIFIER, RONLY, ipFwTable, 3, {2, 1, 9}},
114: {IPFORWARDNEXTHOPAS, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 10}},
115: {IPFORWARDMETRIC1, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 11}},
116: {IPFORWARDMETRIC2, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 12}},
117: {IPFORWARDMETRIC3, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 13}},
118: {IPFORWARDMETRIC4, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 14}},
119: {IPFORWARDMETRIC5, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 15}},
120: {0, GAUGE32, RONLY, ipCidrNumber, 1, {3}},
121: {IPCIDRROUTEDEST, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 1}},
122: {IPCIDRROUTEMASK, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 2}},
123: {IPCIDRROUTETOS, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 3}},
124: {IPCIDRROUTENEXTHOP, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 4}},
125: {IPCIDRROUTEIFINDEX, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 5}},
126: {IPCIDRROUTETYPE, ENUMERATION, RONLY, ipCidrTable, 3, {4, 1, 6}},
127: {IPCIDRROUTEPROTO, ENUMERATION, RONLY, ipCidrTable, 3, {4, 1, 7}},
128: {IPCIDRROUTEAGE, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 8}},
129: {IPCIDRROUTEINFO, OBJECTIDENTIFIER, RONLY, ipCidrTable, 3, {4, 1, 9}},
130: {IPCIDRROUTENEXTHOPAS, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 10}},
131: {IPCIDRROUTEMETRIC1, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 11}},
132: {IPCIDRROUTEMETRIC2, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 12}},
133: {IPCIDRROUTEMETRIC3, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 13}},
134: {IPCIDRROUTEMETRIC4, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 14}},
135: {IPCIDRROUTEMETRIC5, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 15}},
136: {IPCIDRROUTESTATUS, ROWSTATUS, RONLY, ipCidrTable, 3, {4, 1, 16}}
137: };
138:
139:
140: static u_char *
141: ipFwNumber (struct variable *v, oid objid[], size_t *objid_len,
142: int exact, size_t *val_len, WriteMethod **write_method)
143: {
144: static int result;
145: struct route_table *table;
146: struct route_node *rn;
147: struct rib *rib;
148:
149: if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED)
150: return NULL;
151:
152: table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
153: if (! table)
154: return NULL;
155:
156: /* Return number of routing entries. */
157: result = 0;
158: for (rn = route_top (table); rn; rn = route_next (rn))
159: for (rib = rn->info; rib; rib = rib->next)
160: result++;
161:
162: return (u_char *)&result;
163: }
164:
165: static u_char *
166: ipCidrNumber (struct variable *v, oid objid[], size_t *objid_len,
167: int exact, size_t *val_len, WriteMethod **write_method)
168: {
169: static int result;
170: struct route_table *table;
171: struct route_node *rn;
172: struct rib *rib;
173:
174: if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED)
175: return NULL;
176:
177: table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
178: if (! table)
179: return 0;
180:
181: /* Return number of routing entries. */
182: result = 0;
183: for (rn = route_top (table); rn; rn = route_next (rn))
184: for (rib = rn->info; rib; rib = rib->next)
185: result++;
186:
187: return (u_char *)&result;
188: }
189:
190: static int
191: in_addr_cmp(u_char *p1, u_char *p2)
192: {
193: int i;
194:
195: for (i=0; i<4; i++)
196: {
197: if (*p1 < *p2)
198: return -1;
199: if (*p1 > *p2)
200: return 1;
201: p1++; p2++;
202: }
203: return 0;
204: }
205:
206: static int
207: in_addr_add(u_char *p, int num)
208: {
209: int i, ip0;
210:
211: ip0 = *p;
212: p += 4;
213: for (i = 3; 0 <= i; i--) {
214: p--;
215: if (*p + num > 255) {
216: *p += num;
217: num = 1;
218: } else {
219: *p += num;
220: return 1;
221: }
222: }
223: if (ip0 > *p) {
224: /* ip + num > 0xffffffff */
225: return 0;
226: }
227:
228: return 1;
229: }
230:
231: static int
232: proto_trans(int type)
233: {
234: switch (type)
235: {
236: case ZEBRA_ROUTE_SYSTEM:
237: return 1; /* other */
238: case ZEBRA_ROUTE_KERNEL:
239: return 1; /* other */
240: case ZEBRA_ROUTE_CONNECT:
241: return 2; /* local interface */
242: case ZEBRA_ROUTE_STATIC:
243: return 3; /* static route */
244: case ZEBRA_ROUTE_RIP:
245: return 8; /* rip */
246: case ZEBRA_ROUTE_RIPNG:
247: return 1; /* shouldn't happen */
248: case ZEBRA_ROUTE_OSPF:
249: return 13; /* ospf */
250: case ZEBRA_ROUTE_OSPF6:
251: return 1; /* shouldn't happen */
252: case ZEBRA_ROUTE_BGP:
253: return 14; /* bgp */
254: default:
255: return 1; /* other */
256: }
257: }
258:
259: static void
260: check_replace(struct route_node *np2, struct rib *rib2,
261: struct route_node **np, struct rib **rib)
262: {
263: int proto, proto2;
264:
265: if (!*np)
266: {
267: *np = np2;
268: *rib = rib2;
269: return;
270: }
271:
272: if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) < 0)
273: return;
274: if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) > 0)
275: {
276: *np = np2;
277: *rib = rib2;
278: return;
279: }
280:
281: proto = proto_trans((*rib)->type);
282: proto2 = proto_trans(rib2->type);
283:
284: if (proto2 > proto)
285: return;
286: if (proto2 < proto)
287: {
288: *np = np2;
289: *rib = rib2;
290: return;
291: }
292:
293: if (in_addr_cmp((u_char *)&(*rib)->nexthop->gate.ipv4,
294: (u_char *)&rib2->nexthop->gate.ipv4) <= 0)
295: return;
296:
297: *np = np2;
298: *rib = rib2;
299: return;
300: }
301:
302: static void
303: get_fwtable_route_node(struct variable *v, oid objid[], size_t *objid_len,
304: int exact, struct route_node **np, struct rib **rib)
305: {
306: struct in_addr dest;
307: struct route_table *table;
308: struct route_node *np2;
309: struct rib *rib2;
310: int proto;
311: int policy;
312: struct in_addr nexthop;
313: u_char *pnt;
314: int i;
315:
316: /* Init index variables */
317:
318: pnt = (u_char *) &dest;
319: for (i = 0; i < 4; i++)
320: *pnt++ = 0;
321:
322: pnt = (u_char *) &nexthop;
323: for (i = 0; i < 4; i++)
324: *pnt++ = 0;
325:
326: proto = 0;
327: policy = 0;
328:
329: /* Init return variables */
330:
331: *np = NULL;
332: *rib = NULL;
333:
334: /* Short circuit exact matches of wrong length */
335:
336: if (exact && (*objid_len != (unsigned) v->namelen + 10))
337: return;
338:
339: table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
340: if (! table)
341: return;
342:
343: /* Get INDEX information out of OID.
344: * ipForwardDest, ipForwardProto, ipForwardPolicy, ipForwardNextHop
345: */
346:
347: if (*objid_len > (unsigned) v->namelen)
348: oid2in_addr (objid + v->namelen, MIN(4, *objid_len - v->namelen), &dest);
349:
350: if (*objid_len > (unsigned) v->namelen + 4)
351: proto = objid[v->namelen + 4];
352:
353: if (*objid_len > (unsigned) v->namelen + 5)
354: policy = objid[v->namelen + 5];
355:
356: if (*objid_len > (unsigned) v->namelen + 6)
357: oid2in_addr (objid + v->namelen + 6, MIN(4, *objid_len - v->namelen - 6),
358: &nexthop);
359:
360: /* Apply GETNEXT on not exact search */
361:
362: if (!exact && (*objid_len >= (unsigned) v->namelen + 10))
363: {
364: if (! in_addr_add((u_char *) &nexthop, 1))
365: return;
366: }
367:
368: /* For exact: search matching entry in rib table. */
369:
370: if (exact)
371: {
372: if (policy) /* Not supported (yet?) */
373: return;
374: for (*np = route_top (table); *np; *np = route_next (*np))
375: {
376: if (!in_addr_cmp(&(*np)->p.u.prefix, (u_char *)&dest))
377: {
378: for (*rib = (*np)->info; *rib; *rib = (*rib)->next)
379: {
380: if (!in_addr_cmp((u_char *)&(*rib)->nexthop->gate.ipv4,
381: (u_char *)&nexthop))
382: if (proto == proto_trans((*rib)->type))
383: return;
384: }
385: }
386: }
387: return;
388: }
389:
390: /* Search next best entry */
391:
392: for (np2 = route_top (table); np2; np2 = route_next (np2))
393: {
394:
395: /* Check destination first */
396: if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) > 0)
397: for (rib2 = np2->info; rib2; rib2 = rib2->next)
398: check_replace(np2, rib2, np, rib);
399:
400: if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) == 0)
401: { /* have to look at each rib individually */
402: for (rib2 = np2->info; rib2; rib2 = rib2->next)
403: {
404: int proto2, policy2;
405:
406: proto2 = proto_trans(rib2->type);
407: policy2 = 0;
408:
409: if ((policy < policy2)
410: || ((policy == policy2) && (proto < proto2))
411: || ((policy == policy2) && (proto == proto2)
412: && (in_addr_cmp((u_char *)&rib2->nexthop->gate.ipv4,
413: (u_char *) &nexthop) >= 0)
414: ))
415: check_replace(np2, rib2, np, rib);
416: }
417: }
418: }
419:
420: if (!*rib)
421: return;
422:
423: policy = 0;
424: proto = proto_trans((*rib)->type);
425:
426: *objid_len = v->namelen + 10;
427: pnt = (u_char *) &(*np)->p.u.prefix;
428: for (i = 0; i < 4; i++)
429: objid[v->namelen + i] = *pnt++;
430:
431: objid[v->namelen + 4] = proto;
432: objid[v->namelen + 5] = policy;
433:
434: {
435: struct nexthop *nexthop;
436:
437: nexthop = (*rib)->nexthop;
438: if (nexthop)
439: {
440: pnt = (u_char *) &nexthop->gate.ipv4;
441: for (i = 0; i < 4; i++)
442: objid[i + v->namelen + 6] = *pnt++;
443: }
444: }
445:
446: return;
447: }
448:
449: static u_char *
450: ipFwTable (struct variable *v, oid objid[], size_t *objid_len,
451: int exact, size_t *val_len, WriteMethod **write_method)
452: {
453: struct route_node *np;
454: struct rib *rib;
455: static int result;
456: static int resarr[2];
457: static struct in_addr netmask;
458: struct nexthop *nexthop;
459:
460: get_fwtable_route_node(v, objid, objid_len, exact, &np, &rib);
461: if (!np)
462: return NULL;
463:
464: nexthop = rib->nexthop;
465: if (! nexthop)
466: return NULL;
467:
468: switch (v->magic)
469: {
470: case IPFORWARDDEST:
471: *val_len = 4;
472: return &np->p.u.prefix;
473: break;
474: case IPFORWARDMASK:
475: masklen2ip(np->p.prefixlen, &netmask);
476: *val_len = 4;
477: return (u_char *)&netmask;
478: break;
479: case IPFORWARDPOLICY:
480: result = 0;
481: *val_len = sizeof(int);
482: return (u_char *)&result;
483: break;
484: case IPFORWARDNEXTHOP:
485: *val_len = 4;
486: return (u_char *)&nexthop->gate.ipv4;
487: break;
488: case IPFORWARDIFINDEX:
489: *val_len = sizeof(int);
490: return (u_char *)&nexthop->ifindex;
491: break;
492: case IPFORWARDTYPE:
493: if (nexthop->type == NEXTHOP_TYPE_IFINDEX
494: || nexthop->type == NEXTHOP_TYPE_IFNAME)
495: result = 3;
496: else
497: result = 4;
498: *val_len = sizeof(int);
499: return (u_char *)&result;
500: break;
501: case IPFORWARDPROTO:
502: result = proto_trans(rib->type);
503: *val_len = sizeof(int);
504: return (u_char *)&result;
505: break;
506: case IPFORWARDAGE:
507: result = 0;
508: *val_len = sizeof(int);
509: return (u_char *)&result;
510: break;
511: case IPFORWARDINFO:
512: resarr[0] = 0;
513: resarr[1] = 0;
514: *val_len = 2 * sizeof(int);
515: return (u_char *)resarr;
516: break;
517: case IPFORWARDNEXTHOPAS:
518: result = -1;
519: *val_len = sizeof(int);
520: return (u_char *)&result;
521: break;
522: case IPFORWARDMETRIC1:
523: result = 0;
524: *val_len = sizeof(int);
525: return (u_char *)&result;
526: break;
527: case IPFORWARDMETRIC2:
528: result = 0;
529: *val_len = sizeof(int);
530: return (u_char *)&result;
531: break;
532: case IPFORWARDMETRIC3:
533: result = 0;
534: *val_len = sizeof(int);
535: return (u_char *)&result;
536: break;
537: case IPFORWARDMETRIC4:
538: result = 0;
539: *val_len = sizeof(int);
540: return (u_char *)&result;
541: break;
542: case IPFORWARDMETRIC5:
543: result = 0;
544: *val_len = sizeof(int);
545: return (u_char *)&result;
546: break;
547: default:
548: return NULL;
549: break;
550: }
551: return NULL;
552: }
553:
554: static u_char *
555: ipCidrTable (struct variable *v, oid objid[], size_t *objid_len,
556: int exact, size_t *val_len, WriteMethod **write_method)
557: {
558: switch (v->magic)
559: {
560: case IPCIDRROUTEDEST:
561: break;
562: default:
563: return NULL;
564: break;
565: }
566: return NULL;
567: }
568:
569: void
570: zebra_snmp_init ()
571: {
572: smux_init (zebrad.master);
573: REGISTER_MIB("mibII/ipforward", zebra_variables, variable, ipfw_oid);
574: }
575: #endif /* HAVE_SNMP */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>