Annotation of embedaddon/quagga/bgpd/bgp_open.c, revision 1.1.1.3
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: };
190: static const int orf_type_str_max
191: = sizeof(orf_type_str)/sizeof(orf_type_str[0]);
192:
193: static const struct message orf_mode_str[] =
194: {
195: { ORF_MODE_RECEIVE, "Receive" },
196: { ORF_MODE_SEND, "Send" },
197: { ORF_MODE_BOTH, "Both" },
198: };
199: static const int orf_mode_str_max
200: = sizeof(orf_mode_str)/sizeof(orf_mode_str[0]);
201:
202: static int
203: bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr)
204: {
205: struct stream *s = BGP_INPUT (peer);
206: struct capability_orf_entry entry;
207: afi_t afi;
208: safi_t safi;
209: u_char type;
210: u_char mode;
211: u_int16_t sm_cap = 0; /* capability send-mode receive */
212: u_int16_t rm_cap = 0; /* capability receive-mode receive */
213: int i;
214:
215: /* ORF Entry header */
216: bgp_capability_mp_data (s, &entry.mpc);
217: entry.num = stream_getc (s);
218: afi = entry.mpc.afi;
219: safi = entry.mpc.safi;
220:
221: if (BGP_DEBUG (normal, NORMAL))
222: zlog_debug ("%s ORF Cap entry for afi/safi: %u/%u",
223: peer->host, entry.mpc.afi, entry.mpc.safi);
224:
225: /* Check AFI and SAFI. */
226: if (!bgp_afi_safi_valid_indices (entry.mpc.afi, &safi))
227: {
228: zlog_info ("%s Addr-family %d/%d not supported."
229: " Ignoring the ORF capability",
230: peer->host, entry.mpc.afi, entry.mpc.safi);
231: return 0;
232: }
233:
234: /* validate number field */
235: if (sizeof (struct capability_orf_entry) + (entry.num * 2) > hdr->length)
236: {
237: zlog_info ("%s ORF Capability entry length error,"
238: " Cap length %u, num %u",
239: peer->host, hdr->length, entry.num);
240: bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
241: return -1;
242: }
243:
244: for (i = 0 ; i < entry.num ; i++)
245: {
246: type = stream_getc(s);
247: mode = stream_getc(s);
248:
249: /* ORF Mode error check */
250: switch (mode)
251: {
252: case ORF_MODE_BOTH:
253: case ORF_MODE_SEND:
254: case ORF_MODE_RECEIVE:
255: break;
256: default:
257: bgp_capability_orf_not_support (peer, afi, safi, type, mode);
258: continue;
259: }
260: /* ORF Type and afi/safi error checks */
261: /* capcode versus type */
262: switch (hdr->code)
263: {
264: case CAPABILITY_CODE_ORF:
265: switch (type)
266: {
267: case ORF_TYPE_PREFIX:
268: break;
269: default:
270: bgp_capability_orf_not_support (peer, afi, safi, type, mode);
271: continue;
272: }
273: break;
274: case CAPABILITY_CODE_ORF_OLD:
275: switch (type)
276: {
277: case ORF_TYPE_PREFIX_OLD:
278: break;
279: default:
280: bgp_capability_orf_not_support (peer, afi, safi, type, mode);
281: continue;
282: }
283: break;
284: default:
285: bgp_capability_orf_not_support (peer, afi, safi, type, mode);
286: continue;
287: }
288:
289: /* AFI vs SAFI */
290: if (!((afi == AFI_IP && safi == SAFI_UNICAST)
291: || (afi == AFI_IP && safi == SAFI_MULTICAST)
292: || (afi == AFI_IP6 && safi == SAFI_UNICAST)))
293: {
294: bgp_capability_orf_not_support (peer, afi, safi, type, mode);
295: continue;
296: }
297:
298: if (BGP_DEBUG (normal, NORMAL))
299: zlog_debug ("%s OPEN has %s ORF capability"
300: " as %s for afi/safi: %d/%d",
301: peer->host, LOOKUP (orf_type_str, type),
302: LOOKUP (orf_mode_str, mode),
303: entry.mpc.afi, safi);
304:
305: if (hdr->code == CAPABILITY_CODE_ORF)
306: {
307: sm_cap = PEER_CAP_ORF_PREFIX_SM_RCV;
308: rm_cap = PEER_CAP_ORF_PREFIX_RM_RCV;
309: }
310: else if (hdr->code == CAPABILITY_CODE_ORF_OLD)
311: {
312: sm_cap = PEER_CAP_ORF_PREFIX_SM_OLD_RCV;
313: rm_cap = PEER_CAP_ORF_PREFIX_RM_OLD_RCV;
314: }
315: else
316: {
317: bgp_capability_orf_not_support (peer, afi, safi, type, mode);
318: continue;
319: }
320:
321: switch (mode)
322: {
323: case ORF_MODE_BOTH:
324: SET_FLAG (peer->af_cap[afi][safi], sm_cap);
325: SET_FLAG (peer->af_cap[afi][safi], rm_cap);
326: break;
327: case ORF_MODE_SEND:
328: SET_FLAG (peer->af_cap[afi][safi], sm_cap);
329: break;
330: case ORF_MODE_RECEIVE:
331: SET_FLAG (peer->af_cap[afi][safi], rm_cap);
332: break;
333: }
334: }
335: return 0;
336: }
337:
338: static int
339: bgp_capability_orf (struct peer *peer, struct capability_header *hdr)
340: {
341: struct stream *s = BGP_INPUT (peer);
342: size_t end = stream_get_getp (s) + hdr->length;
343:
344: assert (stream_get_getp(s) + sizeof(struct capability_orf_entry) <= end);
345:
346: /* We must have at least one ORF entry, as the caller has already done
347: * minimum length validation for the capability code - for ORF there must
348: * at least one ORF entry (header and unknown number of pairs of bytes).
349: */
350: do
351: {
352: if (bgp_capability_orf_entry (peer, hdr) == -1)
353: return -1;
354: }
355: while (stream_get_getp(s) + sizeof(struct capability_orf_entry) < end);
356:
357: return 0;
358: }
359:
360: static int
361: bgp_capability_restart (struct peer *peer, struct capability_header *caphdr)
362: {
363: struct stream *s = BGP_INPUT (peer);
364: u_int16_t restart_flag_time;
365: int restart_bit = 0;
366: size_t end = stream_get_getp (s) + caphdr->length;
367:
368: SET_FLAG (peer->cap, PEER_CAP_RESTART_RCV);
369: restart_flag_time = stream_getw(s);
370: if (CHECK_FLAG (restart_flag_time, RESTART_R_BIT))
371: restart_bit = 1;
372: UNSET_FLAG (restart_flag_time, 0xF000);
373: peer->v_gr_restart = restart_flag_time;
374:
375: if (BGP_DEBUG (normal, NORMAL))
376: {
377: zlog_debug ("%s OPEN has Graceful Restart capability", peer->host);
378: zlog_debug ("%s Peer has%srestarted. Restart Time : %d",
379: peer->host, restart_bit ? " " : " not ",
380: peer->v_gr_restart);
381: }
382:
1.1.1.3 ! misho 383: while (stream_get_getp (s) + 4 <= end)
1.1 misho 384: {
385: afi_t afi = stream_getw (s);
386: safi_t safi = stream_getc (s);
387: u_char flag = stream_getc (s);
388:
389: if (!bgp_afi_safi_valid_indices (afi, &safi))
390: {
391: if (BGP_DEBUG (normal, NORMAL))
392: zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported."
393: " Ignore the Graceful Restart capability",
394: peer->host, afi, safi);
395: }
396: else if (!peer->afc[afi][safi])
397: {
398: if (BGP_DEBUG (normal, NORMAL))
399: zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled."
400: " Ignore the Graceful Restart capability",
401: peer->host, afi, safi);
402: }
403: else
404: {
405: if (BGP_DEBUG (normal, NORMAL))
406: zlog_debug ("%s Address family %s is%spreserved", peer->host,
407: afi_safi_print (afi, safi),
408: CHECK_FLAG (peer->af_cap[afi][safi],
409: PEER_CAP_RESTART_AF_PRESERVE_RCV)
410: ? " " : " not ");
411:
412: SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV);
413: if (CHECK_FLAG (flag, RESTART_F_BIT))
414: SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV);
415:
416: }
417: }
418: return 0;
419: }
420:
421: static as_t
422: bgp_capability_as4 (struct peer *peer, struct capability_header *hdr)
423: {
1.1.1.2 misho 424: SET_FLAG (peer->cap, PEER_CAP_AS4_RCV);
425:
426: if (hdr->length != CAPABILITY_CODE_AS4_LEN)
427: {
428: zlog_err ("%s AS4 capability has incorrect data length %d",
429: peer->host, hdr->length);
430: return 0;
431: }
432:
1.1 misho 433: as_t as4 = stream_getl (BGP_INPUT(peer));
434:
435: if (BGP_DEBUG (as4, AS4))
436: zlog_debug ("%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u",
437: peer->host, as4);
438: return as4;
439: }
440:
441: static const struct message capcode_str[] =
442: {
443: { CAPABILITY_CODE_MP, "MultiProtocol Extensions" },
444: { CAPABILITY_CODE_REFRESH, "Route Refresh" },
445: { CAPABILITY_CODE_ORF, "Cooperative Route Filtering" },
446: { CAPABILITY_CODE_RESTART, "Graceful Restart" },
447: { CAPABILITY_CODE_AS4, "4-octet AS number" },
448: { CAPABILITY_CODE_DYNAMIC, "Dynamic" },
449: { CAPABILITY_CODE_REFRESH_OLD, "Route Refresh (Old)" },
450: { CAPABILITY_CODE_ORF_OLD, "ORF (Old)" },
451: };
452: static const int capcode_str_max = sizeof(capcode_str)/sizeof(capcode_str[0]);
453:
454: /* Minimum sizes for length field of each cap (so not inc. the header) */
455: static const size_t cap_minsizes[] =
456: {
457: [CAPABILITY_CODE_MP] = sizeof (struct capability_mp_data),
458: [CAPABILITY_CODE_REFRESH] = CAPABILITY_CODE_REFRESH_LEN,
459: [CAPABILITY_CODE_ORF] = sizeof (struct capability_orf_entry),
460: [CAPABILITY_CODE_RESTART] = sizeof (struct capability_gr),
461: [CAPABILITY_CODE_AS4] = CAPABILITY_CODE_AS4_LEN,
462: [CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN,
463: [CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN,
464: [CAPABILITY_CODE_ORF_OLD] = sizeof (struct capability_orf_entry),
465: };
466:
1.1.1.3 ! misho 467: /**
! 468: * Parse given capability.
1.1 misho 469: * XXX: This is reading into a stream, but not using stream API
1.1.1.3 ! misho 470: *
! 471: * @param[out] mp_capability Set to 1 on return iff one or more Multiprotocol
! 472: * capabilities were encountered.
1.1 misho 473: */
474: static int
1.1.1.3 ! misho 475: bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability,
! 476: u_char **error)
1.1 misho 477: {
478: int ret;
479: struct stream *s = BGP_INPUT (peer);
480: size_t end = stream_get_getp (s) + length;
481:
482: assert (STREAM_READABLE (s) >= length);
483:
484: while (stream_get_getp (s) < end)
485: {
486: size_t start;
487: u_char *sp = stream_pnt (s);
488: struct capability_header caphdr;
489:
490: /* We need at least capability code and capability length. */
491: if (stream_get_getp(s) + 2 > end)
492: {
493: zlog_info ("%s Capability length error (< header)", peer->host);
494: bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
495: return -1;
496: }
497:
498: caphdr.code = stream_getc (s);
499: caphdr.length = stream_getc (s);
500: start = stream_get_getp (s);
501:
502: /* Capability length check sanity check. */
503: if (start + caphdr.length > end)
504: {
505: zlog_info ("%s Capability length error (< length)", peer->host);
506: bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
507: return -1;
508: }
509:
510: if (BGP_DEBUG (normal, NORMAL))
511: zlog_debug ("%s OPEN has %s capability (%u), length %u",
512: peer->host,
513: LOOKUP (capcode_str, caphdr.code),
514: caphdr.code, caphdr.length);
515:
516: /* Length sanity check, type-specific, for known capabilities */
517: switch (caphdr.code)
518: {
519: case CAPABILITY_CODE_MP:
520: case CAPABILITY_CODE_REFRESH:
521: case CAPABILITY_CODE_REFRESH_OLD:
522: case CAPABILITY_CODE_ORF:
523: case CAPABILITY_CODE_ORF_OLD:
524: case CAPABILITY_CODE_RESTART:
525: case CAPABILITY_CODE_AS4:
526: case CAPABILITY_CODE_DYNAMIC:
527: /* Check length. */
528: if (caphdr.length < cap_minsizes[caphdr.code])
529: {
530: zlog_info ("%s %s Capability length error: got %u,"
531: " expected at least %u",
532: peer->host,
533: LOOKUP (capcode_str, caphdr.code),
534: caphdr.length,
535: (unsigned) cap_minsizes[caphdr.code]);
536: bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
537: return -1;
538: }
539: /* we deliberately ignore unknown codes, see below */
540: default:
541: break;
542: }
543:
544: switch (caphdr.code)
545: {
546: case CAPABILITY_CODE_MP:
547: {
1.1.1.3 ! misho 548: *mp_capability = 1;
! 549:
1.1 misho 550: /* Ignore capability when override-capability is set. */
551: if (! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
552: {
553: /* Set negotiated value. */
554: ret = bgp_capability_mp (peer, &caphdr);
555:
556: /* Unsupported Capability. */
557: if (ret < 0)
558: {
559: /* Store return data. */
560: memcpy (*error, sp, caphdr.length + 2);
561: *error += caphdr.length + 2;
562: }
563: }
564: }
565: break;
566: case CAPABILITY_CODE_REFRESH:
567: case CAPABILITY_CODE_REFRESH_OLD:
568: {
569: /* BGP refresh capability */
570: if (caphdr.code == CAPABILITY_CODE_REFRESH_OLD)
571: SET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV);
572: else
573: SET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV);
574: }
575: break;
576: case CAPABILITY_CODE_ORF:
577: case CAPABILITY_CODE_ORF_OLD:
578: if (bgp_capability_orf (peer, &caphdr))
579: return -1;
580: break;
581: case CAPABILITY_CODE_RESTART:
582: if (bgp_capability_restart (peer, &caphdr))
583: return -1;
584: break;
585: case CAPABILITY_CODE_DYNAMIC:
586: SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);
587: break;
588: case CAPABILITY_CODE_AS4:
589: /* Already handled as a special-case parsing of the capabilities
590: * at the beginning of OPEN processing. So we care not a jot
591: * for the value really, only error case.
592: */
593: if (!bgp_capability_as4 (peer, &caphdr))
594: return -1;
595: break;
596: default:
597: if (caphdr.code > 128)
598: {
599: /* We don't send Notification for unknown vendor specific
600: capabilities. It seems reasonable for now... */
601: zlog_warn ("%s Vendor specific capability %d",
602: peer->host, caphdr.code);
603: }
604: else
605: {
606: zlog_warn ("%s unrecognized capability code: %d - ignored",
607: peer->host, caphdr.code);
608: memcpy (*error, sp, caphdr.length + 2);
609: *error += caphdr.length + 2;
610: }
611: }
612: if (stream_get_getp(s) != (start + caphdr.length))
613: {
614: if (stream_get_getp(s) > (start + caphdr.length))
615: zlog_warn ("%s Cap-parser for %s read past cap-length, %u!",
616: peer->host, LOOKUP (capcode_str, caphdr.code),
617: caphdr.length);
618: stream_set_getp (s, start + caphdr.length);
619: }
620: }
621: return 0;
622: }
623:
624: static int
625: bgp_auth_parse (struct peer *peer, size_t length)
626: {
627: bgp_notify_send (peer,
628: BGP_NOTIFY_OPEN_ERR,
629: BGP_NOTIFY_OPEN_AUTH_FAILURE);
630: return -1;
631: }
632:
633: static int
634: strict_capability_same (struct peer *peer)
635: {
636: int i, j;
637:
638: for (i = AFI_IP; i < AFI_MAX; i++)
639: for (j = SAFI_UNICAST; j < SAFI_MAX; j++)
640: if (peer->afc[i][j] != peer->afc_nego[i][j])
641: return 0;
642: return 1;
643: }
644:
645: /* peek into option, stores ASN to *as4 if the AS4 capability was found.
646: * Returns 0 if no as4 found, as4cap value otherwise.
647: */
648: as_t
649: peek_for_as4_capability (struct peer *peer, u_char length)
650: {
651: struct stream *s = BGP_INPUT (peer);
652: size_t orig_getp = stream_get_getp (s);
653: size_t end = orig_getp + length;
654: as_t as4 = 0;
655:
656: /* The full capability parser will better flag the error.. */
657: if (STREAM_READABLE(s) < length)
658: return 0;
659:
660: if (BGP_DEBUG (as4, AS4))
661: zlog_info ("%s [AS4] rcv OPEN w/ OPTION parameter len: %u,"
662: " peeking for as4",
663: peer->host, length);
664: /* the error cases we DONT handle, we ONLY try to read as4 out of
665: * correctly formatted options.
666: */
667: while (stream_get_getp(s) < end)
668: {
669: u_char opt_type;
670: u_char opt_length;
671:
672: /* Check the length. */
673: if (stream_get_getp (s) + 2 > end)
674: goto end;
675:
676: /* Fetch option type and length. */
677: opt_type = stream_getc (s);
678: opt_length = stream_getc (s);
679:
680: /* Option length check. */
681: if (stream_get_getp (s) + opt_length > end)
682: goto end;
683:
684: if (opt_type == BGP_OPEN_OPT_CAP)
685: {
686: unsigned long capd_start = stream_get_getp (s);
687: unsigned long capd_end = capd_start + opt_length;
688:
689: assert (capd_end <= end);
690:
691: while (stream_get_getp (s) < capd_end)
692: {
693: struct capability_header hdr;
694:
695: if (stream_get_getp (s) + 2 > capd_end)
696: goto end;
697:
698: hdr.code = stream_getc (s);
699: hdr.length = stream_getc (s);
700:
701: if ((stream_get_getp(s) + hdr.length) > capd_end)
702: goto end;
703:
704: if (hdr.code == CAPABILITY_CODE_AS4)
705: {
706: if (BGP_DEBUG (as4, AS4))
707: zlog_info ("[AS4] found AS4 capability, about to parse");
708: as4 = bgp_capability_as4 (peer, &hdr);
709:
710: goto end;
711: }
712: stream_forward_getp (s, hdr.length);
713: }
714: }
715: }
716:
717: end:
718: stream_set_getp (s, orig_getp);
719: return as4;
720: }
721:
1.1.1.3 ! misho 722: /**
! 723: * Parse open option.
! 724: *
! 725: * @param[out] mp_capability @see bgp_capability_parse() for semantics.
! 726: */
1.1 misho 727: int
1.1.1.3 ! misho 728: bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability)
1.1 misho 729: {
730: int ret;
731: u_char *error;
732: u_char error_data[BGP_MAX_PACKET_SIZE];
733: struct stream *s = BGP_INPUT(peer);
734: size_t end = stream_get_getp (s) + length;
735:
736: ret = 0;
737: error = error_data;
738:
739: if (BGP_DEBUG (normal, NORMAL))
740: zlog_debug ("%s rcv OPEN w/ OPTION parameter len: %u",
741: peer->host, length);
742:
743: while (stream_get_getp(s) < end)
744: {
745: u_char opt_type;
746: u_char opt_length;
747:
748: /* Must have at least an OPEN option header */
749: if (STREAM_READABLE(s) < 2)
750: {
751: zlog_info ("%s Option length error", peer->host);
752: bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
753: return -1;
754: }
755:
756: /* Fetch option type and length. */
757: opt_type = stream_getc (s);
758: opt_length = stream_getc (s);
759:
760: /* Option length check. */
761: if (STREAM_READABLE (s) < opt_length)
762: {
763: zlog_info ("%s Option length error", peer->host);
764: bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
765: return -1;
766: }
767:
768: if (BGP_DEBUG (normal, NORMAL))
769: zlog_debug ("%s rcvd OPEN w/ optional parameter type %u (%s) len %u",
770: peer->host, opt_type,
771: opt_type == BGP_OPEN_OPT_AUTH ? "Authentication" :
772: opt_type == BGP_OPEN_OPT_CAP ? "Capability" : "Unknown",
773: opt_length);
774:
775: switch (opt_type)
776: {
777: case BGP_OPEN_OPT_AUTH:
778: ret = bgp_auth_parse (peer, opt_length);
779: break;
780: case BGP_OPEN_OPT_CAP:
1.1.1.3 ! misho 781: ret = bgp_capability_parse (peer, opt_length, mp_capability, &error);
1.1 misho 782: break;
783: default:
784: bgp_notify_send (peer,
785: BGP_NOTIFY_OPEN_ERR,
786: BGP_NOTIFY_OPEN_UNSUP_PARAM);
787: ret = -1;
788: break;
789: }
790:
791: /* Parse error. To accumulate all unsupported capability codes,
792: bgp_capability_parse does not return -1 when encounter
793: unsupported capability code. To detect that, please check
794: error and erro_data pointer, like below. */
795: if (ret < 0)
796: return -1;
797: }
798:
799: /* All OPEN option is parsed. Check capability when strict compare
800: flag is enabled.*/
801: if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
802: {
803: /* If Unsupported Capability exists. */
804: if (error != error_data)
805: {
806: bgp_notify_send_with_data (peer,
807: BGP_NOTIFY_OPEN_ERR,
808: BGP_NOTIFY_OPEN_UNSUP_CAPBL,
809: error_data, error - error_data);
810: return -1;
811: }
812:
813: /* Check local capability does not negotiated with remote
814: peer. */
815: if (! strict_capability_same (peer))
816: {
817: bgp_notify_send (peer,
818: BGP_NOTIFY_OPEN_ERR,
819: BGP_NOTIFY_OPEN_UNSUP_CAPBL);
820: return -1;
821: }
822: }
823:
1.1.1.3 ! misho 824: /* Check there are no common AFI/SAFIs and send Unsupported Capability
1.1 misho 825: error. */
1.1.1.3 ! misho 826: if (*mp_capability &&
! 827: ! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
1.1 misho 828: {
829: if (! peer->afc_nego[AFI_IP][SAFI_UNICAST]
830: && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST]
831: && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
832: && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST]
833: && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST])
834: {
1.1.1.3 ! misho 835: plog_err (peer->log, "%s [Error] Configured AFI/SAFIs do not "
! 836: "overlap with received MP capabilities",
! 837: peer->host);
1.1 misho 838:
839: if (error != error_data)
840:
841: bgp_notify_send_with_data (peer,
842: BGP_NOTIFY_OPEN_ERR,
843: BGP_NOTIFY_OPEN_UNSUP_CAPBL,
844: error_data, error - error_data);
845: else
846: bgp_notify_send (peer,
847: BGP_NOTIFY_OPEN_ERR,
848: BGP_NOTIFY_OPEN_UNSUP_CAPBL);
849: return -1;
850: }
851: }
852: return 0;
853: }
854:
855: static void
856: bgp_open_capability_orf (struct stream *s, struct peer *peer,
857: afi_t afi, safi_t safi, u_char code)
858: {
859: u_char cap_len;
860: u_char orf_len;
861: unsigned long capp;
862: unsigned long orfp;
863: unsigned long numberp;
864: int number_of_orfs = 0;
865:
866: if (safi == SAFI_MPLS_VPN)
1.1.1.3 ! misho 867: safi = SAFI_MPLS_LABELED_VPN;
1.1 misho 868:
869: stream_putc (s, BGP_OPEN_OPT_CAP);
870: capp = stream_get_endp (s); /* Set Capability Len Pointer */
871: stream_putc (s, 0); /* Capability Length */
872: stream_putc (s, code); /* Capability Code */
873: orfp = stream_get_endp (s); /* Set ORF Len Pointer */
874: stream_putc (s, 0); /* ORF Length */
875: stream_putw (s, afi);
876: stream_putc (s, 0);
877: stream_putc (s, safi);
878: numberp = stream_get_endp (s); /* Set Number Pointer */
879: stream_putc (s, 0); /* Number of ORFs */
880:
881: /* Address Prefix ORF */
882: if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
883: || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
884: {
885: stream_putc (s, (code == CAPABILITY_CODE_ORF ?
886: ORF_TYPE_PREFIX : ORF_TYPE_PREFIX_OLD));
887:
888: if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
889: && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
890: {
891: SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
892: SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
893: stream_putc (s, ORF_MODE_BOTH);
894: }
895: else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
896: {
897: SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
898: stream_putc (s, ORF_MODE_SEND);
899: }
900: else
901: {
902: SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
903: stream_putc (s, ORF_MODE_RECEIVE);
904: }
905: number_of_orfs++;
906: }
907:
908: /* Total Number of ORFs. */
909: stream_putc_at (s, numberp, number_of_orfs);
910:
911: /* Total ORF Len. */
912: orf_len = stream_get_endp (s) - orfp - 1;
913: stream_putc_at (s, orfp, orf_len);
914:
915: /* Total Capability Len. */
916: cap_len = stream_get_endp (s) - capp - 1;
917: stream_putc_at (s, capp, cap_len);
918: }
919:
920: /* Fill in capability open option to the packet. */
921: void
922: bgp_open_capability (struct stream *s, struct peer *peer)
923: {
924: u_char len;
925: unsigned long cp;
926: afi_t afi;
927: safi_t safi;
928: as_t local_as;
929:
930: /* Remember current pointer for Opt Parm Len. */
931: cp = stream_get_endp (s);
932:
933: /* Opt Parm Len. */
934: stream_putc (s, 0);
935:
936: /* Do not send capability. */
937: if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN)
938: || CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
939: return;
940:
941: /* IPv4 unicast. */
942: if (peer->afc[AFI_IP][SAFI_UNICAST])
943: {
944: peer->afc_adv[AFI_IP][SAFI_UNICAST] = 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);
951: stream_putc (s, SAFI_UNICAST);
952: }
953: /* IPv4 multicast. */
954: if (peer->afc[AFI_IP][SAFI_MULTICAST])
955: {
956: peer->afc_adv[AFI_IP][SAFI_MULTICAST] = 1;
957: stream_putc (s, BGP_OPEN_OPT_CAP);
958: stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
959: stream_putc (s, CAPABILITY_CODE_MP);
960: stream_putc (s, CAPABILITY_CODE_MP_LEN);
961: stream_putw (s, AFI_IP);
962: stream_putc (s, 0);
963: stream_putc (s, SAFI_MULTICAST);
964: }
965: /* IPv4 VPN */
966: if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
967: {
968: peer->afc_adv[AFI_IP][SAFI_MPLS_VPN] = 1;
969: stream_putc (s, BGP_OPEN_OPT_CAP);
970: stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
971: stream_putc (s, CAPABILITY_CODE_MP);
972: stream_putc (s, CAPABILITY_CODE_MP_LEN);
973: stream_putw (s, AFI_IP);
974: stream_putc (s, 0);
1.1.1.3 ! misho 975: stream_putc (s, SAFI_MPLS_LABELED_VPN);
1.1 misho 976: }
977: #ifdef HAVE_IPV6
978: /* IPv6 unicast. */
979: if (peer->afc[AFI_IP6][SAFI_UNICAST])
980: {
981: peer->afc_adv[AFI_IP6][SAFI_UNICAST] = 1;
982: stream_putc (s, BGP_OPEN_OPT_CAP);
983: stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
984: stream_putc (s, CAPABILITY_CODE_MP);
985: stream_putc (s, CAPABILITY_CODE_MP_LEN);
986: stream_putw (s, AFI_IP6);
987: stream_putc (s, 0);
988: stream_putc (s, SAFI_UNICAST);
989: }
990: /* IPv6 multicast. */
991: if (peer->afc[AFI_IP6][SAFI_MULTICAST])
992: {
993: peer->afc_adv[AFI_IP6][SAFI_MULTICAST] = 1;
994: stream_putc (s, BGP_OPEN_OPT_CAP);
995: stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
996: stream_putc (s, CAPABILITY_CODE_MP);
997: stream_putc (s, CAPABILITY_CODE_MP_LEN);
998: stream_putw (s, AFI_IP6);
999: stream_putc (s, 0);
1000: stream_putc (s, SAFI_MULTICAST);
1001: }
1002: #endif /* HAVE_IPV6 */
1003:
1004: /* Route refresh. */
1005: SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
1006: stream_putc (s, BGP_OPEN_OPT_CAP);
1007: stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
1008: stream_putc (s, CAPABILITY_CODE_REFRESH_OLD);
1009: stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
1010: stream_putc (s, BGP_OPEN_OPT_CAP);
1011: stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
1012: stream_putc (s, CAPABILITY_CODE_REFRESH);
1013: stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
1014:
1015: /* AS4 */
1016: SET_FLAG (peer->cap, PEER_CAP_AS4_ADV);
1017: stream_putc (s, BGP_OPEN_OPT_CAP);
1018: stream_putc (s, CAPABILITY_CODE_AS4_LEN + 2);
1019: stream_putc (s, CAPABILITY_CODE_AS4);
1020: stream_putc (s, CAPABILITY_CODE_AS4_LEN);
1021: if ( peer->change_local_as )
1022: local_as = peer->change_local_as;
1023: else
1024: local_as = peer->local_as;
1025: stream_putl (s, local_as );
1026:
1027: /* ORF capability. */
1028: for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
1029: for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
1030: if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
1031: || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
1032: {
1033: bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF_OLD);
1034: bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF);
1035: }
1036:
1037: /* Dynamic capability. */
1038: if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
1039: {
1040: SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV);
1041: stream_putc (s, BGP_OPEN_OPT_CAP);
1042: stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
1043: stream_putc (s, CAPABILITY_CODE_DYNAMIC);
1044: stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN);
1045: }
1046:
1047: /* Graceful restart capability */
1048: if (bgp_flag_check (peer->bgp, BGP_FLAG_GRACEFUL_RESTART))
1049: {
1050: SET_FLAG (peer->cap, PEER_CAP_RESTART_ADV);
1051: stream_putc (s, BGP_OPEN_OPT_CAP);
1052: stream_putc (s, CAPABILITY_CODE_RESTART_LEN + 2);
1053: stream_putc (s, CAPABILITY_CODE_RESTART);
1054: stream_putc (s, CAPABILITY_CODE_RESTART_LEN);
1055: stream_putw (s, peer->bgp->restart_time);
1056: }
1057:
1058: /* Total Opt Parm Len. */
1059: len = stream_get_endp (s) - cp - 1;
1060: stream_putc_at (s, cp, len);
1061: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>