blob: 7e66e2f67787e7db641021dde68654375b407e59 [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>
Joakim Tjernlundfb62a3c2008-05-13 20:03:32 +020027#include <net-snmp/net-snmp-includes.h>
28#else
paul718e3742002-12-13 20:15:29 +000029#include <asn1.h>
30#include <snmp.h>
31#include <snmp_impl.h>
Joakim Tjernlundfb62a3c2008-05-13 20:03:32 +020032#endif
paul718e3742002-12-13 20:15:29 +000033
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"
pauldd488a72003-06-19 01:21:07 +000042#include "zebra/zserv.h"
paul718e3742002-12-13 20:15:29 +000043
44#define IPFWMIB 1,3,6,1,2,1,4,24
paul718e3742002-12-13 20:15:29 +000045
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
pauldd488a72003-06-19 01:21:07 +000088extern struct zebra_t zebrad;
89
paul718e3742002-12-13 20:15:29 +000090oid ipfw_oid [] = { IPFWMIB };
paul718e3742002-12-13 20:15:29 +000091
92/* Hook functions. */
93u_char * ipFwNumber ();
94u_char * ipFwTable ();
95u_char * ipCidrNumber ();
96u_char * ipCidrTable ();
97
98struct variable zebra_variables[] =
paul07661cb2003-03-18 00:03:05 +000099 {
100 {0, GAUGE32, RONLY, ipFwNumber, 1, {1}},
101 {IPFORWARDDEST, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 1}},
102 {IPFORWARDMASK, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 2}},
103 {IPFORWARDPOLICY, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 3}},
104 {IPFORWARDNEXTHOP, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 4}},
105 {IPFORWARDIFINDEX, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 5}},
106 {IPFORWARDTYPE, ENUMERATION, RONLY, ipFwTable, 3, {2, 1, 6}},
107 {IPFORWARDPROTO, ENUMERATION, RONLY, ipFwTable, 3, {2, 1, 7}},
108 {IPFORWARDAGE, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 8}},
109 {IPFORWARDINFO, OBJECTIDENTIFIER, RONLY, ipFwTable, 3, {2, 1, 9}},
110 {IPFORWARDNEXTHOPAS, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 10}},
111 {IPFORWARDMETRIC1, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 11}},
112 {IPFORWARDMETRIC2, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 12}},
113 {IPFORWARDMETRIC3, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 13}},
114 {IPFORWARDMETRIC4, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 14}},
115 {IPFORWARDMETRIC5, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 15}},
116 {0, GAUGE32, RONLY, ipCidrNumber, 1, {3}},
117 {IPCIDRROUTEDEST, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 1}},
118 {IPCIDRROUTEMASK, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 2}},
119 {IPCIDRROUTETOS, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 3}},
120 {IPCIDRROUTENEXTHOP, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 4}},
121 {IPCIDRROUTEIFINDEX, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 5}},
122 {IPCIDRROUTETYPE, ENUMERATION, RONLY, ipCidrTable, 3, {4, 1, 6}},
123 {IPCIDRROUTEPROTO, ENUMERATION, RONLY, ipCidrTable, 3, {4, 1, 7}},
124 {IPCIDRROUTEAGE, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 8}},
125 {IPCIDRROUTEINFO, OBJECTIDENTIFIER, RONLY, ipCidrTable, 3, {4, 1, 9}},
126 {IPCIDRROUTENEXTHOPAS, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 10}},
127 {IPCIDRROUTEMETRIC1, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 11}},
128 {IPCIDRROUTEMETRIC2, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 12}},
129 {IPCIDRROUTEMETRIC3, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 13}},
130 {IPCIDRROUTEMETRIC4, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 14}},
131 {IPCIDRROUTEMETRIC5, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 15}},
132 {IPCIDRROUTESTATUS, ROWSTATUS, RONLY, ipCidrTable, 3, {4, 1, 16}}
133 };
paul718e3742002-12-13 20:15:29 +0000134
135
136u_char *
137ipFwNumber (struct variable *v, oid objid[], size_t *objid_len,
138 int exact, size_t *val_len, WriteMethod **write_method)
139{
140 static int result;
paul07661cb2003-03-18 00:03:05 +0000141 struct route_table *table;
142 struct route_node *rn;
paul718e3742002-12-13 20:15:29 +0000143 struct rib *rib;
144
145 if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED)
146 return NULL;
147
paul07661cb2003-03-18 00:03:05 +0000148 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
149 if (! table)
150 return NULL;
151
paul718e3742002-12-13 20:15:29 +0000152 /* Return number of routing entries. */
153 result = 0;
paul07661cb2003-03-18 00:03:05 +0000154 for (rn = route_top (table); rn; rn = route_next (rn))
155 for (rib = rn->info; rib; rib = rib->next)
paul718e3742002-12-13 20:15:29 +0000156 result++;
157
158 return (u_char *)&result;
159}
160
161u_char *
162ipCidrNumber (struct variable *v, oid objid[], size_t *objid_len,
paul07661cb2003-03-18 00:03:05 +0000163 int exact, size_t *val_len, WriteMethod **write_method)
paul718e3742002-12-13 20:15:29 +0000164{
165 static int result;
paul07661cb2003-03-18 00:03:05 +0000166 struct route_table *table;
167 struct route_node *rn;
paul718e3742002-12-13 20:15:29 +0000168 struct rib *rib;
169
170 if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED)
171 return NULL;
172
paul07661cb2003-03-18 00:03:05 +0000173 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
174 if (! table)
175 return 0;
176
paul718e3742002-12-13 20:15:29 +0000177 /* Return number of routing entries. */
178 result = 0;
paul07661cb2003-03-18 00:03:05 +0000179 for (rn = route_top (table); rn; rn = route_next (rn))
180 for (rib = rn->info; rib; rib = rib->next)
paul718e3742002-12-13 20:15:29 +0000181 result++;
182
183 return (u_char *)&result;
184}
185
186int
187in_addr_cmp(u_char *p1, u_char *p2)
188{
189 int i;
190
191 for (i=0; i<4; i++)
192 {
193 if (*p1 < *p2)
194 return -1;
195 if (*p1 > *p2)
196 return 1;
197 p1++; p2++;
198 }
199 return 0;
200}
201
202int
203in_addr_add(u_char *p, int num)
204{
205 int i, ip0;
206
207 ip0 = *p;
208 p += 4;
209 for (i = 3; 0 <= i; i--) {
210 p--;
211 if (*p + num > 255) {
paul07661cb2003-03-18 00:03:05 +0000212 *p += num;
213 num = 1;
paul718e3742002-12-13 20:15:29 +0000214 } else {
paul07661cb2003-03-18 00:03:05 +0000215 *p += num;
216 return 1;
paul718e3742002-12-13 20:15:29 +0000217 }
218 }
219 if (ip0 > *p) {
paul07661cb2003-03-18 00:03:05 +0000220 /* ip + num > 0xffffffff */
221 return 0;
paul718e3742002-12-13 20:15:29 +0000222 }
223
224 return 1;
225}
226
227int proto_trans(int type)
228{
229 switch (type)
230 {
paul07661cb2003-03-18 00:03:05 +0000231 case ZEBRA_ROUTE_SYSTEM:
232 return 1; /* other */
233 case ZEBRA_ROUTE_KERNEL:
234 return 1; /* other */
235 case ZEBRA_ROUTE_CONNECT:
236 return 2; /* local interface */
237 case ZEBRA_ROUTE_STATIC:
238 return 3; /* static route */
239 case ZEBRA_ROUTE_RIP:
240 return 8; /* rip */
241 case ZEBRA_ROUTE_RIPNG:
242 return 1; /* shouldn't happen */
243 case ZEBRA_ROUTE_OSPF:
244 return 13; /* ospf */
245 case ZEBRA_ROUTE_OSPF6:
246 return 1; /* shouldn't happen */
247 case ZEBRA_ROUTE_BGP:
248 return 14; /* bgp */
249 default:
250 return 1; /* other */
paul718e3742002-12-13 20:15:29 +0000251 }
252}
253
254void
255check_replace(struct route_node *np2, struct rib *rib2,
256 struct route_node **np, struct rib **rib)
257{
258 int proto, proto2;
259
260 if (!*np)
261 {
262 *np = np2;
263 *rib = rib2;
264 return;
265 }
266
267 if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) < 0)
268 return;
269 if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) > 0)
270 {
271 *np = np2;
272 *rib = rib2;
273 return;
274 }
275
276 proto = proto_trans((*rib)->type);
277 proto2 = proto_trans(rib2->type);
278
279 if (proto2 > proto)
280 return;
281 if (proto2 < proto)
282 {
283 *np = np2;
284 *rib = rib2;
285 return;
286 }
287
288 if (in_addr_cmp((u_char *)&(*rib)->nexthop->gate.ipv4,
289 (u_char *)&rib2->nexthop->gate.ipv4) <= 0)
290 return;
291
292 *np = np2;
293 *rib = rib2;
294 return;
295}
296
297void
298get_fwtable_route_node(struct variable *v, oid objid[], size_t *objid_len,
299 int exact, struct route_node **np, struct rib **rib)
300{
301 struct in_addr dest;
paul07661cb2003-03-18 00:03:05 +0000302 struct route_table *table;
paul718e3742002-12-13 20:15:29 +0000303 struct route_node *np2;
304 struct rib *rib2;
305 int proto;
306 int policy;
307 struct in_addr nexthop;
308 u_char *pnt;
309 int i;
310
paul07661cb2003-03-18 00:03:05 +0000311 /* Init index variables */
paul718e3742002-12-13 20:15:29 +0000312
313 pnt = (u_char *) &dest;
314 for (i = 0; i < 4; i++)
315 *pnt++ = 0;
316
317 pnt = (u_char *) &nexthop;
318 for (i = 0; i < 4; i++)
319 *pnt++ = 0;
320
321 proto = 0;
322 policy = 0;
323
paul07661cb2003-03-18 00:03:05 +0000324 /* Init return variables */
paul718e3742002-12-13 20:15:29 +0000325
326 *np = NULL;
327 *rib = NULL;
328
paul07661cb2003-03-18 00:03:05 +0000329 /* Short circuit exact matches of wrong length */
paul718e3742002-12-13 20:15:29 +0000330
hasso39db97e2004-10-12 20:50:58 +0000331 if (exact && (*objid_len != (unsigned) v->namelen + 10))
paul718e3742002-12-13 20:15:29 +0000332 return;
333
paul07661cb2003-03-18 00:03:05 +0000334 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
335 if (! table)
336 return;
337
338 /* Get INDEX information out of OID.
339 * ipForwardDest, ipForwardProto, ipForwardPolicy, ipForwardNextHop
340 */
paul718e3742002-12-13 20:15:29 +0000341
342 if (*objid_len > v->namelen)
343 oid2in_addr (objid + v->namelen, MIN(4, *objid_len - v->namelen), &dest);
344
hasso39db97e2004-10-12 20:50:58 +0000345 if (*objid_len > (unsigned) v->namelen + 4)
paul718e3742002-12-13 20:15:29 +0000346 proto = objid[v->namelen + 4];
347
hasso39db97e2004-10-12 20:50:58 +0000348 if (*objid_len > (unsigned) v->namelen + 5)
paul718e3742002-12-13 20:15:29 +0000349 policy = objid[v->namelen + 5];
350
hasso39db97e2004-10-12 20:50:58 +0000351 if (*objid_len > (unsigned) v->namelen + 6)
paul718e3742002-12-13 20:15:29 +0000352 oid2in_addr (objid + v->namelen + 6, MIN(4, *objid_len - v->namelen - 6),
paul07661cb2003-03-18 00:03:05 +0000353 &nexthop);
paul718e3742002-12-13 20:15:29 +0000354
355 /* Apply GETNEXT on not exact search */
356
hasso39db97e2004-10-12 20:50:58 +0000357 if (!exact && (*objid_len >= (unsigned) v->namelen + 10))
paul718e3742002-12-13 20:15:29 +0000358 {
359 if (! in_addr_add((u_char *) &nexthop, 1))
360 return;
361 }
362
363 /* For exact: search matching entry in rib table. */
364
365 if (exact)
366 {
367 if (policy) /* Not supported (yet?) */
368 return;
paul07661cb2003-03-18 00:03:05 +0000369 for (*np = route_top (table); *np; *np = route_next (*np))
paul718e3742002-12-13 20:15:29 +0000370 {
371 if (!in_addr_cmp(&(*np)->p.u.prefix, (u_char *)&dest))
372 {
373 for (*rib = (*np)->info; *rib; *rib = (*rib)->next)
374 {
375 if (!in_addr_cmp((u_char *)&(*rib)->nexthop->gate.ipv4,
paul07661cb2003-03-18 00:03:05 +0000376 (u_char *)&nexthop))
paul718e3742002-12-13 20:15:29 +0000377 if (proto == proto_trans((*rib)->type))
378 return;
379 }
380 }
381 }
382 return;
383 }
384
paul07661cb2003-03-18 00:03:05 +0000385 /* Search next best entry */
paul718e3742002-12-13 20:15:29 +0000386
paul07661cb2003-03-18 00:03:05 +0000387 for (np2 = route_top (table); np2; np2 = route_next (np2))
paul718e3742002-12-13 20:15:29 +0000388 {
389
390 /* Check destination first */
391 if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) > 0)
392 for (rib2 = np2->info; rib2; rib2 = rib2->next)
393 check_replace(np2, rib2, np, rib);
394
395 if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) == 0)
396 { /* have to look at each rib individually */
397 for (rib2 = np2->info; rib2; rib2 = rib2->next)
398 {
399 int proto2, policy2;
400
401 proto2 = proto_trans(rib2->type);
402 policy2 = 0;
403
404 if ((policy < policy2)
405 || ((policy == policy2) && (proto < proto2))
406 || ((policy == policy2) && (proto == proto2)
407 && (in_addr_cmp((u_char *)&rib2->nexthop->gate.ipv4,
408 (u_char *) &nexthop) >= 0)
409 ))
410 check_replace(np2, rib2, np, rib);
411 }
412 }
413 }
414
415 if (!*rib)
416 return;
417
418 policy = 0;
419 proto = proto_trans((*rib)->type);
420
421 *objid_len = v->namelen + 10;
422 pnt = (u_char *) &(*np)->p.u.prefix;
423 for (i = 0; i < 4; i++)
424 objid[v->namelen + i] = *pnt++;
425
426 objid[v->namelen + 4] = proto;
427 objid[v->namelen + 5] = policy;
428
429 {
430 struct nexthop *nexthop;
431
432 nexthop = (*rib)->nexthop;
433 if (nexthop)
434 {
435 pnt = (u_char *) &nexthop->gate.ipv4;
436 for (i = 0; i < 4; i++)
437 objid[i + v->namelen + 6] = *pnt++;
438 }
439 }
440
441 return;
442}
443
444u_char *
445ipFwTable (struct variable *v, oid objid[], size_t *objid_len,
446 int exact, size_t *val_len, WriteMethod **write_method)
447{
448 struct route_node *np;
449 struct rib *rib;
450 static int result;
451 static int resarr[2];
452 static struct in_addr netmask;
453 struct nexthop *nexthop;
454
455 get_fwtable_route_node(v, objid, objid_len, exact, &np, &rib);
456 if (!np)
457 return NULL;
458
459 nexthop = rib->nexthop;
460 if (! nexthop)
461 return NULL;
462
463 switch (v->magic)
464 {
465 case IPFORWARDDEST:
466 *val_len = 4;
467 return &np->p.u.prefix;
468 break;
469 case IPFORWARDMASK:
470 masklen2ip(np->p.prefixlen, &netmask);
471 *val_len = 4;
472 return (u_char *)&netmask;
473 break;
474 case IPFORWARDPOLICY:
475 result = 0;
476 *val_len = sizeof(int);
477 return (u_char *)&result;
478 break;
479 case IPFORWARDNEXTHOP:
480 *val_len = 4;
481 return (u_char *)&nexthop->gate.ipv4;
482 break;
483 case IPFORWARDIFINDEX:
484 *val_len = sizeof(int);
485 return (u_char *)&nexthop->ifindex;
486 break;
487 case IPFORWARDTYPE:
488 if (nexthop->type == NEXTHOP_TYPE_IFINDEX
489 || nexthop->type == NEXTHOP_TYPE_IFNAME)
490 result = 3;
491 else
492 result = 4;
493 *val_len = sizeof(int);
494 return (u_char *)&result;
495 break;
496 case IPFORWARDPROTO:
497 result = proto_trans(rib->type);
498 *val_len = sizeof(int);
499 return (u_char *)&result;
500 break;
501 case IPFORWARDAGE:
502 result = 0;
503 *val_len = sizeof(int);
504 return (u_char *)&result;
505 break;
506 case IPFORWARDINFO:
507 resarr[0] = 0;
508 resarr[1] = 0;
509 *val_len = 2 * sizeof(int);
510 return (u_char *)resarr;
511 break;
512 case IPFORWARDNEXTHOPAS:
513 result = -1;
514 *val_len = sizeof(int);
515 return (u_char *)&result;
516 break;
517 case IPFORWARDMETRIC1:
518 result = 0;
519 *val_len = sizeof(int);
520 return (u_char *)&result;
521 break;
522 case IPFORWARDMETRIC2:
523 result = 0;
524 *val_len = sizeof(int);
525 return (u_char *)&result;
526 break;
527 case IPFORWARDMETRIC3:
528 result = 0;
529 *val_len = sizeof(int);
530 return (u_char *)&result;
531 break;
532 case IPFORWARDMETRIC4:
533 result = 0;
534 *val_len = sizeof(int);
535 return (u_char *)&result;
536 break;
537 case IPFORWARDMETRIC5:
538 result = 0;
539 *val_len = sizeof(int);
540 return (u_char *)&result;
541 break;
542 default:
543 return NULL;
544 break;
545 }
546 return NULL;
547}
548
549u_char *
550ipCidrTable (struct variable *v, oid objid[], size_t *objid_len,
paul07661cb2003-03-18 00:03:05 +0000551 int exact, size_t *val_len, WriteMethod **write_method)
paul718e3742002-12-13 20:15:29 +0000552{
553 switch (v->magic)
554 {
555 case IPCIDRROUTEDEST:
556 break;
557 default:
558 return NULL;
559 break;
560 }
561 return NULL;
562}
563
564void
565zebra_snmp_init ()
566{
hassoc75105a2004-10-13 10:33:26 +0000567 smux_init (zebrad.master);
paul718e3742002-12-13 20:15:29 +0000568 REGISTER_MIB("mibII/ipforward", zebra_variables, variable, ipfw_oid);
paul718e3742002-12-13 20:15:29 +0000569}
570#endif /* HAVE_SNMP */