]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_snmp.c
*: nuke ^L (page feed)
[mirror_frr.git] / zebra / zebra_snmp.c
CommitLineData
07661cb5 1/* FIB SNMP.
718e3744 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
07661cb5 25#include <net-snmp/net-snmp-config.h>
fb62a3ce 26#include <net-snmp/net-snmp-includes.h>
718e3744 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"
dd488a78 36#include "zebra/zserv.h"
6b0655a2 37
718e3744 38#define IPFWMIB 1,3,6,1,2,1,4,24
718e3744 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
6b0655a2 81
dd488a78 82extern struct zebra_t zebrad;
83
718e3744 84oid ipfw_oid [] = { IPFWMIB };
718e3744 85
86/* Hook functions. */
0be8dfb2
CC
87static u_char * ipFwNumber (struct variable *, oid [], size_t *,
88 int, size_t *, WriteMethod **);
89static u_char * ipFwTable (struct variable *, oid [], size_t *,
90 int, size_t *, WriteMethod **);
91static u_char * ipCidrNumber (struct variable *, oid [], size_t *,
92 int, size_t *, WriteMethod **);
93static u_char * ipCidrTable (struct variable *, oid [], size_t *,
94 int, size_t *, WriteMethod **);
718e3744 95
96struct variable zebra_variables[] =
07661cb5 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 };
718e3744 132
6b0655a2 133
0be8dfb2 134static u_char *
718e3744 135ipFwNumber (struct variable *v, oid objid[], size_t *objid_len,
136 int exact, size_t *val_len, WriteMethod **write_method)
137{
138 static int result;
07661cb5 139 struct route_table *table;
140 struct route_node *rn;
718e3744 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
07661cb5 146 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
147 if (! table)
148 return NULL;
149
718e3744 150 /* Return number of routing entries. */
151 result = 0;
07661cb5 152 for (rn = route_top (table); rn; rn = route_next (rn))
9fd92e3c 153 RNODE_FOREACH_RIB (rn, rib)
718e3744 154 result++;
155
156 return (u_char *)&result;
157}
158
0be8dfb2 159static u_char *
718e3744 160ipCidrNumber (struct variable *v, oid objid[], size_t *objid_len,
07661cb5 161 int exact, size_t *val_len, WriteMethod **write_method)
718e3744 162{
163 static int result;
07661cb5 164 struct route_table *table;
165 struct route_node *rn;
718e3744 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
07661cb5 171 table = vrf_table (AFI_IP, SAFI_UNICAST, 0);
172 if (! table)
173 return 0;
174
718e3744 175 /* Return number of routing entries. */
176 result = 0;
07661cb5 177 for (rn = route_top (table); rn; rn = route_next (rn))
9fd92e3c 178 RNODE_FOREACH_RIB (rn, rib)
718e3744 179 result++;
180
181 return (u_char *)&result;
182}
183
0be8dfb2 184static int
718e3744 185in_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
0be8dfb2 200static int
718e3744 201in_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) {
07661cb5 210 *p += num;
211 num = 1;
718e3744 212 } else {
07661cb5 213 *p += num;
214 return 1;
718e3744 215 }
216 }
217 if (ip0 > *p) {
07661cb5 218 /* ip + num > 0xffffffff */
219 return 0;
718e3744 220 }
221
222 return 1;
223}
224
0be8dfb2
CC
225static int
226proto_trans(int type)
718e3744 227{
228 switch (type)
229 {
07661cb5 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 */
718e3744 250 }
251}
252
0be8dfb2 253static void
718e3744 254check_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
0be8dfb2 296static void
718e3744 297get_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;
07661cb5 301 struct route_table *table;
718e3744 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
07661cb5 310 /* Init index variables */
718e3744 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
07661cb5 323 /* Init return variables */
718e3744 324
325 *np = NULL;
326 *rib = NULL;
327
07661cb5 328 /* Short circuit exact matches of wrong length */
718e3744 329
39db97e4 330 if (exact && (*objid_len != (unsigned) v->namelen + 10))
718e3744 331 return;
332
07661cb5 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 */
718e3744 340
0be8dfb2 341 if (*objid_len > (unsigned) v->namelen)
718e3744 342 oid2in_addr (objid + v->namelen, MIN(4, *objid_len - v->namelen), &dest);
343
39db97e4 344 if (*objid_len > (unsigned) v->namelen + 4)
718e3744 345 proto = objid[v->namelen + 4];
346
39db97e4 347 if (*objid_len > (unsigned) v->namelen + 5)
718e3744 348 policy = objid[v->namelen + 5];
349
39db97e4 350 if (*objid_len > (unsigned) v->namelen + 6)
718e3744 351 oid2in_addr (objid + v->namelen + 6, MIN(4, *objid_len - v->namelen - 6),
07661cb5 352 &nexthop);
718e3744 353
354 /* Apply GETNEXT on not exact search */
355
39db97e4 356 if (!exact && (*objid_len >= (unsigned) v->namelen + 10))
718e3744 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;
07661cb5 368 for (*np = route_top (table); *np; *np = route_next (*np))
718e3744 369 {
370 if (!in_addr_cmp(&(*np)->p.u.prefix, (u_char *)&dest))
371 {
9fd92e3c 372 RNODE_FOREACH_RIB (*np, *rib)
718e3744 373 {
374 if (!in_addr_cmp((u_char *)&(*rib)->nexthop->gate.ipv4,
07661cb5 375 (u_char *)&nexthop))
718e3744 376 if (proto == proto_trans((*rib)->type))
377 return;
378 }
379 }
380 }
381 return;
382 }
383
07661cb5 384 /* Search next best entry */
718e3744 385
07661cb5 386 for (np2 = route_top (table); np2; np2 = route_next (np2))
718e3744 387 {
388
389 /* Check destination first */
390 if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) > 0)
9fd92e3c 391 RNODE_FOREACH_RIB (np2, rib2)
718e3744 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 */
9fd92e3c 396 RNODE_FOREACH_RIB (np2, rib2)
718e3744 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
0be8dfb2 443static u_char *
718e3744 444ipFwTable (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
8046ba6e
VB
454 if (smux_header_table(v, objid, objid_len, exact, val_len, write_method)
455 == MATCH_FAILED)
456 return NULL;
457
718e3744 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
0be8dfb2 552static u_char *
718e3744 553ipCidrTable (struct variable *v, oid objid[], size_t *objid_len,
07661cb5 554 int exact, size_t *val_len, WriteMethod **write_method)
718e3744 555{
8046ba6e
VB
556 if (smux_header_table(v, objid, objid_len, exact, val_len, write_method)
557 == MATCH_FAILED)
558 return NULL;
559
718e3744 560 switch (v->magic)
561 {
562 case IPCIDRROUTEDEST:
563 break;
564 default:
565 return NULL;
566 break;
567 }
568 return NULL;
569}
570
571void
572zebra_snmp_init ()
573{
c75105ab 574 smux_init (zebrad.master);
718e3744 575 REGISTER_MIB("mibII/ipforward", zebra_variables, variable, ipfw_oid);
718e3744 576}
577#endif /* HAVE_SNMP */