]> git.proxmox.com Git - mirror_frr.git/blame - zebra/zebra_snmp.c
isisd: implement the 'lsp-too-large' notification
[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. */
d7c0a89a
QY
92static uint8_t *ipFwNumber(struct variable *, oid[], size_t *, int, size_t *,
93 WriteMethod **);
94static uint8_t *ipFwTable(struct variable *, oid[], size_t *, int, size_t *,
d62a17ae 95 WriteMethod **);
d7c0a89a
QY
96static uint8_t *ipCidrNumber(struct variable *, oid[], size_t *, int, size_t *,
97 WriteMethod **);
98static uint8_t *ipCidrTable(struct variable *, oid[], size_t *, int, size_t *,
d62a17ae 99 WriteMethod **);
d62a17ae 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
d7c0a89a
QY
137static uint8_t *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))
a2addae8 158 RNODE_FOREACH_RE (rn, re) {
407c87a6
DS
159 result++;
160 }
d62a17ae 161
d7c0a89a 162 return (uint8_t *)&result;
718e3744 163}
164
d7c0a89a
QY
165static uint8_t *ipCidrNumber(struct variable *v, oid objid[], size_t *objid_len,
166 int exact, size_t *val_len,
167 WriteMethod **write_method)
718e3744 168{
d62a17ae 169 static int result;
170 struct route_table *table;
171 struct route_node *rn;
172 struct route_entry *re;
173
174 if (smux_header_generic(v, objid, objid_len, exact, val_len,
175 write_method)
176 == MATCH_FAILED)
177 return NULL;
178
179 table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
180 if (!table)
181 return 0;
182
183 /* Return number of routing entries. */
184 result = 0;
185 for (rn = route_top(table); rn; rn = route_next(rn))
a2addae8 186 RNODE_FOREACH_RE (rn, re) {
407c87a6
DS
187 result++;
188 }
d62a17ae 189
d7c0a89a 190 return (uint8_t *)&result;
718e3744 191}
192
d7c0a89a 193static int in_addr_cmp(uint8_t *p1, uint8_t *p2)
718e3744 194{
d62a17ae 195 int i;
196
197 for (i = 0; i < 4; i++) {
198 if (*p1 < *p2)
199 return -1;
200 if (*p1 > *p2)
201 return 1;
202 p1++;
203 p2++;
204 }
205 return 0;
718e3744 206}
207
d7c0a89a 208static int in_addr_add(uint8_t *p, int num)
718e3744 209{
d62a17ae 210 int i, ip0;
211
212 ip0 = *p;
213 p += 4;
214 for (i = 3; 0 <= i; i--) {
215 p--;
216 if (*p + num > 255) {
217 *p += num;
218 num = 1;
219 } else {
220 *p += num;
221 return 1;
222 }
223 }
224 if (ip0 > *p) {
225 /* ip + num > 0xffffffff */
226 return 0;
227 }
718e3744 228
d62a17ae 229 return 1;
718e3744 230}
231
d62a17ae 232static int proto_trans(int type)
718e3744 233{
d62a17ae 234 switch (type) {
235 case ZEBRA_ROUTE_SYSTEM:
236 return 1; /* other */
237 case ZEBRA_ROUTE_KERNEL:
238 return 1; /* other */
239 case ZEBRA_ROUTE_CONNECT:
240 return 2; /* local interface */
241 case ZEBRA_ROUTE_STATIC:
242 return 3; /* static route */
243 case ZEBRA_ROUTE_RIP:
244 return 8; /* rip */
245 case ZEBRA_ROUTE_RIPNG:
246 return 1; /* shouldn't happen */
247 case ZEBRA_ROUTE_OSPF:
248 return 13; /* ospf */
249 case ZEBRA_ROUTE_OSPF6:
250 return 1; /* shouldn't happen */
251 case ZEBRA_ROUTE_BGP:
252 return 14; /* bgp */
253 default:
254 return 1; /* other */
255 }
718e3744 256}
257
d62a17ae 258static void check_replace(struct route_node *np2, struct route_entry *re2,
259 struct route_node **np, struct route_entry **re)
718e3744 260{
d62a17ae 261 int proto, proto2;
718e3744 262
d62a17ae 263 if (!*np) {
264 *np = np2;
265 *re = re2;
266 return;
267 }
718e3744 268
d62a17ae 269 if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) < 0)
270 return;
271 if (in_addr_cmp(&(*np)->p.u.prefix, &np2->p.u.prefix) > 0) {
272 *np = np2;
273 *re = re2;
274 return;
275 }
718e3744 276
d62a17ae 277 proto = proto_trans((*re)->type);
278 proto2 = proto_trans(re2->type);
718e3744 279
d62a17ae 280 if (proto2 > proto)
281 return;
282 if (proto2 < proto) {
283 *np = np2;
284 *re = re2;
285 return;
286 }
718e3744 287
d7c0a89a
QY
288 if (in_addr_cmp((uint8_t *)&(*re)->ng.nexthop->gate.ipv4,
289 (uint8_t *)&re2->ng.nexthop->gate.ipv4)
d62a17ae 290 <= 0)
291 return;
718e3744 292
d62a17ae 293 *np = np2;
294 *re = re2;
295 return;
296}
718e3744 297
d62a17ae 298static void get_fwtable_route_node(struct variable *v, oid objid[],
299 size_t *objid_len, int exact,
300 struct route_node **np,
301 struct route_entry **re)
302{
303 struct in_addr dest;
304 struct route_table *table;
305 struct route_node *np2;
306 struct route_entry *re2;
307 int proto;
308 int policy;
309 struct in_addr nexthop;
d7c0a89a 310 uint8_t *pnt;
d62a17ae 311 int i;
312
313 /* Init index variables */
314
d7c0a89a 315 pnt = (uint8_t *)&dest;
d62a17ae 316 for (i = 0; i < 4; i++)
317 *pnt++ = 0;
718e3744 318
d7c0a89a 319 pnt = (uint8_t *)&nexthop;
d62a17ae 320 for (i = 0; i < 4; i++)
321 *pnt++ = 0;
07661cb5 322
d62a17ae 323 proto = 0;
324 policy = 0;
718e3744 325
d62a17ae 326 /* Init return variables */
718e3744 327
d62a17ae 328 *np = NULL;
329 *re = NULL;
718e3744 330
d62a17ae 331 /* Short circuit exact matches of wrong length */
718e3744 332
d62a17ae 333 if (exact && (*objid_len != (unsigned)v->namelen + 10))
334 return;
718e3744 335
d62a17ae 336 table = zebra_vrf_table(AFI_IP, SAFI_UNICAST, VRF_DEFAULT);
337 if (!table)
338 return;
718e3744 339
d62a17ae 340 /* Get INDEX information out of OID.
341 * ipForwardDest, ipForwardProto, ipForwardPolicy, ipForwardNextHop
342 */
718e3744 343
d62a17ae 344 if (*objid_len > (unsigned)v->namelen)
345 oid2in_addr(objid + v->namelen,
346 MIN(4U, *objid_len - v->namelen), &dest);
718e3744 347
d62a17ae 348 if (*objid_len > (unsigned)v->namelen + 4)
349 proto = objid[v->namelen + 4];
350
351 if (*objid_len > (unsigned)v->namelen + 5)
352 policy = objid[v->namelen + 5];
353
354 if (*objid_len > (unsigned)v->namelen + 6)
355 oid2in_addr(objid + v->namelen + 6,
356 MIN(4U, *objid_len - v->namelen - 6), &nexthop);
357
358 /* Apply GETNEXT on not exact search */
359
360 if (!exact && (*objid_len >= (unsigned)v->namelen + 10)) {
d7c0a89a 361 if (!in_addr_add((uint8_t *)&nexthop, 1))
d62a17ae 362 return;
363 }
364
365 /* For exact: search matching entry in rib table. */
366
367 if (exact) {
368 if (policy) /* Not supported (yet?) */
369 return;
370 for (*np = route_top(table); *np; *np = route_next(*np)) {
d7c0a89a
QY
371 if (!in_addr_cmp(&(*np)->p.u.prefix,
372 (uint8_t *)&dest)) {
a2addae8 373 RNODE_FOREACH_RE (*np, *re) {
d7c0a89a
QY
374 if (!in_addr_cmp((uint8_t *)&(*re)
375 ->ng.nexthop
376 ->gate.ipv4,
377 (uint8_t *)&nexthop))
d62a17ae 378 if (proto
379 == proto_trans((*re)->type))
380 return;
381 }
382 }
718e3744 383 }
d62a17ae 384 return;
718e3744 385 }
d62a17ae 386
387 /* Search next best entry */
388
389 for (np2 = route_top(table); np2; np2 = route_next(np2)) {
390
391 /* Check destination first */
d7c0a89a 392 if (in_addr_cmp(&np2->p.u.prefix, (uint8_t *)&dest) > 0)
a2addae8 393 RNODE_FOREACH_RE (np2, re2) {
407c87a6
DS
394 check_replace(np2, re2, np, re);
395 }
d62a17ae 396
d7c0a89a 397 if (in_addr_cmp(&np2->p.u.prefix, (uint8_t *)&dest)
d62a17ae 398 == 0) { /* have to look at each re individually */
a2addae8 399 RNODE_FOREACH_RE (np2, re2) {
d62a17ae 400 int proto2, policy2;
401
402 proto2 = proto_trans(re2->type);
403 policy2 = 0;
404
405 if ((policy < policy2)
406 || ((policy == policy2) && (proto < proto2))
407 || ((policy == policy2) && (proto == proto2)
7ee30f28 408 && (in_addr_cmp(
d7c0a89a
QY
409 (uint8_t *)&re2->ng.nexthop
410 ->gate.ipv4,
411 (uint8_t *)&nexthop)
d62a17ae 412 >= 0)))
413 check_replace(np2, re2, np, re);
414 }
415 }
718e3744 416 }
718e3744 417
d62a17ae 418 if (!*re)
419 return;
718e3744 420
d62a17ae 421 policy = 0;
422 proto = proto_trans((*re)->type);
718e3744 423
d62a17ae 424 *objid_len = v->namelen + 10;
d7c0a89a 425 pnt = (uint8_t *)&(*np)->p.u.prefix;
d62a17ae 426 for (i = 0; i < 4; i++)
427 objid[v->namelen + i] = *pnt++;
718e3744 428
d62a17ae 429 objid[v->namelen + 4] = proto;
430 objid[v->namelen + 5] = policy;
718e3744 431
d62a17ae 432 {
433 struct nexthop *nexthop;
718e3744 434
7ee30f28 435 nexthop = (*re)->ng.nexthop;
d62a17ae 436 if (nexthop) {
d7c0a89a 437 pnt = (uint8_t *)&nexthop->gate.ipv4;
d62a17ae 438 for (i = 0; i < 4; i++)
439 objid[i + v->namelen + 6] = *pnt++;
440 }
441 }
718e3744 442
d62a17ae 443 return;
718e3744 444}
445
d7c0a89a
QY
446static uint8_t *ipFwTable(struct variable *v, oid objid[], size_t *objid_len,
447 int exact, size_t *val_len,
448 WriteMethod **write_method)
718e3744 449{
d62a17ae 450 struct route_node *np;
451 struct route_entry *re;
452 static int result;
453 static int resarr[2];
454 static struct in_addr netmask;
455 struct nexthop *nexthop;
456
457 if (smux_header_table(v, objid, objid_len, exact, val_len, write_method)
458 == MATCH_FAILED)
459 return NULL;
460
461 get_fwtable_route_node(v, objid, objid_len, exact, &np, &re);
462 if (!np)
463 return NULL;
464
7ee30f28 465 nexthop = re->ng.nexthop;
d62a17ae 466 if (!nexthop)
467 return NULL;
468
469 switch (v->magic) {
470 case IPFORWARDDEST:
471 *val_len = 4;
472 return &np->p.u.prefix;
473 break;
474 case IPFORWARDMASK:
475 masklen2ip(np->p.prefixlen, &netmask);
476 *val_len = 4;
d7c0a89a 477 return (uint8_t *)&netmask;
d62a17ae 478 break;
479 case IPFORWARDPOLICY:
480 result = 0;
481 *val_len = sizeof(int);
d7c0a89a 482 return (uint8_t *)&result;
d62a17ae 483 break;
484 case IPFORWARDNEXTHOP:
485 *val_len = 4;
d7c0a89a 486 return (uint8_t *)&nexthop->gate.ipv4;
d62a17ae 487 break;
488 case IPFORWARDIFINDEX:
489 *val_len = sizeof(int);
d7c0a89a 490 return (uint8_t *)&nexthop->ifindex;
d62a17ae 491 break;
492 case IPFORWARDTYPE:
493 if (nexthop->type == NEXTHOP_TYPE_IFINDEX)
494 result = 3;
495 else
496 result = 4;
497 *val_len = sizeof(int);
d7c0a89a 498 return (uint8_t *)&result;
d62a17ae 499 break;
500 case IPFORWARDPROTO:
501 result = proto_trans(re->type);
502 *val_len = sizeof(int);
d7c0a89a 503 return (uint8_t *)&result;
d62a17ae 504 break;
505 case IPFORWARDAGE:
506 result = 0;
507 *val_len = sizeof(int);
d7c0a89a 508 return (uint8_t *)&result;
d62a17ae 509 break;
510 case IPFORWARDINFO:
511 resarr[0] = 0;
512 resarr[1] = 0;
513 *val_len = 2 * sizeof(int);
d7c0a89a 514 return (uint8_t *)resarr;
d62a17ae 515 break;
516 case IPFORWARDNEXTHOPAS:
517 result = -1;
518 *val_len = sizeof(int);
d7c0a89a 519 return (uint8_t *)&result;
d62a17ae 520 break;
521 case IPFORWARDMETRIC1:
522 result = 0;
523 *val_len = sizeof(int);
d7c0a89a 524 return (uint8_t *)&result;
d62a17ae 525 break;
526 case IPFORWARDMETRIC2:
527 result = 0;
528 *val_len = sizeof(int);
d7c0a89a 529 return (uint8_t *)&result;
d62a17ae 530 break;
531 case IPFORWARDMETRIC3:
532 result = 0;
533 *val_len = sizeof(int);
d7c0a89a 534 return (uint8_t *)&result;
d62a17ae 535 break;
536 case IPFORWARDMETRIC4:
537 result = 0;
538 *val_len = sizeof(int);
d7c0a89a 539 return (uint8_t *)&result;
d62a17ae 540 break;
541 case IPFORWARDMETRIC5:
542 result = 0;
543 *val_len = sizeof(int);
d7c0a89a 544 return (uint8_t *)&result;
d62a17ae 545 break;
546 default:
547 return NULL;
548 break;
549 }
550 return NULL;
718e3744 551}
552
d7c0a89a
QY
553static uint8_t *ipCidrTable(struct variable *v, oid objid[], size_t *objid_len,
554 int exact, size_t *val_len,
555 WriteMethod **write_method)
718e3744 556{
d62a17ae 557 if (smux_header_table(v, objid, objid_len, exact, val_len, write_method)
558 == MATCH_FAILED)
559 return NULL;
560
561 switch (v->magic) {
562 case IPCIDRROUTEDEST:
563 break;
564 default:
565 return NULL;
566 break;
567 }
568 return NULL;
718e3744 569}
570
d62a17ae 571static int zebra_snmp_init(struct thread_master *tm)
718e3744 572{
d62a17ae 573 smux_init(tm);
574 REGISTER_MIB("mibII/ipforward", zebra_variables, variable, ipfw_oid);
575 return 0;
5986b66b
DL
576}
577
d62a17ae 578static int zebra_snmp_module_init(void)
5986b66b 579{
d62a17ae 580 hook_register(frr_late_init, zebra_snmp_init);
581 return 0;
718e3744 582}
5986b66b 583
d62a17ae 584FRR_MODULE_SETUP(.name = "zebra_snmp", .version = FRR_VERSION,
585 .description = "zebra AgentX SNMP module",
586 .init = zebra_snmp_module_init, )