+ note the meta-queue in NEWS
[jleu-quagga.git] / zebra / zebra_snmp.c
blob4536026f524886a609224a1b78ea9276efce284d
1 /* FIB SNMP.
2 * Copyright (C) 1999 Kunihiro Ishiguro
4 * This file is part of GNU Zebra.
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.
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.
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.
22 #include <zebra.h>
24 #ifdef HAVE_SNMP
25 #ifdef HAVE_NETSNMP
26 #include <net-snmp/net-snmp-config.h>
27 #endif
28 #include <asn1.h>
29 #include <snmp.h>
30 #include <snmp_impl.h>
32 #include "if.h"
33 #include "log.h"
34 #include "prefix.h"
35 #include "command.h"
36 #include "smux.h"
37 #include "table.h"
39 #include "zebra/rib.h"
40 #include "zebra/zserv.h"
42 #define IPFWMIB 1,3,6,1,2,1,4,24
44 /* ipForwardTable */
45 #define IPFORWARDDEST 1
46 #define IPFORWARDMASK 2
47 #define IPFORWARDPOLICY 3
48 #define IPFORWARDNEXTHOP 4
49 #define IPFORWARDIFINDEX 5
50 #define IPFORWARDTYPE 6
51 #define IPFORWARDPROTO 7
52 #define IPFORWARDAGE 8
53 #define IPFORWARDINFO 9
54 #define IPFORWARDNEXTHOPAS 10
55 #define IPFORWARDMETRIC1 11
56 #define IPFORWARDMETRIC2 12
57 #define IPFORWARDMETRIC3 13
58 #define IPFORWARDMETRIC4 14
59 #define IPFORWARDMETRIC5 15
61 /* ipCidrRouteTable */
62 #define IPCIDRROUTEDEST 1
63 #define IPCIDRROUTEMASK 2
64 #define IPCIDRROUTETOS 3
65 #define IPCIDRROUTENEXTHOP 4
66 #define IPCIDRROUTEIFINDEX 5
67 #define IPCIDRROUTETYPE 6
68 #define IPCIDRROUTEPROTO 7
69 #define IPCIDRROUTEAGE 8
70 #define IPCIDRROUTEINFO 9
71 #define IPCIDRROUTENEXTHOPAS 10
72 #define IPCIDRROUTEMETRIC1 11
73 #define IPCIDRROUTEMETRIC2 12
74 #define IPCIDRROUTEMETRIC3 13
75 #define IPCIDRROUTEMETRIC4 14
76 #define IPCIDRROUTEMETRIC5 15
77 #define IPCIDRROUTESTATUS 16
79 #define INTEGER32 ASN_INTEGER
80 #define GAUGE32 ASN_GAUGE
81 #define ENUMERATION ASN_INTEGER
82 #define ROWSTATUS ASN_INTEGER
83 #define IPADDRESS ASN_IPADDRESS
84 #define OBJECTIDENTIFIER ASN_OBJECT_ID
86 extern struct zebra_t zebrad;
88 oid ipfw_oid [] = { IPFWMIB };
90 /* Hook functions. */
91 u_char * ipFwNumber ();
92 u_char * ipFwTable ();
93 u_char * ipCidrNumber ();
94 u_char * ipCidrTable ();
96 struct variable zebra_variables[] =
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}}
134 u_char *
135 ipFwNumber (struct variable *v, oid objid[], size_t *objid_len,
136 int exact, size_t *val_len, WriteMethod **write_method)
138 static int result;
139 struct route_table *table;
140 struct route_node *rn;
141 struct rib *rib;
143 if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED)
144 return NULL;
146 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
147 if (! table)
148 return NULL;
150 /* Return number of routing entries. */
151 result = 0;
152 for (rn = route_top (table); rn; rn = route_next (rn))
153 for (rib = rn->info; rib; rib = rib->next)
154 result++;
156 return (u_char *)&result;
159 u_char *
160 ipCidrNumber (struct variable *v, oid objid[], size_t *objid_len,
161 int exact, size_t *val_len, WriteMethod **write_method)
163 static int result;
164 struct route_table *table;
165 struct route_node *rn;
166 struct rib *rib;
168 if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED)
169 return NULL;
171 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
172 if (! table)
173 return 0;
175 /* Return number of routing entries. */
176 result = 0;
177 for (rn = route_top (table); rn; rn = route_next (rn))
178 for (rib = rn->info; rib; rib = rib->next)
179 result++;
181 return (u_char *)&result;
185 in_addr_cmp(u_char *p1, u_char *p2)
187 int i;
189 for (i=0; i<4; i++)
191 if (*p1 < *p2)
192 return -1;
193 if (*p1 > *p2)
194 return 1;
195 p1++; p2++;
197 return 0;
200 int
201 in_addr_add(u_char *p, int num)
203 int i, ip0;
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;
217 if (ip0 > *p) {
218 /* ip + num > 0xffffffff */
219 return 0;
222 return 1;
225 int proto_trans(int type)
227 switch (type)
229 case ZEBRA_ROUTE_SYSTEM:
230 return 1; /* other */
231 case ZEBRA_ROUTE_KERNEL:
232 return 1; /* other */
233 case ZEBRA_ROUTE_CONNECT:
234 return 2; /* local interface */
235 case ZEBRA_ROUTE_STATIC:
236 return 3; /* static route */
237 case ZEBRA_ROUTE_RIP:
238 return 8; /* rip */
239 case ZEBRA_ROUTE_RIPNG:
240 return 1; /* shouldn't happen */
241 case ZEBRA_ROUTE_OSPF:
242 return 13; /* ospf */
243 case ZEBRA_ROUTE_OSPF6:
244 return 1; /* shouldn't happen */
245 case ZEBRA_ROUTE_BGP:
246 return 14; /* bgp */
247 default:
248 return 1; /* other */
252 void
253 check_replace(struct route_node *np2, struct rib *rib2,
254 struct route_node **np, struct rib **rib)
256 int proto, proto2;
258 if (!*np)
260 *np = np2;
261 *rib = rib2;
262 return;
265 if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) < 0)
266 return;
267 if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) > 0)
269 *np = np2;
270 *rib = rib2;
271 return;
274 proto = proto_trans((*rib)->type);
275 proto2 = proto_trans(rib2->type);
277 if (proto2 > proto)
278 return;
279 if (proto2 < proto)
281 *np = np2;
282 *rib = rib2;
283 return;
286 if (in_addr_cmp((u_char *)&(*rib)->nexthop->gate.ipv4,
287 (u_char *)&rib2->nexthop->gate.ipv4) <= 0)
288 return;
290 *np = np2;
291 *rib = rib2;
292 return;
295 void
296 get_fwtable_route_node(struct variable *v, oid objid[], size_t *objid_len,
297 int exact, struct route_node **np, struct rib **rib)
299 struct in_addr dest;
300 struct route_table *table;
301 struct route_node *np2;
302 struct rib *rib2;
303 int proto;
304 int policy;
305 struct in_addr nexthop;
306 u_char *pnt;
307 int i;
309 /* Init index variables */
311 pnt = (u_char *) &dest;
312 for (i = 0; i < 4; i++)
313 *pnt++ = 0;
315 pnt = (u_char *) &nexthop;
316 for (i = 0; i < 4; i++)
317 *pnt++ = 0;
319 proto = 0;
320 policy = 0;
322 /* Init return variables */
324 *np = NULL;
325 *rib = NULL;
327 /* Short circuit exact matches of wrong length */
329 if (exact && (*objid_len != (unsigned) v->namelen + 10))
330 return;
332 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
333 if (! table)
334 return;
336 /* Get INDEX information out of OID.
337 * ipForwardDest, ipForwardProto, ipForwardPolicy, ipForwardNextHop
340 if (*objid_len > v->namelen)
341 oid2in_addr (objid + v->namelen, MIN(4, *objid_len - v->namelen), &dest);
343 if (*objid_len > (unsigned) v->namelen + 4)
344 proto = objid[v->namelen + 4];
346 if (*objid_len > (unsigned) v->namelen + 5)
347 policy = objid[v->namelen + 5];
349 if (*objid_len > (unsigned) v->namelen + 6)
350 oid2in_addr (objid + v->namelen + 6, MIN(4, *objid_len - v->namelen - 6),
351 &nexthop);
353 /* Apply GETNEXT on not exact search */
355 if (!exact && (*objid_len >= (unsigned) v->namelen + 10))
357 if (! in_addr_add((u_char *) &nexthop, 1))
358 return;
361 /* For exact: search matching entry in rib table. */
363 if (exact)
365 if (policy) /* Not supported (yet?) */
366 return;
367 for (*np = route_top (table); *np; *np = route_next (*np))
369 if (!in_addr_cmp(&(*np)->p.u.prefix, (u_char *)&dest))
371 for (*rib = (*np)->info; *rib; *rib = (*rib)->next)
373 if (!in_addr_cmp((u_char *)&(*rib)->nexthop->gate.ipv4,
374 (u_char *)&nexthop))
375 if (proto == proto_trans((*rib)->type))
376 return;
380 return;
383 /* Search next best entry */
385 for (np2 = route_top (table); np2; np2 = route_next (np2))
388 /* Check destination first */
389 if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) > 0)
390 for (rib2 = np2->info; rib2; rib2 = rib2->next)
391 check_replace(np2, rib2, np, rib);
393 if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) == 0)
394 { /* have to look at each rib individually */
395 for (rib2 = np2->info; rib2; rib2 = rib2->next)
397 int proto2, policy2;
399 proto2 = proto_trans(rib2->type);
400 policy2 = 0;
402 if ((policy < policy2)
403 || ((policy == policy2) && (proto < proto2))
404 || ((policy == policy2) && (proto == proto2)
405 && (in_addr_cmp((u_char *)&rib2->nexthop->gate.ipv4,
406 (u_char *) &nexthop) >= 0)
408 check_replace(np2, rib2, np, rib);
413 if (!*rib)
414 return;
416 policy = 0;
417 proto = proto_trans((*rib)->type);
419 *objid_len = v->namelen + 10;
420 pnt = (u_char *) &(*np)->p.u.prefix;
421 for (i = 0; i < 4; i++)
422 objid[v->namelen + i] = *pnt++;
424 objid[v->namelen + 4] = proto;
425 objid[v->namelen + 5] = policy;
428 struct nexthop *nexthop;
430 nexthop = (*rib)->nexthop;
431 if (nexthop)
433 pnt = (u_char *) &nexthop->gate.ipv4;
434 for (i = 0; i < 4; i++)
435 objid[i + v->namelen + 6] = *pnt++;
439 return;
442 u_char *
443 ipFwTable (struct variable *v, oid objid[], size_t *objid_len,
444 int exact, size_t *val_len, WriteMethod **write_method)
446 struct route_node *np;
447 struct rib *rib;
448 static int result;
449 static int resarr[2];
450 static struct in_addr netmask;
451 struct nexthop *nexthop;
453 get_fwtable_route_node(v, objid, objid_len, exact, &np, &rib);
454 if (!np)
455 return NULL;
457 nexthop = rib->nexthop;
458 if (! nexthop)
459 return NULL;
461 switch (v->magic)
463 case IPFORWARDDEST:
464 *val_len = 4;
465 return &np->p.u.prefix;
466 break;
467 case IPFORWARDMASK:
468 masklen2ip(np->p.prefixlen, &netmask);
469 *val_len = 4;
470 return (u_char *)&netmask;
471 break;
472 case IPFORWARDPOLICY:
473 result = 0;
474 *val_len = sizeof(int);
475 return (u_char *)&result;
476 break;
477 case IPFORWARDNEXTHOP:
478 *val_len = 4;
479 return (u_char *)&nexthop->gate.ipv4;
480 break;
481 case IPFORWARDIFINDEX:
482 *val_len = sizeof(int);
483 return (u_char *)&nexthop->ifindex;
484 break;
485 case IPFORWARDTYPE:
486 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
487 || nexthop->type == NEXTHOP_TYPE_IFNAME)
488 result = 3;
489 else
490 result = 4;
491 *val_len = sizeof(int);
492 return (u_char *)&result;
493 break;
494 case IPFORWARDPROTO:
495 result = proto_trans(rib->type);
496 *val_len = sizeof(int);
497 return (u_char *)&result;
498 break;
499 case IPFORWARDAGE:
500 result = 0;
501 *val_len = sizeof(int);
502 return (u_char *)&result;
503 break;
504 case IPFORWARDINFO:
505 resarr[0] = 0;
506 resarr[1] = 0;
507 *val_len = 2 * sizeof(int);
508 return (u_char *)resarr;
509 break;
510 case IPFORWARDNEXTHOPAS:
511 result = -1;
512 *val_len = sizeof(int);
513 return (u_char *)&result;
514 break;
515 case IPFORWARDMETRIC1:
516 result = 0;
517 *val_len = sizeof(int);
518 return (u_char *)&result;
519 break;
520 case IPFORWARDMETRIC2:
521 result = 0;
522 *val_len = sizeof(int);
523 return (u_char *)&result;
524 break;
525 case IPFORWARDMETRIC3:
526 result = 0;
527 *val_len = sizeof(int);
528 return (u_char *)&result;
529 break;
530 case IPFORWARDMETRIC4:
531 result = 0;
532 *val_len = sizeof(int);
533 return (u_char *)&result;
534 break;
535 case IPFORWARDMETRIC5:
536 result = 0;
537 *val_len = sizeof(int);
538 return (u_char *)&result;
539 break;
540 default:
541 return NULL;
542 break;
544 return NULL;
547 u_char *
548 ipCidrTable (struct variable *v, oid objid[], size_t *objid_len,
549 int exact, size_t *val_len, WriteMethod **write_method)
551 switch (v->magic)
553 case IPCIDRROUTEDEST:
554 break;
555 default:
556 return NULL;
557 break;
559 return NULL;
562 void
563 zebra_snmp_init ()
565 smux_init (zebrad.master);
566 REGISTER_MIB("mibII/ipforward", zebra_variables, variable, ipfw_oid);
568 #endif /* HAVE_SNMP */