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