blob: 051aaaa7447b85b272893c948d7a70dc30c0531b [file] [log] [blame]
paul07661cb2003-03-18 00:03:05 +00001/* FIB SNMP.
paul718e3742002-12-13 20:15:29 +00002 * 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
paul07661cb2003-03-18 00:03:05 +000025#ifdef HAVE_NETSNMP
26#include <net-snmp/net-snmp-config.h>
27#endif
paul718e3742002-12-13 20:15:29 +000028#include <asn1.h>
29#include <snmp.h>
30#include <snmp_impl.h>
31
32#include "if.h"
33#include "log.h"
34#include "prefix.h"
35#include "command.h"
36#include "smux.h"
37#include "table.h"
38
39#include "zebra/rib.h"
40
41#define IPFWMIB 1,3,6,1,2,1,4,24
42#define ZEBRAOID 1,3,6,1,4,1,3317,1,2,1
43
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
60
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
78
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
85
86oid ipfw_oid [] = { IPFWMIB };
87oid zebra_oid [] = { ZEBRAOID };
88
89/* Hook functions. */
90u_char * ipFwNumber ();
91u_char * ipFwTable ();
92u_char * ipCidrNumber ();
93u_char * ipCidrTable ();
94
95struct variable zebra_variables[] =
paul07661cb2003-03-18 00:03:05 +000096 {
97 {0, GAUGE32, RONLY, ipFwNumber, 1, {1}},
98 {IPFORWARDDEST, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 1}},
99 {IPFORWARDMASK, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 2}},
100 {IPFORWARDPOLICY, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 3}},
101 {IPFORWARDNEXTHOP, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 4}},
102 {IPFORWARDIFINDEX, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 5}},
103 {IPFORWARDTYPE, ENUMERATION, RONLY, ipFwTable, 3, {2, 1, 6}},
104 {IPFORWARDPROTO, ENUMERATION, RONLY, ipFwTable, 3, {2, 1, 7}},
105 {IPFORWARDAGE, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 8}},
106 {IPFORWARDINFO, OBJECTIDENTIFIER, RONLY, ipFwTable, 3, {2, 1, 9}},
107 {IPFORWARDNEXTHOPAS, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 10}},
108 {IPFORWARDMETRIC1, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 11}},
109 {IPFORWARDMETRIC2, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 12}},
110 {IPFORWARDMETRIC3, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 13}},
111 {IPFORWARDMETRIC4, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 14}},
112 {IPFORWARDMETRIC5, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 15}},
113 {0, GAUGE32, RONLY, ipCidrNumber, 1, {3}},
114 {IPCIDRROUTEDEST, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 1}},
115 {IPCIDRROUTEMASK, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 2}},
116 {IPCIDRROUTETOS, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 3}},
117 {IPCIDRROUTENEXTHOP, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 4}},
118 {IPCIDRROUTEIFINDEX, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 5}},
119 {IPCIDRROUTETYPE, ENUMERATION, RONLY, ipCidrTable, 3, {4, 1, 6}},
120 {IPCIDRROUTEPROTO, ENUMERATION, RONLY, ipCidrTable, 3, {4, 1, 7}},
121 {IPCIDRROUTEAGE, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 8}},
122 {IPCIDRROUTEINFO, OBJECTIDENTIFIER, RONLY, ipCidrTable, 3, {4, 1, 9}},
123 {IPCIDRROUTENEXTHOPAS, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 10}},
124 {IPCIDRROUTEMETRIC1, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 11}},
125 {IPCIDRROUTEMETRIC2, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 12}},
126 {IPCIDRROUTEMETRIC3, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 13}},
127 {IPCIDRROUTEMETRIC4, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 14}},
128 {IPCIDRROUTEMETRIC5, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 15}},
129 {IPCIDRROUTESTATUS, ROWSTATUS, RONLY, ipCidrTable, 3, {4, 1, 16}}
130 };
paul718e3742002-12-13 20:15:29 +0000131
132
133u_char *
134ipFwNumber (struct variable *v, oid objid[], size_t *objid_len,
135 int exact, size_t *val_len, WriteMethod **write_method)
136{
137 static int result;
paul07661cb2003-03-18 00:03:05 +0000138 struct route_table *table;
139 struct route_node *rn;
paul718e3742002-12-13 20:15:29 +0000140 struct rib *rib;
141
142 if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED)
143 return NULL;
144
paul07661cb2003-03-18 00:03:05 +0000145 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
146 if (! table)
147 return NULL;
148
paul718e3742002-12-13 20:15:29 +0000149 /* Return number of routing entries. */
150 result = 0;
paul07661cb2003-03-18 00:03:05 +0000151 for (rn = route_top (table); rn; rn = route_next (rn))
152 for (rib = rn->info; rib; rib = rib->next)
paul718e3742002-12-13 20:15:29 +0000153 result++;
154
155 return (u_char *)&result;
156}
157
158u_char *
159ipCidrNumber (struct variable *v, oid objid[], size_t *objid_len,
paul07661cb2003-03-18 00:03:05 +0000160 int exact, size_t *val_len, WriteMethod **write_method)
paul718e3742002-12-13 20:15:29 +0000161{
162 static int result;
paul07661cb2003-03-18 00:03:05 +0000163 struct route_table *table;
164 struct route_node *rn;
paul718e3742002-12-13 20:15:29 +0000165 struct rib *rib;
166
167 if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED)
168 return NULL;
169
paul07661cb2003-03-18 00:03:05 +0000170 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
171 if (! table)
172 return 0;
173
paul718e3742002-12-13 20:15:29 +0000174 /* Return number of routing entries. */
175 result = 0;
paul07661cb2003-03-18 00:03:05 +0000176 for (rn = route_top (table); rn; rn = route_next (rn))
177 for (rib = rn->info; rib; rib = rib->next)
paul718e3742002-12-13 20:15:29 +0000178 result++;
179
180 return (u_char *)&result;
181}
182
183int
184in_addr_cmp(u_char *p1, u_char *p2)
185{
186 int i;
187
188 for (i=0; i<4; i++)
189 {
190 if (*p1 < *p2)
191 return -1;
192 if (*p1 > *p2)
193 return 1;
194 p1++; p2++;
195 }
196 return 0;
197}
198
199int
200in_addr_add(u_char *p, int num)
201{
202 int i, ip0;
203
204 ip0 = *p;
205 p += 4;
206 for (i = 3; 0 <= i; i--) {
207 p--;
208 if (*p + num > 255) {
paul07661cb2003-03-18 00:03:05 +0000209 *p += num;
210 num = 1;
paul718e3742002-12-13 20:15:29 +0000211 } else {
paul07661cb2003-03-18 00:03:05 +0000212 *p += num;
213 return 1;
paul718e3742002-12-13 20:15:29 +0000214 }
215 }
216 if (ip0 > *p) {
paul07661cb2003-03-18 00:03:05 +0000217 /* ip + num > 0xffffffff */
218 return 0;
paul718e3742002-12-13 20:15:29 +0000219 }
220
221 return 1;
222}
223
224int proto_trans(int type)
225{
226 switch (type)
227 {
paul07661cb2003-03-18 00:03:05 +0000228 case ZEBRA_ROUTE_SYSTEM:
229 return 1; /* other */
230 case ZEBRA_ROUTE_KERNEL:
231 return 1; /* other */
232 case ZEBRA_ROUTE_CONNECT:
233 return 2; /* local interface */
234 case ZEBRA_ROUTE_STATIC:
235 return 3; /* static route */
236 case ZEBRA_ROUTE_RIP:
237 return 8; /* rip */
238 case ZEBRA_ROUTE_RIPNG:
239 return 1; /* shouldn't happen */
240 case ZEBRA_ROUTE_OSPF:
241 return 13; /* ospf */
242 case ZEBRA_ROUTE_OSPF6:
243 return 1; /* shouldn't happen */
244 case ZEBRA_ROUTE_BGP:
245 return 14; /* bgp */
246 default:
247 return 1; /* other */
paul718e3742002-12-13 20:15:29 +0000248 }
249}
250
251void
252check_replace(struct route_node *np2, struct rib *rib2,
253 struct route_node **np, struct rib **rib)
254{
255 int proto, proto2;
256
257 if (!*np)
258 {
259 *np = np2;
260 *rib = rib2;
261 return;
262 }
263
264 if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) < 0)
265 return;
266 if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) > 0)
267 {
268 *np = np2;
269 *rib = rib2;
270 return;
271 }
272
273 proto = proto_trans((*rib)->type);
274 proto2 = proto_trans(rib2->type);
275
276 if (proto2 > proto)
277 return;
278 if (proto2 < proto)
279 {
280 *np = np2;
281 *rib = rib2;
282 return;
283 }
284
285 if (in_addr_cmp((u_char *)&(*rib)->nexthop->gate.ipv4,
286 (u_char *)&rib2->nexthop->gate.ipv4) <= 0)
287 return;
288
289 *np = np2;
290 *rib = rib2;
291 return;
292}
293
294void
295get_fwtable_route_node(struct variable *v, oid objid[], size_t *objid_len,
296 int exact, struct route_node **np, struct rib **rib)
297{
298 struct in_addr dest;
paul07661cb2003-03-18 00:03:05 +0000299 struct route_table *table;
paul718e3742002-12-13 20:15:29 +0000300 struct route_node *np2;
301 struct rib *rib2;
302 int proto;
303 int policy;
304 struct in_addr nexthop;
305 u_char *pnt;
306 int i;
307
paul07661cb2003-03-18 00:03:05 +0000308 /* Init index variables */
paul718e3742002-12-13 20:15:29 +0000309
310 pnt = (u_char *) &dest;
311 for (i = 0; i < 4; i++)
312 *pnt++ = 0;
313
314 pnt = (u_char *) &nexthop;
315 for (i = 0; i < 4; i++)
316 *pnt++ = 0;
317
318 proto = 0;
319 policy = 0;
320
paul07661cb2003-03-18 00:03:05 +0000321 /* Init return variables */
paul718e3742002-12-13 20:15:29 +0000322
323 *np = NULL;
324 *rib = NULL;
325
paul07661cb2003-03-18 00:03:05 +0000326 /* Short circuit exact matches of wrong length */
paul718e3742002-12-13 20:15:29 +0000327
328 if (exact && (*objid_len != v->namelen + 10))
329 return;
330
paul07661cb2003-03-18 00:03:05 +0000331 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
332 if (! table)
333 return;
334
335 /* Get INDEX information out of OID.
336 * ipForwardDest, ipForwardProto, ipForwardPolicy, ipForwardNextHop
337 */
paul718e3742002-12-13 20:15:29 +0000338
339 if (*objid_len > v->namelen)
340 oid2in_addr (objid + v->namelen, MIN(4, *objid_len - v->namelen), &dest);
341
342 if (*objid_len > v->namelen + 4)
343 proto = objid[v->namelen + 4];
344
345 if (*objid_len > v->namelen + 5)
346 policy = objid[v->namelen + 5];
347
348 if (*objid_len > v->namelen + 6)
349 oid2in_addr (objid + v->namelen + 6, MIN(4, *objid_len - v->namelen - 6),
paul07661cb2003-03-18 00:03:05 +0000350 &nexthop);
paul718e3742002-12-13 20:15:29 +0000351
352 /* Apply GETNEXT on not exact search */
353
354 if (!exact && (*objid_len >= v->namelen + 10))
355 {
356 if (! in_addr_add((u_char *) &nexthop, 1))
357 return;
358 }
359
360 /* For exact: search matching entry in rib table. */
361
362 if (exact)
363 {
364 if (policy) /* Not supported (yet?) */
365 return;
paul07661cb2003-03-18 00:03:05 +0000366 for (*np = route_top (table); *np; *np = route_next (*np))
paul718e3742002-12-13 20:15:29 +0000367 {
368 if (!in_addr_cmp(&(*np)->p.u.prefix, (u_char *)&dest))
369 {
370 for (*rib = (*np)->info; *rib; *rib = (*rib)->next)
371 {
372 if (!in_addr_cmp((u_char *)&(*rib)->nexthop->gate.ipv4,
paul07661cb2003-03-18 00:03:05 +0000373 (u_char *)&nexthop))
paul718e3742002-12-13 20:15:29 +0000374 if (proto == proto_trans((*rib)->type))
375 return;
376 }
377 }
378 }
379 return;
380 }
381
paul07661cb2003-03-18 00:03:05 +0000382 /* Search next best entry */
paul718e3742002-12-13 20:15:29 +0000383
paul07661cb2003-03-18 00:03:05 +0000384 for (np2 = route_top (table); np2; np2 = route_next (np2))
paul718e3742002-12-13 20:15:29 +0000385 {
386
387 /* Check destination first */
388 if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) > 0)
389 for (rib2 = np2->info; rib2; rib2 = rib2->next)
390 check_replace(np2, rib2, np, rib);
391
392 if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) == 0)
393 { /* have to look at each rib individually */
394 for (rib2 = np2->info; rib2; rib2 = rib2->next)
395 {
396 int proto2, policy2;
397
398 proto2 = proto_trans(rib2->type);
399 policy2 = 0;
400
401 if ((policy < policy2)
402 || ((policy == policy2) && (proto < proto2))
403 || ((policy == policy2) && (proto == proto2)
404 && (in_addr_cmp((u_char *)&rib2->nexthop->gate.ipv4,
405 (u_char *) &nexthop) >= 0)
406 ))
407 check_replace(np2, rib2, np, rib);
408 }
409 }
410 }
411
412 if (!*rib)
413 return;
414
415 policy = 0;
416 proto = proto_trans((*rib)->type);
417
418 *objid_len = v->namelen + 10;
419 pnt = (u_char *) &(*np)->p.u.prefix;
420 for (i = 0; i < 4; i++)
421 objid[v->namelen + i] = *pnt++;
422
423 objid[v->namelen + 4] = proto;
424 objid[v->namelen + 5] = policy;
425
426 {
427 struct nexthop *nexthop;
428
429 nexthop = (*rib)->nexthop;
430 if (nexthop)
431 {
432 pnt = (u_char *) &nexthop->gate.ipv4;
433 for (i = 0; i < 4; i++)
434 objid[i + v->namelen + 6] = *pnt++;
435 }
436 }
437
438 return;
439}
440
441u_char *
442ipFwTable (struct variable *v, oid objid[], size_t *objid_len,
443 int exact, size_t *val_len, WriteMethod **write_method)
444{
445 struct route_node *np;
446 struct rib *rib;
447 static int result;
448 static int resarr[2];
449 static struct in_addr netmask;
450 struct nexthop *nexthop;
451
452 get_fwtable_route_node(v, objid, objid_len, exact, &np, &rib);
453 if (!np)
454 return NULL;
455
456 nexthop = rib->nexthop;
457 if (! nexthop)
458 return NULL;
459
460 switch (v->magic)
461 {
462 case IPFORWARDDEST:
463 *val_len = 4;
464 return &np->p.u.prefix;
465 break;
466 case IPFORWARDMASK:
467 masklen2ip(np->p.prefixlen, &netmask);
468 *val_len = 4;
469 return (u_char *)&netmask;
470 break;
471 case IPFORWARDPOLICY:
472 result = 0;
473 *val_len = sizeof(int);
474 return (u_char *)&result;
475 break;
476 case IPFORWARDNEXTHOP:
477 *val_len = 4;
478 return (u_char *)&nexthop->gate.ipv4;
479 break;
480 case IPFORWARDIFINDEX:
481 *val_len = sizeof(int);
482 return (u_char *)&nexthop->ifindex;
483 break;
484 case IPFORWARDTYPE:
485 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
486 || nexthop->type == NEXTHOP_TYPE_IFNAME)
487 result = 3;
488 else
489 result = 4;
490 *val_len = sizeof(int);
491 return (u_char *)&result;
492 break;
493 case IPFORWARDPROTO:
494 result = proto_trans(rib->type);
495 *val_len = sizeof(int);
496 return (u_char *)&result;
497 break;
498 case IPFORWARDAGE:
499 result = 0;
500 *val_len = sizeof(int);
501 return (u_char *)&result;
502 break;
503 case IPFORWARDINFO:
504 resarr[0] = 0;
505 resarr[1] = 0;
506 *val_len = 2 * sizeof(int);
507 return (u_char *)resarr;
508 break;
509 case IPFORWARDNEXTHOPAS:
510 result = -1;
511 *val_len = sizeof(int);
512 return (u_char *)&result;
513 break;
514 case IPFORWARDMETRIC1:
515 result = 0;
516 *val_len = sizeof(int);
517 return (u_char *)&result;
518 break;
519 case IPFORWARDMETRIC2:
520 result = 0;
521 *val_len = sizeof(int);
522 return (u_char *)&result;
523 break;
524 case IPFORWARDMETRIC3:
525 result = 0;
526 *val_len = sizeof(int);
527 return (u_char *)&result;
528 break;
529 case IPFORWARDMETRIC4:
530 result = 0;
531 *val_len = sizeof(int);
532 return (u_char *)&result;
533 break;
534 case IPFORWARDMETRIC5:
535 result = 0;
536 *val_len = sizeof(int);
537 return (u_char *)&result;
538 break;
539 default:
540 return NULL;
541 break;
542 }
543 return NULL;
544}
545
546u_char *
547ipCidrTable (struct variable *v, oid objid[], size_t *objid_len,
paul07661cb2003-03-18 00:03:05 +0000548 int exact, size_t *val_len, WriteMethod **write_method)
paul718e3742002-12-13 20:15:29 +0000549{
550 switch (v->magic)
551 {
552 case IPCIDRROUTEDEST:
553 break;
554 default:
555 return NULL;
556 break;
557 }
558 return NULL;
559}
560
561void
562zebra_snmp_init ()
563{
564 smux_init (zebra_oid, sizeof (zebra_oid) / sizeof (oid));
565 REGISTER_MIB("mibII/ipforward", zebra_variables, variable, ipfw_oid);
566 smux_start ();
567}
568#endif /* HAVE_SNMP */