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
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
23 * Currently SNMP is only running properly for MIBs in the default VRF.
29 #include <net-snmp/net-snmp-config.h>
30 #include <net-snmp/net-snmp-includes.h>
40 #include "zebra/rib.h"
41 #include "zebra/zserv.h"
43 #define IPFWMIB 1,3,6,1,2,1,4,24
46 #define IPFORWARDDEST 1
47 #define IPFORWARDMASK 2
48 #define IPFORWARDPOLICY 3
49 #define IPFORWARDNEXTHOP 4
50 #define IPFORWARDIFINDEX 5
51 #define IPFORWARDTYPE 6
52 #define IPFORWARDPROTO 7
53 #define IPFORWARDAGE 8
54 #define IPFORWARDINFO 9
55 #define IPFORWARDNEXTHOPAS 10
56 #define IPFORWARDMETRIC1 11
57 #define IPFORWARDMETRIC2 12
58 #define IPFORWARDMETRIC3 13
59 #define IPFORWARDMETRIC4 14
60 #define IPFORWARDMETRIC5 15
62 /* ipCidrRouteTable */
63 #define IPCIDRROUTEDEST 1
64 #define IPCIDRROUTEMASK 2
65 #define IPCIDRROUTETOS 3
66 #define IPCIDRROUTENEXTHOP 4
67 #define IPCIDRROUTEIFINDEX 5
68 #define IPCIDRROUTETYPE 6
69 #define IPCIDRROUTEPROTO 7
70 #define IPCIDRROUTEAGE 8
71 #define IPCIDRROUTEINFO 9
72 #define IPCIDRROUTENEXTHOPAS 10
73 #define IPCIDRROUTEMETRIC1 11
74 #define IPCIDRROUTEMETRIC2 12
75 #define IPCIDRROUTEMETRIC3 13
76 #define IPCIDRROUTEMETRIC4 14
77 #define IPCIDRROUTEMETRIC5 15
78 #define IPCIDRROUTESTATUS 16
80 #define INTEGER32 ASN_INTEGER
81 #define GAUGE32 ASN_GAUGE
82 #define ENUMERATION ASN_INTEGER
83 #define ROWSTATUS ASN_INTEGER
84 #define IPADDRESS ASN_IPADDRESS
85 #define OBJECTIDENTIFIER ASN_OBJECT_ID
87 extern struct zebra_t zebrad;
89 oid ipfw_oid [] = { IPFWMIB };
92 static u_char * ipFwNumber (struct variable *, oid [], size_t *,
93 int, size_t *, WriteMethod **);
94 static u_char * ipFwTable (struct variable *, oid [], size_t *,
95 int, size_t *, WriteMethod **);
96 static u_char * ipCidrNumber (struct variable *, oid [], size_t *,
97 int, size_t *, WriteMethod **);
98 static u_char * ipCidrTable (struct variable *, oid [], size_t *,
99 int, size_t *, WriteMethod **);
101 struct variable zebra_variables[] =
103 {0, GAUGE32, RONLY, ipFwNumber, 1, {1}},
104 {IPFORWARDDEST, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 1}},
105 {IPFORWARDMASK, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 2}},
106 {IPFORWARDPOLICY, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 3}},
107 {IPFORWARDNEXTHOP, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 4}},
108 {IPFORWARDIFINDEX, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 5}},
109 {IPFORWARDTYPE, ENUMERATION, RONLY, ipFwTable, 3, {2, 1, 6}},
110 {IPFORWARDPROTO, ENUMERATION, RONLY, ipFwTable, 3, {2, 1, 7}},
111 {IPFORWARDAGE, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 8}},
112 {IPFORWARDINFO, OBJECTIDENTIFIER, RONLY, ipFwTable, 3, {2, 1, 9}},
113 {IPFORWARDNEXTHOPAS, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 10}},
114 {IPFORWARDMETRIC1, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 11}},
115 {IPFORWARDMETRIC2, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 12}},
116 {IPFORWARDMETRIC3, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 13}},
117 {IPFORWARDMETRIC4, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 14}},
118 {IPFORWARDMETRIC5, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 15}},
119 {0, GAUGE32, RONLY, ipCidrNumber, 1, {3}},
120 {IPCIDRROUTEDEST, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 1}},
121 {IPCIDRROUTEMASK, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 2}},
122 {IPCIDRROUTETOS, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 3}},
123 {IPCIDRROUTENEXTHOP, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 4}},
124 {IPCIDRROUTEIFINDEX, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 5}},
125 {IPCIDRROUTETYPE, ENUMERATION, RONLY, ipCidrTable, 3, {4, 1, 6}},
126 {IPCIDRROUTEPROTO, ENUMERATION, RONLY, ipCidrTable, 3, {4, 1, 7}},
127 {IPCIDRROUTEAGE, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 8}},
128 {IPCIDRROUTEINFO, OBJECTIDENTIFIER, RONLY, ipCidrTable, 3, {4, 1, 9}},
129 {IPCIDRROUTENEXTHOPAS, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 10}},
130 {IPCIDRROUTEMETRIC1, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 11}},
131 {IPCIDRROUTEMETRIC2, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 12}},
132 {IPCIDRROUTEMETRIC3, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 13}},
133 {IPCIDRROUTEMETRIC4, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 14}},
134 {IPCIDRROUTEMETRIC5, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 15}},
135 {IPCIDRROUTESTATUS, ROWSTATUS, RONLY, ipCidrTable, 3, {4, 1, 16}}
140 ipFwNumber (struct variable *v, oid objid[], size_t *objid_len,
141 int exact, size_t *val_len, WriteMethod **write_method)
144 struct route_table *table;
145 struct route_node *rn;
148 if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED)
151 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
155 /* Return number of routing entries. */
157 for (rn = route_top (table); rn; rn = route_next (rn))
158 RNODE_FOREACH_RIB (rn, rib)
161 return (u_char *)&result;
165 ipCidrNumber (struct variable *v, oid objid[], size_t *objid_len,
166 int exact, size_t *val_len, WriteMethod **write_method)
169 struct route_table *table;
170 struct route_node *rn;
173 if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED)
176 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
180 /* Return number of routing entries. */
182 for (rn = route_top (table); rn; rn = route_next (rn))
183 RNODE_FOREACH_RIB (rn, rib)
186 return (u_char *)&result;
190 in_addr_cmp(u_char *p1, u_char *p2)
206 in_addr_add(u_char *p, int num)
212 for (i = 3; 0 <= i; i--) {
214 if (*p + num > 255) {
223 /* ip + num > 0xffffffff */
231 proto_trans(int type)
235 case ZEBRA_ROUTE_SYSTEM:
236 return 1; /* other */
237 case ZEBRA_ROUTE_KERNEL:
238 return 1; /* other */
239 case ZEBRA_ROUTE_CONNECT:
240 return 2; /* local interface */
241 case ZEBRA_ROUTE_STATIC:
242 return 3; /* static route */
243 case ZEBRA_ROUTE_RIP:
245 case ZEBRA_ROUTE_RIPNG:
246 return 1; /* shouldn't happen */
247 case ZEBRA_ROUTE_OSPF:
248 return 13; /* ospf */
249 case ZEBRA_ROUTE_OSPF6:
250 return 1; /* shouldn't happen */
251 case ZEBRA_ROUTE_BGP:
254 return 1; /* other */
259 check_replace(struct route_node *np2, struct rib *rib2,
260 struct route_node **np, struct rib **rib)
271 if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) < 0)
273 if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) > 0)
280 proto = proto_trans((*rib)->type);
281 proto2 = proto_trans(rib2->type);
292 if (in_addr_cmp((u_char *)&(*rib)->nexthop->gate.ipv4,
293 (u_char *)&rib2->nexthop->gate.ipv4) <= 0)
302 get_fwtable_route_node(struct variable *v, oid objid[], size_t *objid_len,
303 int exact, struct route_node **np, struct rib **rib)
306 struct route_table *table;
307 struct route_node *np2;
311 struct in_addr nexthop;
315 /* Init index variables */
317 pnt = (u_char *) &dest;
318 for (i = 0; i < 4; i++)
321 pnt = (u_char *) &nexthop;
322 for (i = 0; i < 4; i++)
328 /* Init return variables */
333 /* Short circuit exact matches of wrong length */
335 if (exact && (*objid_len != (unsigned) v->namelen + 10))
338 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
342 /* Get INDEX information out of OID.
343 * ipForwardDest, ipForwardProto, ipForwardPolicy, ipForwardNextHop
346 if (*objid_len > (unsigned) v->namelen)
347 oid2in_addr (objid + v->namelen, MIN(4, *objid_len - v->namelen), &dest);
349 if (*objid_len > (unsigned) v->namelen + 4)
350 proto = objid[v->namelen + 4];
352 if (*objid_len > (unsigned) v->namelen + 5)
353 policy = objid[v->namelen + 5];
355 if (*objid_len > (unsigned) v->namelen + 6)
356 oid2in_addr (objid + v->namelen + 6, MIN(4, *objid_len - v->namelen - 6),
359 /* Apply GETNEXT on not exact search */
361 if (!exact && (*objid_len >= (unsigned) v->namelen + 10))
363 if (! in_addr_add((u_char *) &nexthop, 1))
367 /* For exact: search matching entry in rib table. */
371 if (policy) /* Not supported (yet?) */
373 for (*np = route_top (table); *np; *np = route_next (*np))
375 if (!in_addr_cmp(&(*np)->p.u.prefix, (u_char *)&dest))
377 RNODE_FOREACH_RIB (*np, *rib)
379 if (!in_addr_cmp((u_char *)&(*rib)->nexthop->gate.ipv4,
381 if (proto == proto_trans((*rib)->type))
389 /* Search next best entry */
391 for (np2 = route_top (table); np2; np2 = route_next (np2))
394 /* Check destination first */
395 if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) > 0)
396 RNODE_FOREACH_RIB (np2, rib2)
397 check_replace(np2, rib2, np, rib);
399 if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) == 0)
400 { /* have to look at each rib individually */
401 RNODE_FOREACH_RIB (np2, rib2)
405 proto2 = proto_trans(rib2->type);
408 if ((policy < policy2)
409 || ((policy == policy2) && (proto < proto2))
410 || ((policy == policy2) && (proto == proto2)
411 && (in_addr_cmp((u_char *)&rib2->nexthop->gate.ipv4,
412 (u_char *) &nexthop) >= 0)
414 check_replace(np2, rib2, np, rib);
423 proto = proto_trans((*rib)->type);
425 *objid_len = v->namelen + 10;
426 pnt = (u_char *) &(*np)->p.u.prefix;
427 for (i = 0; i < 4; i++)
428 objid[v->namelen + i] = *pnt++;
430 objid[v->namelen + 4] = proto;
431 objid[v->namelen + 5] = policy;
434 struct nexthop *nexthop;
436 nexthop = (*rib)->nexthop;
439 pnt = (u_char *) &nexthop->gate.ipv4;
440 for (i = 0; i < 4; i++)
441 objid[i + v->namelen + 6] = *pnt++;
449 ipFwTable (struct variable *v, oid objid[], size_t *objid_len,
450 int exact, size_t *val_len, WriteMethod **write_method)
452 struct route_node *np;
455 static int resarr[2];
456 static struct in_addr netmask;
457 struct nexthop *nexthop;
459 if (smux_header_table(v, objid, objid_len, exact, val_len, write_method)
463 get_fwtable_route_node(v, objid, objid_len, exact, &np, &rib);
467 nexthop = rib->nexthop;
475 return &np->p.u.prefix;
478 masklen2ip(np->p.prefixlen, &netmask);
480 return (u_char *)&netmask;
482 case IPFORWARDPOLICY:
484 *val_len = sizeof(int);
485 return (u_char *)&result;
487 case IPFORWARDNEXTHOP:
489 return (u_char *)&nexthop->gate.ipv4;
491 case IPFORWARDIFINDEX:
492 *val_len = sizeof(int);
493 return (u_char *)&nexthop->ifindex;
496 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
497 || nexthop->type == NEXTHOP_TYPE_IFNAME)
501 *val_len = sizeof(int);
502 return (u_char *)&result;
505 result = proto_trans(rib->type);
506 *val_len = sizeof(int);
507 return (u_char *)&result;
511 *val_len = sizeof(int);
512 return (u_char *)&result;
517 *val_len = 2 * sizeof(int);
518 return (u_char *)resarr;
520 case IPFORWARDNEXTHOPAS:
522 *val_len = sizeof(int);
523 return (u_char *)&result;
525 case IPFORWARDMETRIC1:
527 *val_len = sizeof(int);
528 return (u_char *)&result;
530 case IPFORWARDMETRIC2:
532 *val_len = sizeof(int);
533 return (u_char *)&result;
535 case IPFORWARDMETRIC3:
537 *val_len = sizeof(int);
538 return (u_char *)&result;
540 case IPFORWARDMETRIC4:
542 *val_len = sizeof(int);
543 return (u_char *)&result;
545 case IPFORWARDMETRIC5:
547 *val_len = sizeof(int);
548 return (u_char *)&result;
558 ipCidrTable (struct variable *v, oid objid[], size_t *objid_len,
559 int exact, size_t *val_len, WriteMethod **write_method)
561 if (smux_header_table(v, objid, objid_len, exact, val_len, write_method)
567 case IPCIDRROUTEDEST:
579 smux_init (zebrad.master);
580 REGISTER_MIB("mibII/ipforward", zebra_variables, variable, ipfw_oid);
582 #endif /* HAVE_SNMP */