Annotation of embedaddon/quagga/bgpd/bgp_open.c, revision 1.1.1.4
1.1 misho 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: 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: pnt = peer->notify.data;
59: end = pnt + peer->notify.length;
60:
61: while (pnt < end)
62: {
63: if (pnt + sizeof (struct capability_mp_data) + 2 > end)
64: return;
65:
66: hdr = (struct capability_header *)pnt;
67: if (pnt + hdr->length + 2 > end)
68: return;
69:
70: memcpy (&mpc, pnt + 2, sizeof(struct capability_mp_data));
71:
72: if (hdr->code == CAPABILITY_CODE_MP)
73: {
74: vty_out (vty, " Capability error for: Multi protocol ");
75:
76: switch (ntohs (mpc.afi))
77: {
78: case AFI_IP:
79: vty_out (vty, "AFI IPv4, ");
80: break;
81: case AFI_IP6:
82: vty_out (vty, "AFI IPv6, ");
83: break;
84: default:
85: vty_out (vty, "AFI Unknown %d, ", ntohs (mpc.afi));
86: break;
87: }
88: switch (mpc.safi)
89: {
90: case SAFI_UNICAST:
91: vty_out (vty, "SAFI Unicast");
92: break;
93: case SAFI_MULTICAST:
94: vty_out (vty, "SAFI Multicast");
95: break;
1.1.1.3 misho 96: case SAFI_MPLS_LABELED_VPN:
97: vty_out (vty, "SAFI MPLS-labeled VPN");
1.1 misho 98: break;
99: default:
100: vty_out (vty, "SAFI Unknown %d ", mpc.safi);
101: break;
102: }
103: vty_out (vty, "%s", VTY_NEWLINE);
104: }
105: else if (hdr->code >= 128)
106: vty_out (vty, " Capability error: vendor specific capability code %d",
107: hdr->code);
108: else
109: vty_out (vty, " Capability error: unknown capability code %d",
110: hdr->code);
111:
112: pnt += hdr->length + 2;
113: }
114: }
115:
116: static void
117: bgp_capability_mp_data (struct stream *s, struct capability_mp_data *mpc)
118: {
119: mpc->afi = stream_getw (s);
120: mpc->reserved = stream_getc (s);
121: mpc->safi = stream_getc (s);
122: }
123:
124: int
125: bgp_afi_safi_valid_indices (afi_t afi, safi_t *safi)
126: {
127: switch (afi)
128: {
129: case AFI_IP:
130: #ifdef HAVE_IPV6
131: case AFI_IP6:
132: #endif
133: switch (*safi)
134: {
1.1.1.3 misho 135: /* BGP MPLS-labeled VPN SAFI isn't contigious with others, remap */
136: case SAFI_MPLS_LABELED_VPN:
1.1 misho 137: *safi = SAFI_MPLS_VPN;
138: case SAFI_UNICAST:
139: case SAFI_MULTICAST:
140: case SAFI_MPLS_VPN:
141: return 1;
142: }
143: }
144: zlog_debug ("unknown afi/safi (%u/%u)", afi, *safi);
145:
146: return 0;
147: }
148:
149: /* Set negotiated capability value. */
150: static int
151: bgp_capability_mp (struct peer *peer, struct capability_header *hdr)
152: {
153: struct capability_mp_data mpc;
154: struct stream *s = BGP_INPUT (peer);
155:
156: bgp_capability_mp_data (s, &mpc);
157:
158: if (BGP_DEBUG (normal, NORMAL))
159: zlog_debug ("%s OPEN has MP_EXT CAP for afi/safi: %u/%u",
160: peer->host, mpc.afi, mpc.safi);
161:
162: if (!bgp_afi_safi_valid_indices (mpc.afi, &mpc.safi))
163: return -1;
164:
165: /* Now safi remapped, and afi/safi are valid array indices */
166: peer->afc_recv[mpc.afi][mpc.safi] = 1;
167:
168: if (peer->afc[mpc.afi][mpc.safi])
169: peer->afc_nego[mpc.afi][mpc.safi] = 1;
170: else
171: return -1;
172:
173: return 0;
174: }
175:
176: static void
177: bgp_capability_orf_not_support (struct peer *peer, afi_t afi, safi_t safi,
178: u_char type, u_char mode)
179: {
180: if (BGP_DEBUG (normal, NORMAL))
181: zlog_debug ("%s Addr-family %d/%d has ORF type/mode %d/%d not supported",
182: peer->host, afi, safi, type, mode);
183: }
184:
185: static const struct message orf_type_str[] =
186: {
187: { ORF_TYPE_PREFIX, "Prefixlist" },
188: { ORF_TYPE_PREFIX_OLD, "Prefixlist (old)" },
189: };
1.1.1.4 ! misho 190: static const int orf_type_str_max = array_size(orf_type_str);
1.1 misho 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: };
1.1.1.4 ! misho 198: static const int orf_mode_str_max = array_size(orf_mode_str);
1.1 misho 199:
200: static int
201: bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr)
202: {
203: 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: u_int16_t sm_cap = 0; /* capability send-mode receive */
210: u_int16_t rm_cap = 0; /* capability receive-mode receive */
211: int i;
212:
213: /* ORF Entry header */
214: bgp_capability_mp_data (s, &entry.mpc);
215: entry.num = stream_getc (s);
216: afi = entry.mpc.afi;
217: safi = entry.mpc.safi;
218:
219: if (BGP_DEBUG (normal, NORMAL))
220: zlog_debug ("%s ORF Cap entry for afi/safi: %u/%u",
221: peer->host, entry.mpc.afi, entry.mpc.safi);
222:
223: /* Check AFI and SAFI. */
224: if (!bgp_afi_safi_valid_indices (entry.mpc.afi, &safi))
225: {
226: zlog_info ("%s Addr-family %d/%d not supported."
227: " Ignoring the ORF capability",
228: peer->host, entry.mpc.afi, entry.mpc.safi);
229: return 0;
230: }
231:
232: /* validate number field */
233: if (sizeof (struct capability_orf_entry) + (entry.num * 2) > hdr->length)
234: {
235: zlog_info ("%s ORF Capability entry length error,"
236: " Cap length %u, num %u",
237: peer->host, hdr->length, entry.num);
238: bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
239: return -1;
240: }
241:
242: for (i = 0 ; i < entry.num ; i++)
243: {
244: type = stream_getc(s);
245: mode = stream_getc(s);
246:
247: /* ORF Mode error check */
248: switch (mode)
249: {
250: case ORF_MODE_BOTH:
251: case ORF_MODE_SEND:
252: case ORF_MODE_RECEIVE:
253: break;
254: default:
255: bgp_capability_orf_not_support (peer, afi, safi, type, mode);
256: continue;
257: }
258: /* ORF Type and afi/safi error checks */
259: /* capcode versus type */
260: switch (hdr->code)
261: {
262: case CAPABILITY_CODE_ORF:
263: switch (type)
264: {
265: case ORF_TYPE_PREFIX:
266: break;
267: default:
268: bgp_capability_orf_not_support (peer, afi, safi, type, mode);
269: continue;
270: }
271: break;
272: case CAPABILITY_CODE_ORF_OLD:
273: switch (type)
274: {
275: case ORF_TYPE_PREFIX_OLD:
276: break;
277: default:
278: bgp_capability_orf_not_support (peer, afi, safi, type, mode);
279: continue;
280: }
281: break;
282: default:
283: bgp_capability_orf_not_support (peer, afi, safi, type, mode);
284: continue;
285: }
286:
287: /* AFI vs SAFI */
288: if (!((afi == AFI_IP && safi == SAFI_UNICAST)
289: || (afi == AFI_IP && safi == SAFI_MULTICAST)
290: || (afi == AFI_IP6 && safi == SAFI_UNICAST)))
291: {
292: bgp_capability_orf_not_support (peer, afi, safi, type, mode);
293: continue;
294: }
295:
296: if (BGP_DEBUG (normal, NORMAL))
297: 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: entry.mpc.afi, safi);
302:
303: if (hdr->code == CAPABILITY_CODE_ORF)
304: {
305: sm_cap = PEER_CAP_ORF_PREFIX_SM_RCV;
306: rm_cap = PEER_CAP_ORF_PREFIX_RM_RCV;
307: }
308: else if (hdr->code == CAPABILITY_CODE_ORF_OLD)
309: {
310: sm_cap = PEER_CAP_ORF_PREFIX_SM_OLD_RCV;
311: rm_cap = PEER_CAP_ORF_PREFIX_RM_OLD_RCV;
312: }
313: else
314: {
315: bgp_capability_orf_not_support (peer, afi, safi, type, mode);
316: continue;
317: }
318:
319: switch (mode)
320: {
321: case ORF_MODE_BOTH:
322: SET_FLAG (peer->af_cap[afi][safi], sm_cap);
323: SET_FLAG (peer->af_cap[afi][safi], rm_cap);
324: break;
325: case ORF_MODE_SEND:
326: SET_FLAG (peer->af_cap[afi][safi], sm_cap);
327: break;
328: case ORF_MODE_RECEIVE:
329: SET_FLAG (peer->af_cap[afi][safi], rm_cap);
330: break;
331: }
332: }
333: return 0;
334: }
335:
336: static int
337: bgp_capability_restart (struct peer *peer, struct capability_header *caphdr)
338: {
339: struct stream *s = BGP_INPUT (peer);
340: u_int16_t restart_flag_time;
341: int restart_bit = 0;
342: size_t end = stream_get_getp (s) + caphdr->length;
343:
344: SET_FLAG (peer->cap, PEER_CAP_RESTART_RCV);
345: restart_flag_time = stream_getw(s);
346: if (CHECK_FLAG (restart_flag_time, RESTART_R_BIT))
347: restart_bit = 1;
348: UNSET_FLAG (restart_flag_time, 0xF000);
349: peer->v_gr_restart = restart_flag_time;
350:
351: if (BGP_DEBUG (normal, NORMAL))
352: {
353: zlog_debug ("%s OPEN has Graceful Restart capability", peer->host);
354: zlog_debug ("%s Peer has%srestarted. Restart Time : %d",
355: peer->host, restart_bit ? " " : " not ",
356: peer->v_gr_restart);
357: }
358:
1.1.1.3 misho 359: while (stream_get_getp (s) + 4 <= end)
1.1 misho 360: {
361: afi_t afi = stream_getw (s);
362: safi_t safi = stream_getc (s);
363: u_char flag = stream_getc (s);
364:
365: if (!bgp_afi_safi_valid_indices (afi, &safi))
366: {
367: if (BGP_DEBUG (normal, NORMAL))
368: zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported."
369: " Ignore the Graceful Restart capability",
370: peer->host, afi, safi);
371: }
372: else if (!peer->afc[afi][safi])
373: {
374: if (BGP_DEBUG (normal, NORMAL))
375: 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: if (BGP_DEBUG (normal, NORMAL))
382: zlog_debug ("%s Address family %s is%spreserved", peer->host,
383: afi_safi_print (afi, safi),
384: CHECK_FLAG (peer->af_cap[afi][safi],
385: PEER_CAP_RESTART_AF_PRESERVE_RCV)
386: ? " " : " not ");
387:
388: SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV);
389: if (CHECK_FLAG (flag, RESTART_F_BIT))
390: SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV);
391:
392: }
393: }
394: return 0;
395: }
396:
397: static as_t
398: bgp_capability_as4 (struct peer *peer, struct capability_header *hdr)
399: {
1.1.1.2 misho 400: SET_FLAG (peer->cap, PEER_CAP_AS4_RCV);
401:
402: if (hdr->length != CAPABILITY_CODE_AS4_LEN)
403: {
404: zlog_err ("%s AS4 capability has incorrect data length %d",
405: peer->host, hdr->length);
406: return 0;
407: }
408:
1.1 misho 409: as_t as4 = stream_getl (BGP_INPUT(peer));
410:
411: if (BGP_DEBUG (as4, AS4))
412: zlog_debug ("%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u",
413: peer->host, as4);
414: 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: };
1.1.1.4 ! misho 428: static const int capcode_str_max = array_size(capcode_str);
1.1 misho 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:
1.1.1.3 misho 443: /**
444: * Parse given capability.
1.1 misho 445: * XXX: This is reading into a stream, but not using stream API
1.1.1.3 misho 446: *
447: * @param[out] mp_capability Set to 1 on return iff one or more Multiprotocol
448: * capabilities were encountered.
1.1 misho 449: */
450: static int
1.1.1.3 misho 451: bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability,
452: u_char **error)
1.1 misho 453: {
454: int ret;
455: struct stream *s = BGP_INPUT (peer);
456: size_t end = stream_get_getp (s) + length;
457:
458: assert (STREAM_READABLE (s) >= length);
459:
460: while (stream_get_getp (s) < end)
461: {
462: size_t start;
463: u_char *sp = stream_pnt (s);
464: struct capability_header caphdr;
465:
466: /* We need at least capability code and capability length. */
467: if (stream_get_getp(s) + 2 > end)
468: {
469: zlog_info ("%s Capability length error (< header)", peer->host);
470: bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
471: return -1;
472: }
473:
474: caphdr.code = stream_getc (s);
475: caphdr.length = stream_getc (s);
476: start = stream_get_getp (s);
477:
478: /* Capability length check sanity check. */
479: if (start + caphdr.length > end)
480: {
481: zlog_info ("%s Capability length error (< length)", peer->host);
482: bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
483: return -1;
484: }
485:
486: if (BGP_DEBUG (normal, NORMAL))
487: zlog_debug ("%s OPEN has %s capability (%u), length %u",
488: peer->host,
489: LOOKUP (capcode_str, caphdr.code),
490: caphdr.code, caphdr.length);
491:
492: /* Length sanity check, type-specific, for known capabilities */
493: 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: if (caphdr.length < cap_minsizes[caphdr.code])
505: {
506: zlog_info ("%s %s Capability length error: got %u,"
507: " expected at least %u",
508: peer->host,
509: LOOKUP (capcode_str, caphdr.code),
510: caphdr.length,
511: (unsigned) cap_minsizes[caphdr.code]);
512: bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
513: return -1;
514: }
515: /* we deliberately ignore unknown codes, see below */
516: default:
517: break;
518: }
519:
520: switch (caphdr.code)
521: {
522: case CAPABILITY_CODE_MP:
523: {
1.1.1.3 misho 524: *mp_capability = 1;
525:
1.1 misho 526: /* Ignore capability when override-capability is set. */
527: if (! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
528: {
529: /* Set negotiated value. */
530: ret = bgp_capability_mp (peer, &caphdr);
531:
532: /* Unsupported Capability. */
533: if (ret < 0)
534: {
535: /* Store return data. */
536: memcpy (*error, sp, caphdr.length + 2);
537: *error += caphdr.length + 2;
538: }
539: }
540: }
541: break;
542: case CAPABILITY_CODE_REFRESH:
543: case CAPABILITY_CODE_REFRESH_OLD:
544: {
545: /* BGP refresh capability */
546: if (caphdr.code == CAPABILITY_CODE_REFRESH_OLD)
547: SET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV);
548: else
549: SET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV);
550: }
551: break;
552: case CAPABILITY_CODE_ORF:
553: case CAPABILITY_CODE_ORF_OLD:
1.1.1.4 ! misho 554: if (bgp_capability_orf_entry (peer, &caphdr))
1.1 misho 555: return -1;
556: break;
557: case CAPABILITY_CODE_RESTART:
558: if (bgp_capability_restart (peer, &caphdr))
559: return -1;
560: break;
561: case CAPABILITY_CODE_DYNAMIC:
562: SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);
563: 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: if (!bgp_capability_as4 (peer, &caphdr))
570: return -1;
571: break;
572: default:
573: if (caphdr.code > 128)
574: {
575: /* We don't send Notification for unknown vendor specific
576: capabilities. It seems reasonable for now... */
577: zlog_warn ("%s Vendor specific capability %d",
578: peer->host, caphdr.code);
579: }
580: else
581: {
582: zlog_warn ("%s unrecognized capability code: %d - ignored",
583: peer->host, caphdr.code);
584: memcpy (*error, sp, caphdr.length + 2);
585: *error += caphdr.length + 2;
586: }
587: }
588: if (stream_get_getp(s) != (start + caphdr.length))
589: {
590: if (stream_get_getp(s) > (start + caphdr.length))
591: zlog_warn ("%s Cap-parser for %s read past cap-length, %u!",
592: peer->host, LOOKUP (capcode_str, caphdr.code),
593: caphdr.length);
594: stream_set_getp (s, start + caphdr.length);
595: }
596: }
597: return 0;
598: }
599:
600: static int
601: bgp_auth_parse (struct peer *peer, size_t length)
602: {
603: bgp_notify_send (peer,
604: BGP_NOTIFY_OPEN_ERR,
605: BGP_NOTIFY_OPEN_AUTH_FAILURE);
606: return -1;
607: }
608:
609: static int
610: strict_capability_same (struct peer *peer)
611: {
612: int i, j;
613:
614: for (i = AFI_IP; i < AFI_MAX; i++)
615: for (j = SAFI_UNICAST; j < SAFI_MAX; j++)
616: if (peer->afc[i][j] != peer->afc_nego[i][j])
617: return 0;
618: 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: peek_for_as4_capability (struct peer *peer, u_char length)
626: {
627: struct stream *s = BGP_INPUT (peer);
628: size_t orig_getp = stream_get_getp (s);
629: size_t end = orig_getp + length;
630: as_t as4 = 0;
631:
632: /* The full capability parser will better flag the error.. */
633: if (STREAM_READABLE(s) < length)
634: return 0;
635:
636: if (BGP_DEBUG (as4, AS4))
637: 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: while (stream_get_getp(s) < end)
644: {
645: u_char opt_type;
646: u_char opt_length;
647:
648: /* Check the length. */
649: if (stream_get_getp (s) + 2 > end)
650: goto end;
651:
652: /* Fetch option type and length. */
653: opt_type = stream_getc (s);
654: opt_length = stream_getc (s);
655:
656: /* Option length check. */
657: if (stream_get_getp (s) + opt_length > end)
658: goto end;
659:
660: if (opt_type == BGP_OPEN_OPT_CAP)
661: {
662: unsigned long capd_start = stream_get_getp (s);
663: unsigned long capd_end = capd_start + opt_length;
664:
665: assert (capd_end <= end);
666:
667: while (stream_get_getp (s) < capd_end)
668: {
669: struct capability_header hdr;
670:
671: if (stream_get_getp (s) + 2 > capd_end)
672: goto end;
673:
674: hdr.code = stream_getc (s);
675: hdr.length = stream_getc (s);
676:
677: if ((stream_get_getp(s) + hdr.length) > capd_end)
678: goto end;
679:
680: if (hdr.code == CAPABILITY_CODE_AS4)
681: {
682: if (BGP_DEBUG (as4, AS4))
683: zlog_info ("[AS4] found AS4 capability, about to parse");
684: as4 = bgp_capability_as4 (peer, &hdr);
685:
686: goto end;
687: }
688: stream_forward_getp (s, hdr.length);
689: }
690: }
691: }
692:
693: end:
694: stream_set_getp (s, orig_getp);
695: return as4;
696: }
697:
1.1.1.3 misho 698: /**
699: * Parse open option.
700: *
701: * @param[out] mp_capability @see bgp_capability_parse() for semantics.
702: */
1.1 misho 703: int
1.1.1.3 misho 704: bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability)
1.1 misho 705: {
706: int ret;
707: u_char *error;
708: u_char error_data[BGP_MAX_PACKET_SIZE];
709: struct stream *s = BGP_INPUT(peer);
710: size_t end = stream_get_getp (s) + length;
711:
712: ret = 0;
713: error = error_data;
714:
715: if (BGP_DEBUG (normal, NORMAL))
716: zlog_debug ("%s rcv OPEN w/ OPTION parameter len: %u",
717: peer->host, length);
718:
719: 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: if (STREAM_READABLE(s) < 2)
726: {
727: zlog_info ("%s Option length error", peer->host);
728: bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
729: return -1;
730: }
731:
732: /* Fetch option type and length. */
733: opt_type = stream_getc (s);
734: opt_length = stream_getc (s);
735:
736: /* Option length check. */
737: if (STREAM_READABLE (s) < opt_length)
738: {
739: zlog_info ("%s Option length error", peer->host);
740: bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
741: return -1;
742: }
743:
744: if (BGP_DEBUG (normal, NORMAL))
745: 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: opt_type == BGP_OPEN_OPT_CAP ? "Capability" : "Unknown",
749: opt_length);
750:
751: switch (opt_type)
752: {
753: case BGP_OPEN_OPT_AUTH:
754: ret = bgp_auth_parse (peer, opt_length);
755: break;
756: case BGP_OPEN_OPT_CAP:
1.1.1.3 misho 757: ret = bgp_capability_parse (peer, opt_length, mp_capability, &error);
1.1 misho 758: break;
759: default:
760: bgp_notify_send (peer,
761: BGP_NOTIFY_OPEN_ERR,
762: BGP_NOTIFY_OPEN_UNSUP_PARAM);
763: ret = -1;
764: 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: if (ret < 0)
772: return -1;
773: }
774:
775: /* All OPEN option is parsed. Check capability when strict compare
776: flag is enabled.*/
777: if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
778: {
779: /* If Unsupported Capability exists. */
780: if (error != error_data)
781: {
782: bgp_notify_send_with_data (peer,
783: BGP_NOTIFY_OPEN_ERR,
784: BGP_NOTIFY_OPEN_UNSUP_CAPBL,
785: error_data, error - error_data);
786: return -1;
787: }
788:
789: /* Check local capability does not negotiated with remote
790: peer. */
791: if (! strict_capability_same (peer))
792: {
793: bgp_notify_send (peer,
794: BGP_NOTIFY_OPEN_ERR,
795: BGP_NOTIFY_OPEN_UNSUP_CAPBL);
796: return -1;
797: }
798: }
799:
1.1.1.3 misho 800: /* Check there are no common AFI/SAFIs and send Unsupported Capability
1.1 misho 801: error. */
1.1.1.3 misho 802: if (*mp_capability &&
803: ! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
1.1 misho 804: {
805: if (! peer->afc_nego[AFI_IP][SAFI_UNICAST]
806: && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST]
807: && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
808: && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST]
809: && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
810: {
1.1.1.3 misho 811: plog_err (peer->log, "%s [Error] Configured AFI/SAFIs do not "
812: "overlap with received MP capabilities",
813: peer->host);
1.1 misho 814:
815: if (error != error_data)
816:
817: bgp_notify_send_with_data (peer,
818: BGP_NOTIFY_OPEN_ERR,
819: BGP_NOTIFY_OPEN_UNSUP_CAPBL,
820: error_data, error - error_data);
821: else
822: bgp_notify_send (peer,
823: BGP_NOTIFY_OPEN_ERR,
824: BGP_NOTIFY_OPEN_UNSUP_CAPBL);
825: return -1;
826: }
827: }
828: return 0;
829: }
830:
831: static void
832: 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: int number_of_orfs = 0;
841:
842: if (safi == SAFI_MPLS_VPN)
1.1.1.3 misho 843: safi = SAFI_MPLS_LABELED_VPN;
1.1 misho 844:
845: stream_putc (s, BGP_OPEN_OPT_CAP);
846: capp = stream_get_endp (s); /* Set Capability Len Pointer */
847: stream_putc (s, 0); /* Capability Length */
848: stream_putc (s, code); /* Capability Code */
849: orfp = stream_get_endp (s); /* Set ORF Len Pointer */
850: stream_putc (s, 0); /* ORF Length */
851: stream_putw (s, afi);
852: stream_putc (s, 0);
853: stream_putc (s, safi);
854: numberp = stream_get_endp (s); /* Set Number Pointer */
855: stream_putc (s, 0); /* Number of ORFs */
856:
857: /* Address Prefix ORF */
858: if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
859: || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
860: {
861: stream_putc (s, (code == CAPABILITY_CODE_ORF ?
862: ORF_TYPE_PREFIX : ORF_TYPE_PREFIX_OLD));
863:
864: if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
865: && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
866: {
867: SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
868: SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
869: stream_putc (s, ORF_MODE_BOTH);
870: }
871: else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
872: {
873: SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
874: stream_putc (s, ORF_MODE_SEND);
875: }
876: else
877: {
878: SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
879: stream_putc (s, ORF_MODE_RECEIVE);
880: }
881: number_of_orfs++;
882: }
883:
884: /* Total Number of ORFs. */
885: stream_putc_at (s, numberp, number_of_orfs);
886:
887: /* Total ORF Len. */
888: orf_len = stream_get_endp (s) - orfp - 1;
889: stream_putc_at (s, orfp, orf_len);
890:
891: /* Total Capability Len. */
892: cap_len = stream_get_endp (s) - capp - 1;
893: stream_putc_at (s, capp, cap_len);
894: }
895:
896: /* Fill in capability open option to the packet. */
897: void
898: 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: cp = stream_get_endp (s);
908:
909: /* Opt Parm Len. */
910: stream_putc (s, 0);
911:
912: /* Do not send capability. */
913: if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN)
914: || CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
915: return;
916:
917: /* IPv4 unicast. */
918: if (peer->afc[AFI_IP][SAFI_UNICAST])
919: {
920: peer->afc_adv[AFI_IP][SAFI_UNICAST] = 1;
921: stream_putc (s, BGP_OPEN_OPT_CAP);
922: stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
923: stream_putc (s, CAPABILITY_CODE_MP);
924: stream_putc (s, CAPABILITY_CODE_MP_LEN);
925: stream_putw (s, AFI_IP);
926: stream_putc (s, 0);
927: stream_putc (s, SAFI_UNICAST);
928: }
929: /* IPv4 multicast. */
930: if (peer->afc[AFI_IP][SAFI_MULTICAST])
931: {
932: peer->afc_adv[AFI_IP][SAFI_MULTICAST] = 1;
933: stream_putc (s, BGP_OPEN_OPT_CAP);
934: stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
935: stream_putc (s, CAPABILITY_CODE_MP);
936: stream_putc (s, CAPABILITY_CODE_MP_LEN);
937: stream_putw (s, AFI_IP);
938: stream_putc (s, 0);
939: stream_putc (s, SAFI_MULTICAST);
940: }
941: /* IPv4 VPN */
942: if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
943: {
944: peer->afc_adv[AFI_IP][SAFI_MPLS_VPN] = 1;
945: stream_putc (s, BGP_OPEN_OPT_CAP);
946: stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
947: stream_putc (s, CAPABILITY_CODE_MP);
948: stream_putc (s, CAPABILITY_CODE_MP_LEN);
949: stream_putw (s, AFI_IP);
950: stream_putc (s, 0);
1.1.1.3 misho 951: stream_putc (s, SAFI_MPLS_LABELED_VPN);
1.1 misho 952: }
953: #ifdef HAVE_IPV6
954: /* IPv6 unicast. */
955: if (peer->afc[AFI_IP6][SAFI_UNICAST])
956: {
957: peer->afc_adv[AFI_IP6][SAFI_UNICAST] = 1;
958: stream_putc (s, BGP_OPEN_OPT_CAP);
959: stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
960: stream_putc (s, CAPABILITY_CODE_MP);
961: stream_putc (s, CAPABILITY_CODE_MP_LEN);
962: stream_putw (s, AFI_IP6);
963: stream_putc (s, 0);
964: stream_putc (s, SAFI_UNICAST);
965: }
966: /* IPv6 multicast. */
967: if (peer->afc[AFI_IP6][SAFI_MULTICAST])
968: {
969: peer->afc_adv[AFI_IP6][SAFI_MULTICAST] = 1;
970: stream_putc (s, BGP_OPEN_OPT_CAP);
971: stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
972: stream_putc (s, CAPABILITY_CODE_MP);
973: stream_putc (s, CAPABILITY_CODE_MP_LEN);
974: stream_putw (s, AFI_IP6);
975: stream_putc (s, 0);
976: stream_putc (s, SAFI_MULTICAST);
977: }
978: #endif /* HAVE_IPV6 */
979:
980: /* Route refresh. */
981: SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
982: stream_putc (s, BGP_OPEN_OPT_CAP);
983: stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
984: stream_putc (s, CAPABILITY_CODE_REFRESH_OLD);
985: stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
986: stream_putc (s, BGP_OPEN_OPT_CAP);
987: stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
988: stream_putc (s, CAPABILITY_CODE_REFRESH);
989: stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
990:
991: /* AS4 */
992: SET_FLAG (peer->cap, PEER_CAP_AS4_ADV);
993: stream_putc (s, BGP_OPEN_OPT_CAP);
994: stream_putc (s, CAPABILITY_CODE_AS4_LEN + 2);
995: stream_putc (s, CAPABILITY_CODE_AS4);
996: stream_putc (s, CAPABILITY_CODE_AS4_LEN);
997: if ( peer->change_local_as )
998: local_as = peer->change_local_as;
999: else
1000: local_as = peer->local_as;
1001: stream_putl (s, local_as );
1002:
1003: /* ORF capability. */
1004: for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1005: for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
1006: if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
1007: || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
1008: {
1009: bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF_OLD);
1010: bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF);
1011: }
1012:
1013: /* Dynamic capability. */
1014: if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
1015: {
1016: SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV);
1017: stream_putc (s, BGP_OPEN_OPT_CAP);
1018: stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
1019: stream_putc (s, CAPABILITY_CODE_DYNAMIC);
1020: stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN);
1021: }
1022:
1023: /* Graceful restart capability */
1024: if (bgp_flag_check (peer->bgp, BGP_FLAG_GRACEFUL_RESTART))
1025: {
1026: SET_FLAG (peer->cap, PEER_CAP_RESTART_ADV);
1027: stream_putc (s, BGP_OPEN_OPT_CAP);
1028: stream_putc (s, CAPABILITY_CODE_RESTART_LEN + 2);
1029: stream_putc (s, CAPABILITY_CODE_RESTART);
1030: stream_putc (s, CAPABILITY_CODE_RESTART_LEN);
1031: stream_putw (s, peer->bgp->restart_time);
1032: }
1033:
1034: /* Total Opt Parm Len. */
1035: len = stream_get_endp (s) - cp - 1;
1036: stream_putc_at (s, cp, len);
1037: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>