]>
git.proxmox.com Git - mirror_frr.git/blob - zebra/zebra_snmp.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 1999 Kunihiro Ishiguro
7 * Currently SNMP is only running properly for MIBs in the default VRF.
12 #include <net-snmp/net-snmp-config.h>
13 #include <net-snmp/net-snmp-includes.h>
24 #include "lib/version.h"
26 #include "zebra/rib.h"
27 #include "zebra/zserv.h"
28 #include "zebra/zebra_vrf.h"
30 #define IPFWMIB 1,3,6,1,2,1,4,24
33 #define IPFORWARDDEST 1
34 #define IPFORWARDMASK 2
35 #define IPFORWARDPOLICY 3
36 #define IPFORWARDNEXTHOP 4
37 #define IPFORWARDIFINDEX 5
38 #define IPFORWARDTYPE 6
39 #define IPFORWARDPROTO 7
40 #define IPFORWARDAGE 8
41 #define IPFORWARDINFO 9
42 #define IPFORWARDNEXTHOPAS 10
43 #define IPFORWARDMETRIC1 11
44 #define IPFORWARDMETRIC2 12
45 #define IPFORWARDMETRIC3 13
46 #define IPFORWARDMETRIC4 14
47 #define IPFORWARDMETRIC5 15
49 /* ipCidrRouteTable */
50 #define IPCIDRROUTEDEST 1
51 #define IPCIDRROUTEMASK 2
52 #define IPCIDRROUTETOS 3
53 #define IPCIDRROUTENEXTHOP 4
54 #define IPCIDRROUTEIFINDEX 5
55 #define IPCIDRROUTETYPE 6
56 #define IPCIDRROUTEPROTO 7
57 #define IPCIDRROUTEAGE 8
58 #define IPCIDRROUTEINFO 9
59 #define IPCIDRROUTENEXTHOPAS 10
60 #define IPCIDRROUTEMETRIC1 11
61 #define IPCIDRROUTEMETRIC2 12
62 #define IPCIDRROUTEMETRIC3 13
63 #define IPCIDRROUTEMETRIC4 14
64 #define IPCIDRROUTEMETRIC5 15
65 #define IPCIDRROUTESTATUS 16
67 #define INTEGER32 ASN_INTEGER
68 #define GAUGE32 ASN_GAUGE
69 #define ENUMERATION ASN_INTEGER
70 #define ROWSTATUS ASN_INTEGER
71 #define IPADDRESS ASN_IPADDRESS
72 #define OBJECTIDENTIFIER ASN_OBJECT_ID
74 static oid ipfw_oid
[] = {IPFWMIB
};
77 static uint8_t *ipFwNumber(struct variable
*, oid
[], size_t *, int, size_t *,
79 static uint8_t *ipFwTable(struct variable
*, oid
[], size_t *, int, size_t *,
81 static uint8_t *ipCidrNumber(struct variable
*, oid
[], size_t *, int, size_t *,
83 static uint8_t *ipCidrTable(struct variable
*, oid
[], size_t *, int, size_t *,
86 static struct variable zebra_variables
[] = {
87 {0, GAUGE32
, RONLY
, ipFwNumber
, 1, {1}},
88 {IPFORWARDDEST
, IPADDRESS
, RONLY
, ipFwTable
, 3, {2, 1, 1}},
89 {IPFORWARDMASK
, IPADDRESS
, RONLY
, ipFwTable
, 3, {2, 1, 2}},
90 {IPFORWARDPOLICY
, INTEGER32
, RONLY
, ipFwTable
, 3, {2, 1, 3}},
91 {IPFORWARDNEXTHOP
, IPADDRESS
, RONLY
, ipFwTable
, 3, {2, 1, 4}},
92 {IPFORWARDIFINDEX
, INTEGER32
, RONLY
, ipFwTable
, 3, {2, 1, 5}},
93 {IPFORWARDTYPE
, ENUMERATION
, RONLY
, ipFwTable
, 3, {2, 1, 6}},
94 {IPFORWARDPROTO
, ENUMERATION
, RONLY
, ipFwTable
, 3, {2, 1, 7}},
95 {IPFORWARDAGE
, INTEGER32
, RONLY
, ipFwTable
, 3, {2, 1, 8}},
96 {IPFORWARDINFO
, OBJECTIDENTIFIER
, RONLY
, ipFwTable
, 3, {2, 1, 9}},
97 {IPFORWARDNEXTHOPAS
, INTEGER32
, RONLY
, ipFwTable
, 3, {2, 1, 10}},
98 {IPFORWARDMETRIC1
, INTEGER32
, RONLY
, ipFwTable
, 3, {2, 1, 11}},
99 {IPFORWARDMETRIC2
, INTEGER32
, RONLY
, ipFwTable
, 3, {2, 1, 12}},
100 {IPFORWARDMETRIC3
, INTEGER32
, RONLY
, ipFwTable
, 3, {2, 1, 13}},
101 {IPFORWARDMETRIC4
, INTEGER32
, RONLY
, ipFwTable
, 3, {2, 1, 14}},
102 {IPFORWARDMETRIC5
, INTEGER32
, RONLY
, ipFwTable
, 3, {2, 1, 15}},
103 {0, GAUGE32
, RONLY
, ipCidrNumber
, 1, {3}},
104 {IPCIDRROUTEDEST
, IPADDRESS
, RONLY
, ipCidrTable
, 3, {4, 1, 1}},
105 {IPCIDRROUTEMASK
, IPADDRESS
, RONLY
, ipCidrTable
, 3, {4, 1, 2}},
106 {IPCIDRROUTETOS
, INTEGER32
, RONLY
, ipCidrTable
, 3, {4, 1, 3}},
107 {IPCIDRROUTENEXTHOP
, IPADDRESS
, RONLY
, ipCidrTable
, 3, {4, 1, 4}},
108 {IPCIDRROUTEIFINDEX
, INTEGER32
, RONLY
, ipCidrTable
, 3, {4, 1, 5}},
109 {IPCIDRROUTETYPE
, ENUMERATION
, RONLY
, ipCidrTable
, 3, {4, 1, 6}},
110 {IPCIDRROUTEPROTO
, ENUMERATION
, RONLY
, ipCidrTable
, 3, {4, 1, 7}},
111 {IPCIDRROUTEAGE
, INTEGER32
, RONLY
, ipCidrTable
, 3, {4, 1, 8}},
112 {IPCIDRROUTEINFO
, OBJECTIDENTIFIER
, RONLY
, ipCidrTable
, 3, {4, 1, 9}},
113 {IPCIDRROUTENEXTHOPAS
, INTEGER32
, RONLY
, ipCidrTable
, 3, {4, 1, 10}},
114 {IPCIDRROUTEMETRIC1
, INTEGER32
, RONLY
, ipCidrTable
, 3, {4, 1, 11}},
115 {IPCIDRROUTEMETRIC2
, INTEGER32
, RONLY
, ipCidrTable
, 3, {4, 1, 12}},
116 {IPCIDRROUTEMETRIC3
, INTEGER32
, RONLY
, ipCidrTable
, 3, {4, 1, 13}},
117 {IPCIDRROUTEMETRIC4
, INTEGER32
, RONLY
, ipCidrTable
, 3, {4, 1, 14}},
118 {IPCIDRROUTEMETRIC5
, INTEGER32
, RONLY
, ipCidrTable
, 3, {4, 1, 15}},
119 {IPCIDRROUTESTATUS
, ROWSTATUS
, RONLY
, ipCidrTable
, 3, {4, 1, 16}}};
122 static uint8_t *ipFwNumber(struct variable
*v
, oid objid
[], size_t *objid_len
,
123 int exact
, size_t *val_len
,
124 WriteMethod
**write_method
)
127 struct route_table
*table
;
128 struct route_node
*rn
;
129 struct route_entry
*re
;
131 if (smux_header_generic(v
, objid
, objid_len
, exact
, val_len
,
136 table
= zebra_vrf_table(AFI_IP
, SAFI_UNICAST
, VRF_DEFAULT
);
140 /* Return number of routing entries. */
142 for (rn
= route_top(table
); rn
; rn
= route_next(rn
))
143 RNODE_FOREACH_RE (rn
, re
) {
147 return (uint8_t *)&result
;
150 static uint8_t *ipCidrNumber(struct variable
*v
, oid objid
[], size_t *objid_len
,
151 int exact
, size_t *val_len
,
152 WriteMethod
**write_method
)
155 struct route_table
*table
;
156 struct route_node
*rn
;
157 struct route_entry
*re
;
159 if (smux_header_generic(v
, objid
, objid_len
, exact
, val_len
,
164 table
= zebra_vrf_table(AFI_IP
, SAFI_UNICAST
, VRF_DEFAULT
);
168 /* Return number of routing entries. */
170 for (rn
= route_top(table
); rn
; rn
= route_next(rn
))
171 RNODE_FOREACH_RE (rn
, re
) {
175 return (uint8_t *)&result
;
178 static int in_addr_cmp(uint8_t *p1
, uint8_t *p2
)
182 for (i
= 0; i
< 4; i
++) {
193 static int in_addr_add(uint8_t *p
, int num
)
199 for (i
= 3; 0 <= i
; i
--) {
201 if (*p
+ num
> 255) {
210 /* ip + num > 0xffffffff */
217 static int proto_trans(int type
)
220 case ZEBRA_ROUTE_SYSTEM
:
221 return 1; /* other */
222 case ZEBRA_ROUTE_KERNEL
:
223 return 1; /* other */
224 case ZEBRA_ROUTE_CONNECT
:
225 return 2; /* local interface */
226 case ZEBRA_ROUTE_STATIC
:
227 return 3; /* static route */
228 case ZEBRA_ROUTE_RIP
:
230 case ZEBRA_ROUTE_RIPNG
:
231 return 1; /* shouldn't happen */
232 case ZEBRA_ROUTE_OSPF
:
233 return 13; /* ospf */
234 case ZEBRA_ROUTE_OSPF6
:
235 return 1; /* shouldn't happen */
236 case ZEBRA_ROUTE_BGP
:
239 return 1; /* other */
243 static void check_replace(struct route_node
*np2
, struct route_entry
*re2
,
244 struct route_node
**np
, struct route_entry
**re
)
254 if (prefix_cmp(&(*np
)->p
, &np2
->p
) < 0)
256 if (prefix_cmp(&(*np
)->p
, &np2
->p
) > 0) {
262 proto
= proto_trans((*re
)->type
);
263 proto2
= proto_trans(re2
->type
);
267 if (proto2
< proto
) {
273 if (in_addr_cmp((uint8_t *)&(*re
)->nhe
->nhg
.nexthop
->gate
.ipv4
,
274 (uint8_t *)&re2
->nhe
->nhg
.nexthop
->gate
.ipv4
)
283 static void get_fwtable_route_node(struct variable
*v
, oid objid
[],
284 size_t *objid_len
, int exact
,
285 struct route_node
**np
,
286 struct route_entry
**re
)
289 struct route_table
*table
;
290 struct route_node
*np2
;
291 struct route_entry
*re2
;
294 struct in_addr nexthop
;
298 /* Init index variables */
300 pnt
= (uint8_t *)&dest
;
301 for (i
= 0; i
< 4; i
++)
304 pnt
= (uint8_t *)&nexthop
;
305 for (i
= 0; i
< 4; i
++)
311 /* Init return variables */
316 /* Short circuit exact matches of wrong length */
318 if (exact
&& (*objid_len
!= (unsigned)v
->namelen
+ 10))
321 table
= zebra_vrf_table(AFI_IP
, SAFI_UNICAST
, VRF_DEFAULT
);
325 /* Get INDEX information out of OID.
326 * ipForwardDest, ipForwardProto, ipForwardPolicy, ipForwardNextHop
329 if (*objid_len
> (unsigned)v
->namelen
)
330 oid2in_addr(objid
+ v
->namelen
,
331 MIN(4U, *objid_len
- v
->namelen
), &dest
);
333 if (*objid_len
> (unsigned)v
->namelen
+ 4)
334 proto
= objid
[v
->namelen
+ 4];
336 if (*objid_len
> (unsigned)v
->namelen
+ 5)
337 policy
= objid
[v
->namelen
+ 5];
339 if (*objid_len
> (unsigned)v
->namelen
+ 6)
340 oid2in_addr(objid
+ v
->namelen
+ 6,
341 MIN(4U, *objid_len
- v
->namelen
- 6), &nexthop
);
343 /* Apply GETNEXT on not exact search */
345 if (!exact
&& (*objid_len
>= (unsigned)v
->namelen
+ 10)) {
346 if (!in_addr_add((uint8_t *)&nexthop
, 1))
350 /* For exact: search matching entry in rib table. */
353 if (policy
) /* Not supported (yet?) */
355 for (*np
= route_top(table
); *np
; *np
= route_next(*np
)) {
356 if (!in_addr_cmp(&(*np
)->p
.u
.prefix
,
358 RNODE_FOREACH_RE (*np
, *re
) {
359 if (!in_addr_cmp((uint8_t *)&(*re
)->nhe
362 (uint8_t *)&nexthop
))
364 == proto_trans((*re
)->type
))
372 /* Search next best entry */
374 for (np2
= route_top(table
); np2
; np2
= route_next(np2
)) {
376 /* Check destination first */
377 if (in_addr_cmp(&np2
->p
.u
.prefix
, (uint8_t *)&dest
) > 0)
378 RNODE_FOREACH_RE (np2
, re2
) {
379 check_replace(np2
, re2
, np
, re
);
382 if (in_addr_cmp(&np2
->p
.u
.prefix
, (uint8_t *)&dest
)
383 == 0) { /* have to look at each re individually */
384 RNODE_FOREACH_RE (np2
, re2
) {
387 proto2
= proto_trans(re2
->type
);
390 if ((policy
< policy2
)
391 || ((policy
== policy2
) && (proto
< proto2
))
392 || ((policy
== policy2
) && (proto
== proto2
)
395 ->nhg
.nexthop
->gate
.ipv4
,
398 check_replace(np2
, re2
, np
, re
);
407 proto
= proto_trans((*re
)->type
);
409 *objid_len
= v
->namelen
+ 10;
410 pnt
= (uint8_t *)&(*np
)->p
.u
.prefix
;
411 for (i
= 0; i
< 4; i
++)
412 objid
[v
->namelen
+ i
] = *pnt
++;
414 objid
[v
->namelen
+ 4] = proto
;
415 objid
[v
->namelen
+ 5] = policy
;
418 struct nexthop
*nexthop
;
420 nexthop
= (*re
)->nhe
->nhg
.nexthop
;
422 pnt
= (uint8_t *)&nexthop
->gate
.ipv4
;
423 for (i
= 0; i
< 4; i
++)
424 objid
[i
+ v
->namelen
+ 6] = *pnt
++;
431 static uint8_t *ipFwTable(struct variable
*v
, oid objid
[], size_t *objid_len
,
432 int exact
, size_t *val_len
,
433 WriteMethod
**write_method
)
435 struct route_node
*np
;
436 struct route_entry
*re
;
438 static int resarr
[2];
439 static struct in_addr netmask
;
440 struct nexthop
*nexthop
;
442 if (smux_header_table(v
, objid
, objid_len
, exact
, val_len
, write_method
)
446 get_fwtable_route_node(v
, objid
, objid_len
, exact
, &np
, &re
);
450 nexthop
= re
->nhe
->nhg
.nexthop
;
457 return &np
->p
.u
.prefix
;
459 masklen2ip(np
->p
.prefixlen
, &netmask
);
461 return (uint8_t *)&netmask
;
462 case IPFORWARDPOLICY
:
464 *val_len
= sizeof(int);
465 return (uint8_t *)&result
;
466 case IPFORWARDNEXTHOP
:
468 return (uint8_t *)&nexthop
->gate
.ipv4
;
469 case IPFORWARDIFINDEX
:
470 *val_len
= sizeof(int);
471 return (uint8_t *)&nexthop
->ifindex
;
473 if (nexthop
->type
== NEXTHOP_TYPE_IFINDEX
)
477 *val_len
= sizeof(int);
478 return (uint8_t *)&result
;
480 result
= proto_trans(re
->type
);
481 *val_len
= sizeof(int);
482 return (uint8_t *)&result
;
485 *val_len
= sizeof(int);
486 return (uint8_t *)&result
;
490 *val_len
= 2 * sizeof(int);
491 return (uint8_t *)resarr
;
492 case IPFORWARDNEXTHOPAS
:
494 *val_len
= sizeof(int);
495 return (uint8_t *)&result
;
496 case IPFORWARDMETRIC1
:
498 *val_len
= sizeof(int);
499 return (uint8_t *)&result
;
500 case IPFORWARDMETRIC2
:
502 *val_len
= sizeof(int);
503 return (uint8_t *)&result
;
504 case IPFORWARDMETRIC3
:
506 *val_len
= sizeof(int);
507 return (uint8_t *)&result
;
508 case IPFORWARDMETRIC4
:
510 *val_len
= sizeof(int);
511 return (uint8_t *)&result
;
512 case IPFORWARDMETRIC5
:
514 *val_len
= sizeof(int);
515 return (uint8_t *)&result
;
522 static uint8_t *ipCidrTable(struct variable
*v
, oid objid
[], size_t *objid_len
,
523 int exact
, size_t *val_len
,
524 WriteMethod
**write_method
)
526 if (smux_header_table(v
, objid
, objid_len
, exact
, val_len
, write_method
)
531 case IPCIDRROUTEDEST
:
539 static int zebra_snmp_init(struct thread_master
*tm
)
542 REGISTER_MIB("mibII/ipforward", zebra_variables
, variable
, ipfw_oid
);
546 static int zebra_snmp_module_init(void)
548 hook_register(frr_late_init
, zebra_snmp_init
);
552 FRR_MODULE_SETUP(.name
= "zebra_snmp", .version
= FRR_VERSION
,
553 .description
= "zebra AgentX SNMP module",
554 .init
= zebra_snmp_module_init
,