]> git.proxmox.com Git - mirror_frr.git/blame - bgpd/bgp_snmp.c
Merge pull request #8637 from opensourcerouting/pim-vrf-acl-fixes
[mirror_frr.git] / bgpd / bgp_snmp.c
CommitLineData
718e3744 1/* BGP4 SNMP support
896014f4
DL
2 * Copyright (C) 1999, 2000 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 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
19 */
718e3744 20
21#include <zebra.h>
22
07661cb5 23#include <net-snmp/net-snmp-config.h>
fb62a3ce 24#include <net-snmp/net-snmp-includes.h>
718e3744 25
26#include "if.h"
27#include "log.h"
28#include "prefix.h"
29#include "command.h"
30#include "thread.h"
31#include "smux.h"
039f3a34 32#include "filter.h"
5986b66b
DL
33#include "hook.h"
34#include "libfrr.h"
09781197 35#include "lib/version.h"
718e3744 36
37#include "bgpd/bgpd.h"
38#include "bgpd/bgp_table.h"
39#include "bgpd/bgp_aspath.h"
40#include "bgpd/bgp_attr.h"
41#include "bgpd/bgp_route.h"
42#include "bgpd/bgp_fsm.h"
aa53f693 43#include "bgpd/bgp_mplsvpn_snmp.h"
6b0655a2 44
718e3744 45/* BGP4-MIB described in RFC1657. */
46#define BGP4MIB 1,3,6,1,2,1,15
47
020709f9 48/* BGP TRAP. */
49#define BGPESTABLISHED 1
c258527b 50#define BGPBACKWARDTRANSITION 2
020709f9 51
718e3744 52/* BGP MIB bgpVersion. */
53#define BGPVERSION 0
54
55/* BGP MIB bgpLocalAs. */
56#define BGPLOCALAS 0
57
58/* BGP MIB bgpPeerTable. */
59#define BGPPEERIDENTIFIER 1
60#define BGPPEERSTATE 2
61#define BGPPEERADMINSTATUS 3
62#define BGPPEERNEGOTIATEDVERSION 4
63#define BGPPEERLOCALADDR 5
64#define BGPPEERLOCALPORT 6
65#define BGPPEERREMOTEADDR 7
66#define BGPPEERREMOTEPORT 8
67#define BGPPEERREMOTEAS 9
68#define BGPPEERINUPDATES 10
69#define BGPPEEROUTUPDATES 11
70#define BGPPEERINTOTALMESSAGES 12
71#define BGPPEEROUTTOTALMESSAGES 13
72#define BGPPEERLASTERROR 14
73#define BGPPEERFSMESTABLISHEDTRANSITIONS 15
74#define BGPPEERFSMESTABLISHEDTIME 16
75#define BGPPEERCONNECTRETRYINTERVAL 17
76#define BGPPEERHOLDTIME 18
77#define BGPPEERKEEPALIVE 19
78#define BGPPEERHOLDTIMECONFIGURED 20
79#define BGPPEERKEEPALIVECONFIGURED 21
bd4b893f
DW
80#define BGPPEERMINROUTEADVERTISEMENTINTERVAL 22
81#define BGPPEERINUPDATEELAPSEDTIME 23
718e3744 82
83/* BGP MIB bgpIdentifier. */
84#define BGPIDENTIFIER 0
85
86/* BGP MIB bgpRcvdPathAttrTable */
87#define BGPPATHATTRPEER 1
88#define BGPPATHATTRDESTNETWORK 2
89#define BGPPATHATTRORIGIN 3
90#define BGPPATHATTRASPATH 4
91#define BGPPATHATTRNEXTHOP 5
92#define BGPPATHATTRINTERASMETRIC 6
93
94/* BGP MIB bgp4PathAttrTable. */
95#define BGP4PATHATTRPEER 1
96#define BGP4PATHATTRIPADDRPREFIXLEN 2
97#define BGP4PATHATTRIPADDRPREFIX 3
98#define BGP4PATHATTRORIGIN 4
99#define BGP4PATHATTRASPATHSEGMENT 5
100#define BGP4PATHATTRNEXTHOP 6
101#define BGP4PATHATTRMULTIEXITDISC 7
102#define BGP4PATHATTRLOCALPREF 8
103#define BGP4PATHATTRATOMICAGGREGATE 9
104#define BGP4PATHATTRAGGREGATORAS 10
105#define BGP4PATHATTRAGGREGATORADDR 11
106#define BGP4PATHATTRCALCLOCALPREF 12
107#define BGP4PATHATTRBEST 13
108#define BGP4PATHATTRUNKNOWN 14
109
110/* SNMP value hack. */
111#define INTEGER ASN_INTEGER
112#define INTEGER32 ASN_INTEGER
113#define COUNTER32 ASN_COUNTER
114#define OCTET_STRING ASN_OCTET_STR
115#define IPADDRESS ASN_IPADDRESS
116#define GAUGE32 ASN_UNSIGNED
6b0655a2 117
718e3744 118/* Declare static local variables for convenience. */
119SNMP_LOCAL_VARIABLES
120
121/* BGP-MIB instances. */
d62a17ae 122static oid bgp_oid[] = {BGP4MIB};
123static oid bgp_trap_oid[] = {BGP4MIB, 0};
718e3744 124
125/* IP address 0.0.0.0. */
d62a17ae 126static struct in_addr bgp_empty_addr = {.s_addr = 0};
718e3744 127
128/* Hook functions. */
d7c0a89a
QY
129static uint8_t *bgpVersion(struct variable *, oid[], size_t *, int, size_t *,
130 WriteMethod **);
131static uint8_t *bgpLocalAs(struct variable *, oid[], size_t *, int, size_t *,
132 WriteMethod **);
133static uint8_t *bgpPeerTable(struct variable *, oid[], size_t *, int, size_t *,
d62a17ae 134 WriteMethod **);
d7c0a89a
QY
135static uint8_t *bgpRcvdPathAttrTable(struct variable *, oid[], size_t *, int,
136 size_t *, WriteMethod **);
137static uint8_t *bgpIdentifier(struct variable *, oid[], size_t *, int, size_t *,
138 WriteMethod **);
139static uint8_t *bgp4PathAttrTable(struct variable *, oid[], size_t *, int,
140 size_t *, WriteMethod **);
141/* static uint8_t *bgpTraps (); */
718e3744 142
d62a17ae 143static struct variable bgp_variables[] = {
144 /* BGP version. */
145 {BGPVERSION, OCTET_STRING, RONLY, bgpVersion, 1, {1}},
146 /* BGP local AS. */
147 {BGPLOCALAS, INTEGER, RONLY, bgpLocalAs, 1, {2}},
148 /* BGP peer table. */
149 {BGPPEERIDENTIFIER, IPADDRESS, RONLY, bgpPeerTable, 3, {3, 1, 1}},
150 {BGPPEERSTATE, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 2}},
151 {BGPPEERADMINSTATUS, INTEGER, RWRITE, bgpPeerTable, 3, {3, 1, 3}},
152 {BGPPEERNEGOTIATEDVERSION,
153 INTEGER32,
154 RONLY,
155 bgpPeerTable,
156 3,
157 {3, 1, 4}},
158 {BGPPEERLOCALADDR, IPADDRESS, RONLY, bgpPeerTable, 3, {3, 1, 5}},
159 {BGPPEERLOCALPORT, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 6}},
160 {BGPPEERREMOTEADDR, IPADDRESS, RONLY, bgpPeerTable, 3, {3, 1, 7}},
161 {BGPPEERREMOTEPORT, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 8}},
162 {BGPPEERREMOTEAS, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 9}},
163 {BGPPEERINUPDATES, COUNTER32, RONLY, bgpPeerTable, 3, {3, 1, 10}},
164 {BGPPEEROUTUPDATES, COUNTER32, RONLY, bgpPeerTable, 3, {3, 1, 11}},
165 {BGPPEERINTOTALMESSAGES, COUNTER32, RONLY, bgpPeerTable, 3, {3, 1, 12}},
166 {BGPPEEROUTTOTALMESSAGES,
167 COUNTER32,
168 RONLY,
169 bgpPeerTable,
170 3,
171 {3, 1, 13}},
172 {BGPPEERLASTERROR, OCTET_STRING, RONLY, bgpPeerTable, 3, {3, 1, 14}},
173 {BGPPEERFSMESTABLISHEDTRANSITIONS,
174 COUNTER32,
175 RONLY,
176 bgpPeerTable,
177 3,
178 {3, 1, 15}},
179 {BGPPEERFSMESTABLISHEDTIME,
180 GAUGE32,
181 RONLY,
182 bgpPeerTable,
183 3,
184 {3, 1, 16}},
185 {BGPPEERCONNECTRETRYINTERVAL,
186 INTEGER,
187 RWRITE,
188 bgpPeerTable,
189 3,
190 {3, 1, 17}},
191 {BGPPEERHOLDTIME, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 18}},
192 {BGPPEERKEEPALIVE, INTEGER, RONLY, bgpPeerTable, 3, {3, 1, 19}},
193 {BGPPEERHOLDTIMECONFIGURED,
194 INTEGER,
195 RWRITE,
196 bgpPeerTable,
197 3,
198 {3, 1, 20}},
199 {BGPPEERKEEPALIVECONFIGURED,
200 INTEGER,
201 RWRITE,
202 bgpPeerTable,
203 3,
204 {3, 1, 21}},
205 {BGPPEERMINROUTEADVERTISEMENTINTERVAL,
206 INTEGER,
207 RWRITE,
208 bgpPeerTable,
209 3,
210 {3, 1, 23}},
211 {BGPPEERINUPDATEELAPSEDTIME,
212 GAUGE32,
213 RONLY,
214 bgpPeerTable,
215 3,
216 {3, 1, 24}},
217 /* BGP identifier. */
218 {BGPIDENTIFIER, IPADDRESS, RONLY, bgpIdentifier, 1, {4}},
219 /* BGP received path attribute table. */
220 {BGPPATHATTRPEER, IPADDRESS, RONLY, bgpRcvdPathAttrTable, 3, {5, 1, 1}},
221 {BGPPATHATTRDESTNETWORK,
222 IPADDRESS,
223 RONLY,
224 bgpRcvdPathAttrTable,
225 3,
226 {5, 1, 2}},
227 {BGPPATHATTRORIGIN, INTEGER, RONLY, bgpRcvdPathAttrTable, 3, {5, 1, 3}},
228 {BGPPATHATTRASPATH,
229 OCTET_STRING,
230 RONLY,
231 bgpRcvdPathAttrTable,
232 3,
233 {5, 1, 4}},
234 {BGPPATHATTRNEXTHOP,
235 IPADDRESS,
236 RONLY,
237 bgpRcvdPathAttrTable,
238 3,
239 {5, 1, 5}},
240 {BGPPATHATTRINTERASMETRIC,
241 INTEGER32,
242 RONLY,
243 bgpRcvdPathAttrTable,
244 3,
245 {5, 1, 6}},
246 /* BGP-4 received path attribute table. */
247 {BGP4PATHATTRPEER, IPADDRESS, RONLY, bgp4PathAttrTable, 3, {6, 1, 1}},
248 {BGP4PATHATTRIPADDRPREFIXLEN,
249 INTEGER,
250 RONLY,
251 bgp4PathAttrTable,
252 3,
253 {6, 1, 2}},
254 {BGP4PATHATTRIPADDRPREFIX,
255 IPADDRESS,
256 RONLY,
257 bgp4PathAttrTable,
258 3,
259 {6, 1, 3}},
260 {BGP4PATHATTRORIGIN, INTEGER, RONLY, bgp4PathAttrTable, 3, {6, 1, 4}},
261 {BGP4PATHATTRASPATHSEGMENT,
262 OCTET_STRING,
263 RONLY,
264 bgp4PathAttrTable,
265 3,
266 {6, 1, 5}},
267 {BGP4PATHATTRNEXTHOP,
268 IPADDRESS,
269 RONLY,
270 bgp4PathAttrTable,
271 3,
272 {6, 1, 6}},
273 {BGP4PATHATTRMULTIEXITDISC,
274 INTEGER,
275 RONLY,
276 bgp4PathAttrTable,
277 3,
278 {6, 1, 7}},
279 {BGP4PATHATTRLOCALPREF,
280 INTEGER,
281 RONLY,
282 bgp4PathAttrTable,
283 3,
284 {6, 1, 8}},
285 {BGP4PATHATTRATOMICAGGREGATE,
286 INTEGER,
287 RONLY,
288 bgp4PathAttrTable,
289 3,
290 {6, 1, 9}},
291 {BGP4PATHATTRAGGREGATORAS,
292 INTEGER,
293 RONLY,
294 bgp4PathAttrTable,
295 3,
296 {6, 1, 10}},
297 {BGP4PATHATTRAGGREGATORADDR,
298 IPADDRESS,
299 RONLY,
300 bgp4PathAttrTable,
301 3,
302 {6, 1, 11}},
303 {BGP4PATHATTRCALCLOCALPREF,
304 INTEGER,
305 RONLY,
306 bgp4PathAttrTable,
307 3,
308 {6, 1, 12}},
309 {BGP4PATHATTRBEST, INTEGER, RONLY, bgp4PathAttrTable, 3, {6, 1, 13}},
310 {BGP4PATHATTRUNKNOWN,
311 OCTET_STRING,
312 RONLY,
313 bgp4PathAttrTable,
314 3,
315 {6, 1, 14}},
718e3744 316};
dd488a78 317
6b0655a2 318
d7c0a89a
QY
319static uint8_t *bgpVersion(struct variable *v, oid name[], size_t *length,
320 int exact, size_t *var_len,
321 WriteMethod **write_method)
718e3744 322{
d7c0a89a 323 static uint8_t version;
718e3744 324
d62a17ae 325 if (smux_header_generic(v, name, length, exact, var_len, write_method)
326 == MATCH_FAILED)
327 return NULL;
718e3744 328
d62a17ae 329 /* Retrun BGP version. Zebra bgpd only support version 4. */
330 version = (0x80 >> (BGP_VERSION_4 - 1));
718e3744 331
d62a17ae 332 /* Return octet string length 1. */
333 *var_len = 1;
c4efd0f4 334 return &version;
718e3744 335}
336
d7c0a89a
QY
337static uint8_t *bgpLocalAs(struct variable *v, oid name[], size_t *length,
338 int exact, size_t *var_len,
339 WriteMethod **write_method)
718e3744 340{
d62a17ae 341 struct bgp *bgp;
718e3744 342
d62a17ae 343 if (smux_header_generic(v, name, length, exact, var_len, write_method)
344 == MATCH_FAILED)
345 return NULL;
718e3744 346
d62a17ae 347 /* Get BGP structure. */
348 bgp = bgp_get_default();
349 if (!bgp)
350 return NULL;
718e3744 351
d62a17ae 352 return SNMP_INTEGER(bgp->as);
718e3744 353}
354
d62a17ae 355static struct peer *peer_lookup_addr_ipv4(struct in_addr *src)
718e3744 356{
d62a17ae 357 struct bgp *bgp;
358 struct peer *peer;
359 struct listnode *node;
55443115 360 struct listnode *bgpnode;
d62a17ae 361
55443115
VB
362 for (ALL_LIST_ELEMENTS_RO(bm->bgp, bgpnode, bgp)) {
363 for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
364 if (sockunion_family(&peer->su) != AF_INET)
365 continue;
d62a17ae 366
55443115
VB
367 if (sockunion2ip(&peer->su) == src->s_addr)
368 return peer;
369 }
718e3744 370 }
2b8e62f2 371
d62a17ae 372 return NULL;
718e3744 373}
374
d62a17ae 375static struct peer *bgp_peer_lookup_next(struct in_addr *src)
718e3744 376{
d62a17ae 377 struct bgp *bgp;
378 struct peer *peer;
2b8e62f2 379 struct peer *next_peer = NULL;
d62a17ae 380 struct listnode *node;
55443115
VB
381 struct listnode *bgpnode;
382
383 for (ALL_LIST_ELEMENTS_RO(bm->bgp, bgpnode, bgp)) {
384 for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
385 if (sockunion_family(&peer->su) != AF_INET)
386 continue;
387 if (ntohl(sockunion2ip(&peer->su)) <= ntohl(src->s_addr))
388 continue;
389
390 if (!next_peer
391 || ntohl(sockunion2ip(&next_peer->su))
392 > ntohl(sockunion2ip(&peer->su))) {
393 next_peer = peer;
394 }
d62a17ae 395 }
718e3744 396 }
2b8e62f2
PM
397
398 if (next_peer) {
399 src->s_addr = sockunion2ip(&next_peer->su);
400 return next_peer;
401 }
402
d62a17ae 403 return NULL;
718e3744 404}
405
9a8382f1
DL
406/* 1.3.6.1.2.1.15.3.1.x = 10 */
407#define PEERTAB_NAMELEN 10
408
d62a17ae 409static struct peer *bgpPeerTable_lookup(struct variable *v, oid name[],
410 size_t *length, struct in_addr *addr,
411 int exact)
718e3744 412{
d62a17ae 413 struct peer *peer = NULL;
414 size_t namelen = v ? v->namelen : PEERTAB_NAMELEN;
415 int len;
718e3744 416
d62a17ae 417 if (exact) {
418 /* Check the length. */
419 if (*length - namelen != sizeof(struct in_addr))
420 return NULL;
421
422 oid2in_addr(name + namelen, IN_ADDR_SIZE, addr);
423
424 peer = peer_lookup_addr_ipv4(addr);
425 return peer;
426 } else {
427 len = *length - namelen;
428 if (len > 4)
429 len = 4;
718e3744 430
d62a17ae 431 oid2in_addr(name + namelen, len, addr);
718e3744 432
d62a17ae 433 peer = bgp_peer_lookup_next(addr);
434
435 if (peer == NULL)
436 return NULL;
437
9e263221 438 oid_copy_in_addr(name + namelen, addr);
d62a17ae 439 *length = sizeof(struct in_addr) + namelen;
440
441 return peer;
442 }
443 return NULL;
718e3744 444}
445
446/* BGP write methods. */
d7c0a89a
QY
447static int write_bgpPeerTable(int action, uint8_t *var_val,
448 uint8_t var_val_type, size_t var_val_len,
449 uint8_t *statP, oid *name, size_t length)
718e3744 450{
d62a17ae 451 struct in_addr addr;
452 struct peer *peer;
453 long intval;
9a8382f1 454
d62a17ae 455 if (var_val_type != ASN_INTEGER) {
456 return SNMP_ERR_WRONGTYPE;
457 }
458 if (var_val_len != sizeof(long)) {
459 return SNMP_ERR_WRONGLENGTH;
460 }
718e3744 461
d62a17ae 462 intval = *(long *)var_val;
718e3744 463
d62a17ae 464 memset(&addr, 0, sizeof(struct in_addr));
718e3744 465
d62a17ae 466 peer = bgpPeerTable_lookup(NULL, name, &length, &addr, 1);
467 if (!peer)
468 return SNMP_ERR_NOSUCHNAME;
718e3744 469
d62a17ae 470 if (action != SNMP_MSG_INTERNAL_SET_COMMIT)
471 return SNMP_ERR_NOERROR;
9a8382f1 472
d62a17ae 473 zlog_info("%s: SNMP write .%ld = %ld", peer->host,
474 (long)name[PEERTAB_NAMELEN - 1], intval);
718e3744 475
d62a17ae 476 switch (name[PEERTAB_NAMELEN - 1]) {
477 case BGPPEERADMINSTATUS:
718e3744 478#define BGP_PeerAdmin_stop 1
479#define BGP_PeerAdmin_start 2
d62a17ae 480 /* When the peer is established, */
481 if (intval == BGP_PeerAdmin_stop)
482 BGP_EVENT_ADD(peer, BGP_Stop);
483 else if (intval == BGP_PeerAdmin_start)
484 ; /* Do nothing. */
485 else
486 return SNMP_ERR_NOSUCHNAME;
487 break;
488 case BGPPEERCONNECTRETRYINTERVAL:
b90a8e13 489 peer_flag_set(peer, PEER_FLAG_TIMER_CONNECT);
d62a17ae 490 peer->connect = intval;
491 peer->v_connect = intval;
492 break;
493 case BGPPEERHOLDTIMECONFIGURED:
b90a8e13 494 peer_flag_set(peer, PEER_FLAG_TIMER);
d62a17ae 495 peer->holdtime = intval;
496 peer->v_holdtime = intval;
497 break;
498 case BGPPEERKEEPALIVECONFIGURED:
b90a8e13 499 peer_flag_set(peer, PEER_FLAG_TIMER);
d62a17ae 500 peer->keepalive = intval;
501 peer->v_keepalive = intval;
502 break;
503 case BGPPEERMINROUTEADVERTISEMENTINTERVAL:
504 peer->v_routeadv = intval;
505 break;
506 }
507 return SNMP_ERR_NOERROR;
718e3744 508}
509
d7c0a89a
QY
510static uint8_t *bgpPeerTable(struct variable *v, oid name[], size_t *length,
511 int exact, size_t *var_len,
512 WriteMethod **write_method)
718e3744 513{
d62a17ae 514 static struct in_addr addr;
515 struct peer *peer;
0112e9e0 516 uint32_t ui, uo;
d62a17ae 517
518 if (smux_header_table(v, name, length, exact, var_len, write_method)
519 == MATCH_FAILED)
520 return NULL;
521 memset(&addr, 0, sizeof(struct in_addr));
522
523 peer = bgpPeerTable_lookup(v, name, length, &addr, exact);
524 if (!peer)
525 return NULL;
526
527 switch (v->magic) {
528 case BGPPEERIDENTIFIER:
529 return SNMP_IPADDRESS(peer->remote_id);
d62a17ae 530 case BGPPEERSTATE:
531 return SNMP_INTEGER(peer->status);
d62a17ae 532 case BGPPEERADMINSTATUS:
533 *write_method = write_bgpPeerTable;
718e3744 534#define BGP_PeerAdmin_stop 1
535#define BGP_PeerAdmin_start 2
d62a17ae 536 if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN))
537 return SNMP_INTEGER(BGP_PeerAdmin_stop);
538 else
539 return SNMP_INTEGER(BGP_PeerAdmin_start);
d62a17ae 540 case BGPPEERNEGOTIATEDVERSION:
541 return SNMP_INTEGER(BGP_VERSION_4);
d62a17ae 542 case BGPPEERLOCALADDR:
543 if (peer->su_local)
544 return SNMP_IPADDRESS(peer->su_local->sin.sin_addr);
545 else
546 return SNMP_IPADDRESS(bgp_empty_addr);
d62a17ae 547 case BGPPEERLOCALPORT:
548 if (peer->su_local)
549 return SNMP_INTEGER(
550 ntohs(peer->su_local->sin.sin_port));
551 else
552 return SNMP_INTEGER(0);
d62a17ae 553 case BGPPEERREMOTEADDR:
554 if (peer->su_remote)
555 return SNMP_IPADDRESS(peer->su_remote->sin.sin_addr);
556 else
557 return SNMP_IPADDRESS(bgp_empty_addr);
d62a17ae 558 case BGPPEERREMOTEPORT:
559 if (peer->su_remote)
560 return SNMP_INTEGER(
561 ntohs(peer->su_remote->sin.sin_port));
562 else
563 return SNMP_INTEGER(0);
d62a17ae 564 case BGPPEERREMOTEAS:
565 return SNMP_INTEGER(peer->as);
d62a17ae 566 case BGPPEERINUPDATES:
0112e9e0
QY
567 ui = atomic_load_explicit(&peer->update_in,
568 memory_order_relaxed);
569 return SNMP_INTEGER(ui);
d62a17ae 570 case BGPPEEROUTUPDATES:
0112e9e0
QY
571 uo = atomic_load_explicit(&peer->update_out,
572 memory_order_relaxed);
573 return SNMP_INTEGER(uo);
d62a17ae 574 case BGPPEERINTOTALMESSAGES:
0112e9e0 575 return SNMP_INTEGER(PEER_TOTAL_RX(peer));
d62a17ae 576 case BGPPEEROUTTOTALMESSAGES:
0112e9e0 577 return SNMP_INTEGER(PEER_TOTAL_TX(peer));
d62a17ae 578 case BGPPEERLASTERROR: {
d7c0a89a 579 static uint8_t lasterror[2];
d62a17ae 580 lasterror[0] = peer->notify.code;
581 lasterror[1] = peer->notify.subcode;
582 *var_len = 2;
d7c0a89a 583 return (uint8_t *)&lasterror;
75202267 584 }
d62a17ae 585 case BGPPEERFSMESTABLISHEDTRANSITIONS:
586 return SNMP_INTEGER(peer->established);
d62a17ae 587 case BGPPEERFSMESTABLISHEDTIME:
588 if (peer->uptime == 0)
589 return SNMP_INTEGER(0);
590 else
591 return SNMP_INTEGER(bgp_clock() - peer->uptime);
d62a17ae 592 case BGPPEERCONNECTRETRYINTERVAL:
593 *write_method = write_bgpPeerTable;
594 return SNMP_INTEGER(peer->v_connect);
d62a17ae 595 case BGPPEERHOLDTIME:
596 return SNMP_INTEGER(peer->v_holdtime);
d62a17ae 597 case BGPPEERKEEPALIVE:
598 return SNMP_INTEGER(peer->v_keepalive);
d62a17ae 599 case BGPPEERHOLDTIMECONFIGURED:
600 *write_method = write_bgpPeerTable;
b90a8e13 601 if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER))
d62a17ae 602 return SNMP_INTEGER(peer->holdtime);
603 else
604 return SNMP_INTEGER(peer->v_holdtime);
d62a17ae 605 case BGPPEERKEEPALIVECONFIGURED:
606 *write_method = write_bgpPeerTable;
b90a8e13 607 if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER))
d62a17ae 608 return SNMP_INTEGER(peer->keepalive);
609 else
610 return SNMP_INTEGER(peer->v_keepalive);
d62a17ae 611 case BGPPEERMINROUTEADVERTISEMENTINTERVAL:
612 *write_method = write_bgpPeerTable;
613 return SNMP_INTEGER(peer->v_routeadv);
d62a17ae 614 case BGPPEERINUPDATEELAPSEDTIME:
615 if (peer->update_time == 0)
616 return SNMP_INTEGER(0);
617 else
618 return SNMP_INTEGER(bgp_clock() - peer->update_time);
d62a17ae 619 default:
620 return NULL;
d62a17ae 621 }
622 return NULL;
718e3744 623}
624
d7c0a89a
QY
625static uint8_t *bgpIdentifier(struct variable *v, oid name[], size_t *length,
626 int exact, size_t *var_len,
627 WriteMethod **write_method)
718e3744 628{
d62a17ae 629 struct bgp *bgp;
718e3744 630
d62a17ae 631 if (smux_header_generic(v, name, length, exact, var_len, write_method)
632 == MATCH_FAILED)
633 return NULL;
718e3744 634
d62a17ae 635 bgp = bgp_get_default();
636 if (!bgp)
637 return NULL;
718e3744 638
d62a17ae 639 return SNMP_IPADDRESS(bgp->router_id);
718e3744 640}
641
d7c0a89a
QY
642static uint8_t *bgpRcvdPathAttrTable(struct variable *v, oid name[],
643 size_t *length, int exact, size_t *var_len,
644 WriteMethod **write_method)
718e3744 645{
d62a17ae 646 /* Received Path Attribute Table. This table contains, one entry
647 per path to a network, path attributes received from all peers
648 running BGP version 3 or less. This table is obsolete, having
649 been replaced in functionality with the bgp4PathAttrTable. */
650 return NULL;
718e3744 651}
652
4b7e6066
DS
653static struct bgp_path_info *bgp4PathAttrLookup(struct variable *v, oid name[],
654 size_t *length, struct bgp *bgp,
655 struct prefix_ipv4 *addr,
656 int exact)
718e3744 657{
d62a17ae 658 oid *offset;
659 int offsetlen;
9b6d8fcf 660 struct bgp_path_info *path;
4b7e6066 661 struct bgp_path_info *min;
9bcb3eef 662 struct bgp_dest *dest;
d62a17ae 663 union sockunion su;
664 unsigned int len;
665 struct in_addr paddr;
666
667 sockunion_init(&su);
668
669#define BGP_PATHATTR_ENTRY_OFFSET (IN_ADDR_SIZE + 1 + IN_ADDR_SIZE)
670
671 if (exact) {
672 if (*length - v->namelen != BGP_PATHATTR_ENTRY_OFFSET)
673 return NULL;
674
675 /* Set OID offset for prefix. */
676 offset = name + v->namelen;
677 oid2in_addr(offset, IN_ADDR_SIZE, &addr->prefix);
678 offset += IN_ADDR_SIZE;
679
680 /* Prefix length. */
681 addr->prefixlen = *offset;
682 offset++;
683
684 /* Peer address. */
685 su.sin.sin_family = AF_INET;
686 oid2in_addr(offset, IN_ADDR_SIZE, &su.sin.sin_addr);
687
688 /* Lookup node. */
9bcb3eef
DS
689 dest = bgp_node_lookup(bgp->rib[AFI_IP][SAFI_UNICAST],
690 (struct prefix *)addr);
691 if (dest) {
9bcb3eef 692 for (path = bgp_dest_get_bgp_path_info(dest); path;
6f94b685 693 path = path->next)
9b6d8fcf
DS
694 if (sockunion_same(&path->peer->su, &su))
695 return path;
e71ad4b6
DA
696
697 bgp_dest_unlock_node(dest);
d62a17ae 698 }
699 } else {
700 offset = name + v->namelen;
701 offsetlen = *length - v->namelen;
702 len = offsetlen;
718e3744 703
d62a17ae 704 if (offsetlen == 0)
9bcb3eef 705 dest = bgp_table_top(bgp->rib[AFI_IP][SAFI_UNICAST]);
d62a17ae 706 else {
707 if (len > IN_ADDR_SIZE)
708 len = IN_ADDR_SIZE;
718e3744 709
d62a17ae 710 oid2in_addr(offset, len, &addr->prefix);
718e3744 711
d62a17ae 712 offset += IN_ADDR_SIZE;
713 offsetlen -= IN_ADDR_SIZE;
718e3744 714
d62a17ae 715 if (offsetlen > 0)
716 addr->prefixlen = *offset;
717 else
718 addr->prefixlen = len * 8;
718e3744 719
9bcb3eef
DS
720 dest = bgp_node_get(bgp->rib[AFI_IP][SAFI_UNICAST],
721 (struct prefix *)addr);
718e3744 722
d62a17ae 723 offset++;
724 offsetlen--;
725 }
718e3744 726
d62a17ae 727 if (offsetlen > 0) {
728 len = offsetlen;
729 if (len > IN_ADDR_SIZE)
730 len = IN_ADDR_SIZE;
731
732 oid2in_addr(offset, len, &paddr);
733 } else
975a328e 734 paddr.s_addr = INADDR_ANY;
d62a17ae 735
9bcb3eef 736 if (!dest)
d62a17ae 737 return NULL;
738
739 do {
740 min = NULL;
741
9bcb3eef 742 for (path = bgp_dest_get_bgp_path_info(dest); path;
6f94b685 743 path = path->next) {
9b6d8fcf 744 if (path->peer->su.sin.sin_family == AF_INET
d62a17ae 745 && ntohl(paddr.s_addr)
9b6d8fcf 746 < ntohl(path->peer->su.sin
d62a17ae 747 .sin_addr
748 .s_addr)) {
749 if (min) {
9b6d8fcf 750 if (ntohl(path->peer->su.sin
d62a17ae 751 .sin_addr
752 .s_addr)
753 < ntohl(min->peer->su.sin
754 .sin_addr
755 .s_addr))
9b6d8fcf 756 min = path;
d62a17ae 757 } else
9b6d8fcf 758 min = path;
d62a17ae 759 }
760 }
761
762 if (min) {
b54892e0 763 const struct prefix *rn_p =
9bcb3eef 764 bgp_dest_get_prefix(dest);
b54892e0 765
d62a17ae 766 *length =
767 v->namelen + BGP_PATHATTR_ENTRY_OFFSET;
768
769 offset = name + v->namelen;
9e263221 770 oid_copy_in_addr(offset, &rn_p->u.prefix4);
d62a17ae 771 offset += IN_ADDR_SIZE;
b54892e0 772 *offset = rn_p->prefixlen;
d62a17ae 773 offset++;
9e263221
PR
774 oid_copy_in_addr(offset,
775 &min->peer->su.sin.sin_addr);
b54892e0
DS
776 addr->prefix = rn_p->u.prefix4;
777 addr->prefixlen = rn_p->prefixlen;
d62a17ae 778
9bcb3eef 779 bgp_dest_unlock_node(dest);
d62a17ae 780
781 return min;
782 }
783
975a328e 784 paddr.s_addr = INADDR_ANY;
9bcb3eef 785 } while ((dest = bgp_route_next(dest)) != NULL);
718e3744 786 }
d62a17ae 787 return NULL;
718e3744 788}
789
d7c0a89a
QY
790static uint8_t *bgp4PathAttrTable(struct variable *v, oid name[],
791 size_t *length, int exact, size_t *var_len,
792 WriteMethod **write_method)
718e3744 793{
d62a17ae 794 struct bgp *bgp;
9b6d8fcf 795 struct bgp_path_info *path;
d62a17ae 796 struct prefix_ipv4 addr;
797
798 bgp = bgp_get_default();
799 if (!bgp)
800 return NULL;
801
802 if (smux_header_table(v, name, length, exact, var_len, write_method)
803 == MATCH_FAILED)
804 return NULL;
805 memset(&addr, 0, sizeof(struct prefix_ipv4));
806
9b6d8fcf
DS
807 path = bgp4PathAttrLookup(v, name, length, bgp, &addr, exact);
808 if (!path)
d62a17ae 809 return NULL;
810
811 switch (v->magic) {
812 case BGP4PATHATTRPEER: /* 1 */
9b6d8fcf 813 return SNMP_IPADDRESS(path->peer->su.sin.sin_addr);
d62a17ae 814 case BGP4PATHATTRIPADDRPREFIXLEN: /* 2 */
815 return SNMP_INTEGER(addr.prefixlen);
d62a17ae 816 case BGP4PATHATTRIPADDRPREFIX: /* 3 */
817 return SNMP_IPADDRESS(addr.prefix);
d62a17ae 818 case BGP4PATHATTRORIGIN: /* 4 */
9b6d8fcf 819 return SNMP_INTEGER(path->attr->origin);
d62a17ae 820 case BGP4PATHATTRASPATHSEGMENT: /* 5 */
9b6d8fcf 821 return aspath_snmp_pathseg(path->attr->aspath, var_len);
d62a17ae 822 case BGP4PATHATTRNEXTHOP: /* 6 */
9b6d8fcf 823 return SNMP_IPADDRESS(path->attr->nexthop);
d62a17ae 824 case BGP4PATHATTRMULTIEXITDISC: /* 7 */
9b6d8fcf 825 return SNMP_INTEGER(path->attr->med);
d62a17ae 826 case BGP4PATHATTRLOCALPREF: /* 8 */
9b6d8fcf 827 return SNMP_INTEGER(path->attr->local_pref);
d62a17ae 828 case BGP4PATHATTRATOMICAGGREGATE: /* 9 */
829 return SNMP_INTEGER(1);
d62a17ae 830 case BGP4PATHATTRAGGREGATORAS: /* 10 */
9b6d8fcf 831 return SNMP_INTEGER(path->attr->aggregator_as);
d62a17ae 832 case BGP4PATHATTRAGGREGATORADDR: /* 11 */
9b6d8fcf 833 return SNMP_IPADDRESS(path->attr->aggregator_addr);
d62a17ae 834 case BGP4PATHATTRCALCLOCALPREF: /* 12 */
835 return SNMP_INTEGER(-1);
d62a17ae 836 case BGP4PATHATTRBEST: /* 13 */
718e3744 837#define BGP4_PathAttrBest_false 1
838#define BGP4_PathAttrBest_true 2
a9a0989b 839 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
d62a17ae 840 return SNMP_INTEGER(BGP4_PathAttrBest_true);
841 else
842 return SNMP_INTEGER(BGP4_PathAttrBest_false);
d62a17ae 843 case BGP4PATHATTRUNKNOWN: /* 14 */
844 *var_len = 0;
845 return NULL;
d62a17ae 846 }
847 return NULL;
718e3744 848}
6b0655a2 849
718e3744 850/* BGP Traps. */
c1e99f63
PR
851static struct trap_object bgpTrapList[] = {{3, {3, 1, BGPPEERREMOTEADDR} },
852 {3, {3, 1, BGPPEERLASTERROR} },
853 {3, {3, 1, BGPPEERSTATE} } };
718e3744 854
d62a17ae 855static int bgpTrapEstablished(struct peer *peer)
718e3744 856{
d62a17ae 857 int ret;
858 struct in_addr addr;
859 oid index[sizeof(oid) * IN_ADDR_SIZE];
860
7d8d0eab 861 /* Check if this peer just went to Established */
fd2e2db6 862 if ((peer->ostatus != OpenConfirm) || !(peer_established(peer)))
7d8d0eab
MKS
863 return 0;
864
d62a17ae 865 ret = inet_aton(peer->host, &addr);
866 if (ret == 0)
867 return 0;
868
9e263221 869 oid_copy_in_addr(index, &addr);
d62a17ae 870
97e21b4b
DS
871 smux_trap(bgp_variables, array_size(bgp_variables), bgp_trap_oid,
872 array_size(bgp_trap_oid), bgp_oid,
873 sizeof(bgp_oid) / sizeof(oid), index, IN_ADDR_SIZE,
874 bgpTrapList, array_size(bgpTrapList), BGPESTABLISHED);
d62a17ae 875 return 0;
718e3744 876}
877
d62a17ae 878static int bgpTrapBackwardTransition(struct peer *peer)
718e3744 879{
d62a17ae 880 int ret;
881 struct in_addr addr;
882 oid index[sizeof(oid) * IN_ADDR_SIZE];
883
884 ret = inet_aton(peer->host, &addr);
885 if (ret == 0)
886 return 0;
887
9e263221 888 oid_copy_in_addr(index, &addr);
d62a17ae 889
97b5d752
QY
890 smux_trap(bgp_variables, array_size(bgp_variables), bgp_trap_oid,
891 array_size(bgp_trap_oid), bgp_oid,
0d6f7fd6 892 sizeof(bgp_oid) / sizeof(oid), index, IN_ADDR_SIZE,
97b5d752 893 bgpTrapList, array_size(bgpTrapList), BGPBACKWARDTRANSITION);
d62a17ae 894 return 0;
718e3744 895}
896
d62a17ae 897static int bgp_snmp_init(struct thread_master *tm)
5986b66b 898{
d62a17ae 899 smux_init(tm);
900 REGISTER_MIB("mibII/bgp", bgp_variables, variable, bgp_oid);
aa53f693 901 bgp_mpls_l3vpn_module_init();
d62a17ae 902 return 0;
5986b66b 903}
3012671f 904
d62a17ae 905static int bgp_snmp_module_init(void)
718e3744 906{
7d8d0eab 907 hook_register(peer_status_changed, bgpTrapEstablished);
d62a17ae 908 hook_register(peer_backward_transition, bgpTrapBackwardTransition);
909 hook_register(frr_late_init, bgp_snmp_init);
910 return 0;
718e3744 911}
5986b66b 912
d62a17ae 913FRR_MODULE_SETUP(.name = "bgpd_snmp", .version = FRR_VERSION,
914 .description = "bgpd AgentX SNMP module",
80413c20
DL
915 .init = bgp_snmp_module_init,
916);