]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_snmp.c
bgpd, lib, zebra: Rename if_update_vrf -> if_update
[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
b72ede27
FL
22/*
23 * Currently SNMP is only running properly for MIBs in the default VRF.
24 */
25
718e3744 26#include <zebra.h>
27
28#ifdef HAVE_SNMP
07661cb5 29#include <net-snmp/net-snmp-config.h>
fb62a3ce 30#include <net-snmp/net-snmp-includes.h>
718e3744 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"
b72ede27 38#include "vrf.h"
718e3744 39
40#include "zebra/rib.h"
dd488a78 41#include "zebra/zserv.h"
050ceb3b 42#include "zebra/zebra_vrf.h"
6b0655a2 43
718e3744 44#define IPFWMIB 1,3,6,1,2,1,4,24
718e3744 45
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
6b0655a2 87
1c6f50bf 88static oid ipfw_oid [] = { IPFWMIB };
718e3744 89
90/* Hook functions. */
0be8dfb2
CC
91static u_char * ipFwNumber (struct variable *, oid [], size_t *,
92 int, size_t *, WriteMethod **);
93static u_char * ipFwTable (struct variable *, oid [], size_t *,
94 int, size_t *, WriteMethod **);
95static u_char * ipCidrNumber (struct variable *, oid [], size_t *,
96 int, size_t *, WriteMethod **);
97static u_char * ipCidrTable (struct variable *, oid [], size_t *,
98 int, size_t *, WriteMethod **);
718e3744 99
1c6f50bf 100static struct variable zebra_variables[] =
07661cb5 101 {
102 {0, GAUGE32, RONLY, ipFwNumber, 1, {1}},
103 {IPFORWARDDEST, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 1}},
104 {IPFORWARDMASK, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 2}},
105 {IPFORWARDPOLICY, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 3}},
106 {IPFORWARDNEXTHOP, IPADDRESS, RONLY, ipFwTable, 3, {2, 1, 4}},
107 {IPFORWARDIFINDEX, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 5}},
108 {IPFORWARDTYPE, ENUMERATION, RONLY, ipFwTable, 3, {2, 1, 6}},
109 {IPFORWARDPROTO, ENUMERATION, RONLY, ipFwTable, 3, {2, 1, 7}},
110 {IPFORWARDAGE, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 8}},
111 {IPFORWARDINFO, OBJECTIDENTIFIER, RONLY, ipFwTable, 3, {2, 1, 9}},
112 {IPFORWARDNEXTHOPAS, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 10}},
113 {IPFORWARDMETRIC1, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 11}},
114 {IPFORWARDMETRIC2, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 12}},
115 {IPFORWARDMETRIC3, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 13}},
116 {IPFORWARDMETRIC4, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 14}},
117 {IPFORWARDMETRIC5, INTEGER32, RONLY, ipFwTable, 3, {2, 1, 15}},
118 {0, GAUGE32, RONLY, ipCidrNumber, 1, {3}},
119 {IPCIDRROUTEDEST, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 1}},
120 {IPCIDRROUTEMASK, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 2}},
121 {IPCIDRROUTETOS, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 3}},
122 {IPCIDRROUTENEXTHOP, IPADDRESS, RONLY, ipCidrTable, 3, {4, 1, 4}},
123 {IPCIDRROUTEIFINDEX, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 5}},
124 {IPCIDRROUTETYPE, ENUMERATION, RONLY, ipCidrTable, 3, {4, 1, 6}},
125 {IPCIDRROUTEPROTO, ENUMERATION, RONLY, ipCidrTable, 3, {4, 1, 7}},
126 {IPCIDRROUTEAGE, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 8}},
127 {IPCIDRROUTEINFO, OBJECTIDENTIFIER, RONLY, ipCidrTable, 3, {4, 1, 9}},
128 {IPCIDRROUTENEXTHOPAS, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 10}},
129 {IPCIDRROUTEMETRIC1, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 11}},
130 {IPCIDRROUTEMETRIC2, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 12}},
131 {IPCIDRROUTEMETRIC3, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 13}},
132 {IPCIDRROUTEMETRIC4, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 14}},
133 {IPCIDRROUTEMETRIC5, INTEGER32, RONLY, ipCidrTable, 3, {4, 1, 15}},
134 {IPCIDRROUTESTATUS, ROWSTATUS, RONLY, ipCidrTable, 3, {4, 1, 16}}
135 };
718e3744 136
6b0655a2 137
0be8dfb2 138static u_char *
718e3744 139ipFwNumber (struct variable *v, oid objid[], size_t *objid_len,
140 int exact, size_t *val_len, WriteMethod **write_method)
141{
142 static int result;
07661cb5 143 struct route_table *table;
144 struct route_node *rn;
718e3744 145 struct rib *rib;
146
147 if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED)
148 return NULL;
149
b72ede27 150 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
07661cb5 151 if (! table)
152 return NULL;
153
718e3744 154 /* Return number of routing entries. */
155 result = 0;
07661cb5 156 for (rn = route_top (table); rn; rn = route_next (rn))
9fd92e3c 157 RNODE_FOREACH_RIB (rn, rib)
718e3744 158 result++;
159
160 return (u_char *)&result;
161}
162
0be8dfb2 163static u_char *
718e3744 164ipCidrNumber (struct variable *v, oid objid[], size_t *objid_len,
07661cb5 165 int exact, size_t *val_len, WriteMethod **write_method)
718e3744 166{
167 static int result;
07661cb5 168 struct route_table *table;
169 struct route_node *rn;
718e3744 170 struct rib *rib;
171
172 if (smux_header_generic(v, objid, objid_len, exact, val_len, write_method) == MATCH_FAILED)
173 return NULL;
174
b72ede27 175 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
07661cb5 176 if (! table)
177 return 0;
178
718e3744 179 /* Return number of routing entries. */
180 result = 0;
07661cb5 181 for (rn = route_top (table); rn; rn = route_next (rn))
9fd92e3c 182 RNODE_FOREACH_RIB (rn, rib)
718e3744 183 result++;
184
185 return (u_char *)&result;
186}
187
0be8dfb2 188static int
718e3744 189in_addr_cmp(u_char *p1, u_char *p2)
190{
191 int i;
192
193 for (i=0; i<4; i++)
194 {
195 if (*p1 < *p2)
196 return -1;
197 if (*p1 > *p2)
198 return 1;
199 p1++; p2++;
200 }
201 return 0;
202}
203
0be8dfb2 204static int
718e3744 205in_addr_add(u_char *p, int num)
206{
207 int i, ip0;
208
209 ip0 = *p;
210 p += 4;
211 for (i = 3; 0 <= i; i--) {
212 p--;
213 if (*p + num > 255) {
07661cb5 214 *p += num;
215 num = 1;
718e3744 216 } else {
07661cb5 217 *p += num;
218 return 1;
718e3744 219 }
220 }
221 if (ip0 > *p) {
07661cb5 222 /* ip + num > 0xffffffff */
223 return 0;
718e3744 224 }
225
226 return 1;
227}
228
0be8dfb2
CC
229static int
230proto_trans(int type)
718e3744 231{
232 switch (type)
233 {
07661cb5 234 case ZEBRA_ROUTE_SYSTEM:
235 return 1; /* other */
236 case ZEBRA_ROUTE_KERNEL:
237 return 1; /* other */
238 case ZEBRA_ROUTE_CONNECT:
239 return 2; /* local interface */
240 case ZEBRA_ROUTE_STATIC:
241 return 3; /* static route */
242 case ZEBRA_ROUTE_RIP:
243 return 8; /* rip */
244 case ZEBRA_ROUTE_RIPNG:
245 return 1; /* shouldn't happen */
246 case ZEBRA_ROUTE_OSPF:
247 return 13; /* ospf */
248 case ZEBRA_ROUTE_OSPF6:
249 return 1; /* shouldn't happen */
250 case ZEBRA_ROUTE_BGP:
251 return 14; /* bgp */
252 default:
253 return 1; /* other */
718e3744 254 }
255}
256
0be8dfb2 257static void
718e3744 258check_replace(struct route_node *np2, struct rib *rib2,
259 struct route_node **np, struct rib **rib)
260{
261 int proto, proto2;
262
263 if (!*np)
264 {
265 *np = np2;
266 *rib = rib2;
267 return;
268 }
269
270 if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) < 0)
271 return;
272 if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) > 0)
273 {
274 *np = np2;
275 *rib = rib2;
276 return;
277 }
278
279 proto = proto_trans((*rib)->type);
280 proto2 = proto_trans(rib2->type);
281
282 if (proto2 > proto)
283 return;
284 if (proto2 < proto)
285 {
286 *np = np2;
287 *rib = rib2;
288 return;
289 }
290
291 if (in_addr_cmp((u_char *)&(*rib)->nexthop->gate.ipv4,
292 (u_char *)&rib2->nexthop->gate.ipv4) <= 0)
293 return;
294
295 *np = np2;
296 *rib = rib2;
297 return;
298}
299
0be8dfb2 300static void
718e3744 301get_fwtable_route_node(struct variable *v, oid objid[], size_t *objid_len,
302 int exact, struct route_node **np, struct rib **rib)
303{
304 struct in_addr dest;
07661cb5 305 struct route_table *table;
718e3744 306 struct route_node *np2;
307 struct rib *rib2;
308 int proto;
309 int policy;
310 struct in_addr nexthop;
311 u_char *pnt;
312 int i;
313
07661cb5 314 /* Init index variables */
718e3744 315
316 pnt = (u_char *) &dest;
317 for (i = 0; i < 4; i++)
318 *pnt++ = 0;
319
320 pnt = (u_char *) &nexthop;
321 for (i = 0; i < 4; i++)
322 *pnt++ = 0;
323
324 proto = 0;
325 policy = 0;
326
07661cb5 327 /* Init return variables */
718e3744 328
329 *np = NULL;
330 *rib = NULL;
331
07661cb5 332 /* Short circuit exact matches of wrong length */
718e3744 333
39db97e4 334 if (exact && (*objid_len != (unsigned) v->namelen + 10))
718e3744 335 return;
336
b72ede27 337 table = zebra_vrf_table (AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
07661cb5 338 if (! table)
339 return;
340
341 /* Get INDEX information out of OID.
342 * ipForwardDest, ipForwardProto, ipForwardPolicy, ipForwardNextHop
343 */
718e3744 344
0be8dfb2 345 if (*objid_len > (unsigned) v->namelen)
7961551a 346 oid2in_addr (objid + v->namelen, MIN(4U, *objid_len - v->namelen), &dest);
718e3744 347
39db97e4 348 if (*objid_len > (unsigned) v->namelen + 4)
718e3744 349 proto = objid[v->namelen + 4];
350
39db97e4 351 if (*objid_len > (unsigned) v->namelen + 5)
718e3744 352 policy = objid[v->namelen + 5];
353
39db97e4 354 if (*objid_len > (unsigned) v->namelen + 6)
7961551a 355 oid2in_addr (objid + v->namelen + 6, MIN(4U, *objid_len - v->namelen - 6),
07661cb5 356 &nexthop);
718e3744 357
358 /* Apply GETNEXT on not exact search */
359
39db97e4 360 if (!exact && (*objid_len >= (unsigned) v->namelen + 10))
718e3744 361 {
362 if (! in_addr_add((u_char *) &nexthop, 1))
363 return;
364 }
365
366 /* For exact: search matching entry in rib table. */
367
368 if (exact)
369 {
370 if (policy) /* Not supported (yet?) */
371 return;
07661cb5 372 for (*np = route_top (table); *np; *np = route_next (*np))
718e3744 373 {
374 if (!in_addr_cmp(&(*np)->p.u.prefix, (u_char *)&dest))
375 {
9fd92e3c 376 RNODE_FOREACH_RIB (*np, *rib)
718e3744 377 {
378 if (!in_addr_cmp((u_char *)&(*rib)->nexthop->gate.ipv4,
07661cb5 379 (u_char *)&nexthop))
718e3744 380 if (proto == proto_trans((*rib)->type))
381 return;
382 }
383 }
384 }
385 return;
386 }
387
07661cb5 388 /* Search next best entry */
718e3744 389
07661cb5 390 for (np2 = route_top (table); np2; np2 = route_next (np2))
718e3744 391 {
392
393 /* Check destination first */
394 if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) > 0)
9fd92e3c 395 RNODE_FOREACH_RIB (np2, rib2)
718e3744 396 check_replace(np2, rib2, np, rib);
397
398 if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) == 0)
399 { /* have to look at each rib individually */
9fd92e3c 400 RNODE_FOREACH_RIB (np2, rib2)
718e3744 401 {
402 int proto2, policy2;
403
404 proto2 = proto_trans(rib2->type);
405 policy2 = 0;
406
407 if ((policy < policy2)
408 || ((policy == policy2) && (proto < proto2))
409 || ((policy == policy2) && (proto == proto2)
410 && (in_addr_cmp((u_char *)&rib2->nexthop->gate.ipv4,
411 (u_char *) &nexthop) >= 0)
412 ))
413 check_replace(np2, rib2, np, rib);
414 }
415 }
416 }
417
418 if (!*rib)
419 return;
420
421 policy = 0;
422 proto = proto_trans((*rib)->type);
423
424 *objid_len = v->namelen + 10;
425 pnt = (u_char *) &(*np)->p.u.prefix;
426 for (i = 0; i < 4; i++)
427 objid[v->namelen + i] = *pnt++;
428
429 objid[v->namelen + 4] = proto;
430 objid[v->namelen + 5] = policy;
431
432 {
433 struct nexthop *nexthop;
434
435 nexthop = (*rib)->nexthop;
436 if (nexthop)
437 {
438 pnt = (u_char *) &nexthop->gate.ipv4;
439 for (i = 0; i < 4; i++)
440 objid[i + v->namelen + 6] = *pnt++;
441 }
442 }
443
444 return;
445}
446
0be8dfb2 447static u_char *
718e3744 448ipFwTable (struct variable *v, oid objid[], size_t *objid_len,
449 int exact, size_t *val_len, WriteMethod **write_method)
450{
451 struct route_node *np;
452 struct rib *rib;
453 static int result;
454 static int resarr[2];
455 static struct in_addr netmask;
456 struct nexthop *nexthop;
457
8046ba6e
VB
458 if (smux_header_table(v, objid, objid_len, exact, val_len, write_method)
459 == MATCH_FAILED)
460 return NULL;
461
718e3744 462 get_fwtable_route_node(v, objid, objid_len, exact, &np, &rib);
463 if (!np)
464 return NULL;
465
466 nexthop = rib->nexthop;
467 if (! nexthop)
468 return NULL;
469
470 switch (v->magic)
471 {
472 case IPFORWARDDEST:
473 *val_len = 4;
474 return &np->p.u.prefix;
475 break;
476 case IPFORWARDMASK:
477 masklen2ip(np->p.prefixlen, &netmask);
478 *val_len = 4;
479 return (u_char *)&netmask;
480 break;
481 case IPFORWARDPOLICY:
482 result = 0;
483 *val_len = sizeof(int);
484 return (u_char *)&result;
485 break;
486 case IPFORWARDNEXTHOP:
487 *val_len = 4;
488 return (u_char *)&nexthop->gate.ipv4;
489 break;
490 case IPFORWARDIFINDEX:
491 *val_len = sizeof(int);
492 return (u_char *)&nexthop->ifindex;
493 break;
494 case IPFORWARDTYPE:
3ee39b5b 495 if (nexthop->type == NEXTHOP_TYPE_IFINDEX)
718e3744 496 result = 3;
497 else
498 result = 4;
499 *val_len = sizeof(int);
500 return (u_char *)&result;
501 break;
502 case IPFORWARDPROTO:
503 result = proto_trans(rib->type);
504 *val_len = sizeof(int);
505 return (u_char *)&result;
506 break;
507 case IPFORWARDAGE:
508 result = 0;
509 *val_len = sizeof(int);
510 return (u_char *)&result;
511 break;
512 case IPFORWARDINFO:
513 resarr[0] = 0;
514 resarr[1] = 0;
515 *val_len = 2 * sizeof(int);
516 return (u_char *)resarr;
517 break;
518 case IPFORWARDNEXTHOPAS:
519 result = -1;
520 *val_len = sizeof(int);
521 return (u_char *)&result;
522 break;
523 case IPFORWARDMETRIC1:
524 result = 0;
525 *val_len = sizeof(int);
526 return (u_char *)&result;
527 break;
528 case IPFORWARDMETRIC2:
529 result = 0;
530 *val_len = sizeof(int);
531 return (u_char *)&result;
532 break;
533 case IPFORWARDMETRIC3:
534 result = 0;
535 *val_len = sizeof(int);
536 return (u_char *)&result;
537 break;
538 case IPFORWARDMETRIC4:
539 result = 0;
540 *val_len = sizeof(int);
541 return (u_char *)&result;
542 break;
543 case IPFORWARDMETRIC5:
544 result = 0;
545 *val_len = sizeof(int);
546 return (u_char *)&result;
547 break;
548 default:
549 return NULL;
550 break;
551 }
552 return NULL;
553}
554
0be8dfb2 555static u_char *
718e3744 556ipCidrTable (struct variable *v, oid objid[], size_t *objid_len,
07661cb5 557 int exact, size_t *val_len, WriteMethod **write_method)
718e3744 558{
8046ba6e
VB
559 if (smux_header_table(v, objid, objid_len, exact, val_len, write_method)
560 == MATCH_FAILED)
561 return NULL;
562
718e3744 563 switch (v->magic)
564 {
565 case IPCIDRROUTEDEST:
566 break;
567 default:
568 return NULL;
569 break;
570 }
571 return NULL;
572}
573
574void
575zebra_snmp_init ()
576{
c75105ab 577 smux_init (zebrad.master);
718e3744 578 REGISTER_MIB("mibII/ipforward", zebra_variables, variable, ipfw_oid);
718e3744 579}
580#endif /* HAVE_SNMP */