]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_snmp.c
*: reindent
[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 *
896014f4
DL
16 * You should have received a copy of the GNU General Public License along
17 * with this program; see the file COPYING; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
718e3744 19 */
20
b72ede27
FL
21/*
22 * Currently SNMP is only running properly for MIBs in the default VRF.
23 */
24
718e3744 25#include <zebra.h>
26
07661cb5 27#include <net-snmp/net-snmp-config.h>
fb62a3ce 28#include <net-snmp/net-snmp-includes.h>
718e3744 29
30#include "if.h"
31#include "log.h"
32#include "prefix.h"
33#include "command.h"
34#include "smux.h"
35#include "table.h"
b72ede27 36#include "vrf.h"
5986b66b
DL
37#include "hook.h"
38#include "libfrr.h"
39#include "version.h"
718e3744 40
41#include "zebra/rib.h"
dd488a78 42#include "zebra/zserv.h"
050ceb3b 43#include "zebra/zebra_vrf.h"
6b0655a2 44
718e3744 45#define IPFWMIB 1,3,6,1,2,1,4,24
718e3744 46
47/* ipForwardTable */
48#define IPFORWARDDEST 1
49#define IPFORWARDMASK 2
50#define IPFORWARDPOLICY 3
51#define IPFORWARDNEXTHOP 4
52#define IPFORWARDIFINDEX 5
53#define IPFORWARDTYPE 6
54#define IPFORWARDPROTO 7
55#define IPFORWARDAGE 8
56#define IPFORWARDINFO 9
57#define IPFORWARDNEXTHOPAS 10
58#define IPFORWARDMETRIC1 11
59#define IPFORWARDMETRIC2 12
60#define IPFORWARDMETRIC3 13
61#define IPFORWARDMETRIC4 14
62#define IPFORWARDMETRIC5 15
63
64/* ipCidrRouteTable */
65#define IPCIDRROUTEDEST 1
66#define IPCIDRROUTEMASK 2
67#define IPCIDRROUTETOS 3
68#define IPCIDRROUTENEXTHOP 4
69#define IPCIDRROUTEIFINDEX 5
70#define IPCIDRROUTETYPE 6
71#define IPCIDRROUTEPROTO 7
72#define IPCIDRROUTEAGE 8
73#define IPCIDRROUTEINFO 9
74#define IPCIDRROUTENEXTHOPAS 10
75#define IPCIDRROUTEMETRIC1 11
76#define IPCIDRROUTEMETRIC2 12
77#define IPCIDRROUTEMETRIC3 13
78#define IPCIDRROUTEMETRIC4 14
79#define IPCIDRROUTEMETRIC5 15
80#define IPCIDRROUTESTATUS 16
81
82#define INTEGER32 ASN_INTEGER
83#define GAUGE32 ASN_GAUGE
84#define ENUMERATION ASN_INTEGER
85#define ROWSTATUS ASN_INTEGER
86#define IPADDRESS ASN_IPADDRESS
87#define OBJECTIDENTIFIER ASN_OBJECT_ID
6b0655a2 88
d62a17ae 89static oid ipfw_oid[] = {IPFWMIB};
718e3744 90
91/* Hook functions. */
d62a17ae 92static u_char *ipFwNumber(struct variable *, oid[], size_t *, int, size_t *,
93 WriteMethod **);
94static u_char *ipFwTable(struct variable *, oid[], size_t *, int, size_t *,
95 WriteMethod **);
96static u_char *ipCidrNumber(struct variable *, oid[], size_t *, int, size_t *,
97 WriteMethod **);
98static u_char *ipCidrTable(struct variable *, oid[], size_t *, int, size_t *,
99 WriteMethod **);
100
101static struct variable zebra_variables[] = {
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
136
137static u_char *ipFwNumber(struct variable *v, oid objid[], size_t *objid_len,
138 int exact, size_t *val_len,
139 WriteMethod **write_method)
718e3744 140{
d62a17ae 141 static int result;
142 struct route_table *table;
143 struct route_node *rn;
144 struct route_entry *re;
145
146 if (smux_header_generic(v, objid, objid_len, exact, val_len,
147 write_method)
148 == MATCH_FAILED)
149 return NULL;
150
151 table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
152 if (!table)
153 return NULL;
154
155 /* Return number of routing entries. */
156 result = 0;
157 for (rn = route_top(table); rn; rn = route_next(rn))
158 RNODE_FOREACH_RE(rn, re)
159 result++;
160
161 return (u_char *)&result;
718e3744 162}
163
d62a17ae 164static u_char *ipCidrNumber(struct variable *v, oid objid[], size_t *objid_len,
165 int exact, size_t *val_len,
166 WriteMethod **write_method)
718e3744 167{
d62a17ae 168 static int result;
169 struct route_table *table;
170 struct route_node *rn;
171 struct route_entry *re;
172
173 if (smux_header_generic(v, objid, objid_len, exact, val_len,
174 write_method)
175 == MATCH_FAILED)
176 return NULL;
177
178 table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
179 if (!table)
180 return 0;
181
182 /* Return number of routing entries. */
183 result = 0;
184 for (rn = route_top(table); rn; rn = route_next(rn))
185 RNODE_FOREACH_RE(rn, re)
186 result++;
187
188 return (u_char *)&result;
718e3744 189}
190
d62a17ae 191static int in_addr_cmp(u_char *p1, u_char *p2)
718e3744 192{
d62a17ae 193 int i;
194
195 for (i = 0; i < 4; i++) {
196 if (*p1 < *p2)
197 return -1;
198 if (*p1 > *p2)
199 return 1;
200 p1++;
201 p2++;
202 }
203 return 0;
718e3744 204}
205
d62a17ae 206static int in_addr_add(u_char *p, int num)
718e3744 207{
d62a17ae 208 int i, ip0;
209
210 ip0 = *p;
211 p += 4;
212 for (i = 3; 0 <= i; i--) {
213 p--;
214 if (*p + num > 255) {
215 *p += num;
216 num = 1;
217 } else {
218 *p += num;
219 return 1;
220 }
221 }
222 if (ip0 > *p) {
223 /* ip + num > 0xffffffff */
224 return 0;
225 }
718e3744 226
d62a17ae 227 return 1;
718e3744 228}
229
d62a17ae 230static int proto_trans(int type)
718e3744 231{
d62a17ae 232 switch (type) {
233 case ZEBRA_ROUTE_SYSTEM:
234 return 1; /* other */
235 case ZEBRA_ROUTE_KERNEL:
236 return 1; /* other */
237 case ZEBRA_ROUTE_CONNECT:
238 return 2; /* local interface */
239 case ZEBRA_ROUTE_STATIC:
240 return 3; /* static route */
241 case ZEBRA_ROUTE_RIP:
242 return 8; /* rip */
243 case ZEBRA_ROUTE_RIPNG:
244 return 1; /* shouldn't happen */
245 case ZEBRA_ROUTE_OSPF:
246 return 13; /* ospf */
247 case ZEBRA_ROUTE_OSPF6:
248 return 1; /* shouldn't happen */
249 case ZEBRA_ROUTE_BGP:
250 return 14; /* bgp */
251 default:
252 return 1; /* other */
253 }
718e3744 254}
255
d62a17ae 256static void check_replace(struct route_node *np2, struct route_entry *re2,
257 struct route_node **np, struct route_entry **re)
718e3744 258{
d62a17ae 259 int proto, proto2;
718e3744 260
d62a17ae 261 if (!*np) {
262 *np = np2;
263 *re = re2;
264 return;
265 }
718e3744 266
d62a17ae 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 *np = np2;
271 *re = re2;
272 return;
273 }
718e3744 274
d62a17ae 275 proto = proto_trans((*re)->type);
276 proto2 = proto_trans(re2->type);
718e3744 277
d62a17ae 278 if (proto2 > proto)
279 return;
280 if (proto2 < proto) {
281 *np = np2;
282 *re = re2;
283 return;
284 }
718e3744 285
d62a17ae 286 if (in_addr_cmp((u_char *)&(*re)->nexthop->gate.ipv4,
287 (u_char *)&re2->nexthop->gate.ipv4)
288 <= 0)
289 return;
718e3744 290
d62a17ae 291 *np = np2;
292 *re = re2;
293 return;
294}
718e3744 295
d62a17ae 296static void get_fwtable_route_node(struct variable *v, oid objid[],
297 size_t *objid_len, int exact,
298 struct route_node **np,
299 struct route_entry **re)
300{
301 struct in_addr dest;
302 struct route_table *table;
303 struct route_node *np2;
304 struct route_entry *re2;
305 int proto;
306 int policy;
307 struct in_addr nexthop;
308 u_char *pnt;
309 int i;
310
311 /* Init index variables */
312
313 pnt = (u_char *)&dest;
314 for (i = 0; i < 4; i++)
315 *pnt++ = 0;
718e3744 316
d62a17ae 317 pnt = (u_char *)&nexthop;
318 for (i = 0; i < 4; i++)
319 *pnt++ = 0;
07661cb5 320
d62a17ae 321 proto = 0;
322 policy = 0;
718e3744 323
d62a17ae 324 /* Init return variables */
718e3744 325
d62a17ae 326 *np = NULL;
327 *re = NULL;
718e3744 328
d62a17ae 329 /* Short circuit exact matches of wrong length */
718e3744 330
d62a17ae 331 if (exact && (*objid_len != (unsigned)v->namelen + 10))
332 return;
718e3744 333
d62a17ae 334 table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
335 if (!table)
336 return;
718e3744 337
d62a17ae 338 /* Get INDEX information out of OID.
339 * ipForwardDest, ipForwardProto, ipForwardPolicy, ipForwardNextHop
340 */
718e3744 341
d62a17ae 342 if (*objid_len > (unsigned)v->namelen)
343 oid2in_addr(objid + v->namelen,
344 MIN(4U, *objid_len - v->namelen), &dest);
718e3744 345
d62a17ae 346 if (*objid_len > (unsigned)v->namelen + 4)
347 proto = objid[v->namelen + 4];
348
349 if (*objid_len > (unsigned)v->namelen + 5)
350 policy = objid[v->namelen + 5];
351
352 if (*objid_len > (unsigned)v->namelen + 6)
353 oid2in_addr(objid + v->namelen + 6,
354 MIN(4U, *objid_len - v->namelen - 6), &nexthop);
355
356 /* Apply GETNEXT on not exact search */
357
358 if (!exact && (*objid_len >= (unsigned)v->namelen + 10)) {
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 if (policy) /* Not supported (yet?) */
367 return;
368 for (*np = route_top(table); *np; *np = route_next(*np)) {
369 if (!in_addr_cmp(&(*np)->p.u.prefix, (u_char *)&dest)) {
370 RNODE_FOREACH_RE(*np, *re)
371 {
372 if (!in_addr_cmp((u_char *)&(*re)
373 ->nexthop->gate
374 .ipv4,
375 (u_char *)&nexthop))
376 if (proto
377 == proto_trans((*re)->type))
378 return;
379 }
380 }
718e3744 381 }
d62a17ae 382 return;
718e3744 383 }
d62a17ae 384
385 /* Search next best entry */
386
387 for (np2 = route_top(table); np2; np2 = route_next(np2)) {
388
389 /* Check destination first */
390 if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest) > 0)
391 RNODE_FOREACH_RE(np2, re2)
f0f77c9a 392 check_replace(np2, re2, np, re);
d62a17ae 393
394 if (in_addr_cmp(&np2->p.u.prefix, (u_char *)&dest)
395 == 0) { /* have to look at each re individually */
396 RNODE_FOREACH_RE(np2, re2)
397 {
398 int proto2, policy2;
399
400 proto2 = proto_trans(re2->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 *)&re2->nexthop
407 ->gate.ipv4,
408 (u_char *)&nexthop)
409 >= 0)))
410 check_replace(np2, re2, np, re);
411 }
412 }
718e3744 413 }
718e3744 414
d62a17ae 415 if (!*re)
416 return;
718e3744 417
d62a17ae 418 policy = 0;
419 proto = proto_trans((*re)->type);
718e3744 420
d62a17ae 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++;
718e3744 425
d62a17ae 426 objid[v->namelen + 4] = proto;
427 objid[v->namelen + 5] = policy;
718e3744 428
d62a17ae 429 {
430 struct nexthop *nexthop;
718e3744 431
d62a17ae 432 nexthop = (*re)->nexthop;
433 if (nexthop) {
434 pnt = (u_char *)&nexthop->gate.ipv4;
435 for (i = 0; i < 4; i++)
436 objid[i + v->namelen + 6] = *pnt++;
437 }
438 }
718e3744 439
d62a17ae 440 return;
718e3744 441}
442
d62a17ae 443static u_char *ipFwTable(struct variable *v, oid objid[], size_t *objid_len,
444 int exact, size_t *val_len, WriteMethod **write_method)
718e3744 445{
d62a17ae 446 struct route_node *np;
447 struct route_entry *re;
448 static int result;
449 static int resarr[2];
450 static struct in_addr netmask;
451 struct nexthop *nexthop;
452
453 if (smux_header_table(v, objid, objid_len, exact, val_len, write_method)
454 == MATCH_FAILED)
455 return NULL;
456
457 get_fwtable_route_node(v, objid, objid_len, exact, &np, &re);
458 if (!np)
459 return NULL;
460
461 nexthop = re->nexthop;
462 if (!nexthop)
463 return NULL;
464
465 switch (v->magic) {
466 case IPFORWARDDEST:
467 *val_len = 4;
468 return &np->p.u.prefix;
469 break;
470 case IPFORWARDMASK:
471 masklen2ip(np->p.prefixlen, &netmask);
472 *val_len = 4;
473 return (u_char *)&netmask;
474 break;
475 case IPFORWARDPOLICY:
476 result = 0;
477 *val_len = sizeof(int);
478 return (u_char *)&result;
479 break;
480 case IPFORWARDNEXTHOP:
481 *val_len = 4;
482 return (u_char *)&nexthop->gate.ipv4;
483 break;
484 case IPFORWARDIFINDEX:
485 *val_len = sizeof(int);
486 return (u_char *)&nexthop->ifindex;
487 break;
488 case IPFORWARDTYPE:
489 if (nexthop->type == NEXTHOP_TYPE_IFINDEX)
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(re->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;
718e3744 547}
548
d62a17ae 549static u_char *ipCidrTable(struct variable *v, oid objid[], size_t *objid_len,
550 int exact, size_t *val_len,
551 WriteMethod **write_method)
718e3744 552{
d62a17ae 553 if (smux_header_table(v, objid, objid_len, exact, val_len, write_method)
554 == MATCH_FAILED)
555 return NULL;
556
557 switch (v->magic) {
558 case IPCIDRROUTEDEST:
559 break;
560 default:
561 return NULL;
562 break;
563 }
564 return NULL;
718e3744 565}
566
d62a17ae 567static int zebra_snmp_init(struct thread_master *tm)
718e3744 568{
d62a17ae 569 smux_init(tm);
570 REGISTER_MIB("mibII/ipforward", zebra_variables, variable, ipfw_oid);
571 return 0;
5986b66b
DL
572}
573
d62a17ae 574static int zebra_snmp_module_init(void)
5986b66b 575{
d62a17ae 576 hook_register(frr_late_init, zebra_snmp_init);
577 return 0;
718e3744 578}
5986b66b 579
d62a17ae 580FRR_MODULE_SETUP(.name = "zebra_snmp", .version = FRR_VERSION,
581 .description = "zebra AgentX SNMP module",
582 .init = zebra_snmp_module_init, )