]> git.proxmox.com Git - mirror_frr.git/blob - bgpd/bgp_snmp.c
Merge pull request #9083 from mobash-rasool/pim-upst-3
[mirror_frr.git] / bgpd / bgp_snmp.c
1 /* BGP4 SNMP support
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 */
20
21 #include <zebra.h>
22
23 #include <net-snmp/net-snmp-config.h>
24 #include <net-snmp/net-snmp-includes.h>
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"
32 #include "filter.h"
33 #include "hook.h"
34 #include "libfrr.h"
35 #include "lib/version.h"
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"
43 #include "bgpd/bgp_mplsvpn_snmp.h"
44
45 /* BGP4-MIB described in RFC1657. */
46 #define BGP4MIB 1,3,6,1,2,1,15
47
48 /* BGP TRAP. */
49 #define BGPESTABLISHED 1
50 #define BGPBACKWARDTRANSITION 2
51
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
80 #define BGPPEERMINROUTEADVERTISEMENTINTERVAL 22
81 #define BGPPEERINUPDATEELAPSEDTIME 23
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
117
118 /* Declare static local variables for convenience. */
119 SNMP_LOCAL_VARIABLES
120
121 /* BGP-MIB instances. */
122 static oid bgp_oid[] = {BGP4MIB};
123 static oid bgp_trap_oid[] = {BGP4MIB, 0};
124
125 /* IP address 0.0.0.0. */
126 static struct in_addr bgp_empty_addr = {.s_addr = 0};
127
128 /* Hook functions. */
129 static uint8_t *bgpVersion(struct variable *, oid[], size_t *, int, size_t *,
130 WriteMethod **);
131 static uint8_t *bgpLocalAs(struct variable *, oid[], size_t *, int, size_t *,
132 WriteMethod **);
133 static uint8_t *bgpPeerTable(struct variable *, oid[], size_t *, int, size_t *,
134 WriteMethod **);
135 static uint8_t *bgpRcvdPathAttrTable(struct variable *, oid[], size_t *, int,
136 size_t *, WriteMethod **);
137 static uint8_t *bgpIdentifier(struct variable *, oid[], size_t *, int, size_t *,
138 WriteMethod **);
139 static uint8_t *bgp4PathAttrTable(struct variable *, oid[], size_t *, int,
140 size_t *, WriteMethod **);
141 /* static uint8_t *bgpTraps (); */
142
143 static 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}},
316 };
317
318
319 static uint8_t *bgpVersion(struct variable *v, oid name[], size_t *length,
320 int exact, size_t *var_len,
321 WriteMethod **write_method)
322 {
323 static uint8_t version;
324
325 if (smux_header_generic(v, name, length, exact, var_len, write_method)
326 == MATCH_FAILED)
327 return NULL;
328
329 /* Return BGP version. Zebra bgpd only support version 4. */
330 version = (0x80 >> (BGP_VERSION_4 - 1));
331
332 /* Return octet string length 1. */
333 *var_len = 1;
334 return &version;
335 }
336
337 static uint8_t *bgpLocalAs(struct variable *v, oid name[], size_t *length,
338 int exact, size_t *var_len,
339 WriteMethod **write_method)
340 {
341 struct bgp *bgp;
342
343 if (smux_header_generic(v, name, length, exact, var_len, write_method)
344 == MATCH_FAILED)
345 return NULL;
346
347 /* Get BGP structure. */
348 bgp = bgp_get_default();
349 if (!bgp)
350 return NULL;
351
352 return SNMP_INTEGER(bgp->as);
353 }
354
355 static struct peer *peer_lookup_addr_ipv4(struct in_addr *src)
356 {
357 struct bgp *bgp;
358 struct peer *peer;
359 struct listnode *node;
360 struct listnode *bgpnode;
361
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;
366
367 if (sockunion2ip(&peer->su) == src->s_addr)
368 return peer;
369 }
370 }
371
372 return NULL;
373 }
374
375 static struct peer *bgp_peer_lookup_next(struct in_addr *src)
376 {
377 struct bgp *bgp;
378 struct peer *peer;
379 struct peer *next_peer = NULL;
380 struct listnode *node;
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 }
395 }
396 }
397
398 if (next_peer) {
399 src->s_addr = sockunion2ip(&next_peer->su);
400 return next_peer;
401 }
402
403 return NULL;
404 }
405
406 /* 1.3.6.1.2.1.15.3.1.x = 10 */
407 #define PEERTAB_NAMELEN 10
408
409 static struct peer *bgpPeerTable_lookup(struct variable *v, oid name[],
410 size_t *length, struct in_addr *addr,
411 int exact)
412 {
413 struct peer *peer = NULL;
414 size_t namelen = v ? v->namelen : PEERTAB_NAMELEN;
415 int len;
416
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;
430
431 oid2in_addr(name + namelen, len, addr);
432
433 peer = bgp_peer_lookup_next(addr);
434
435 if (peer == NULL)
436 return NULL;
437
438 oid_copy_in_addr(name + namelen, addr);
439 *length = sizeof(struct in_addr) + namelen;
440
441 return peer;
442 }
443 return NULL;
444 }
445
446 /* BGP write methods. */
447 static 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)
450 {
451 struct in_addr addr;
452 struct peer *peer;
453 long intval;
454
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 }
461
462 intval = *(long *)var_val;
463
464 memset(&addr, 0, sizeof(struct in_addr));
465
466 peer = bgpPeerTable_lookup(NULL, name, &length, &addr, 1);
467 if (!peer)
468 return SNMP_ERR_NOSUCHNAME;
469
470 if (action != SNMP_MSG_INTERNAL_SET_COMMIT)
471 return SNMP_ERR_NOERROR;
472
473 zlog_info("%s: SNMP write .%ld = %ld", peer->host,
474 (long)name[PEERTAB_NAMELEN - 1], intval);
475
476 switch (name[PEERTAB_NAMELEN - 1]) {
477 case BGPPEERADMINSTATUS:
478 #define BGP_PeerAdmin_stop 1
479 #define BGP_PeerAdmin_start 2
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:
489 peer_flag_set(peer, PEER_FLAG_TIMER_CONNECT);
490 peer->connect = intval;
491 peer->v_connect = intval;
492 break;
493 case BGPPEERHOLDTIMECONFIGURED:
494 peer_flag_set(peer, PEER_FLAG_TIMER);
495 peer->holdtime = intval;
496 peer->v_holdtime = intval;
497 break;
498 case BGPPEERKEEPALIVECONFIGURED:
499 peer_flag_set(peer, PEER_FLAG_TIMER);
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;
508 }
509
510 static uint8_t *bgpPeerTable(struct variable *v, oid name[], size_t *length,
511 int exact, size_t *var_len,
512 WriteMethod **write_method)
513 {
514 static struct in_addr addr;
515 struct peer *peer;
516 uint32_t ui, uo;
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);
530 case BGPPEERSTATE:
531 return SNMP_INTEGER(peer->status);
532 case BGPPEERADMINSTATUS:
533 *write_method = write_bgpPeerTable;
534 #define BGP_PeerAdmin_stop 1
535 #define BGP_PeerAdmin_start 2
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);
540 case BGPPEERNEGOTIATEDVERSION:
541 return SNMP_INTEGER(BGP_VERSION_4);
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);
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);
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);
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);
564 case BGPPEERREMOTEAS:
565 return SNMP_INTEGER(peer->as);
566 case BGPPEERINUPDATES:
567 ui = atomic_load_explicit(&peer->update_in,
568 memory_order_relaxed);
569 return SNMP_INTEGER(ui);
570 case BGPPEEROUTUPDATES:
571 uo = atomic_load_explicit(&peer->update_out,
572 memory_order_relaxed);
573 return SNMP_INTEGER(uo);
574 case BGPPEERINTOTALMESSAGES:
575 return SNMP_INTEGER(PEER_TOTAL_RX(peer));
576 case BGPPEEROUTTOTALMESSAGES:
577 return SNMP_INTEGER(PEER_TOTAL_TX(peer));
578 case BGPPEERLASTERROR: {
579 static uint8_t lasterror[2];
580 lasterror[0] = peer->notify.code;
581 lasterror[1] = peer->notify.subcode;
582 *var_len = 2;
583 return (uint8_t *)&lasterror;
584 }
585 case BGPPEERFSMESTABLISHEDTRANSITIONS:
586 return SNMP_INTEGER(peer->established);
587 case BGPPEERFSMESTABLISHEDTIME:
588 if (peer->uptime == 0)
589 return SNMP_INTEGER(0);
590 else
591 return SNMP_INTEGER(bgp_clock() - peer->uptime);
592 case BGPPEERCONNECTRETRYINTERVAL:
593 *write_method = write_bgpPeerTable;
594 return SNMP_INTEGER(peer->v_connect);
595 case BGPPEERHOLDTIME:
596 return SNMP_INTEGER(peer->v_holdtime);
597 case BGPPEERKEEPALIVE:
598 return SNMP_INTEGER(peer->v_keepalive);
599 case BGPPEERHOLDTIMECONFIGURED:
600 *write_method = write_bgpPeerTable;
601 if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER))
602 return SNMP_INTEGER(peer->holdtime);
603 else
604 return SNMP_INTEGER(peer->v_holdtime);
605 case BGPPEERKEEPALIVECONFIGURED:
606 *write_method = write_bgpPeerTable;
607 if (CHECK_FLAG(peer->flags, PEER_FLAG_TIMER))
608 return SNMP_INTEGER(peer->keepalive);
609 else
610 return SNMP_INTEGER(peer->v_keepalive);
611 case BGPPEERMINROUTEADVERTISEMENTINTERVAL:
612 *write_method = write_bgpPeerTable;
613 return SNMP_INTEGER(peer->v_routeadv);
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);
619 default:
620 return NULL;
621 }
622 return NULL;
623 }
624
625 static uint8_t *bgpIdentifier(struct variable *v, oid name[], size_t *length,
626 int exact, size_t *var_len,
627 WriteMethod **write_method)
628 {
629 struct bgp *bgp;
630
631 if (smux_header_generic(v, name, length, exact, var_len, write_method)
632 == MATCH_FAILED)
633 return NULL;
634
635 bgp = bgp_get_default();
636 if (!bgp)
637 return NULL;
638
639 return SNMP_IPADDRESS(bgp->router_id);
640 }
641
642 static uint8_t *bgpRcvdPathAttrTable(struct variable *v, oid name[],
643 size_t *length, int exact, size_t *var_len,
644 WriteMethod **write_method)
645 {
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;
651 }
652
653 static 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)
657 {
658 oid *offset;
659 int offsetlen;
660 struct bgp_path_info *path;
661 struct bgp_path_info *min;
662 struct bgp_dest *dest;
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. */
689 dest = bgp_node_lookup(bgp->rib[AFI_IP][SAFI_UNICAST],
690 (struct prefix *)addr);
691 if (dest) {
692 for (path = bgp_dest_get_bgp_path_info(dest); path;
693 path = path->next)
694 if (sockunion_same(&path->peer->su, &su))
695 return path;
696
697 bgp_dest_unlock_node(dest);
698 }
699 } else {
700 offset = name + v->namelen;
701 offsetlen = *length - v->namelen;
702 len = offsetlen;
703
704 if (offsetlen == 0)
705 dest = bgp_table_top(bgp->rib[AFI_IP][SAFI_UNICAST]);
706 else {
707 if (len > IN_ADDR_SIZE)
708 len = IN_ADDR_SIZE;
709
710 oid2in_addr(offset, len, &addr->prefix);
711
712 offset += IN_ADDR_SIZE;
713 offsetlen -= IN_ADDR_SIZE;
714
715 if (offsetlen > 0)
716 addr->prefixlen = *offset;
717 else
718 addr->prefixlen = len * 8;
719
720 dest = bgp_node_get(bgp->rib[AFI_IP][SAFI_UNICAST],
721 (struct prefix *)addr);
722
723 offset++;
724 offsetlen--;
725 }
726
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
734 paddr.s_addr = INADDR_ANY;
735
736 if (!dest)
737 return NULL;
738
739 do {
740 min = NULL;
741
742 for (path = bgp_dest_get_bgp_path_info(dest); path;
743 path = path->next) {
744 if (path->peer->su.sin.sin_family == AF_INET
745 && ntohl(paddr.s_addr)
746 < ntohl(path->peer->su.sin
747 .sin_addr
748 .s_addr)) {
749 if (min) {
750 if (ntohl(path->peer->su.sin
751 .sin_addr
752 .s_addr)
753 < ntohl(min->peer->su.sin
754 .sin_addr
755 .s_addr))
756 min = path;
757 } else
758 min = path;
759 }
760 }
761
762 if (min) {
763 const struct prefix *rn_p =
764 bgp_dest_get_prefix(dest);
765
766 *length =
767 v->namelen + BGP_PATHATTR_ENTRY_OFFSET;
768
769 offset = name + v->namelen;
770 oid_copy_in_addr(offset, &rn_p->u.prefix4);
771 offset += IN_ADDR_SIZE;
772 *offset = rn_p->prefixlen;
773 offset++;
774 oid_copy_in_addr(offset,
775 &min->peer->su.sin.sin_addr);
776 addr->prefix = rn_p->u.prefix4;
777 addr->prefixlen = rn_p->prefixlen;
778
779 bgp_dest_unlock_node(dest);
780
781 return min;
782 }
783
784 paddr.s_addr = INADDR_ANY;
785 } while ((dest = bgp_route_next(dest)) != NULL);
786 }
787 return NULL;
788 }
789
790 static uint8_t *bgp4PathAttrTable(struct variable *v, oid name[],
791 size_t *length, int exact, size_t *var_len,
792 WriteMethod **write_method)
793 {
794 struct bgp *bgp;
795 struct bgp_path_info *path;
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
807 path = bgp4PathAttrLookup(v, name, length, bgp, &addr, exact);
808 if (!path)
809 return NULL;
810
811 switch (v->magic) {
812 case BGP4PATHATTRPEER: /* 1 */
813 return SNMP_IPADDRESS(path->peer->su.sin.sin_addr);
814 case BGP4PATHATTRIPADDRPREFIXLEN: /* 2 */
815 return SNMP_INTEGER(addr.prefixlen);
816 case BGP4PATHATTRIPADDRPREFIX: /* 3 */
817 return SNMP_IPADDRESS(addr.prefix);
818 case BGP4PATHATTRORIGIN: /* 4 */
819 return SNMP_INTEGER(path->attr->origin);
820 case BGP4PATHATTRASPATHSEGMENT: /* 5 */
821 return aspath_snmp_pathseg(path->attr->aspath, var_len);
822 case BGP4PATHATTRNEXTHOP: /* 6 */
823 return SNMP_IPADDRESS(path->attr->nexthop);
824 case BGP4PATHATTRMULTIEXITDISC: /* 7 */
825 return SNMP_INTEGER(path->attr->med);
826 case BGP4PATHATTRLOCALPREF: /* 8 */
827 return SNMP_INTEGER(path->attr->local_pref);
828 case BGP4PATHATTRATOMICAGGREGATE: /* 9 */
829 return SNMP_INTEGER(1);
830 case BGP4PATHATTRAGGREGATORAS: /* 10 */
831 return SNMP_INTEGER(path->attr->aggregator_as);
832 case BGP4PATHATTRAGGREGATORADDR: /* 11 */
833 return SNMP_IPADDRESS(path->attr->aggregator_addr);
834 case BGP4PATHATTRCALCLOCALPREF: /* 12 */
835 return SNMP_INTEGER(-1);
836 case BGP4PATHATTRBEST: /* 13 */
837 #define BGP4_PathAttrBest_false 1
838 #define BGP4_PathAttrBest_true 2
839 if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
840 return SNMP_INTEGER(BGP4_PathAttrBest_true);
841 else
842 return SNMP_INTEGER(BGP4_PathAttrBest_false);
843 case BGP4PATHATTRUNKNOWN: /* 14 */
844 *var_len = 0;
845 return NULL;
846 }
847 return NULL;
848 }
849
850 /* BGP Traps. */
851 static struct trap_object bgpTrapList[] = {{3, {3, 1, BGPPEERREMOTEADDR} },
852 {3, {3, 1, BGPPEERLASTERROR} },
853 {3, {3, 1, BGPPEERSTATE} } };
854
855 static int bgpTrapEstablished(struct peer *peer)
856 {
857 int ret;
858 struct in_addr addr;
859 oid index[sizeof(oid) * IN_ADDR_SIZE];
860
861 /* Check if this peer just went to Established */
862 if ((peer->ostatus != OpenConfirm) || !(peer_established(peer)))
863 return 0;
864
865 ret = inet_aton(peer->host, &addr);
866 if (ret == 0)
867 return 0;
868
869 oid_copy_in_addr(index, &addr);
870
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);
875 return 0;
876 }
877
878 static int bgpTrapBackwardTransition(struct peer *peer)
879 {
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
888 oid_copy_in_addr(index, &addr);
889
890 smux_trap(bgp_variables, array_size(bgp_variables), bgp_trap_oid,
891 array_size(bgp_trap_oid), bgp_oid,
892 sizeof(bgp_oid) / sizeof(oid), index, IN_ADDR_SIZE,
893 bgpTrapList, array_size(bgpTrapList), BGPBACKWARDTRANSITION);
894 return 0;
895 }
896
897 static int bgp_snmp_init(struct thread_master *tm)
898 {
899 smux_init(tm);
900 REGISTER_MIB("mibII/bgp", bgp_variables, variable, bgp_oid);
901 bgp_mpls_l3vpn_module_init();
902 return 0;
903 }
904
905 static int bgp_snmp_module_init(void)
906 {
907 hook_register(peer_status_changed, bgpTrapEstablished);
908 hook_register(peer_backward_transition, bgpTrapBackwardTransition);
909 hook_register(frr_late_init, bgp_snmp_init);
910 return 0;
911 }
912
913 FRR_MODULE_SETUP(.name = "bgpd_snmp", .version = FRR_VERSION,
914 .description = "bgpd AgentX SNMP module",
915 .init = bgp_snmp_module_init,
916 );