Line data Source code
1 : /* BGP open message handling
2 : Copyright (C) 1998, 1999 Kunihiro Ishiguro
3 :
4 : This file is part of GNU Zebra.
5 :
6 : GNU Zebra is free software; you can redistribute it and/or modify it
7 : under the terms of the GNU General Public License as published by the
8 : Free Software Foundation; either version 2, or (at your option) any
9 : later version.
10 :
11 : GNU Zebra is distributed in the hope that it will be useful, but
12 : WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : General Public License for more details.
15 :
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 : #include "linklist.h"
24 : #include "prefix.h"
25 : #include "stream.h"
26 : #include "thread.h"
27 : #include "log.h"
28 : #include "command.h"
29 : #include "memory.h"
30 :
31 : #include "bgpd/bgpd.h"
32 : #include "bgpd/bgp_attr.h"
33 : #include "bgpd/bgp_debug.h"
34 : #include "bgpd/bgp_fsm.h"
35 : #include "bgpd/bgp_packet.h"
36 : #include "bgpd/bgp_open.h"
37 : #include "bgpd/bgp_aspath.h"
38 : #include "bgpd/bgp_vty.h"
39 :
40 : /* BGP-4 Multiprotocol Extentions lead us to the complex world. We can
41 : negotiate remote peer supports extentions or not. But if
42 : remote-peer doesn't supports negotiation process itself. We would
43 : like to do manual configuration.
44 :
45 : So there is many configurable point. First of all we want set each
46 : peer whether we send capability negotiation to the peer or not.
47 : Next, if we send capability to the peer we want to set my capabilty
48 : inforation at each peer. */
49 :
50 : void
51 0 : bgp_capability_vty_out (struct vty *vty, struct peer *peer)
52 : {
53 : char *pnt;
54 : char *end;
55 : struct capability_mp_data mpc;
56 : struct capability_header *hdr;
57 :
58 0 : pnt = peer->notify.data;
59 0 : end = pnt + peer->notify.length;
60 :
61 0 : while (pnt < end)
62 : {
63 0 : if (pnt + sizeof (struct capability_mp_data) + 2 > end)
64 0 : return;
65 :
66 0 : hdr = (struct capability_header *)pnt;
67 0 : if (pnt + hdr->length + 2 > end)
68 0 : return;
69 :
70 0 : memcpy (&mpc, pnt + 2, sizeof(struct capability_mp_data));
71 :
72 0 : if (hdr->code == CAPABILITY_CODE_MP)
73 : {
74 0 : vty_out (vty, " Capability error for: Multi protocol ");
75 :
76 0 : switch (ntohs (mpc.afi))
77 : {
78 : case AFI_IP:
79 0 : vty_out (vty, "AFI IPv4, ");
80 0 : break;
81 : case AFI_IP6:
82 0 : vty_out (vty, "AFI IPv6, ");
83 0 : break;
84 : default:
85 0 : vty_out (vty, "AFI Unknown %d, ", ntohs (mpc.afi));
86 0 : break;
87 : }
88 0 : switch (mpc.safi)
89 : {
90 : case SAFI_UNICAST:
91 0 : vty_out (vty, "SAFI Unicast");
92 0 : break;
93 : case SAFI_MULTICAST:
94 0 : vty_out (vty, "SAFI Multicast");
95 0 : break;
96 : case SAFI_MPLS_LABELED_VPN:
97 0 : vty_out (vty, "SAFI MPLS-labeled VPN");
98 0 : break;
99 : default:
100 0 : vty_out (vty, "SAFI Unknown %d ", mpc.safi);
101 0 : break;
102 : }
103 0 : vty_out (vty, "%s", VTY_NEWLINE);
104 : }
105 0 : else if (hdr->code >= 128)
106 0 : vty_out (vty, " Capability error: vendor specific capability code %d",
107 0 : hdr->code);
108 : else
109 0 : vty_out (vty, " Capability error: unknown capability code %d",
110 0 : hdr->code);
111 :
112 0 : pnt += hdr->length + 2;
113 : }
114 : }
115 :
116 : static void
117 27 : bgp_capability_mp_data (struct stream *s, struct capability_mp_data *mpc)
118 : {
119 27 : mpc->afi = stream_getw (s);
120 27 : mpc->reserved = stream_getc (s);
121 27 : mpc->safi = stream_getc (s);
122 27 : }
123 :
124 : int
125 54 : bgp_afi_safi_valid_indices (afi_t afi, safi_t *safi)
126 : {
127 54 : switch (afi)
128 : {
129 : case AFI_IP:
130 : #ifdef HAVE_IPV6
131 : case AFI_IP6:
132 : #endif
133 52 : switch (*safi)
134 : {
135 : /* BGP MPLS-labeled VPN SAFI isn't contigious with others, remap */
136 : case SAFI_MPLS_LABELED_VPN:
137 4 : *safi = SAFI_MPLS_VPN;
138 : case SAFI_UNICAST:
139 : case SAFI_MULTICAST:
140 : case SAFI_MPLS_VPN:
141 52 : return 1;
142 : }
143 : }
144 2 : zlog_debug ("unknown afi/safi (%u/%u)", afi, *safi);
145 :
146 2 : return 0;
147 : }
148 :
149 : /* Set negotiated capability value. */
150 : static int
151 19 : bgp_capability_mp (struct peer *peer, struct capability_header *hdr)
152 : {
153 : struct capability_mp_data mpc;
154 19 : struct stream *s = BGP_INPUT (peer);
155 :
156 19 : bgp_capability_mp_data (s, &mpc);
157 :
158 19 : if (BGP_DEBUG (normal, NORMAL))
159 38 : zlog_debug ("%s OPEN has MP_EXT CAP for afi/safi: %u/%u",
160 38 : peer->host, mpc.afi, mpc.safi);
161 :
162 19 : if (!bgp_afi_safi_valid_indices (mpc.afi, &mpc.safi))
163 1 : return -1;
164 :
165 : /* Now safi remapped, and afi/safi are valid array indices */
166 18 : peer->afc_recv[mpc.afi][mpc.safi] = 1;
167 :
168 18 : if (peer->afc[mpc.afi][mpc.safi])
169 18 : peer->afc_nego[mpc.afi][mpc.safi] = 1;
170 : else
171 0 : return -1;
172 :
173 18 : return 0;
174 : }
175 :
176 : static void
177 10 : bgp_capability_orf_not_support (struct peer *peer, afi_t afi, safi_t safi,
178 : u_char type, u_char mode)
179 : {
180 10 : if (BGP_DEBUG (normal, NORMAL))
181 10 : zlog_debug ("%s Addr-family %d/%d has ORF type/mode %d/%d not supported",
182 : peer->host, afi, safi, type, mode);
183 10 : }
184 :
185 : static const struct message orf_type_str[] =
186 : {
187 : { ORF_TYPE_PREFIX, "Prefixlist" },
188 : { ORF_TYPE_PREFIX_OLD, "Prefixlist (old)" },
189 : };
190 : static const int orf_type_str_max = array_size(orf_type_str);
191 :
192 : static const struct message orf_mode_str[] =
193 : {
194 : { ORF_MODE_RECEIVE, "Receive" },
195 : { ORF_MODE_SEND, "Send" },
196 : { ORF_MODE_BOTH, "Both" },
197 : };
198 : static const int orf_mode_str_max = array_size(orf_mode_str);
199 :
200 : static int
201 8 : bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr)
202 : {
203 8 : struct stream *s = BGP_INPUT (peer);
204 : struct capability_orf_entry entry;
205 : afi_t afi;
206 : safi_t safi;
207 : u_char type;
208 : u_char mode;
209 8 : u_int16_t sm_cap = 0; /* capability send-mode receive */
210 8 : u_int16_t rm_cap = 0; /* capability receive-mode receive */
211 : int i;
212 :
213 : /* ORF Entry header */
214 8 : bgp_capability_mp_data (s, &entry.mpc);
215 8 : entry.num = stream_getc (s);
216 8 : afi = entry.mpc.afi;
217 8 : safi = entry.mpc.safi;
218 :
219 8 : if (BGP_DEBUG (normal, NORMAL))
220 16 : zlog_debug ("%s ORF Cap entry for afi/safi: %u/%u",
221 16 : peer->host, entry.mpc.afi, entry.mpc.safi);
222 :
223 : /* Check AFI and SAFI. */
224 8 : if (!bgp_afi_safi_valid_indices (entry.mpc.afi, &safi))
225 : {
226 0 : zlog_info ("%s Addr-family %d/%d not supported."
227 : " Ignoring the ORF capability",
228 0 : peer->host, entry.mpc.afi, entry.mpc.safi);
229 0 : return 0;
230 : }
231 :
232 : /* validate number field */
233 8 : if (sizeof (struct capability_orf_entry) + (entry.num * 2) > hdr->length)
234 : {
235 0 : zlog_info ("%s ORF Capability entry length error,"
236 : " Cap length %u, num %u",
237 0 : peer->host, hdr->length, entry.num);
238 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
239 0 : return -1;
240 : }
241 :
242 26 : for (i = 0 ; i < entry.num ; i++)
243 : {
244 18 : type = stream_getc(s);
245 18 : mode = stream_getc(s);
246 :
247 : /* ORF Mode error check */
248 18 : switch (mode)
249 : {
250 : case ORF_MODE_BOTH:
251 : case ORF_MODE_SEND:
252 : case ORF_MODE_RECEIVE:
253 18 : break;
254 : default:
255 0 : bgp_capability_orf_not_support (peer, afi, safi, type, mode);
256 0 : continue;
257 : }
258 : /* ORF Type and afi/safi error checks */
259 : /* capcode versus type */
260 18 : switch (hdr->code)
261 : {
262 : case CAPABILITY_CODE_ORF:
263 17 : switch (type)
264 : {
265 : case ORF_TYPE_PREFIX:
266 7 : break;
267 : default:
268 10 : bgp_capability_orf_not_support (peer, afi, safi, type, mode);
269 10 : continue;
270 : }
271 7 : break;
272 : case CAPABILITY_CODE_ORF_OLD:
273 1 : switch (type)
274 : {
275 : case ORF_TYPE_PREFIX_OLD:
276 1 : break;
277 : default:
278 0 : bgp_capability_orf_not_support (peer, afi, safi, type, mode);
279 0 : continue;
280 : }
281 1 : break;
282 : default:
283 0 : bgp_capability_orf_not_support (peer, afi, safi, type, mode);
284 0 : continue;
285 : }
286 :
287 : /* AFI vs SAFI */
288 8 : if (!((afi == AFI_IP && safi == SAFI_UNICAST)
289 0 : || (afi == AFI_IP && safi == SAFI_MULTICAST)
290 0 : || (afi == AFI_IP6 && safi == SAFI_UNICAST)))
291 : {
292 0 : bgp_capability_orf_not_support (peer, afi, safi, type, mode);
293 0 : continue;
294 : }
295 :
296 8 : if (BGP_DEBUG (normal, NORMAL))
297 16 : zlog_debug ("%s OPEN has %s ORF capability"
298 : " as %s for afi/safi: %d/%d",
299 : peer->host, LOOKUP (orf_type_str, type),
300 : LOOKUP (orf_mode_str, mode),
301 8 : entry.mpc.afi, safi);
302 :
303 8 : if (hdr->code == CAPABILITY_CODE_ORF)
304 : {
305 7 : sm_cap = PEER_CAP_ORF_PREFIX_SM_RCV;
306 7 : rm_cap = PEER_CAP_ORF_PREFIX_RM_RCV;
307 : }
308 1 : else if (hdr->code == CAPABILITY_CODE_ORF_OLD)
309 : {
310 1 : sm_cap = PEER_CAP_ORF_PREFIX_SM_OLD_RCV;
311 1 : rm_cap = PEER_CAP_ORF_PREFIX_RM_OLD_RCV;
312 : }
313 : else
314 : {
315 0 : bgp_capability_orf_not_support (peer, afi, safi, type, mode);
316 0 : continue;
317 : }
318 :
319 8 : switch (mode)
320 : {
321 : case ORF_MODE_BOTH:
322 8 : SET_FLAG (peer->af_cap[afi][safi], sm_cap);
323 8 : SET_FLAG (peer->af_cap[afi][safi], rm_cap);
324 8 : break;
325 : case ORF_MODE_SEND:
326 0 : SET_FLAG (peer->af_cap[afi][safi], sm_cap);
327 0 : break;
328 : case ORF_MODE_RECEIVE:
329 0 : SET_FLAG (peer->af_cap[afi][safi], rm_cap);
330 0 : break;
331 : }
332 : }
333 8 : return 0;
334 : }
335 :
336 : static int
337 2 : bgp_capability_restart (struct peer *peer, struct capability_header *caphdr)
338 : {
339 2 : struct stream *s = BGP_INPUT (peer);
340 : u_int16_t restart_flag_time;
341 2 : int restart_bit = 0;
342 2 : size_t end = stream_get_getp (s) + caphdr->length;
343 :
344 2 : SET_FLAG (peer->cap, PEER_CAP_RESTART_RCV);
345 2 : restart_flag_time = stream_getw(s);
346 2 : if (CHECK_FLAG (restart_flag_time, RESTART_R_BIT))
347 2 : restart_bit = 1;
348 2 : UNSET_FLAG (restart_flag_time, 0xF000);
349 2 : peer->v_gr_restart = restart_flag_time;
350 :
351 2 : if (BGP_DEBUG (normal, NORMAL))
352 : {
353 2 : zlog_debug ("%s OPEN has Graceful Restart capability", peer->host);
354 2 : zlog_debug ("%s Peer has%srestarted. Restart Time : %d",
355 : peer->host, restart_bit ? " " : " not ",
356 : peer->v_gr_restart);
357 : }
358 :
359 9 : while (stream_get_getp (s) + 4 <= end)
360 : {
361 5 : afi_t afi = stream_getw (s);
362 5 : safi_t safi = stream_getc (s);
363 5 : u_char flag = stream_getc (s);
364 :
365 5 : if (!bgp_afi_safi_valid_indices (afi, &safi))
366 : {
367 0 : if (BGP_DEBUG (normal, NORMAL))
368 0 : zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported."
369 : " Ignore the Graceful Restart capability",
370 : peer->host, afi, safi);
371 : }
372 5 : else if (!peer->afc[afi][safi])
373 : {
374 0 : if (BGP_DEBUG (normal, NORMAL))
375 0 : zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled."
376 : " Ignore the Graceful Restart capability",
377 : peer->host, afi, safi);
378 : }
379 : else
380 : {
381 5 : if (BGP_DEBUG (normal, NORMAL))
382 5 : zlog_debug ("%s Address family %s is%spreserved", peer->host,
383 : afi_safi_print (afi, safi),
384 5 : CHECK_FLAG (peer->af_cap[afi][safi],
385 : PEER_CAP_RESTART_AF_PRESERVE_RCV)
386 : ? " " : " not ");
387 :
388 5 : SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV);
389 5 : if (CHECK_FLAG (flag, RESTART_F_BIT))
390 0 : SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV);
391 :
392 : }
393 : }
394 2 : return 0;
395 : }
396 :
397 : static as_t
398 11 : bgp_capability_as4 (struct peer *peer, struct capability_header *hdr)
399 : {
400 11 : SET_FLAG (peer->cap, PEER_CAP_AS4_RCV);
401 :
402 11 : if (hdr->length != CAPABILITY_CODE_AS4_LEN)
403 : {
404 1 : zlog_err ("%s AS4 capability has incorrect data length %d",
405 1 : peer->host, hdr->length);
406 1 : return 0;
407 : }
408 :
409 10 : as_t as4 = stream_getl (BGP_INPUT(peer));
410 :
411 10 : if (BGP_DEBUG (as4, AS4))
412 10 : zlog_debug ("%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u",
413 : peer->host, as4);
414 10 : return as4;
415 : }
416 :
417 : static const struct message capcode_str[] =
418 : {
419 : { CAPABILITY_CODE_MP, "MultiProtocol Extensions" },
420 : { CAPABILITY_CODE_REFRESH, "Route Refresh" },
421 : { CAPABILITY_CODE_ORF, "Cooperative Route Filtering" },
422 : { CAPABILITY_CODE_RESTART, "Graceful Restart" },
423 : { CAPABILITY_CODE_AS4, "4-octet AS number" },
424 : { CAPABILITY_CODE_DYNAMIC, "Dynamic" },
425 : { CAPABILITY_CODE_REFRESH_OLD, "Route Refresh (Old)" },
426 : { CAPABILITY_CODE_ORF_OLD, "ORF (Old)" },
427 : };
428 : static const int capcode_str_max = array_size(capcode_str);
429 :
430 : /* Minimum sizes for length field of each cap (so not inc. the header) */
431 : static const size_t cap_minsizes[] =
432 : {
433 : [CAPABILITY_CODE_MP] = sizeof (struct capability_mp_data),
434 : [CAPABILITY_CODE_REFRESH] = CAPABILITY_CODE_REFRESH_LEN,
435 : [CAPABILITY_CODE_ORF] = sizeof (struct capability_orf_entry),
436 : [CAPABILITY_CODE_RESTART] = sizeof (struct capability_gr),
437 : [CAPABILITY_CODE_AS4] = CAPABILITY_CODE_AS4_LEN,
438 : [CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN,
439 : [CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN,
440 : [CAPABILITY_CODE_ORF_OLD] = sizeof (struct capability_orf_entry),
441 : };
442 :
443 : /**
444 : * Parse given capability.
445 : * XXX: This is reading into a stream, but not using stream API
446 : *
447 : * @param[out] mp_capability Set to 1 on return iff one or more Multiprotocol
448 : * capabilities were encountered.
449 : */
450 : static int
451 55 : bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability,
452 : u_char **error)
453 : {
454 : int ret;
455 55 : struct stream *s = BGP_INPUT (peer);
456 55 : size_t end = stream_get_getp (s) + length;
457 :
458 55 : assert (STREAM_READABLE (s) >= length);
459 :
460 165 : while (stream_get_getp (s) < end)
461 : {
462 : size_t start;
463 67 : u_char *sp = stream_pnt (s);
464 : struct capability_header caphdr;
465 :
466 : /* We need at least capability code and capability length. */
467 67 : if (stream_get_getp(s) + 2 > end)
468 : {
469 0 : zlog_info ("%s Capability length error (< header)", peer->host);
470 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
471 12 : return -1;
472 : }
473 :
474 67 : caphdr.code = stream_getc (s);
475 67 : caphdr.length = stream_getc (s);
476 67 : start = stream_get_getp (s);
477 :
478 : /* Capability length check sanity check. */
479 67 : if (start + caphdr.length > end)
480 : {
481 6 : zlog_info ("%s Capability length error (< length)", peer->host);
482 6 : bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
483 6 : return -1;
484 : }
485 :
486 61 : if (BGP_DEBUG (normal, NORMAL))
487 183 : zlog_debug ("%s OPEN has %s capability (%u), length %u",
488 : peer->host,
489 61 : LOOKUP (capcode_str, caphdr.code),
490 122 : caphdr.code, caphdr.length);
491 :
492 : /* Length sanity check, type-specific, for known capabilities */
493 61 : switch (caphdr.code)
494 : {
495 : case CAPABILITY_CODE_MP:
496 : case CAPABILITY_CODE_REFRESH:
497 : case CAPABILITY_CODE_REFRESH_OLD:
498 : case CAPABILITY_CODE_ORF:
499 : case CAPABILITY_CODE_ORF_OLD:
500 : case CAPABILITY_CODE_RESTART:
501 : case CAPABILITY_CODE_AS4:
502 : case CAPABILITY_CODE_DYNAMIC:
503 : /* Check length. */
504 60 : if (caphdr.length < cap_minsizes[caphdr.code])
505 : {
506 18 : zlog_info ("%s %s Capability length error: got %u,"
507 : " expected at least %u",
508 : peer->host,
509 6 : LOOKUP (capcode_str, caphdr.code),
510 6 : caphdr.length,
511 6 : (unsigned) cap_minsizes[caphdr.code]);
512 6 : bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
513 6 : return -1;
514 : }
515 : /* we deliberately ignore unknown codes, see below */
516 : default:
517 55 : break;
518 : }
519 :
520 55 : switch (caphdr.code)
521 : {
522 : case CAPABILITY_CODE_MP:
523 : {
524 19 : *mp_capability = 1;
525 :
526 : /* Ignore capability when override-capability is set. */
527 19 : if (! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
528 : {
529 : /* Set negotiated value. */
530 19 : ret = bgp_capability_mp (peer, &caphdr);
531 :
532 : /* Unsupported Capability. */
533 19 : if (ret < 0)
534 : {
535 : /* Store return data. */
536 1 : memcpy (*error, sp, caphdr.length + 2);
537 1 : *error += caphdr.length + 2;
538 : }
539 : }
540 : }
541 19 : break;
542 : case CAPABILITY_CODE_REFRESH:
543 : case CAPABILITY_CODE_REFRESH_OLD:
544 : {
545 : /* BGP refresh capability */
546 17 : if (caphdr.code == CAPABILITY_CODE_REFRESH_OLD)
547 6 : SET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV);
548 : else
549 11 : SET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV);
550 : }
551 17 : break;
552 : case CAPABILITY_CODE_ORF:
553 : case CAPABILITY_CODE_ORF_OLD:
554 8 : if (bgp_capability_orf_entry (peer, &caphdr))
555 0 : return -1;
556 8 : break;
557 : case CAPABILITY_CODE_RESTART:
558 2 : if (bgp_capability_restart (peer, &caphdr))
559 0 : return -1;
560 2 : break;
561 : case CAPABILITY_CODE_DYNAMIC:
562 3 : SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);
563 3 : break;
564 : case CAPABILITY_CODE_AS4:
565 : /* Already handled as a special-case parsing of the capabilities
566 : * at the beginning of OPEN processing. So we care not a jot
567 : * for the value really, only error case.
568 : */
569 5 : if (!bgp_capability_as4 (peer, &caphdr))
570 0 : return -1;
571 5 : break;
572 : default:
573 1 : if (caphdr.code > 128)
574 : {
575 : /* We don't send Notification for unknown vendor specific
576 : capabilities. It seems reasonable for now... */
577 0 : zlog_warn ("%s Vendor specific capability %d",
578 0 : peer->host, caphdr.code);
579 : }
580 : else
581 : {
582 1 : zlog_warn ("%s unrecognized capability code: %d - ignored",
583 1 : peer->host, caphdr.code);
584 1 : memcpy (*error, sp, caphdr.length + 2);
585 1 : *error += caphdr.length + 2;
586 : }
587 : }
588 55 : if (stream_get_getp(s) != (start + caphdr.length))
589 : {
590 8 : if (stream_get_getp(s) > (start + caphdr.length))
591 0 : zlog_warn ("%s Cap-parser for %s read past cap-length, %u!",
592 0 : peer->host, LOOKUP (capcode_str, caphdr.code),
593 0 : caphdr.length);
594 8 : stream_set_getp (s, start + caphdr.length);
595 : }
596 : }
597 43 : return 0;
598 : }
599 :
600 : static int
601 0 : bgp_auth_parse (struct peer *peer, size_t length)
602 : {
603 0 : bgp_notify_send (peer,
604 : BGP_NOTIFY_OPEN_ERR,
605 : BGP_NOTIFY_OPEN_AUTH_FAILURE);
606 0 : return -1;
607 : }
608 :
609 : static int
610 0 : strict_capability_same (struct peer *peer)
611 : {
612 : int i, j;
613 :
614 0 : for (i = AFI_IP; i < AFI_MAX; i++)
615 0 : for (j = SAFI_UNICAST; j < SAFI_MAX; j++)
616 0 : if (peer->afc[i][j] != peer->afc_nego[i][j])
617 0 : return 0;
618 0 : return 1;
619 : }
620 :
621 : /* peek into option, stores ASN to *as4 if the AS4 capability was found.
622 : * Returns 0 if no as4 found, as4cap value otherwise.
623 : */
624 : as_t
625 37 : peek_for_as4_capability (struct peer *peer, u_char length)
626 : {
627 37 : struct stream *s = BGP_INPUT (peer);
628 37 : size_t orig_getp = stream_get_getp (s);
629 37 : size_t end = orig_getp + length;
630 37 : as_t as4 = 0;
631 :
632 : /* The full capability parser will better flag the error.. */
633 37 : if (STREAM_READABLE(s) < length)
634 0 : return 0;
635 :
636 37 : if (BGP_DEBUG (as4, AS4))
637 37 : zlog_info ("%s [AS4] rcv OPEN w/ OPTION parameter len: %u,"
638 : " peeking for as4",
639 : peer->host, length);
640 : /* the error cases we DONT handle, we ONLY try to read as4 out of
641 : * correctly formatted options.
642 : */
643 113 : while (stream_get_getp(s) < end)
644 : {
645 : u_char opt_type;
646 : u_char opt_length;
647 :
648 : /* Check the length. */
649 52 : if (stream_get_getp (s) + 2 > end)
650 0 : goto end;
651 :
652 : /* Fetch option type and length. */
653 52 : opt_type = stream_getc (s);
654 52 : opt_length = stream_getc (s);
655 :
656 : /* Option length check. */
657 52 : if (stream_get_getp (s) + opt_length > end)
658 0 : goto end;
659 :
660 52 : if (opt_type == BGP_OPEN_OPT_CAP)
661 : {
662 52 : unsigned long capd_start = stream_get_getp (s);
663 52 : unsigned long capd_end = capd_start + opt_length;
664 :
665 52 : assert (capd_end <= end);
666 :
667 156 : while (stream_get_getp (s) < capd_end)
668 : {
669 : struct capability_header hdr;
670 :
671 65 : if (stream_get_getp (s) + 2 > capd_end)
672 13 : goto end;
673 :
674 65 : hdr.code = stream_getc (s);
675 65 : hdr.length = stream_getc (s);
676 :
677 65 : if ((stream_get_getp(s) + hdr.length) > capd_end)
678 7 : goto end;
679 :
680 58 : if (hdr.code == CAPABILITY_CODE_AS4)
681 : {
682 6 : if (BGP_DEBUG (as4, AS4))
683 6 : zlog_info ("[AS4] found AS4 capability, about to parse");
684 6 : as4 = bgp_capability_as4 (peer, &hdr);
685 :
686 6 : goto end;
687 : }
688 52 : stream_forward_getp (s, hdr.length);
689 : }
690 : }
691 : }
692 :
693 : end:
694 37 : stream_set_getp (s, orig_getp);
695 37 : return as4;
696 : }
697 :
698 : /**
699 : * Parse open option.
700 : *
701 : * @param[out] mp_capability @see bgp_capability_parse() for semantics.
702 : */
703 : int
704 37 : bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability)
705 : {
706 : int ret;
707 : u_char *error;
708 : u_char error_data[BGP_MAX_PACKET_SIZE];
709 37 : struct stream *s = BGP_INPUT(peer);
710 37 : size_t end = stream_get_getp (s) + length;
711 :
712 37 : ret = 0;
713 37 : error = error_data;
714 :
715 37 : if (BGP_DEBUG (normal, NORMAL))
716 37 : zlog_debug ("%s rcv OPEN w/ OPTION parameter len: %u",
717 : peer->host, length);
718 :
719 117 : while (stream_get_getp(s) < end)
720 : {
721 : u_char opt_type;
722 : u_char opt_length;
723 :
724 : /* Must have at least an OPEN option header */
725 55 : if (STREAM_READABLE(s) < 2)
726 : {
727 0 : zlog_info ("%s Option length error", peer->host);
728 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
729 0 : return -1;
730 : }
731 :
732 : /* Fetch option type and length. */
733 55 : opt_type = stream_getc (s);
734 55 : opt_length = stream_getc (s);
735 :
736 : /* Option length check. */
737 55 : if (STREAM_READABLE (s) < opt_length)
738 : {
739 0 : zlog_info ("%s Option length error", peer->host);
740 0 : bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
741 0 : return -1;
742 : }
743 :
744 55 : if (BGP_DEBUG (normal, NORMAL))
745 110 : zlog_debug ("%s rcvd OPEN w/ optional parameter type %u (%s) len %u",
746 : peer->host, opt_type,
747 : opt_type == BGP_OPEN_OPT_AUTH ? "Authentication" :
748 55 : opt_type == BGP_OPEN_OPT_CAP ? "Capability" : "Unknown",
749 : opt_length);
750 :
751 55 : switch (opt_type)
752 : {
753 : case BGP_OPEN_OPT_AUTH:
754 0 : ret = bgp_auth_parse (peer, opt_length);
755 0 : break;
756 : case BGP_OPEN_OPT_CAP:
757 55 : ret = bgp_capability_parse (peer, opt_length, mp_capability, &error);
758 55 : break;
759 : default:
760 0 : bgp_notify_send (peer,
761 : BGP_NOTIFY_OPEN_ERR,
762 : BGP_NOTIFY_OPEN_UNSUP_PARAM);
763 0 : ret = -1;
764 0 : break;
765 : }
766 :
767 : /* Parse error. To accumulate all unsupported capability codes,
768 : bgp_capability_parse does not return -1 when encounter
769 : unsupported capability code. To detect that, please check
770 : error and erro_data pointer, like below. */
771 55 : if (ret < 0)
772 12 : return -1;
773 : }
774 :
775 : /* All OPEN option is parsed. Check capability when strict compare
776 : flag is enabled.*/
777 25 : if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
778 : {
779 : /* If Unsupported Capability exists. */
780 0 : if (error != error_data)
781 : {
782 0 : bgp_notify_send_with_data (peer,
783 : BGP_NOTIFY_OPEN_ERR,
784 : BGP_NOTIFY_OPEN_UNSUP_CAPBL,
785 0 : error_data, error - error_data);
786 0 : return -1;
787 : }
788 :
789 : /* Check local capability does not negotiated with remote
790 : peer. */
791 0 : if (! strict_capability_same (peer))
792 : {
793 0 : bgp_notify_send (peer,
794 : BGP_NOTIFY_OPEN_ERR,
795 : BGP_NOTIFY_OPEN_UNSUP_CAPBL);
796 0 : return -1;
797 : }
798 : }
799 :
800 : /* Check there are no common AFI/SAFIs and send Unsupported Capability
801 : error. */
802 38 : if (*mp_capability &&
803 13 : ! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
804 : {
805 13 : if (! peer->afc_nego[AFI_IP][SAFI_UNICAST]
806 0 : && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST]
807 0 : && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
808 0 : && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST]
809 0 : && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
810 : {
811 0 : plog_err (peer->log, "%s [Error] Configured AFI/SAFIs do not "
812 : "overlap with received MP capabilities",
813 : peer->host);
814 :
815 0 : if (error != error_data)
816 :
817 0 : bgp_notify_send_with_data (peer,
818 : BGP_NOTIFY_OPEN_ERR,
819 : BGP_NOTIFY_OPEN_UNSUP_CAPBL,
820 0 : error_data, error - error_data);
821 : else
822 0 : bgp_notify_send (peer,
823 : BGP_NOTIFY_OPEN_ERR,
824 : BGP_NOTIFY_OPEN_UNSUP_CAPBL);
825 0 : return -1;
826 : }
827 : }
828 25 : return 0;
829 : }
830 :
831 : static void
832 0 : bgp_open_capability_orf (struct stream *s, struct peer *peer,
833 : afi_t afi, safi_t safi, u_char code)
834 : {
835 : u_char cap_len;
836 : u_char orf_len;
837 : unsigned long capp;
838 : unsigned long orfp;
839 : unsigned long numberp;
840 0 : int number_of_orfs = 0;
841 :
842 0 : if (safi == SAFI_MPLS_VPN)
843 0 : safi = SAFI_MPLS_LABELED_VPN;
844 :
845 0 : stream_putc (s, BGP_OPEN_OPT_CAP);
846 0 : capp = stream_get_endp (s); /* Set Capability Len Pointer */
847 0 : stream_putc (s, 0); /* Capability Length */
848 0 : stream_putc (s, code); /* Capability Code */
849 0 : orfp = stream_get_endp (s); /* Set ORF Len Pointer */
850 0 : stream_putc (s, 0); /* ORF Length */
851 0 : stream_putw (s, afi);
852 0 : stream_putc (s, 0);
853 0 : stream_putc (s, safi);
854 0 : numberp = stream_get_endp (s); /* Set Number Pointer */
855 0 : stream_putc (s, 0); /* Number of ORFs */
856 :
857 : /* Address Prefix ORF */
858 0 : if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
859 0 : || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
860 : {
861 0 : stream_putc (s, (code == CAPABILITY_CODE_ORF ?
862 : ORF_TYPE_PREFIX : ORF_TYPE_PREFIX_OLD));
863 :
864 0 : if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
865 0 : && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
866 : {
867 0 : SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
868 0 : SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
869 0 : stream_putc (s, ORF_MODE_BOTH);
870 : }
871 0 : else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
872 : {
873 0 : SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
874 0 : stream_putc (s, ORF_MODE_SEND);
875 : }
876 : else
877 : {
878 0 : SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
879 0 : stream_putc (s, ORF_MODE_RECEIVE);
880 : }
881 0 : number_of_orfs++;
882 : }
883 :
884 : /* Total Number of ORFs. */
885 0 : stream_putc_at (s, numberp, number_of_orfs);
886 :
887 : /* Total ORF Len. */
888 0 : orf_len = stream_get_endp (s) - orfp - 1;
889 0 : stream_putc_at (s, orfp, orf_len);
890 :
891 : /* Total Capability Len. */
892 0 : cap_len = stream_get_endp (s) - capp - 1;
893 0 : stream_putc_at (s, capp, cap_len);
894 0 : }
895 :
896 : /* Fill in capability open option to the packet. */
897 : void
898 0 : bgp_open_capability (struct stream *s, struct peer *peer)
899 : {
900 : u_char len;
901 : unsigned long cp;
902 : afi_t afi;
903 : safi_t safi;
904 : as_t local_as;
905 :
906 : /* Remember current pointer for Opt Parm Len. */
907 0 : cp = stream_get_endp (s);
908 :
909 : /* Opt Parm Len. */
910 0 : stream_putc (s, 0);
911 :
912 : /* Do not send capability. */
913 0 : if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN)
914 0 : || CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
915 0 : return;
916 :
917 : /* IPv4 unicast. */
918 0 : if (peer->afc[AFI_IP][SAFI_UNICAST])
919 : {
920 0 : peer->afc_adv[AFI_IP][SAFI_UNICAST] = 1;
921 0 : stream_putc (s, BGP_OPEN_OPT_CAP);
922 0 : stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
923 0 : stream_putc (s, CAPABILITY_CODE_MP);
924 0 : stream_putc (s, CAPABILITY_CODE_MP_LEN);
925 0 : stream_putw (s, AFI_IP);
926 0 : stream_putc (s, 0);
927 0 : stream_putc (s, SAFI_UNICAST);
928 : }
929 : /* IPv4 multicast. */
930 0 : if (peer->afc[AFI_IP][SAFI_MULTICAST])
931 : {
932 0 : peer->afc_adv[AFI_IP][SAFI_MULTICAST] = 1;
933 0 : stream_putc (s, BGP_OPEN_OPT_CAP);
934 0 : stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
935 0 : stream_putc (s, CAPABILITY_CODE_MP);
936 0 : stream_putc (s, CAPABILITY_CODE_MP_LEN);
937 0 : stream_putw (s, AFI_IP);
938 0 : stream_putc (s, 0);
939 0 : stream_putc (s, SAFI_MULTICAST);
940 : }
941 : /* IPv4 VPN */
942 0 : if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
943 : {
944 0 : peer->afc_adv[AFI_IP][SAFI_MPLS_VPN] = 1;
945 0 : stream_putc (s, BGP_OPEN_OPT_CAP);
946 0 : stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
947 0 : stream_putc (s, CAPABILITY_CODE_MP);
948 0 : stream_putc (s, CAPABILITY_CODE_MP_LEN);
949 0 : stream_putw (s, AFI_IP);
950 0 : stream_putc (s, 0);
951 0 : stream_putc (s, SAFI_MPLS_LABELED_VPN);
952 : }
953 : #ifdef HAVE_IPV6
954 : /* IPv6 unicast. */
955 0 : if (peer->afc[AFI_IP6][SAFI_UNICAST])
956 : {
957 0 : peer->afc_adv[AFI_IP6][SAFI_UNICAST] = 1;
958 0 : stream_putc (s, BGP_OPEN_OPT_CAP);
959 0 : stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
960 0 : stream_putc (s, CAPABILITY_CODE_MP);
961 0 : stream_putc (s, CAPABILITY_CODE_MP_LEN);
962 0 : stream_putw (s, AFI_IP6);
963 0 : stream_putc (s, 0);
964 0 : stream_putc (s, SAFI_UNICAST);
965 : }
966 : /* IPv6 multicast. */
967 0 : if (peer->afc[AFI_IP6][SAFI_MULTICAST])
968 : {
969 0 : peer->afc_adv[AFI_IP6][SAFI_MULTICAST] = 1;
970 0 : stream_putc (s, BGP_OPEN_OPT_CAP);
971 0 : stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
972 0 : stream_putc (s, CAPABILITY_CODE_MP);
973 0 : stream_putc (s, CAPABILITY_CODE_MP_LEN);
974 0 : stream_putw (s, AFI_IP6);
975 0 : stream_putc (s, 0);
976 0 : stream_putc (s, SAFI_MULTICAST);
977 : }
978 : #endif /* HAVE_IPV6 */
979 :
980 : /* Route refresh. */
981 0 : SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
982 0 : stream_putc (s, BGP_OPEN_OPT_CAP);
983 0 : stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
984 0 : stream_putc (s, CAPABILITY_CODE_REFRESH_OLD);
985 0 : stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
986 0 : stream_putc (s, BGP_OPEN_OPT_CAP);
987 0 : stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
988 0 : stream_putc (s, CAPABILITY_CODE_REFRESH);
989 0 : stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
990 :
991 : /* AS4 */
992 0 : SET_FLAG (peer->cap, PEER_CAP_AS4_ADV);
993 0 : stream_putc (s, BGP_OPEN_OPT_CAP);
994 0 : stream_putc (s, CAPABILITY_CODE_AS4_LEN + 2);
995 0 : stream_putc (s, CAPABILITY_CODE_AS4);
996 0 : stream_putc (s, CAPABILITY_CODE_AS4_LEN);
997 0 : if ( peer->change_local_as )
998 0 : local_as = peer->change_local_as;
999 : else
1000 0 : local_as = peer->local_as;
1001 0 : stream_putl (s, local_as );
1002 :
1003 : /* ORF capability. */
1004 0 : for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1005 0 : for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
1006 0 : if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
1007 0 : || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
1008 : {
1009 0 : bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF_OLD);
1010 0 : bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF);
1011 : }
1012 :
1013 : /* Dynamic capability. */
1014 0 : if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
1015 : {
1016 0 : SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV);
1017 0 : stream_putc (s, BGP_OPEN_OPT_CAP);
1018 0 : stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
1019 0 : stream_putc (s, CAPABILITY_CODE_DYNAMIC);
1020 0 : stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN);
1021 : }
1022 :
1023 : /* Graceful restart capability */
1024 0 : if (bgp_flag_check (peer->bgp, BGP_FLAG_GRACEFUL_RESTART))
1025 : {
1026 0 : SET_FLAG (peer->cap, PEER_CAP_RESTART_ADV);
1027 0 : stream_putc (s, BGP_OPEN_OPT_CAP);
1028 0 : stream_putc (s, CAPABILITY_CODE_RESTART_LEN + 2);
1029 0 : stream_putc (s, CAPABILITY_CODE_RESTART);
1030 0 : stream_putc (s, CAPABILITY_CODE_RESTART_LEN);
1031 0 : stream_putw (s, peer->bgp->restart_time);
1032 : }
1033 :
1034 : /* Total Opt Parm Len. */
1035 0 : len = stream_get_endp (s) - cp - 1;
1036 0 : stream_putc_at (s, cp, len);
1037 : }
|