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