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