blob: 1d18779bfc506b3cb6453b509556fd162615fb8d [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* BGP packet management routine.
2 Copyright (C) 1999 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "thread.h"
24#include "stream.h"
25#include "network.h"
26#include "prefix.h"
27#include "command.h"
28#include "log.h"
29#include "memory.h"
30#include "sockunion.h" /* for inet_ntop () */
Timo Teräsef757702015-04-29 09:43:04 +030031#include "sockopt.h"
paul718e3742002-12-13 20:15:29 +000032#include "linklist.h"
33#include "plist.h"
Donald Sharp04907292016-01-07 10:03:01 -050034#include "filter.h"
paul718e3742002-12-13 20:15:29 +000035
36#include "bgpd/bgpd.h"
37#include "bgpd/bgp_table.h"
38#include "bgpd/bgp_dump.h"
39#include "bgpd/bgp_attr.h"
40#include "bgpd/bgp_debug.h"
41#include "bgpd/bgp_fsm.h"
42#include "bgpd/bgp_route.h"
43#include "bgpd/bgp_packet.h"
44#include "bgpd/bgp_open.h"
45#include "bgpd/bgp_aspath.h"
46#include "bgpd/bgp_community.h"
47#include "bgpd/bgp_ecommunity.h"
48#include "bgpd/bgp_network.h"
49#include "bgpd/bgp_mplsvpn.h"
Lou Berger298cc2f2016-01-12 13:42:02 -050050#include "bgpd/bgp_encap.h"
paul718e3742002-12-13 20:15:29 +000051#include "bgpd/bgp_advertise.h"
hasso93406d82005-02-02 14:40:33 +000052#include "bgpd/bgp_vty.h"
paul718e3742002-12-13 20:15:29 +000053
54int stream_put_prefix (struct stream *, struct prefix *);
David Lamparter6b0655a2014-06-04 06:53:35 +020055
paul718e3742002-12-13 20:15:29 +000056/* Set up BGP packet marker and packet type. */
57static int
58bgp_packet_set_marker (struct stream *s, u_char type)
59{
60 int i;
61
62 /* Fill in marker. */
63 for (i = 0; i < BGP_MARKER_SIZE; i++)
64 stream_putc (s, 0xff);
65
66 /* Dummy total length. This field is should be filled in later on. */
67 stream_putw (s, 0);
68
69 /* BGP packet type. */
70 stream_putc (s, type);
71
72 /* Return current stream size. */
paul9985f832005-02-09 15:51:56 +000073 return stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +000074}
75
76/* Set BGP packet header size entry. If size is zero then use current
77 stream size. */
78static int
79bgp_packet_set_size (struct stream *s)
80{
81 int cp;
82
83 /* Preserve current pointer. */
paul9985f832005-02-09 15:51:56 +000084 cp = stream_get_endp (s);
85 stream_putw_at (s, BGP_MARKER_SIZE, cp);
paul718e3742002-12-13 20:15:29 +000086
87 return cp;
88}
89
90/* Add new packet to the peer. */
paul94f2b392005-06-28 12:44:16 +000091static void
paul718e3742002-12-13 20:15:29 +000092bgp_packet_add (struct peer *peer, struct stream *s)
93{
94 /* Add packet to the end of list. */
95 stream_fifo_push (peer->obuf, s);
96}
97
98/* Free first packet. */
paul94f2b392005-06-28 12:44:16 +000099static void
paul718e3742002-12-13 20:15:29 +0000100bgp_packet_delete (struct peer *peer)
101{
102 stream_free (stream_fifo_pop (peer->obuf));
103}
104
paul718e3742002-12-13 20:15:29 +0000105/* Check file descriptor whether connect is established. */
106static void
107bgp_connect_check (struct peer *peer)
108{
109 int status;
paul5228ad22004-06-04 17:58:18 +0000110 socklen_t slen;
paul718e3742002-12-13 20:15:29 +0000111 int ret;
112
113 /* Anyway I have to reset read and write thread. */
114 BGP_READ_OFF (peer->t_read);
115 BGP_WRITE_OFF (peer->t_write);
116
117 /* Check file descriptor. */
118 slen = sizeof (status);
pauleb821182004-05-01 08:44:08 +0000119 ret = getsockopt(peer->fd, SOL_SOCKET, SO_ERROR, (void *) &status, &slen);
paul718e3742002-12-13 20:15:29 +0000120
121 /* If getsockopt is fail, this is fatal error. */
122 if (ret < 0)
123 {
124 zlog (peer->log, LOG_INFO, "can't get sockopt for nonblocking connect");
125 BGP_EVENT_ADD (peer, TCP_fatal_error);
126 return;
127 }
128
129 /* When status is 0 then TCP connection is established. */
130 if (status == 0)
131 {
132 BGP_EVENT_ADD (peer, TCP_connection_open);
133 }
134 else
135 {
136 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +0000137 plog_debug (peer->log, "%s [Event] Connect failed (%s)",
ajs6099b3b2004-11-20 02:06:59 +0000138 peer->host, safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000139 BGP_EVENT_ADD (peer, TCP_connection_open_failed);
140 }
141}
142
143/* Make BGP update packet. */
paul94f2b392005-06-28 12:44:16 +0000144static struct stream *
paul718e3742002-12-13 20:15:29 +0000145bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
146{
147 struct stream *s;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000148 struct stream *snlri;
paul718e3742002-12-13 20:15:29 +0000149 struct bgp_adj_out *adj;
150 struct bgp_advertise *adv;
151 struct stream *packet;
152 struct bgp_node *rn = NULL;
153 struct bgp_info *binfo = NULL;
154 bgp_size_t total_attr_len = 0;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000155 unsigned long attrlen_pos = 0;
156 size_t mpattrlen_pos = 0;
157 size_t mpattr_pos = 0;
paul718e3742002-12-13 20:15:29 +0000158
159 s = peer->work;
160 stream_reset (s);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000161 snlri = peer->scratch;
162 stream_reset (snlri);
paul718e3742002-12-13 20:15:29 +0000163
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100164 adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->update);
paul718e3742002-12-13 20:15:29 +0000165
166 while (adv)
167 {
Paul Jakmaed3ebfa2006-10-15 23:50:16 +0000168 assert (adv->rn);
169 rn = adv->rn;
paul718e3742002-12-13 20:15:29 +0000170 adj = adv->adj;
171 if (adv->binfo)
172 binfo = adv->binfo;
paul718e3742002-12-13 20:15:29 +0000173
174 /* When remaining space can't include NLRI and it's length. */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000175 if (STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) <=
Lou Berger050defe2016-01-12 13:41:59 -0500176 (BGP_NLRI_LENGTH + bgp_packet_mpattr_prefix_size(afi,safi,&rn->p)))
paul718e3742002-12-13 20:15:29 +0000177 break;
178
179 /* If packet is empty, set attribute. */
180 if (stream_empty (s))
181 {
Lou Berger050defe2016-01-12 13:41:59 -0500182 struct prefix_rd *prd = NULL;
183 u_char *tag = NULL;
Paul Jakmaed3ebfa2006-10-15 23:50:16 +0000184 struct peer *from = NULL;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000185
Lou Berger050defe2016-01-12 13:41:59 -0500186 if (rn->prn)
187 prd = (struct prefix_rd *) &rn->prn->p;
Greg Troxeld3ddb222010-09-17 10:47:49 -0400188 if (binfo)
Lou Berger050defe2016-01-12 13:41:59 -0500189 {
190 from = binfo->peer;
191 if (binfo->extra)
192 tag = binfo->extra->tag;
193 }
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000194
195 /* 1: Write the BGP message header - 16 bytes marker, 2 bytes length,
196 * one byte message type.
197 */
paul718e3742002-12-13 20:15:29 +0000198 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000199
200 /* 2: withdrawn routes length */
paul718e3742002-12-13 20:15:29 +0000201 stream_putw (s, 0);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000202
203 /* 3: total attributes length - attrlen_pos stores the position */
204 attrlen_pos = stream_get_endp (s);
205 stream_putw (s, 0);
206
207 /* 4: if there is MP_REACH_NLRI attribute, that should be the first
208 * attribute, according to draft-ietf-idr-error-handling. Save the
209 * position.
210 */
211 mpattr_pos = stream_get_endp(s);
212
213 /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */
214 total_attr_len = bgp_packet_attribute (NULL, peer, s,
paul5228ad22004-06-04 17:58:18 +0000215 adv->baa->attr,
Lou Berger298cc2f2016-01-12 13:42:02 -0500216 ((afi == AFI_IP && safi == SAFI_UNICAST) ?
217 &rn->p : NULL),
218 afi, safi,
Lou Berger050defe2016-01-12 13:41:59 -0500219 from, prd, tag);
paul718e3742002-12-13 20:15:29 +0000220 }
221
222 if (afi == AFI_IP && safi == SAFI_UNICAST)
223 stream_put_prefix (s, &rn->p);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000224 else
225 {
226 /* Encode the prefix in MP_REACH_NLRI attribute */
227 struct prefix_rd *prd = NULL;
228 u_char *tag = NULL;
229
230 if (rn->prn)
231 prd = (struct prefix_rd *) &rn->prn->p;
232 if (binfo && binfo->extra)
233 tag = binfo->extra->tag;
234
235 if (stream_empty(snlri))
236 mpattrlen_pos = bgp_packet_mpattr_start(snlri, afi, safi,
237 adv->baa->attr);
238 bgp_packet_mpattr_prefix(snlri, afi, safi, &rn->p, prd, tag);
239 }
paul718e3742002-12-13 20:15:29 +0000240 if (BGP_DEBUG (update, UPDATE_OUT))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000241 {
242 char buf[INET6_BUFSIZ];
243
244 zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d",
245 peer->host,
246 inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ),
247 rn->p.prefixlen);
248 }
paul718e3742002-12-13 20:15:29 +0000249
250 /* Synchnorize attribute. */
251 if (adj->attr)
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000252 bgp_attr_unintern (&adj->attr);
paul718e3742002-12-13 20:15:29 +0000253 else
254 peer->scount[afi][safi]++;
255
256 adj->attr = bgp_attr_intern (adv->baa->attr);
257
258 adv = bgp_advertise_clean (peer, adj, afi, safi);
paul718e3742002-12-13 20:15:29 +0000259 }
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000260
paul718e3742002-12-13 20:15:29 +0000261 if (! stream_empty (s))
262 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000263 if (!stream_empty(snlri))
264 {
265 bgp_packet_mpattr_end(snlri, mpattrlen_pos);
266 total_attr_len += stream_get_endp(snlri);
267 }
268
269 /* set the total attribute length correctly */
270 stream_putw_at (s, attrlen_pos, total_attr_len);
271
272 if (!stream_empty(snlri))
273 packet = stream_dupcat(s, snlri, mpattr_pos);
274 else
275 packet = stream_dup (s);
276 bgp_packet_set_size (packet);
paul718e3742002-12-13 20:15:29 +0000277 bgp_packet_add (peer, packet);
pauleb821182004-05-01 08:44:08 +0000278 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000279 stream_reset (s);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000280 stream_reset (snlri);
paul718e3742002-12-13 20:15:29 +0000281 return packet;
282 }
283 return NULL;
hasso93406d82005-02-02 14:40:33 +0000284}
paul718e3742002-12-13 20:15:29 +0000285
paul94f2b392005-06-28 12:44:16 +0000286static struct stream *
hasso93406d82005-02-02 14:40:33 +0000287bgp_update_packet_eor (struct peer *peer, afi_t afi, safi_t safi)
288{
289 struct stream *s;
hasso93406d82005-02-02 14:40:33 +0000290
Paul Jakma750e8142008-07-22 21:11:48 +0000291 if (DISABLE_BGP_ANNOUNCE)
292 return NULL;
hasso93406d82005-02-02 14:40:33 +0000293
294 if (BGP_DEBUG (normal, NORMAL))
295 zlog_debug ("send End-of-RIB for %s to %s", afi_safi_print (afi, safi), peer->host);
296
297 s = stream_new (BGP_MAX_PACKET_SIZE);
298
299 /* Make BGP update packet. */
300 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
301
302 /* Unfeasible Routes Length */
303 stream_putw (s, 0);
304
305 if (afi == AFI_IP && safi == SAFI_UNICAST)
306 {
307 /* Total Path Attribute Length */
308 stream_putw (s, 0);
309 }
310 else
311 {
312 /* Total Path Attribute Length */
313 stream_putw (s, 6);
314 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
315 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
316 stream_putc (s, 3);
317 stream_putw (s, afi);
318 stream_putc (s, safi);
319 }
320
321 bgp_packet_set_size (s);
Donald Sharpa752c3b2015-08-18 08:48:53 -0400322 bgp_packet_add (peer, s);
323 return s;
paul718e3742002-12-13 20:15:29 +0000324}
325
326/* Make BGP withdraw packet. */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000327/* For ipv4 unicast:
328 16-octet marker | 2-octet length | 1-octet type |
329 2-octet withdrawn route length | withdrawn prefixes | 2-octet attrlen (=0)
330*/
331/* For other afi/safis:
332 16-octet marker | 2-octet length | 1-octet type |
333 2-octet withdrawn route length (=0) | 2-octet attrlen |
334 mp_unreach attr type | attr len | afi | safi | withdrawn prefixes
335*/
paul94f2b392005-06-28 12:44:16 +0000336static struct stream *
paul718e3742002-12-13 20:15:29 +0000337bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi)
338{
339 struct stream *s;
340 struct stream *packet;
341 struct bgp_adj_out *adj;
342 struct bgp_advertise *adv;
343 struct bgp_node *rn;
paul718e3742002-12-13 20:15:29 +0000344 bgp_size_t unfeasible_len;
345 bgp_size_t total_attr_len;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000346 size_t mp_start = 0;
347 size_t attrlen_pos = 0;
348 size_t mplen_pos = 0;
349 u_char first_time = 1;
paul718e3742002-12-13 20:15:29 +0000350
351 s = peer->work;
352 stream_reset (s);
353
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100354 while ((adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->withdraw)) != NULL)
paul718e3742002-12-13 20:15:29 +0000355 {
Paul Jakmaed3ebfa2006-10-15 23:50:16 +0000356 assert (adv->rn);
paul718e3742002-12-13 20:15:29 +0000357 adj = adv->adj;
358 rn = adv->rn;
paul718e3742002-12-13 20:15:29 +0000359
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000360 if (STREAM_REMAIN (s)
hasso4372df72004-05-20 10:20:02 +0000361 < (BGP_NLRI_LENGTH + BGP_TOTAL_ATTR_LEN + PSIZE (rn->p.prefixlen)))
paul718e3742002-12-13 20:15:29 +0000362 break;
363
364 if (stream_empty (s))
365 {
366 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000367 stream_putw (s, 0); /* unfeasible routes length */
paul718e3742002-12-13 20:15:29 +0000368 }
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000369 else
370 first_time = 0;
paul718e3742002-12-13 20:15:29 +0000371
372 if (afi == AFI_IP && safi == SAFI_UNICAST)
373 stream_put_prefix (s, &rn->p);
374 else
375 {
Paul Jakmaa3b6ea52006-05-04 07:52:12 +0000376 struct prefix_rd *prd = NULL;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000377
Paul Jakmaa3b6ea52006-05-04 07:52:12 +0000378 if (rn->prn)
379 prd = (struct prefix_rd *) &rn->prn->p;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000380
381 /* If first time, format the MP_UNREACH header */
382 if (first_time)
383 {
384 attrlen_pos = stream_get_endp (s);
385 /* total attr length = 0 for now. reevaluate later */
386 stream_putw (s, 0);
387 mp_start = stream_get_endp (s);
388 mplen_pos = bgp_packet_mpunreach_start(s, afi, safi);
389 }
390
391 bgp_packet_mpunreach_prefix(s, &rn->p, afi, safi, prd, NULL);
paul718e3742002-12-13 20:15:29 +0000392 }
393
394 if (BGP_DEBUG (update, UPDATE_OUT))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000395 {
396 char buf[INET6_BUFSIZ];
397
398 zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d -- unreachable",
399 peer->host,
400 inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ),
401 rn->p.prefixlen);
402 }
paul718e3742002-12-13 20:15:29 +0000403
404 peer->scount[afi][safi]--;
405
406 bgp_adj_out_remove (rn, adj, peer, afi, safi);
407 bgp_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +0000408 }
409
410 if (! stream_empty (s))
411 {
412 if (afi == AFI_IP && safi == SAFI_UNICAST)
413 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000414 unfeasible_len
paul9985f832005-02-09 15:51:56 +0000415 = stream_get_endp (s) - BGP_HEADER_SIZE - BGP_UNFEASIBLE_LEN;
paul718e3742002-12-13 20:15:29 +0000416 stream_putw_at (s, BGP_HEADER_SIZE, unfeasible_len);
417 stream_putw (s, 0);
418 }
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000419 else
420 {
421 /* Set the mp_unreach attr's length */
422 bgp_packet_mpunreach_end(s, mplen_pos);
423
424 /* Set total path attribute length. */
425 total_attr_len = stream_get_endp(s) - mp_start;
426 stream_putw_at (s, attrlen_pos, total_attr_len);
427 }
paul718e3742002-12-13 20:15:29 +0000428 bgp_packet_set_size (s);
paule83e2082005-05-19 02:12:25 +0000429 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +0000430 bgp_packet_add (peer, packet);
431 stream_reset (s);
432 return packet;
433 }
434
435 return NULL;
436}
437
438void
439bgp_default_update_send (struct peer *peer, struct attr *attr,
440 afi_t afi, safi_t safi, struct peer *from)
441{
442 struct stream *s;
paul718e3742002-12-13 20:15:29 +0000443 struct prefix p;
444 unsigned long pos;
445 bgp_size_t total_attr_len;
paul718e3742002-12-13 20:15:29 +0000446
Paul Jakma750e8142008-07-22 21:11:48 +0000447 if (DISABLE_BGP_ANNOUNCE)
448 return;
paul718e3742002-12-13 20:15:29 +0000449
450 if (afi == AFI_IP)
451 str2prefix ("0.0.0.0/0", &p);
452#ifdef HAVE_IPV6
453 else
454 str2prefix ("::/0", &p);
455#endif /* HAVE_IPV6 */
456
457 /* Logging the attribute. */
458 if (BGP_DEBUG (update, UPDATE_OUT))
459 {
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000460 char attrstr[BUFSIZ];
461 char buf[INET6_BUFSIZ];
462 attrstr[0] = '\0';
463
paul718e3742002-12-13 20:15:29 +0000464 bgp_dump_attr (peer, attr, attrstr, BUFSIZ);
ajs6b514742004-12-08 21:03:23 +0000465 zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d %s",
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000466 peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ),
paul718e3742002-12-13 20:15:29 +0000467 p.prefixlen, attrstr);
468 }
469
470 s = stream_new (BGP_MAX_PACKET_SIZE);
471
472 /* Make BGP update packet. */
473 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
474
475 /* Unfeasible Routes Length. */
476 stream_putw (s, 0);
477
478 /* Make place for total attribute length. */
paul9985f832005-02-09 15:51:56 +0000479 pos = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000480 stream_putw (s, 0);
481 total_attr_len = bgp_packet_attribute (NULL, peer, s, attr, &p, afi, safi, from, NULL, NULL);
482
483 /* Set Total Path Attribute Length. */
484 stream_putw_at (s, pos, total_attr_len);
485
486 /* NLRI set. */
487 if (p.family == AF_INET && safi == SAFI_UNICAST)
488 stream_put_prefix (s, &p);
489
490 /* Set size. */
491 bgp_packet_set_size (s);
492
paul718e3742002-12-13 20:15:29 +0000493 /* Dump packet if debug option is set. */
494#ifdef DEBUG
jardin2d74db52005-10-01 00:07:50 +0000495 /* bgp_packet_dump (packet); */
paul718e3742002-12-13 20:15:29 +0000496#endif /* DEBUG */
497
498 /* Add packet to the peer. */
Donald Sharpa752c3b2015-08-18 08:48:53 -0400499 bgp_packet_add (peer, s);
paul718e3742002-12-13 20:15:29 +0000500
pauleb821182004-05-01 08:44:08 +0000501 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000502}
503
504void
505bgp_default_withdraw_send (struct peer *peer, afi_t afi, safi_t safi)
506{
507 struct stream *s;
paul718e3742002-12-13 20:15:29 +0000508 struct prefix p;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000509 unsigned long attrlen_pos = 0;
paul718e3742002-12-13 20:15:29 +0000510 unsigned long cp;
511 bgp_size_t unfeasible_len;
512 bgp_size_t total_attr_len;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000513 size_t mp_start = 0;
514 size_t mplen_pos = 0;
paul718e3742002-12-13 20:15:29 +0000515
Paul Jakma750e8142008-07-22 21:11:48 +0000516 if (DISABLE_BGP_ANNOUNCE)
517 return;
paul718e3742002-12-13 20:15:29 +0000518
519 if (afi == AFI_IP)
520 str2prefix ("0.0.0.0/0", &p);
521#ifdef HAVE_IPV6
522 else
523 str2prefix ("::/0", &p);
524#endif /* HAVE_IPV6 */
525
526 total_attr_len = 0;
paul718e3742002-12-13 20:15:29 +0000527
528 if (BGP_DEBUG (update, UPDATE_OUT))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000529 {
530 char buf[INET6_BUFSIZ];
531
532 zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d -- unreachable",
533 peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ),
534 p.prefixlen);
535 }
paul718e3742002-12-13 20:15:29 +0000536
537 s = stream_new (BGP_MAX_PACKET_SIZE);
538
539 /* Make BGP update packet. */
540 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
541
542 /* Unfeasible Routes Length. */;
paul9985f832005-02-09 15:51:56 +0000543 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000544 stream_putw (s, 0);
545
546 /* Withdrawn Routes. */
547 if (p.family == AF_INET && safi == SAFI_UNICAST)
548 {
549 stream_put_prefix (s, &p);
550
paul9985f832005-02-09 15:51:56 +0000551 unfeasible_len = stream_get_endp (s) - cp - 2;
paul718e3742002-12-13 20:15:29 +0000552
553 /* Set unfeasible len. */
554 stream_putw_at (s, cp, unfeasible_len);
555
556 /* Set total path attribute length. */
557 stream_putw (s, 0);
558 }
559 else
560 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000561 attrlen_pos = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000562 stream_putw (s, 0);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000563 mp_start = stream_get_endp (s);
564 mplen_pos = bgp_packet_mpunreach_start(s, afi, safi);
565 bgp_packet_mpunreach_prefix(s, &p, afi, safi, NULL, NULL);
566
567 /* Set the mp_unreach attr's length */
568 bgp_packet_mpunreach_end(s, mplen_pos);
paul718e3742002-12-13 20:15:29 +0000569
570 /* Set total path attribute length. */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000571 total_attr_len = stream_get_endp(s) - mp_start;
572 stream_putw_at (s, attrlen_pos, total_attr_len);
paul718e3742002-12-13 20:15:29 +0000573 }
574
575 bgp_packet_set_size (s);
576
paul718e3742002-12-13 20:15:29 +0000577 /* Add packet to the peer. */
Donald Sharpa752c3b2015-08-18 08:48:53 -0400578 bgp_packet_add (peer, s);
paul718e3742002-12-13 20:15:29 +0000579
pauleb821182004-05-01 08:44:08 +0000580 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000581}
582
583/* Get next packet to be written. */
paul94f2b392005-06-28 12:44:16 +0000584static struct stream *
paul718e3742002-12-13 20:15:29 +0000585bgp_write_packet (struct peer *peer)
586{
587 afi_t afi;
588 safi_t safi;
589 struct stream *s = NULL;
590 struct bgp_advertise *adv;
591
592 s = stream_fifo_head (peer->obuf);
593 if (s)
594 return s;
595
596 for (afi = AFI_IP; afi < AFI_MAX; afi++)
597 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
598 {
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100599 adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->withdraw);
paul718e3742002-12-13 20:15:29 +0000600 if (adv)
601 {
602 s = bgp_withdraw_packet (peer, afi, safi);
603 if (s)
604 return s;
605 }
606 }
607
608 for (afi = AFI_IP; afi < AFI_MAX; afi++)
609 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
610 {
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100611 adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->update);
paul718e3742002-12-13 20:15:29 +0000612 if (adv)
613 {
614 if (adv->binfo && adv->binfo->uptime < peer->synctime)
hasso93406d82005-02-02 14:40:33 +0000615 {
616 if (CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_RCV)
617 && CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_ADV)
Vipin Kumardd49eb12014-09-30 14:36:38 -0700618 && ! (CHECK_FLAG (adv->binfo->peer->cap,
619 PEER_CAP_RESTART_BIT_RCV) &&
620 CHECK_FLAG (adv->binfo->peer->cap,
621 PEER_CAP_RESTART_BIT_ADV))
hasso93406d82005-02-02 14:40:33 +0000622 && ! CHECK_FLAG (adv->binfo->flags, BGP_INFO_STALE)
623 && safi != SAFI_MPLS_VPN)
624 {
625 if (CHECK_FLAG (adv->binfo->peer->af_sflags[afi][safi],
626 PEER_STATUS_EOR_RECEIVED))
627 s = bgp_update_packet (peer, afi, safi);
628 }
629 else
630 s = bgp_update_packet (peer, afi, safi);
631 }
paul718e3742002-12-13 20:15:29 +0000632
633 if (s)
634 return s;
635 }
hasso93406d82005-02-02 14:40:33 +0000636
637 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV))
638 {
639 if (peer->afc_nego[afi][safi] && peer->synctime
640 && ! CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND)
641 && safi != SAFI_MPLS_VPN)
642 {
643 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND);
644 return bgp_update_packet_eor (peer, afi, safi);
645 }
646 }
paul718e3742002-12-13 20:15:29 +0000647 }
648
649 return NULL;
650}
651
652/* Is there partially written packet or updates we can send right
653 now. */
paul94f2b392005-06-28 12:44:16 +0000654static int
paul718e3742002-12-13 20:15:29 +0000655bgp_write_proceed (struct peer *peer)
656{
657 afi_t afi;
658 safi_t safi;
659 struct bgp_advertise *adv;
660
661 if (stream_fifo_head (peer->obuf))
662 return 1;
663
664 for (afi = AFI_IP; afi < AFI_MAX; afi++)
665 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
666 if (FIFO_HEAD (&peer->sync[afi][safi]->withdraw))
667 return 1;
668
669 for (afi = AFI_IP; afi < AFI_MAX; afi++)
670 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100671 if ((adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->update)) != NULL)
paul718e3742002-12-13 20:15:29 +0000672 if (adv->binfo->uptime < peer->synctime)
673 return 1;
674
675 return 0;
676}
677
678/* Write packet to the peer. */
679int
680bgp_write (struct thread *thread)
681{
682 struct peer *peer;
683 u_char type;
684 struct stream *s;
685 int num;
paulfd79ac92004-10-13 05:06:08 +0000686 unsigned int count = 0;
paul718e3742002-12-13 20:15:29 +0000687
688 /* Yes first of all get peer pointer. */
689 peer = THREAD_ARG (thread);
690 peer->t_write = NULL;
691
692 /* For non-blocking IO check. */
693 if (peer->status == Connect)
694 {
695 bgp_connect_check (peer);
696 return 0;
697 }
698
Stephen Hemmingereac57022010-08-05 10:26:25 -0700699 s = bgp_write_packet (peer);
700 if (!s)
701 return 0; /* nothing to send */
702
703 sockopt_cork (peer->fd, 1);
704
705 /* Nonblocking write until TCP output buffer is full. */
706 do
paul718e3742002-12-13 20:15:29 +0000707 {
708 int writenum;
paul718e3742002-12-13 20:15:29 +0000709
710 /* Number of bytes to be sent. */
711 writenum = stream_get_endp (s) - stream_get_getp (s);
712
713 /* Call write() system call. */
pauleb821182004-05-01 08:44:08 +0000714 num = write (peer->fd, STREAM_PNT (s), writenum);
Stephen Hemminger35398582010-08-05 10:26:23 -0700715 if (num < 0)
paul718e3742002-12-13 20:15:29 +0000716 {
Stephen Hemmingereac57022010-08-05 10:26:25 -0700717 /* write failed either retry needed or error */
718 if (ERRNO_IO_RETRY(errno))
719 break;
720
721 BGP_EVENT_ADD (peer, TCP_fatal_error);
paul718e3742002-12-13 20:15:29 +0000722 return 0;
723 }
Stephen Hemminger35398582010-08-05 10:26:23 -0700724
paul718e3742002-12-13 20:15:29 +0000725 if (num != writenum)
726 {
Stephen Hemminger35398582010-08-05 10:26:23 -0700727 /* Partial write */
paul9985f832005-02-09 15:51:56 +0000728 stream_forward_getp (s, num);
Stephen Hemmingereac57022010-08-05 10:26:25 -0700729 break;
paul718e3742002-12-13 20:15:29 +0000730 }
731
732 /* Retrieve BGP packet type. */
733 stream_set_getp (s, BGP_MARKER_SIZE + 2);
734 type = stream_getc (s);
735
736 switch (type)
737 {
738 case BGP_MSG_OPEN:
739 peer->open_out++;
740 break;
741 case BGP_MSG_UPDATE:
742 peer->update_out++;
743 break;
744 case BGP_MSG_NOTIFY:
745 peer->notify_out++;
746 /* Double start timer. */
747 peer->v_start *= 2;
748
749 /* Overflow check. */
750 if (peer->v_start >= (60 * 2))
751 peer->v_start = (60 * 2);
752
Paul Jakmaca058a32006-09-14 02:58:49 +0000753 /* Flush any existing events */
Paul Jakmadcdf3992006-10-15 23:39:59 +0000754 BGP_EVENT_ADD (peer, BGP_Stop);
Stephen Hemminger3a69f742013-01-11 18:27:23 +0000755 goto done;
756
paul718e3742002-12-13 20:15:29 +0000757 case BGP_MSG_KEEPALIVE:
758 peer->keepalive_out++;
759 break;
760 case BGP_MSG_ROUTE_REFRESH_NEW:
761 case BGP_MSG_ROUTE_REFRESH_OLD:
762 peer->refresh_out++;
763 break;
764 case BGP_MSG_CAPABILITY:
765 peer->dynamic_cap_out++;
766 break;
767 }
768
769 /* OK we send packet so delete it. */
770 bgp_packet_delete (peer);
paul718e3742002-12-13 20:15:29 +0000771 }
Stephen Hemmingereac57022010-08-05 10:26:25 -0700772 while (++count < BGP_WRITE_PACKET_MAX &&
773 (s = bgp_write_packet (peer)) != NULL);
paul718e3742002-12-13 20:15:29 +0000774
775 if (bgp_write_proceed (peer))
pauleb821182004-05-01 08:44:08 +0000776 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
Stephen Hemminger3a69f742013-01-11 18:27:23 +0000777
778 done:
779 sockopt_cork (peer->fd, 0);
paul718e3742002-12-13 20:15:29 +0000780 return 0;
781}
782
783/* This is only for sending NOTIFICATION message to neighbor. */
paul94f2b392005-06-28 12:44:16 +0000784static int
paul718e3742002-12-13 20:15:29 +0000785bgp_write_notify (struct peer *peer)
786{
Stephen Hemminger35398582010-08-05 10:26:23 -0700787 int ret, val;
paul718e3742002-12-13 20:15:29 +0000788 u_char type;
789 struct stream *s;
790
791 /* There should be at least one packet. */
792 s = stream_fifo_head (peer->obuf);
793 if (!s)
794 return 0;
795 assert (stream_get_endp (s) >= BGP_HEADER_SIZE);
796
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000797 /* Stop collecting data within the socket */
798 sockopt_cork (peer->fd, 0);
799
David Lamparter8ff202e2013-07-31 14:39:41 +0200800 /* socket is in nonblocking mode, if we can't deliver the NOTIFY, well,
801 * we only care about getting a clean shutdown at this point. */
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000802 ret = write (peer->fd, STREAM_DATA (s), stream_get_endp (s));
David Lamparter8ff202e2013-07-31 14:39:41 +0200803
804 /* only connection reset/close gets counted as TCP_fatal_error, failure
805 * to write the entire NOTIFY doesn't get different FSM treatment */
paul718e3742002-12-13 20:15:29 +0000806 if (ret <= 0)
807 {
Paul Jakmadcdf3992006-10-15 23:39:59 +0000808 BGP_EVENT_ADD (peer, TCP_fatal_error);
paul718e3742002-12-13 20:15:29 +0000809 return 0;
810 }
811
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000812 /* Disable Nagle, make NOTIFY packet go out right away */
813 val = 1;
814 (void) setsockopt (peer->fd, IPPROTO_TCP, TCP_NODELAY,
815 (char *) &val, sizeof (val));
816
paul718e3742002-12-13 20:15:29 +0000817 /* Retrieve BGP packet type. */
818 stream_set_getp (s, BGP_MARKER_SIZE + 2);
819 type = stream_getc (s);
820
821 assert (type == BGP_MSG_NOTIFY);
822
823 /* Type should be notify. */
824 peer->notify_out++;
825
826 /* Double start timer. */
827 peer->v_start *= 2;
828
829 /* Overflow check. */
830 if (peer->v_start >= (60 * 2))
831 peer->v_start = (60 * 2);
832
Paul Jakmadcdf3992006-10-15 23:39:59 +0000833 BGP_EVENT_ADD (peer, BGP_Stop);
paul718e3742002-12-13 20:15:29 +0000834
835 return 0;
836}
837
838/* Make keepalive packet and send it to the peer. */
839void
840bgp_keepalive_send (struct peer *peer)
841{
842 struct stream *s;
843 int length;
844
845 s = stream_new (BGP_MAX_PACKET_SIZE);
846
847 /* Make keepalive packet. */
848 bgp_packet_set_marker (s, BGP_MSG_KEEPALIVE);
849
850 /* Set packet size. */
851 length = bgp_packet_set_size (s);
852
853 /* Dump packet if debug option is set. */
854 /* bgp_packet_dump (s); */
855
856 if (BGP_DEBUG (keepalive, KEEPALIVE))
ajs6b514742004-12-08 21:03:23 +0000857 zlog_debug ("%s sending KEEPALIVE", peer->host);
paul718e3742002-12-13 20:15:29 +0000858 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000859 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000860 peer->host, BGP_MSG_KEEPALIVE, length);
861
862 /* Add packet to the peer. */
863 bgp_packet_add (peer, s);
864
pauleb821182004-05-01 08:44:08 +0000865 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000866}
867
868/* Make open packet and send it to the peer. */
869void
870bgp_open_send (struct peer *peer)
871{
872 struct stream *s;
873 int length;
874 u_int16_t send_holdtime;
875 as_t local_as;
876
877 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
878 send_holdtime = peer->holdtime;
879 else
880 send_holdtime = peer->bgp->default_holdtime;
881
882 /* local-as Change */
883 if (peer->change_local_as)
884 local_as = peer->change_local_as;
885 else
886 local_as = peer->local_as;
887
888 s = stream_new (BGP_MAX_PACKET_SIZE);
889
890 /* Make open packet. */
891 bgp_packet_set_marker (s, BGP_MSG_OPEN);
892
893 /* Set open packet values. */
894 stream_putc (s, BGP_VERSION_4); /* BGP version */
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000895 stream_putw (s, (local_as <= BGP_AS_MAX) ? (u_int16_t) local_as
896 : BGP_AS_TRANS);
paul718e3742002-12-13 20:15:29 +0000897 stream_putw (s, send_holdtime); /* Hold Time */
898 stream_put_in_addr (s, &peer->local_id); /* BGP Identifier */
899
900 /* Set capability code. */
901 bgp_open_capability (s, peer);
902
903 /* Set BGP packet length. */
904 length = bgp_packet_set_size (s);
905
906 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +0400907 zlog_debug ("%s sending OPEN, version %d, my as %u, holdtime %d, id %s",
paul718e3742002-12-13 20:15:29 +0000908 peer->host, BGP_VERSION_4, local_as,
909 send_holdtime, inet_ntoa (peer->local_id));
910
911 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000912 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000913 peer->host, BGP_MSG_OPEN, length);
914
915 /* Dump packet if debug option is set. */
916 /* bgp_packet_dump (s); */
917
918 /* Add packet to the peer. */
919 bgp_packet_add (peer, s);
920
pauleb821182004-05-01 08:44:08 +0000921 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000922}
923
924/* Send BGP notify packet with data potion. */
925void
926bgp_notify_send_with_data (struct peer *peer, u_char code, u_char sub_code,
927 u_char *data, size_t datalen)
928{
929 struct stream *s;
930 int length;
931
932 /* Allocate new stream. */
933 s = stream_new (BGP_MAX_PACKET_SIZE);
934
935 /* Make nitify packet. */
936 bgp_packet_set_marker (s, BGP_MSG_NOTIFY);
937
938 /* Set notify packet values. */
939 stream_putc (s, code); /* BGP notify code */
940 stream_putc (s, sub_code); /* BGP notify sub_code */
941
942 /* If notify data is present. */
943 if (data)
944 stream_write (s, data, datalen);
945
946 /* Set BGP packet length. */
947 length = bgp_packet_set_size (s);
948
949 /* Add packet to the peer. */
950 stream_fifo_clean (peer->obuf);
951 bgp_packet_add (peer, s);
952
953 /* For debug */
954 {
955 struct bgp_notify bgp_notify;
956 int first = 0;
957 int i;
958 char c[4];
959
960 bgp_notify.code = code;
961 bgp_notify.subcode = sub_code;
962 bgp_notify.data = NULL;
963 bgp_notify.length = length - BGP_MSG_NOTIFY_MIN_SIZE;
964
965 if (bgp_notify.length)
966 {
967 bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
968 for (i = 0; i < bgp_notify.length; i++)
969 if (first)
970 {
971 sprintf (c, " %02x", data[i]);
972 strcat (bgp_notify.data, c);
973 }
974 else
975 {
976 first = 1;
977 sprintf (c, "%02x", data[i]);
978 strcpy (bgp_notify.data, c);
979 }
980 }
981 bgp_notify_print (peer, &bgp_notify, "sending");
Daniel Walton363c9032015-10-21 06:42:54 -0700982
paul718e3742002-12-13 20:15:29 +0000983 if (bgp_notify.data)
Daniel Walton363c9032015-10-21 06:42:54 -0700984 {
985 XFREE (MTYPE_TMP, bgp_notify.data);
986 bgp_notify.data = NULL;
987 bgp_notify.length = 0;
988 }
paul718e3742002-12-13 20:15:29 +0000989 }
990
991 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000992 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000993 peer->host, BGP_MSG_NOTIFY, length);
994
hassoe0701b72004-05-20 09:19:34 +0000995 /* peer reset cause */
996 if (sub_code != BGP_NOTIFY_CEASE_CONFIG_CHANGE)
997 {
998 if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET)
heasley1212dc12011-09-12 13:27:52 +0400999 {
1000 peer->last_reset = PEER_DOWN_USER_RESET;
1001 zlog_info ("Notification sent to neighbor %s: User reset", peer->host);
1002 }
hassoe0701b72004-05-20 09:19:34 +00001003 else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN)
heasley1212dc12011-09-12 13:27:52 +04001004 {
1005 peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
1006 zlog_info ("Notification sent to neighbor %s: shutdown", peer->host);
1007 }
hassoe0701b72004-05-20 09:19:34 +00001008 else
heasley1212dc12011-09-12 13:27:52 +04001009 {
1010 peer->last_reset = PEER_DOWN_NOTIFY_SEND;
1011 zlog_info ("Notification sent to neighbor %s: type %u/%u",
1012 peer->host, code, sub_code);
1013 }
hassoe0701b72004-05-20 09:19:34 +00001014 }
heasley1212dc12011-09-12 13:27:52 +04001015 else
1016 zlog_info ("Notification sent to neighbor %s: configuration change",
1017 peer->host);
hassoe0701b72004-05-20 09:19:34 +00001018
Denis Ovsienko7ccf5e52011-09-10 16:53:30 +04001019 /* Call immediately. */
paul718e3742002-12-13 20:15:29 +00001020 BGP_WRITE_OFF (peer->t_write);
1021
1022 bgp_write_notify (peer);
1023}
1024
1025/* Send BGP notify packet. */
1026void
1027bgp_notify_send (struct peer *peer, u_char code, u_char sub_code)
1028{
1029 bgp_notify_send_with_data (peer, code, sub_code, NULL, 0);
1030}
1031
paul718e3742002-12-13 20:15:29 +00001032/* Send route refresh message to the peer. */
1033void
1034bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
1035 u_char orf_type, u_char when_to_refresh, int remove)
1036{
1037 struct stream *s;
paul718e3742002-12-13 20:15:29 +00001038 int length;
1039 struct bgp_filter *filter;
1040 int orf_refresh = 0;
1041
Paul Jakma750e8142008-07-22 21:11:48 +00001042 if (DISABLE_BGP_ANNOUNCE)
1043 return;
paul718e3742002-12-13 20:15:29 +00001044
1045 filter = &peer->filter[afi][safi];
1046
1047 /* Adjust safi code. */
1048 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001049 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +00001050
1051 s = stream_new (BGP_MAX_PACKET_SIZE);
1052
1053 /* Make BGP update packet. */
1054 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
1055 bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_NEW);
1056 else
1057 bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_OLD);
1058
1059 /* Encode Route Refresh message. */
1060 stream_putw (s, afi);
1061 stream_putc (s, 0);
1062 stream_putc (s, safi);
1063
1064 if (orf_type == ORF_TYPE_PREFIX
1065 || orf_type == ORF_TYPE_PREFIX_OLD)
1066 if (remove || filter->plist[FILTER_IN].plist)
1067 {
1068 u_int16_t orf_len;
1069 unsigned long orfp;
1070
1071 orf_refresh = 1;
1072 stream_putc (s, when_to_refresh);
1073 stream_putc (s, orf_type);
paul9985f832005-02-09 15:51:56 +00001074 orfp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00001075 stream_putw (s, 0);
1076
1077 if (remove)
1078 {
1079 UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
1080 stream_putc (s, ORF_COMMON_PART_REMOVE_ALL);
1081 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001082 zlog_debug ("%s sending REFRESH_REQ to remove ORF(%d) (%s) for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001083 peer->host, orf_type,
1084 (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
1085 afi, safi);
1086 }
1087 else
1088 {
1089 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
1090 prefix_bgp_orf_entry (s, filter->plist[FILTER_IN].plist,
1091 ORF_COMMON_PART_ADD, ORF_COMMON_PART_PERMIT,
1092 ORF_COMMON_PART_DENY);
1093 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001094 zlog_debug ("%s sending REFRESH_REQ with pfxlist ORF(%d) (%s) for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001095 peer->host, orf_type,
1096 (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
1097 afi, safi);
1098 }
1099
1100 /* Total ORF Entry Len. */
paul9985f832005-02-09 15:51:56 +00001101 orf_len = stream_get_endp (s) - orfp - 2;
paul718e3742002-12-13 20:15:29 +00001102 stream_putw_at (s, orfp, orf_len);
1103 }
1104
1105 /* Set packet size. */
1106 length = bgp_packet_set_size (s);
1107
1108 if (BGP_DEBUG (normal, NORMAL))
1109 {
1110 if (! orf_refresh)
ajs6b514742004-12-08 21:03:23 +00001111 zlog_debug ("%s sending REFRESH_REQ for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001112 peer->host, afi, safi);
ajs6b514742004-12-08 21:03:23 +00001113 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +00001114 peer->host, CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV) ?
1115 BGP_MSG_ROUTE_REFRESH_NEW : BGP_MSG_ROUTE_REFRESH_OLD, length);
1116 }
1117
paul718e3742002-12-13 20:15:29 +00001118 /* Add packet to the peer. */
Donald Sharpa752c3b2015-08-18 08:48:53 -04001119 bgp_packet_add (peer, s);
paul718e3742002-12-13 20:15:29 +00001120
pauleb821182004-05-01 08:44:08 +00001121 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +00001122}
1123
1124/* Send capability message to the peer. */
1125void
1126bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi,
1127 int capability_code, int action)
1128{
1129 struct stream *s;
paul718e3742002-12-13 20:15:29 +00001130 int length;
1131
1132 /* Adjust safi code. */
1133 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001134 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +00001135
1136 s = stream_new (BGP_MAX_PACKET_SIZE);
1137
1138 /* Make BGP update packet. */
1139 bgp_packet_set_marker (s, BGP_MSG_CAPABILITY);
1140
1141 /* Encode MP_EXT capability. */
1142 if (capability_code == CAPABILITY_CODE_MP)
1143 {
1144 stream_putc (s, action);
1145 stream_putc (s, CAPABILITY_CODE_MP);
1146 stream_putc (s, CAPABILITY_CODE_MP_LEN);
1147 stream_putw (s, afi);
1148 stream_putc (s, 0);
1149 stream_putc (s, safi);
1150
1151 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001152 zlog_debug ("%s sending CAPABILITY has %s MP_EXT CAP for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001153 peer->host, action == CAPABILITY_ACTION_SET ?
1154 "Advertising" : "Removing", afi, safi);
1155 }
1156
paul718e3742002-12-13 20:15:29 +00001157 /* Set packet size. */
1158 length = bgp_packet_set_size (s);
1159
paul718e3742002-12-13 20:15:29 +00001160
1161 /* Add packet to the peer. */
Donald Sharpa752c3b2015-08-18 08:48:53 -04001162 bgp_packet_add (peer, s);
paul718e3742002-12-13 20:15:29 +00001163
1164 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001165 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +00001166 peer->host, BGP_MSG_CAPABILITY, length);
1167
pauleb821182004-05-01 08:44:08 +00001168 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +00001169}
David Lamparter6b0655a2014-06-04 06:53:35 +02001170
paul718e3742002-12-13 20:15:29 +00001171/* RFC1771 6.8 Connection collision detection. */
paul94f2b392005-06-28 12:44:16 +00001172static int
pauleb821182004-05-01 08:44:08 +00001173bgp_collision_detect (struct peer *new, struct in_addr remote_id)
paul718e3742002-12-13 20:15:29 +00001174{
pauleb821182004-05-01 08:44:08 +00001175 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001176 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001177 struct bgp *bgp;
1178
1179 bgp = bgp_get_default ();
1180 if (! bgp)
1181 return 0;
1182
1183 /* Upon receipt of an OPEN message, the local system must examine
1184 all of its connections that are in the OpenConfirm state. A BGP
1185 speaker may also examine connections in an OpenSent state if it
1186 knows the BGP Identifier of the peer by means outside of the
1187 protocol. If among these connections there is a connection to a
1188 remote BGP speaker whose BGP Identifier equals the one in the
1189 OPEN message, then the local system performs the following
1190 collision resolution procedure: */
1191
paul1eb8ef22005-04-07 07:30:20 +00001192 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001193 {
1194 /* Under OpenConfirm status, local peer structure already hold
1195 remote router ID. */
pauleb821182004-05-01 08:44:08 +00001196
1197 if (peer != new
1198 && (peer->status == OpenConfirm || peer->status == OpenSent)
1199 && sockunion_same (&peer->su, &new->su))
1200 {
paul718e3742002-12-13 20:15:29 +00001201 /* 1. The BGP Identifier of the local system is compared to
1202 the BGP Identifier of the remote system (as specified in
1203 the OPEN message). */
1204
1205 if (ntohl (peer->local_id.s_addr) < ntohl (remote_id.s_addr))
1206 {
1207 /* 2. If the value of the local BGP Identifier is less
1208 than the remote one, the local system closes BGP
1209 connection that already exists (the one that is
1210 already in the OpenConfirm state), and accepts BGP
1211 connection initiated by the remote system. */
1212
pauleb821182004-05-01 08:44:08 +00001213 if (peer->fd >= 0)
hassoe0701b72004-05-20 09:19:34 +00001214 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
paul718e3742002-12-13 20:15:29 +00001215 return 1;
1216 }
1217 else
1218 {
1219 /* 3. Otherwise, the local system closes newly created
1220 BGP connection (the one associated with the newly
1221 received OPEN message), and continues to use the
1222 existing one (the one that is already in the
1223 OpenConfirm state). */
1224
pauleb821182004-05-01 08:44:08 +00001225 if (new->fd >= 0)
paulf5ba3872004-07-09 12:11:31 +00001226 bgp_notify_send (new, BGP_NOTIFY_CEASE,
1227 BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
paul718e3742002-12-13 20:15:29 +00001228 return -1;
1229 }
pauleb821182004-05-01 08:44:08 +00001230 }
1231 }
paul718e3742002-12-13 20:15:29 +00001232 return 0;
1233}
1234
paul94f2b392005-06-28 12:44:16 +00001235static int
paul718e3742002-12-13 20:15:29 +00001236bgp_open_receive (struct peer *peer, bgp_size_t size)
1237{
1238 int ret;
1239 u_char version;
1240 u_char optlen;
1241 u_int16_t holdtime;
1242 u_int16_t send_holdtime;
1243 as_t remote_as;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001244 as_t as4 = 0;
paul718e3742002-12-13 20:15:29 +00001245 struct peer *realpeer;
1246 struct in_addr remote_id;
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001247 int mp_capability;
paul5228ad22004-06-04 17:58:18 +00001248 u_int8_t notify_data_remote_as[2];
1249 u_int8_t notify_data_remote_id[4];
paul718e3742002-12-13 20:15:29 +00001250
1251 realpeer = NULL;
1252
1253 /* Parse open packet. */
1254 version = stream_getc (peer->ibuf);
1255 memcpy (notify_data_remote_as, stream_pnt (peer->ibuf), 2);
1256 remote_as = stream_getw (peer->ibuf);
1257 holdtime = stream_getw (peer->ibuf);
1258 memcpy (notify_data_remote_id, stream_pnt (peer->ibuf), 4);
1259 remote_id.s_addr = stream_get_ipv4 (peer->ibuf);
1260
1261 /* Receive OPEN message log */
1262 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001263 zlog_debug ("%s rcv OPEN, version %d, remote-as (in open) %u,"
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001264 " holdtime %d, id %s",
1265 peer->host, version, remote_as, holdtime,
1266 inet_ntoa (remote_id));
1267
1268 /* BEGIN to read the capability here, but dont do it yet */
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001269 mp_capability = 0;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001270 optlen = stream_getc (peer->ibuf);
1271
1272 if (optlen != 0)
1273 {
1274 /* We need the as4 capability value *right now* because
1275 * if it is there, we have not got the remote_as yet, and without
1276 * that we do not know which peer is connecting to us now.
1277 */
1278 as4 = peek_for_as4_capability (peer, optlen);
1279 }
1280
1281 /* Just in case we have a silly peer who sends AS4 capability set to 0 */
1282 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) && !as4)
1283 {
1284 zlog_err ("%s bad OPEN, got AS4 capability, but AS4 set to 0",
1285 peer->host);
1286 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1287 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1288 return -1;
1289 }
1290
1291 if (remote_as == BGP_AS_TRANS)
1292 {
1293 /* Take the AS4 from the capability. We must have received the
1294 * capability now! Otherwise we have a asn16 peer who uses
1295 * BGP_AS_TRANS, for some unknown reason.
1296 */
1297 if (as4 == BGP_AS_TRANS)
1298 {
1299 zlog_err ("%s [AS4] NEW speaker using AS_TRANS for AS4, not allowed",
1300 peer->host);
1301 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1302 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1303 return -1;
1304 }
1305
1306 if (!as4 && BGP_DEBUG (as4, AS4))
1307 zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but no AS4."
1308 " Odd, but proceeding.", peer->host);
1309 else if (as4 < BGP_AS_MAX && BGP_DEBUG (as4, AS4))
Paul Jakma0df7c912008-07-21 21:02:49 +00001310 zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but AS4 (%u) fits "
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001311 "in 2-bytes, very odd peer.", peer->host, as4);
1312 if (as4)
1313 remote_as = as4;
1314 }
1315 else
1316 {
1317 /* We may have a partner with AS4 who has an asno < BGP_AS_MAX */
1318 /* If we have got the capability, peer->as4cap must match remote_as */
1319 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)
1320 && as4 != remote_as)
1321 {
1322 /* raise error, log this, close session */
1323 zlog_err ("%s bad OPEN, got AS4 capability, but remote_as %u"
1324 " mismatch with 16bit 'myasn' %u in open",
1325 peer->host, as4, remote_as);
1326 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1327 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1328 return -1;
1329 }
1330 }
1331
paul718e3742002-12-13 20:15:29 +00001332 /* Lookup peer from Open packet. */
1333 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1334 {
1335 int as = 0;
1336
1337 realpeer = peer_lookup_with_open (&peer->su, remote_as, &remote_id, &as);
1338
1339 if (! realpeer)
1340 {
1341 /* Peer's source IP address is check in bgp_accept(), so this
1342 must be AS number mismatch or remote-id configuration
1343 mismatch. */
1344 if (as)
1345 {
1346 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001347 zlog_debug ("%s bad OPEN, wrong router identifier %s",
1348 peer->host, inet_ntoa (remote_id));
1349 bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
1350 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
1351 notify_data_remote_id, 4);
paul718e3742002-12-13 20:15:29 +00001352 }
1353 else
1354 {
1355 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001356 zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
ajs6b514742004-12-08 21:03:23 +00001357 peer->host, remote_as, peer->as);
1358 bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
1359 BGP_NOTIFY_OPEN_BAD_PEER_AS,
1360 notify_data_remote_as, 2);
paul718e3742002-12-13 20:15:29 +00001361 }
1362 return -1;
1363 }
1364 }
1365
1366 /* When collision is detected and this peer is closed. Retrun
1367 immidiately. */
1368 ret = bgp_collision_detect (peer, remote_id);
1369 if (ret < 0)
1370 return ret;
1371
pauleb821182004-05-01 08:44:08 +00001372 /* Hack part. */
1373 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1374 {
hasso93406d82005-02-02 14:40:33 +00001375 if (realpeer->status == Established
1376 && CHECK_FLAG (realpeer->sflags, PEER_STATUS_NSF_MODE))
1377 {
1378 realpeer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
1379 SET_FLAG (realpeer->sflags, PEER_STATUS_NSF_WAIT);
1380 }
1381 else if (ret == 0 && realpeer->status != Active
1382 && realpeer->status != OpenSent
Paul Jakma6e199262008-09-09 17:14:33 +01001383 && realpeer->status != OpenConfirm
1384 && realpeer->status != Connect)
pauleb821182004-05-01 08:44:08 +00001385 {
Paul Jakma2b2fc562008-09-06 13:09:35 +01001386 /* XXX: This is an awful problem..
1387 *
1388 * According to the RFC we should just let this connection (of the
1389 * accepted 'peer') continue on to Established if the other
1390 * connection (the 'realpeer' one) is in state Connect, and deal
1391 * with the more larval FSM as/when it gets far enough to receive
1392 * an Open. We don't do that though, we instead close the (more
1393 * developed) accepted connection.
1394 *
1395 * This means there's a race, which if hit, can loop:
1396 *
1397 * FSM for A FSM for B
1398 * realpeer accept-peer realpeer accept-peer
1399 *
1400 * Connect Connect
1401 * Active
1402 * OpenSent OpenSent
1403 * <arrive here,
1404 * Notify, delete>
1405 * Idle Active
1406 * OpenSent OpenSent
1407 * <arrive here,
1408 * Notify, delete>
1409 * Idle
1410 * <wait> <wait>
1411 * Connect Connect
1412 *
1413 *
1414 * If both sides are Quagga, they're almost certain to wait for
1415 * the same amount of time of course (which doesn't preclude other
1416 * implementations also waiting for same time). The race is
1417 * exacerbated by high-latency (in bgpd and/or the network).
1418 *
1419 * The reason we do this is because our FSM is tied to our peer
1420 * structure, which carries our configuration information, etc.
1421 * I.e. we can't let the accepted-peer FSM continue on as it is,
1422 * cause it's not associated with any actual peer configuration -
1423 * it's just a dummy.
1424 *
1425 * It's possible we could hack-fix this by just bgp_stop'ing the
1426 * realpeer and continueing on with the 'transfer FSM' below.
1427 * Ideally, we need to seperate FSMs from struct peer.
1428 *
1429 * Setting one side to passive avoids the race, as a workaround.
1430 */
pauleb821182004-05-01 08:44:08 +00001431 if (BGP_DEBUG (events, EVENTS))
hasso93406d82005-02-02 14:40:33 +00001432 zlog_debug ("%s peer status is %s close connection",
1433 realpeer->host, LOOKUP (bgp_status_msg,
1434 realpeer->status));
1435 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1436 BGP_NOTIFY_CEASE_CONNECT_REJECT);
1437
pauleb821182004-05-01 08:44:08 +00001438 return -1;
1439 }
1440
1441 if (BGP_DEBUG (events, EVENTS))
Paul Jakma6e199262008-09-09 17:14:33 +01001442 zlog_debug ("%s [Event] Transfer accept BGP peer to real (state %s)",
1443 peer->host,
1444 LOOKUP (bgp_status_msg, realpeer->status));
pauleb821182004-05-01 08:44:08 +00001445
1446 bgp_stop (realpeer);
1447
1448 /* Transfer file descriptor. */
1449 realpeer->fd = peer->fd;
1450 peer->fd = -1;
1451
1452 /* Transfer input buffer. */
1453 stream_free (realpeer->ibuf);
1454 realpeer->ibuf = peer->ibuf;
1455 realpeer->packet_size = peer->packet_size;
1456 peer->ibuf = NULL;
1457
1458 /* Transfer status. */
1459 realpeer->status = peer->status;
1460 bgp_stop (peer);
paul200df112005-06-01 11:17:05 +00001461
pauleb821182004-05-01 08:44:08 +00001462 /* peer pointer change. Open packet send to neighbor. */
1463 peer = realpeer;
1464 bgp_open_send (peer);
1465 if (peer->fd < 0)
1466 {
1467 zlog_err ("bgp_open_receive peer's fd is negative value %d",
1468 peer->fd);
1469 return -1;
1470 }
1471 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
1472 }
1473
paul718e3742002-12-13 20:15:29 +00001474 /* remote router-id check. */
1475 if (remote_id.s_addr == 0
Denis Ovsienko733cd9e2011-12-17 19:39:30 +04001476 || IPV4_CLASS_DE (ntohl (remote_id.s_addr))
paul718e3742002-12-13 20:15:29 +00001477 || ntohl (peer->local_id.s_addr) == ntohl (remote_id.s_addr))
1478 {
1479 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001480 zlog_debug ("%s bad OPEN, wrong router identifier %s",
paul718e3742002-12-13 20:15:29 +00001481 peer->host, inet_ntoa (remote_id));
1482 bgp_notify_send_with_data (peer,
1483 BGP_NOTIFY_OPEN_ERR,
1484 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
1485 notify_data_remote_id, 4);
1486 return -1;
1487 }
1488
1489 /* Set remote router-id */
1490 peer->remote_id = remote_id;
1491
1492 /* Peer BGP version check. */
1493 if (version != BGP_VERSION_4)
1494 {
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001495 u_int16_t maxver = htons(BGP_VERSION_4);
1496 /* XXX this reply may not be correct if version < 4 XXX */
paul718e3742002-12-13 20:15:29 +00001497 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001498 zlog_debug ("%s bad protocol version, remote requested %d, local request %d",
paul718e3742002-12-13 20:15:29 +00001499 peer->host, version, BGP_VERSION_4);
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001500 /* Data must be in network byte order here */
paul718e3742002-12-13 20:15:29 +00001501 bgp_notify_send_with_data (peer,
1502 BGP_NOTIFY_OPEN_ERR,
1503 BGP_NOTIFY_OPEN_UNSUP_VERSION,
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001504 (u_int8_t *) &maxver, 2);
paul718e3742002-12-13 20:15:29 +00001505 return -1;
1506 }
1507
1508 /* Check neighbor as number. */
1509 if (remote_as != peer->as)
1510 {
1511 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001512 zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
paul718e3742002-12-13 20:15:29 +00001513 peer->host, remote_as, peer->as);
1514 bgp_notify_send_with_data (peer,
1515 BGP_NOTIFY_OPEN_ERR,
1516 BGP_NOTIFY_OPEN_BAD_PEER_AS,
1517 notify_data_remote_as, 2);
1518 return -1;
1519 }
1520
1521 /* From the rfc: Upon receipt of an OPEN message, a BGP speaker MUST
1522 calculate the value of the Hold Timer by using the smaller of its
1523 configured Hold Time and the Hold Time received in the OPEN message.
1524 The Hold Time MUST be either zero or at least three seconds. An
1525 implementation may reject connections on the basis of the Hold Time. */
1526
1527 if (holdtime < 3 && holdtime != 0)
1528 {
1529 bgp_notify_send (peer,
1530 BGP_NOTIFY_OPEN_ERR,
1531 BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
1532 return -1;
1533 }
1534
1535 /* From the rfc: A reasonable maximum time between KEEPALIVE messages
1536 would be one third of the Hold Time interval. KEEPALIVE messages
1537 MUST NOT be sent more frequently than one per second. An
1538 implementation MAY adjust the rate at which it sends KEEPALIVE
1539 messages as a function of the Hold Time interval. */
1540
1541 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
1542 send_holdtime = peer->holdtime;
1543 else
1544 send_holdtime = peer->bgp->default_holdtime;
1545
1546 if (holdtime < send_holdtime)
1547 peer->v_holdtime = holdtime;
1548 else
1549 peer->v_holdtime = send_holdtime;
1550
1551 peer->v_keepalive = peer->v_holdtime / 3;
1552
1553 /* Open option part parse. */
paul718e3742002-12-13 20:15:29 +00001554 if (optlen != 0)
1555 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001556 if ((ret = bgp_open_option_parse (peer, optlen, &mp_capability)) < 0)
Paul Jakma58617392012-01-09 20:59:26 +00001557 {
1558 bgp_notify_send (peer,
1559 BGP_NOTIFY_OPEN_ERR,
Paul Jakma68ec4242015-11-25 17:14:34 +00001560 BGP_NOTIFY_OPEN_UNSPECIFIC);
Paul Jakma58617392012-01-09 20:59:26 +00001561 return ret;
1562 }
paul718e3742002-12-13 20:15:29 +00001563 }
1564 else
1565 {
1566 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001567 zlog_debug ("%s rcvd OPEN w/ OPTION parameter len: 0",
paul718e3742002-12-13 20:15:29 +00001568 peer->host);
1569 }
1570
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001571 /*
1572 * Assume that the peer supports the locally configured set of
1573 * AFI/SAFIs if the peer did not send us any Mulitiprotocol
1574 * capabilities, or if 'override-capability' is configured.
1575 */
1576 if (! mp_capability ||
1577 CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
paul718e3742002-12-13 20:15:29 +00001578 {
1579 peer->afc_nego[AFI_IP][SAFI_UNICAST] = peer->afc[AFI_IP][SAFI_UNICAST];
1580 peer->afc_nego[AFI_IP][SAFI_MULTICAST] = peer->afc[AFI_IP][SAFI_MULTICAST];
1581 peer->afc_nego[AFI_IP6][SAFI_UNICAST] = peer->afc[AFI_IP6][SAFI_UNICAST];
1582 peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = peer->afc[AFI_IP6][SAFI_MULTICAST];
1583 }
1584
1585 /* Get sockname. */
1586 bgp_getsockname (peer);
Timo Teräs0edba8b2015-10-22 11:35:17 +03001587 peer->rtt = sockopt_tcp_rtt (peer->fd);
paul718e3742002-12-13 20:15:29 +00001588
1589 BGP_EVENT_ADD (peer, Receive_OPEN_message);
1590
1591 peer->packet_size = 0;
1592 if (peer->ibuf)
1593 stream_reset (peer->ibuf);
1594
1595 return 0;
1596}
1597
1598/* Parse BGP Update packet and make attribute object. */
paul94f2b392005-06-28 12:44:16 +00001599static int
paul718e3742002-12-13 20:15:29 +00001600bgp_update_receive (struct peer *peer, bgp_size_t size)
1601{
1602 int ret;
1603 u_char *end;
1604 struct stream *s;
1605 struct attr attr;
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001606 struct attr_extra extra;
paul718e3742002-12-13 20:15:29 +00001607 bgp_size_t attribute_len;
1608 bgp_size_t update_len;
1609 bgp_size_t withdraw_len;
1610 struct bgp_nlri update;
1611 struct bgp_nlri withdraw;
1612 struct bgp_nlri mp_update;
1613 struct bgp_nlri mp_withdraw;
paul718e3742002-12-13 20:15:29 +00001614
1615 /* Status must be Established. */
1616 if (peer->status != Established)
1617 {
1618 zlog_err ("%s [FSM] Update packet received under status %s",
1619 peer->host, LOOKUP (bgp_status_msg, peer->status));
1620 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
1621 return -1;
1622 }
1623
1624 /* Set initial values. */
1625 memset (&attr, 0, sizeof (struct attr));
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001626 memset (&extra, 0, sizeof (struct attr_extra));
paul718e3742002-12-13 20:15:29 +00001627 memset (&update, 0, sizeof (struct bgp_nlri));
1628 memset (&withdraw, 0, sizeof (struct bgp_nlri));
1629 memset (&mp_update, 0, sizeof (struct bgp_nlri));
1630 memset (&mp_withdraw, 0, sizeof (struct bgp_nlri));
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001631 attr.extra = &extra;
paul718e3742002-12-13 20:15:29 +00001632
1633 s = peer->ibuf;
1634 end = stream_pnt (s) + size;
1635
1636 /* RFC1771 6.3 If the Unfeasible Routes Length or Total Attribute
1637 Length is too large (i.e., if Unfeasible Routes Length + Total
1638 Attribute Length + 23 exceeds the message Length), then the Error
1639 Subcode is set to Malformed Attribute List. */
1640 if (stream_pnt (s) + 2 > end)
1641 {
1642 zlog_err ("%s [Error] Update packet error"
1643 " (packet length is short for unfeasible length)",
1644 peer->host);
1645 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1646 BGP_NOTIFY_UPDATE_MAL_ATTR);
1647 return -1;
1648 }
1649
1650 /* Unfeasible Route Length. */
1651 withdraw_len = stream_getw (s);
1652
1653 /* Unfeasible Route Length check. */
1654 if (stream_pnt (s) + withdraw_len > end)
1655 {
1656 zlog_err ("%s [Error] Update packet error"
1657 " (packet unfeasible length overflow %d)",
1658 peer->host, withdraw_len);
1659 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1660 BGP_NOTIFY_UPDATE_MAL_ATTR);
1661 return -1;
1662 }
1663
1664 /* Unfeasible Route packet format check. */
1665 if (withdraw_len > 0)
1666 {
Lou Berger050defe2016-01-12 13:41:59 -05001667 ret = bgp_nlri_sanity_check (peer, AFI_IP, SAFI_UNICAST, stream_pnt (s), withdraw_len);
paul718e3742002-12-13 20:15:29 +00001668 if (ret < 0)
1669 return -1;
1670
1671 if (BGP_DEBUG (packet, PACKET_RECV))
ajs6b514742004-12-08 21:03:23 +00001672 zlog_debug ("%s [Update:RECV] Unfeasible NLRI received", peer->host);
paul718e3742002-12-13 20:15:29 +00001673
1674 withdraw.afi = AFI_IP;
1675 withdraw.safi = SAFI_UNICAST;
1676 withdraw.nlri = stream_pnt (s);
1677 withdraw.length = withdraw_len;
paul9985f832005-02-09 15:51:56 +00001678 stream_forward_getp (s, withdraw_len);
paul718e3742002-12-13 20:15:29 +00001679 }
1680
1681 /* Attribute total length check. */
1682 if (stream_pnt (s) + 2 > end)
1683 {
1684 zlog_warn ("%s [Error] Packet Error"
1685 " (update packet is short for attribute length)",
1686 peer->host);
1687 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1688 BGP_NOTIFY_UPDATE_MAL_ATTR);
1689 return -1;
1690 }
1691
1692 /* Fetch attribute total length. */
1693 attribute_len = stream_getw (s);
1694
1695 /* Attribute length check. */
1696 if (stream_pnt (s) + attribute_len > end)
1697 {
1698 zlog_warn ("%s [Error] Packet Error"
1699 " (update packet attribute length overflow %d)",
1700 peer->host, attribute_len);
1701 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1702 BGP_NOTIFY_UPDATE_MAL_ATTR);
1703 return -1;
1704 }
Paul Jakmab881c702010-11-23 16:35:42 +00001705
1706 /* Certain attribute parsing errors should not be considered bad enough
1707 * to reset the session for, most particularly any partial/optional
1708 * attributes that have 'tunneled' over speakers that don't understand
1709 * them. Instead we withdraw only the prefix concerned.
1710 *
1711 * Complicates the flow a little though..
1712 */
1713 bgp_attr_parse_ret_t attr_parse_ret = BGP_ATTR_PARSE_PROCEED;
1714 /* This define morphs the update case into a withdraw when lower levels
1715 * have signalled an error condition where this is best.
1716 */
1717#define NLRI_ATTR_ARG (attr_parse_ret != BGP_ATTR_PARSE_WITHDRAW ? &attr : NULL)
paul718e3742002-12-13 20:15:29 +00001718
1719 /* Parse attribute when it exists. */
1720 if (attribute_len)
1721 {
Paul Jakmab881c702010-11-23 16:35:42 +00001722 attr_parse_ret = bgp_attr_parse (peer, &attr, attribute_len,
paul718e3742002-12-13 20:15:29 +00001723 &mp_update, &mp_withdraw);
Paul Jakmab881c702010-11-23 16:35:42 +00001724 if (attr_parse_ret == BGP_ATTR_PARSE_ERROR)
David Lamparterf80f8382014-06-04 01:00:51 +02001725 {
1726 bgp_attr_unintern_sub (&attr);
Lou Berger050defe2016-01-12 13:41:59 -05001727 bgp_attr_flush (&attr);
David Lamparterf80f8382014-06-04 01:00:51 +02001728 return -1;
1729 }
paul718e3742002-12-13 20:15:29 +00001730 }
Paul Jakmab881c702010-11-23 16:35:42 +00001731
paul718e3742002-12-13 20:15:29 +00001732 /* Logging the attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001733 if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW
1734 || BGP_DEBUG (update, UPDATE_IN))
paul718e3742002-12-13 20:15:29 +00001735 {
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +00001736 char attrstr[BUFSIZ];
1737 attrstr[0] = '\0';
1738
paule01f9cb2004-07-09 17:48:53 +00001739 ret= bgp_dump_attr (peer, &attr, attrstr, BUFSIZ);
Paul Jakmab881c702010-11-23 16:35:42 +00001740 int lvl = (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
1741 ? LOG_ERR : LOG_DEBUG;
1742
1743 if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
1744 zlog (peer->log, LOG_ERR,
1745 "%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.",
1746 peer->host);
paule01f9cb2004-07-09 17:48:53 +00001747
1748 if (ret)
Paul Jakmab881c702010-11-23 16:35:42 +00001749 zlog (peer->log, lvl, "%s rcvd UPDATE w/ attr: %s",
paule01f9cb2004-07-09 17:48:53 +00001750 peer->host, attrstr);
paul718e3742002-12-13 20:15:29 +00001751 }
Paul Jakmab881c702010-11-23 16:35:42 +00001752
paul718e3742002-12-13 20:15:29 +00001753 /* Network Layer Reachability Information. */
1754 update_len = end - stream_pnt (s);
1755
1756 if (update_len)
1757 {
1758 /* Check NLRI packet format and prefix length. */
Lou Berger050defe2016-01-12 13:41:59 -05001759 ret = bgp_nlri_sanity_check (peer, AFI_IP, SAFI_UNICAST, stream_pnt (s), update_len);
paul718e3742002-12-13 20:15:29 +00001760 if (ret < 0)
Paul Jakmab881c702010-11-23 16:35:42 +00001761 {
1762 bgp_attr_unintern_sub (&attr);
Lou Berger050defe2016-01-12 13:41:59 -05001763 bgp_attr_flush (&attr);
Paul Jakmab881c702010-11-23 16:35:42 +00001764 return -1;
1765 }
paul718e3742002-12-13 20:15:29 +00001766
1767 /* Set NLRI portion to structure. */
1768 update.afi = AFI_IP;
1769 update.safi = SAFI_UNICAST;
1770 update.nlri = stream_pnt (s);
1771 update.length = update_len;
paul9985f832005-02-09 15:51:56 +00001772 stream_forward_getp (s, update_len);
paul718e3742002-12-13 20:15:29 +00001773 }
1774
1775 /* NLRI is processed only when the peer is configured specific
1776 Address Family and Subsequent Address Family. */
1777 if (peer->afc[AFI_IP][SAFI_UNICAST])
1778 {
1779 if (withdraw.length)
1780 bgp_nlri_parse (peer, NULL, &withdraw);
1781
1782 if (update.length)
Paul Jakmab881c702010-11-23 16:35:42 +00001783 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &update);
paule01f9cb2004-07-09 17:48:53 +00001784
hassof4184462005-02-01 20:13:16 +00001785 if (mp_update.length
1786 && mp_update.afi == AFI_IP
1787 && mp_update.safi == SAFI_UNICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001788 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
hassof4184462005-02-01 20:13:16 +00001789
1790 if (mp_withdraw.length
1791 && mp_withdraw.afi == AFI_IP
1792 && mp_withdraw.safi == SAFI_UNICAST)
1793 bgp_nlri_parse (peer, NULL, &mp_withdraw);
1794
paule01f9cb2004-07-09 17:48:53 +00001795 if (! attribute_len && ! withdraw_len)
1796 {
1797 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001798 SET_FLAG (peer->af_sflags[AFI_IP][SAFI_UNICAST],
1799 PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001800
hasso93406d82005-02-02 14:40:33 +00001801 /* NSF delete stale route */
1802 if (peer->nsf[AFI_IP][SAFI_UNICAST])
1803 bgp_clear_stale_route (peer, AFI_IP, SAFI_UNICAST);
1804
1805 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001806 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001807 peer->host);
1808 }
paul718e3742002-12-13 20:15:29 +00001809 }
1810 if (peer->afc[AFI_IP][SAFI_MULTICAST])
1811 {
1812 if (mp_update.length
Lou Berger9da04bc2016-01-12 13:41:55 -05001813 && mp_update.afi == AFI_IP
paul718e3742002-12-13 20:15:29 +00001814 && mp_update.safi == SAFI_MULTICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001815 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001816
1817 if (mp_withdraw.length
Lou Berger9da04bc2016-01-12 13:41:55 -05001818 && mp_withdraw.afi == AFI_IP
paul718e3742002-12-13 20:15:29 +00001819 && mp_withdraw.safi == SAFI_MULTICAST)
1820 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001821
hasso93406d82005-02-02 14:40:33 +00001822 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001823 && mp_withdraw.afi == AFI_IP
1824 && mp_withdraw.safi == SAFI_MULTICAST
1825 && mp_withdraw.length == 0)
1826 {
1827 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001828 SET_FLAG (peer->af_sflags[AFI_IP][SAFI_MULTICAST],
1829 PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001830
hasso93406d82005-02-02 14:40:33 +00001831 /* NSF delete stale route */
1832 if (peer->nsf[AFI_IP][SAFI_MULTICAST])
1833 bgp_clear_stale_route (peer, AFI_IP, SAFI_MULTICAST);
1834
1835 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001836 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Multicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001837 peer->host);
1838 }
paul718e3742002-12-13 20:15:29 +00001839 }
1840 if (peer->afc[AFI_IP6][SAFI_UNICAST])
1841 {
1842 if (mp_update.length
1843 && mp_update.afi == AFI_IP6
1844 && mp_update.safi == SAFI_UNICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001845 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001846
1847 if (mp_withdraw.length
1848 && mp_withdraw.afi == AFI_IP6
1849 && mp_withdraw.safi == SAFI_UNICAST)
1850 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001851
hasso93406d82005-02-02 14:40:33 +00001852 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001853 && mp_withdraw.afi == AFI_IP6
1854 && mp_withdraw.safi == SAFI_UNICAST
1855 && mp_withdraw.length == 0)
1856 {
1857 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001858 SET_FLAG (peer->af_sflags[AFI_IP6][SAFI_UNICAST], PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001859
hasso93406d82005-02-02 14:40:33 +00001860 /* NSF delete stale route */
1861 if (peer->nsf[AFI_IP6][SAFI_UNICAST])
1862 bgp_clear_stale_route (peer, AFI_IP6, SAFI_UNICAST);
1863
1864 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001865 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001866 peer->host);
1867 }
paul718e3742002-12-13 20:15:29 +00001868 }
1869 if (peer->afc[AFI_IP6][SAFI_MULTICAST])
1870 {
1871 if (mp_update.length
1872 && mp_update.afi == AFI_IP6
1873 && mp_update.safi == SAFI_MULTICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001874 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001875
1876 if (mp_withdraw.length
1877 && mp_withdraw.afi == AFI_IP6
1878 && mp_withdraw.safi == SAFI_MULTICAST)
1879 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001880
hasso93406d82005-02-02 14:40:33 +00001881 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001882 && mp_withdraw.afi == AFI_IP6
1883 && mp_withdraw.safi == SAFI_MULTICAST
1884 && mp_withdraw.length == 0)
1885 {
1886 /* End-of-RIB received */
1887
hasso93406d82005-02-02 14:40:33 +00001888 /* NSF delete stale route */
1889 if (peer->nsf[AFI_IP6][SAFI_MULTICAST])
1890 bgp_clear_stale_route (peer, AFI_IP6, SAFI_MULTICAST);
1891
paule01f9cb2004-07-09 17:48:53 +00001892 if (BGP_DEBUG (update, UPDATE_IN))
ajs6b514742004-12-08 21:03:23 +00001893 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Multicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001894 peer->host);
1895 }
paul718e3742002-12-13 20:15:29 +00001896 }
1897 if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
1898 {
1899 if (mp_update.length
1900 && mp_update.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001901 && mp_update.safi == SAFI_MPLS_LABELED_VPN)
Lou Berger9da04bc2016-01-12 13:41:55 -05001902 bgp_nlri_parse_vpn (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001903
1904 if (mp_withdraw.length
1905 && mp_withdraw.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001906 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN)
Lou Berger9da04bc2016-01-12 13:41:55 -05001907 bgp_nlri_parse_vpn (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001908
hasso93406d82005-02-02 14:40:33 +00001909 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001910 && mp_withdraw.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001911 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN
paule01f9cb2004-07-09 17:48:53 +00001912 && mp_withdraw.length == 0)
1913 {
1914 /* End-of-RIB received */
1915
1916 if (BGP_DEBUG (update, UPDATE_IN))
ajs6b514742004-12-08 21:03:23 +00001917 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for VPNv4 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001918 peer->host);
1919 }
paul718e3742002-12-13 20:15:29 +00001920 }
Lou Berger9da04bc2016-01-12 13:41:55 -05001921 if (peer->afc[AFI_IP6][SAFI_MPLS_VPN])
1922 {
1923 if (mp_update.length
1924 && mp_update.afi == AFI_IP6
1925 && mp_update.safi == SAFI_MPLS_LABELED_VPN)
1926 bgp_nlri_parse_vpn (peer, NLRI_ATTR_ARG, &mp_update);
1927
1928 if (mp_withdraw.length
1929 && mp_withdraw.afi == AFI_IP6
1930 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN)
1931 bgp_nlri_parse_vpn (peer, NULL, &mp_withdraw);
1932
1933 if (! withdraw_len
1934 && mp_withdraw.afi == AFI_IP6
1935 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN
1936 && mp_withdraw.length == 0)
1937 {
1938 /* End-of-RIB received */
1939
1940 if (BGP_DEBUG (update, UPDATE_IN))
1941 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for VPNv4 Unicast from %s",
1942 peer->host);
1943 }
1944 }
Lou Berger298cc2f2016-01-12 13:42:02 -05001945 if (peer->afc[AFI_IP][SAFI_ENCAP])
1946 {
1947 if (mp_update.length
1948 && mp_update.afi == AFI_IP
1949 && mp_update.safi == SAFI_ENCAP)
1950 bgp_nlri_parse_encap (mp_update.afi, peer, &attr, &mp_update, 0);
1951
1952 if (mp_withdraw.length
1953 && mp_withdraw.afi == AFI_IP
1954 && mp_withdraw.safi == SAFI_ENCAP)
1955 bgp_nlri_parse_encap (mp_withdraw.afi, peer, &attr, &mp_withdraw, 1);
1956
1957 if (! withdraw_len
1958 && mp_withdraw.afi == AFI_IP
1959 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN
1960 && mp_withdraw.length == 0)
1961 {
1962 /* End-of-RIB received */
1963
1964 if (BGP_DEBUG (update, UPDATE_IN))
1965 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for Encap Unicast from %s",
1966 peer->host);
1967 }
1968 }
1969 if (peer->afc[AFI_IP6][SAFI_ENCAP])
1970 {
1971 if (mp_update.length
1972 && mp_update.afi == AFI_IP6
1973 && mp_update.safi == SAFI_ENCAP)
1974 bgp_nlri_parse_encap (mp_update.afi, peer, &attr, &mp_update, 0);
1975
1976 if (mp_withdraw.length
1977 && mp_withdraw.afi == AFI_IP6
1978 && mp_withdraw.safi == SAFI_ENCAP)
1979 bgp_nlri_parse_encap (mp_withdraw.afi, peer, &attr, &mp_withdraw, 1);
1980
1981 if (! withdraw_len
1982 && mp_withdraw.afi == AFI_IP6
1983 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN
1984 && mp_withdraw.length == 0)
1985 {
1986 /* End-of-RIB received */
1987
1988 if (BGP_DEBUG (update, UPDATE_IN))
1989 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for Encap Unicast from %s",
1990 peer->host);
1991 }
1992 }
paul718e3742002-12-13 20:15:29 +00001993
1994 /* Everything is done. We unintern temporary structures which
1995 interned in bgp_attr_parse(). */
Paul Jakmab881c702010-11-23 16:35:42 +00001996 bgp_attr_unintern_sub (&attr);
Lou Berger050defe2016-01-12 13:41:59 -05001997 bgp_attr_flush (&attr);
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001998
paul718e3742002-12-13 20:15:29 +00001999 /* If peering is stopped due to some reason, do not generate BGP
2000 event. */
2001 if (peer->status != Established)
2002 return 0;
2003
2004 /* Increment packet counter. */
2005 peer->update_in++;
Stephen Hemminger65957882010-01-15 16:22:10 +03002006 peer->update_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00002007
Jorge Boncompte [DTI2]e2c38e62012-06-20 17:45:50 +02002008 /* Rearm holdtime timer */
Jorge Boncompte [DTI2]6a4677b2012-05-07 16:53:07 +00002009 BGP_TIMER_OFF (peer->t_holdtime);
Jorge Boncompte [DTI2]e2c38e62012-06-20 17:45:50 +02002010 bgp_timer_set (peer);
paul718e3742002-12-13 20:15:29 +00002011
2012 return 0;
2013}
2014
2015/* Notify message treatment function. */
paul94f2b392005-06-28 12:44:16 +00002016static void
paul718e3742002-12-13 20:15:29 +00002017bgp_notify_receive (struct peer *peer, bgp_size_t size)
2018{
2019 struct bgp_notify bgp_notify;
2020
2021 if (peer->notify.data)
2022 {
2023 XFREE (MTYPE_TMP, peer->notify.data);
2024 peer->notify.data = NULL;
2025 peer->notify.length = 0;
2026 }
2027
2028 bgp_notify.code = stream_getc (peer->ibuf);
2029 bgp_notify.subcode = stream_getc (peer->ibuf);
2030 bgp_notify.length = size - 2;
2031 bgp_notify.data = NULL;
2032
2033 /* Preserv notify code and sub code. */
2034 peer->notify.code = bgp_notify.code;
2035 peer->notify.subcode = bgp_notify.subcode;
2036 /* For further diagnostic record returned Data. */
2037 if (bgp_notify.length)
2038 {
2039 peer->notify.length = size - 2;
2040 peer->notify.data = XMALLOC (MTYPE_TMP, size - 2);
2041 memcpy (peer->notify.data, stream_pnt (peer->ibuf), size - 2);
2042 }
2043
2044 /* For debug */
2045 {
2046 int i;
2047 int first = 0;
2048 char c[4];
2049
2050 if (bgp_notify.length)
2051 {
2052 bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
2053 for (i = 0; i < bgp_notify.length; i++)
2054 if (first)
2055 {
2056 sprintf (c, " %02x", stream_getc (peer->ibuf));
2057 strcat (bgp_notify.data, c);
2058 }
2059 else
2060 {
2061 first = 1;
2062 sprintf (c, "%02x", stream_getc (peer->ibuf));
2063 strcpy (bgp_notify.data, c);
2064 }
2065 }
2066
2067 bgp_notify_print(peer, &bgp_notify, "received");
2068 if (bgp_notify.data)
Daniel Walton363c9032015-10-21 06:42:54 -07002069 {
2070 XFREE (MTYPE_TMP, bgp_notify.data);
2071 bgp_notify.data = NULL;
2072 bgp_notify.length = 0;
2073 }
paul718e3742002-12-13 20:15:29 +00002074 }
2075
2076 /* peer count update */
2077 peer->notify_in++;
2078
hassoe0701b72004-05-20 09:19:34 +00002079 if (peer->status == Established)
2080 peer->last_reset = PEER_DOWN_NOTIFY_RECEIVED;
2081
paul718e3742002-12-13 20:15:29 +00002082 /* We have to check for Notify with Unsupported Optional Parameter.
2083 in that case we fallback to open without the capability option.
2084 But this done in bgp_stop. We just mark it here to avoid changing
2085 the fsm tables. */
2086 if (bgp_notify.code == BGP_NOTIFY_OPEN_ERR &&
2087 bgp_notify.subcode == BGP_NOTIFY_OPEN_UNSUP_PARAM )
2088 UNSET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
2089
paul718e3742002-12-13 20:15:29 +00002090 BGP_EVENT_ADD (peer, Receive_NOTIFICATION_message);
2091}
2092
2093/* Keepalive treatment function -- get keepalive send keepalive */
paul94f2b392005-06-28 12:44:16 +00002094static void
paul718e3742002-12-13 20:15:29 +00002095bgp_keepalive_receive (struct peer *peer, bgp_size_t size)
2096{
2097 if (BGP_DEBUG (keepalive, KEEPALIVE))
ajs6b514742004-12-08 21:03:23 +00002098 zlog_debug ("%s KEEPALIVE rcvd", peer->host);
paul718e3742002-12-13 20:15:29 +00002099
2100 BGP_EVENT_ADD (peer, Receive_KEEPALIVE_message);
2101}
2102
2103/* Route refresh message is received. */
paul94f2b392005-06-28 12:44:16 +00002104static void
paul718e3742002-12-13 20:15:29 +00002105bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
2106{
2107 afi_t afi;
2108 safi_t safi;
paul718e3742002-12-13 20:15:29 +00002109 struct stream *s;
2110
2111 /* If peer does not have the capability, send notification. */
2112 if (! CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_ADV))
2113 {
2114 plog_err (peer->log, "%s [Error] BGP route refresh is not enabled",
2115 peer->host);
2116 bgp_notify_send (peer,
2117 BGP_NOTIFY_HEADER_ERR,
2118 BGP_NOTIFY_HEADER_BAD_MESTYPE);
2119 return;
2120 }
2121
2122 /* Status must be Established. */
2123 if (peer->status != Established)
2124 {
2125 plog_err (peer->log,
2126 "%s [Error] Route refresh packet received under status %s",
2127 peer->host, LOOKUP (bgp_status_msg, peer->status));
2128 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
2129 return;
2130 }
2131
2132 s = peer->ibuf;
2133
2134 /* Parse packet. */
2135 afi = stream_getw (s);
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002136 /* reserved byte */
2137 stream_getc (s);
paul718e3742002-12-13 20:15:29 +00002138 safi = stream_getc (s);
2139
2140 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002141 zlog_debug ("%s rcvd REFRESH_REQ for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00002142 peer->host, afi, safi);
2143
2144 /* Check AFI and SAFI. */
2145 if ((afi != AFI_IP && afi != AFI_IP6)
2146 || (safi != SAFI_UNICAST && safi != SAFI_MULTICAST
Denis Ovsienko42e6d742011-07-14 12:36:19 +04002147 && safi != SAFI_MPLS_LABELED_VPN))
paul718e3742002-12-13 20:15:29 +00002148 {
2149 if (BGP_DEBUG (normal, NORMAL))
2150 {
ajs6b514742004-12-08 21:03:23 +00002151 zlog_debug ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored",
paul718e3742002-12-13 20:15:29 +00002152 peer->host, afi, safi);
2153 }
2154 return;
2155 }
2156
2157 /* Adjust safi code. */
Denis Ovsienko42e6d742011-07-14 12:36:19 +04002158 if (safi == SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00002159 safi = SAFI_MPLS_VPN;
2160
2161 if (size != BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE)
2162 {
2163 u_char *end;
2164 u_char when_to_refresh;
2165 u_char orf_type;
2166 u_int16_t orf_len;
2167
2168 if (size - (BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE) < 5)
2169 {
2170 zlog_info ("%s ORF route refresh length error", peer->host);
2171 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2172 return;
2173 }
2174
2175 when_to_refresh = stream_getc (s);
2176 end = stream_pnt (s) + (size - 5);
2177
Paul Jakma370b64a2007-12-22 16:49:52 +00002178 while ((stream_pnt (s) + 2) < end)
paul718e3742002-12-13 20:15:29 +00002179 {
2180 orf_type = stream_getc (s);
2181 orf_len = stream_getw (s);
Paul Jakma370b64a2007-12-22 16:49:52 +00002182
2183 /* orf_len in bounds? */
2184 if ((stream_pnt (s) + orf_len) > end)
2185 break; /* XXX: Notify instead?? */
paul718e3742002-12-13 20:15:29 +00002186 if (orf_type == ORF_TYPE_PREFIX
2187 || orf_type == ORF_TYPE_PREFIX_OLD)
2188 {
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002189 uint8_t *p_pnt = stream_pnt (s);
2190 uint8_t *p_end = stream_pnt (s) + orf_len;
paul718e3742002-12-13 20:15:29 +00002191 struct orf_prefix orfp;
2192 u_char common = 0;
2193 u_int32_t seq;
2194 int psize;
2195 char name[BUFSIZ];
paul718e3742002-12-13 20:15:29 +00002196 int ret;
2197
2198 if (BGP_DEBUG (normal, NORMAL))
2199 {
ajs6b514742004-12-08 21:03:23 +00002200 zlog_debug ("%s rcvd Prefixlist ORF(%d) length %d",
paul718e3742002-12-13 20:15:29 +00002201 peer->host, orf_type, orf_len);
2202 }
2203
Paul Jakma370b64a2007-12-22 16:49:52 +00002204 /* we're going to read at least 1 byte of common ORF header,
2205 * and 7 bytes of ORF Address-filter entry from the stream
2206 */
2207 if (orf_len < 7)
2208 break;
2209
paul718e3742002-12-13 20:15:29 +00002210 /* ORF prefix-list name */
2211 sprintf (name, "%s.%d.%d", peer->host, afi, safi);
2212
2213 while (p_pnt < p_end)
2214 {
Chris Halld64379e2010-05-14 16:38:39 +04002215 /* If the ORF entry is malformed, want to read as much of it
2216 * as possible without going beyond the bounds of the entry,
2217 * to maximise debug information.
2218 */
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002219 int ok;
paul718e3742002-12-13 20:15:29 +00002220 memset (&orfp, 0, sizeof (struct orf_prefix));
2221 common = *p_pnt++;
Chris Halld64379e2010-05-14 16:38:39 +04002222 /* after ++: p_pnt <= p_end */
paul718e3742002-12-13 20:15:29 +00002223 if (common & ORF_COMMON_PART_REMOVE_ALL)
2224 {
2225 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002226 zlog_debug ("%s rcvd Remove-All pfxlist ORF request", peer->host);
David Lamparterc9c06d02015-04-13 10:21:35 +02002227 prefix_bgp_orf_remove_all (afi, name);
paul718e3742002-12-13 20:15:29 +00002228 break;
2229 }
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002230 ok = ((size_t)(p_end - p_pnt) >= sizeof(u_int32_t)) ;
Denis Ovsienkobb915f52011-12-13 21:11:39 +04002231 if (ok)
Chris Halld64379e2010-05-14 16:38:39 +04002232 {
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002233 memcpy (&seq, p_pnt, sizeof (u_int32_t));
2234 p_pnt += sizeof (u_int32_t);
2235 orfp.seq = ntohl (seq);
Chris Halld64379e2010-05-14 16:38:39 +04002236 }
2237 else
2238 p_pnt = p_end ;
2239
2240 if ((ok = (p_pnt < p_end)))
2241 orfp.ge = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */
2242 if ((ok = (p_pnt < p_end)))
2243 orfp.le = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */
2244 if ((ok = (p_pnt < p_end)))
2245 orfp.p.prefixlen = *p_pnt++ ;
2246 orfp.p.family = afi2family (afi); /* afi checked already */
2247
2248 psize = PSIZE (orfp.p.prefixlen); /* 0 if not ok */
2249 if (psize > prefix_blen(&orfp.p)) /* valid for family ? */
2250 {
2251 ok = 0 ;
2252 psize = prefix_blen(&orfp.p) ;
2253 }
2254 if (psize > (p_end - p_pnt)) /* valid for packet ? */
2255 {
2256 ok = 0 ;
2257 psize = p_end - p_pnt ;
2258 }
2259
2260 if (psize > 0)
2261 memcpy (&orfp.p.u.prefix, p_pnt, psize);
paul718e3742002-12-13 20:15:29 +00002262 p_pnt += psize;
2263
2264 if (BGP_DEBUG (normal, NORMAL))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +00002265 {
2266 char buf[INET6_BUFSIZ];
2267
2268 zlog_debug ("%s rcvd %s %s seq %u %s/%d ge %d le %d%s",
2269 peer->host,
2270 (common & ORF_COMMON_PART_REMOVE ? "Remove" : "Add"),
2271 (common & ORF_COMMON_PART_DENY ? "deny" : "permit"),
2272 orfp.seq,
2273 inet_ntop (orfp.p.family, &orfp.p.u.prefix, buf, INET6_BUFSIZ),
2274 orfp.p.prefixlen, orfp.ge, orfp.le,
2275 ok ? "" : " MALFORMED");
2276 }
2277
Chris Halld64379e2010-05-14 16:38:39 +04002278 if (ok)
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002279 ret = prefix_bgp_orf_set (name, afi, &orfp,
2280 (common & ORF_COMMON_PART_DENY ? 0 : 1 ),
2281 (common & ORF_COMMON_PART_REMOVE ? 0 : 1));
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002282
2283 if (!ok || (ok && ret != CMD_SUCCESS))
paul718e3742002-12-13 20:15:29 +00002284 {
2285 if (BGP_DEBUG (normal, NORMAL))
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002286 zlog_debug ("%s Received misformatted prefixlist ORF."
2287 " Remove All pfxlist", peer->host);
David Lamparterc9c06d02015-04-13 10:21:35 +02002288 prefix_bgp_orf_remove_all (afi, name);
paul718e3742002-12-13 20:15:29 +00002289 break;
2290 }
2291 }
2292 peer->orf_plist[afi][safi] =
David Lamparterc9c06d02015-04-13 10:21:35 +02002293 prefix_bgp_orf_lookup (afi, name);
paul718e3742002-12-13 20:15:29 +00002294 }
paul9985f832005-02-09 15:51:56 +00002295 stream_forward_getp (s, orf_len);
paul718e3742002-12-13 20:15:29 +00002296 }
2297 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002298 zlog_debug ("%s rcvd Refresh %s ORF request", peer->host,
paul718e3742002-12-13 20:15:29 +00002299 when_to_refresh == REFRESH_DEFER ? "Defer" : "Immediate");
2300 if (when_to_refresh == REFRESH_DEFER)
2301 return;
2302 }
2303
2304 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2305 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH))
2306 UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
2307
2308 /* Perform route refreshment to the peer */
2309 bgp_announce_route (peer, afi, safi);
2310}
2311
paul94f2b392005-06-28 12:44:16 +00002312static int
paul718e3742002-12-13 20:15:29 +00002313bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
2314{
2315 u_char *end;
Paul Jakma6d582722007-08-06 15:21:45 +00002316 struct capability_mp_data mpc;
2317 struct capability_header *hdr;
paul718e3742002-12-13 20:15:29 +00002318 u_char action;
paul718e3742002-12-13 20:15:29 +00002319 afi_t afi;
2320 safi_t safi;
2321
paul718e3742002-12-13 20:15:29 +00002322 end = pnt + length;
2323
2324 while (pnt < end)
Paul Jakma6d582722007-08-06 15:21:45 +00002325 {
paul718e3742002-12-13 20:15:29 +00002326 /* We need at least action, capability code and capability length. */
2327 if (pnt + 3 > end)
2328 {
2329 zlog_info ("%s Capability length error", peer->host);
2330 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2331 return -1;
2332 }
paul718e3742002-12-13 20:15:29 +00002333 action = *pnt;
Paul Jakma6d582722007-08-06 15:21:45 +00002334 hdr = (struct capability_header *)(pnt + 1);
2335
paul718e3742002-12-13 20:15:29 +00002336 /* Action value check. */
2337 if (action != CAPABILITY_ACTION_SET
2338 && action != CAPABILITY_ACTION_UNSET)
2339 {
2340 zlog_info ("%s Capability Action Value error %d",
2341 peer->host, action);
2342 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2343 return -1;
2344 }
2345
2346 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002347 zlog_debug ("%s CAPABILITY has action: %d, code: %u, length %u",
Paul Jakma6d582722007-08-06 15:21:45 +00002348 peer->host, action, hdr->code, hdr->length);
paul718e3742002-12-13 20:15:29 +00002349
2350 /* Capability length check. */
Paul Jakma6d582722007-08-06 15:21:45 +00002351 if ((pnt + hdr->length + 3) > end)
paul718e3742002-12-13 20:15:29 +00002352 {
2353 zlog_info ("%s Capability length error", peer->host);
2354 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2355 return -1;
2356 }
2357
Paul Jakma6d582722007-08-06 15:21:45 +00002358 /* Fetch structure to the byte stream. */
2359 memcpy (&mpc, pnt + 3, sizeof (struct capability_mp_data));
2360
paul718e3742002-12-13 20:15:29 +00002361 /* We know MP Capability Code. */
Paul Jakma6d582722007-08-06 15:21:45 +00002362 if (hdr->code == CAPABILITY_CODE_MP)
paul718e3742002-12-13 20:15:29 +00002363 {
Paul Jakma6d582722007-08-06 15:21:45 +00002364 afi = ntohs (mpc.afi);
2365 safi = mpc.safi;
paul718e3742002-12-13 20:15:29 +00002366
2367 /* Ignore capability when override-capability is set. */
2368 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
2369 continue;
Paul Jakma6d582722007-08-06 15:21:45 +00002370
2371 if (!bgp_afi_safi_valid_indices (afi, &safi))
2372 {
2373 if (BGP_DEBUG (normal, NORMAL))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002374 zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid "
2375 "(%u/%u)", peer->host, afi, safi);
Paul Jakma6d582722007-08-06 15:21:45 +00002376 continue;
2377 }
2378
paul718e3742002-12-13 20:15:29 +00002379 /* Address family check. */
Paul Jakma6d582722007-08-06 15:21:45 +00002380 if (BGP_DEBUG (normal, NORMAL))
2381 zlog_debug ("%s CAPABILITY has %s MP_EXT CAP for afi/safi: %u/%u",
2382 peer->host,
2383 action == CAPABILITY_ACTION_SET
2384 ? "Advertising" : "Removing",
2385 ntohs(mpc.afi) , mpc.safi);
2386
2387 if (action == CAPABILITY_ACTION_SET)
2388 {
2389 peer->afc_recv[afi][safi] = 1;
2390 if (peer->afc[afi][safi])
2391 {
2392 peer->afc_nego[afi][safi] = 1;
2393 bgp_announce_route (peer, afi, safi);
2394 }
2395 }
2396 else
2397 {
2398 peer->afc_recv[afi][safi] = 0;
2399 peer->afc_nego[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00002400
Paul Jakma6d582722007-08-06 15:21:45 +00002401 if (peer_active_nego (peer))
Chris Caputo228da422009-07-18 05:44:03 +00002402 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
Paul Jakma6d582722007-08-06 15:21:45 +00002403 else
2404 BGP_EVENT_ADD (peer, BGP_Stop);
2405 }
paul718e3742002-12-13 20:15:29 +00002406 }
paul718e3742002-12-13 20:15:29 +00002407 else
2408 {
2409 zlog_warn ("%s unrecognized capability code: %d - ignored",
Paul Jakma6d582722007-08-06 15:21:45 +00002410 peer->host, hdr->code);
paul718e3742002-12-13 20:15:29 +00002411 }
Paul Jakma6d582722007-08-06 15:21:45 +00002412 pnt += hdr->length + 3;
paul718e3742002-12-13 20:15:29 +00002413 }
2414 return 0;
2415}
2416
Paul Jakma01b7ce22009-06-18 12:34:43 +01002417/* Dynamic Capability is received.
2418 *
2419 * This is exported for unit-test purposes
2420 */
Paul Jakma6d582722007-08-06 15:21:45 +00002421int
paul718e3742002-12-13 20:15:29 +00002422bgp_capability_receive (struct peer *peer, bgp_size_t size)
2423{
2424 u_char *pnt;
paul718e3742002-12-13 20:15:29 +00002425
2426 /* Fetch pointer. */
2427 pnt = stream_pnt (peer->ibuf);
2428
2429 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002430 zlog_debug ("%s rcv CAPABILITY", peer->host);
paul718e3742002-12-13 20:15:29 +00002431
2432 /* If peer does not have the capability, send notification. */
2433 if (! CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV))
2434 {
2435 plog_err (peer->log, "%s [Error] BGP dynamic capability is not enabled",
2436 peer->host);
2437 bgp_notify_send (peer,
2438 BGP_NOTIFY_HEADER_ERR,
2439 BGP_NOTIFY_HEADER_BAD_MESTYPE);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002440 return -1;
paul718e3742002-12-13 20:15:29 +00002441 }
2442
2443 /* Status must be Established. */
2444 if (peer->status != Established)
2445 {
2446 plog_err (peer->log,
2447 "%s [Error] Dynamic capability packet received under status %s", peer->host, LOOKUP (bgp_status_msg, peer->status));
2448 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002449 return -1;
paul718e3742002-12-13 20:15:29 +00002450 }
2451
2452 /* Parse packet. */
Paul Jakma6d582722007-08-06 15:21:45 +00002453 return bgp_capability_msg_parse (peer, pnt, size);
paul718e3742002-12-13 20:15:29 +00002454}
David Lamparter6b0655a2014-06-04 06:53:35 +02002455
paul718e3742002-12-13 20:15:29 +00002456/* BGP read utility function. */
paul94f2b392005-06-28 12:44:16 +00002457static int
paul718e3742002-12-13 20:15:29 +00002458bgp_read_packet (struct peer *peer)
2459{
2460 int nbytes;
2461 int readsize;
2462
paul9985f832005-02-09 15:51:56 +00002463 readsize = peer->packet_size - stream_get_endp (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00002464
2465 /* If size is zero then return. */
2466 if (! readsize)
2467 return 0;
2468
2469 /* Read packet from fd. */
Stephen Hemminger35398582010-08-05 10:26:23 -07002470 nbytes = stream_read_try (peer->ibuf, peer->fd, readsize);
paul718e3742002-12-13 20:15:29 +00002471
2472 /* If read byte is smaller than zero then error occured. */
2473 if (nbytes < 0)
2474 {
Stephen Hemminger35398582010-08-05 10:26:23 -07002475 /* Transient error should retry */
2476 if (nbytes == -2)
paul718e3742002-12-13 20:15:29 +00002477 return -1;
2478
2479 plog_err (peer->log, "%s [Error] bgp_read_packet error: %s",
ajs6099b3b2004-11-20 02:06:59 +00002480 peer->host, safe_strerror (errno));
hasso93406d82005-02-02 14:40:33 +00002481
2482 if (peer->status == Established)
2483 {
2484 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
2485 {
2486 peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
2487 SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
2488 }
2489 else
2490 peer->last_reset = PEER_DOWN_CLOSE_SESSION;
2491 }
2492
paul718e3742002-12-13 20:15:29 +00002493 BGP_EVENT_ADD (peer, TCP_fatal_error);
2494 return -1;
2495 }
2496
2497 /* When read byte is zero : clear bgp peer and return */
2498 if (nbytes == 0)
2499 {
2500 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +00002501 plog_debug (peer->log, "%s [Event] BGP connection closed fd %d",
pauleb821182004-05-01 08:44:08 +00002502 peer->host, peer->fd);
hassoe0701b72004-05-20 09:19:34 +00002503
2504 if (peer->status == Established)
hasso93406d82005-02-02 14:40:33 +00002505 {
2506 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
2507 {
2508 peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
2509 SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
2510 }
2511 else
2512 peer->last_reset = PEER_DOWN_CLOSE_SESSION;
2513 }
hassoe0701b72004-05-20 09:19:34 +00002514
paul718e3742002-12-13 20:15:29 +00002515 BGP_EVENT_ADD (peer, TCP_connection_closed);
2516 return -1;
2517 }
2518
2519 /* We read partial packet. */
paul9985f832005-02-09 15:51:56 +00002520 if (stream_get_endp (peer->ibuf) != peer->packet_size)
paul718e3742002-12-13 20:15:29 +00002521 return -1;
2522
2523 return 0;
2524}
2525
2526/* Marker check. */
paul94f2b392005-06-28 12:44:16 +00002527static int
paul718e3742002-12-13 20:15:29 +00002528bgp_marker_all_one (struct stream *s, int length)
2529{
2530 int i;
2531
2532 for (i = 0; i < length; i++)
2533 if (s->data[i] != 0xff)
2534 return 0;
2535
2536 return 1;
2537}
2538
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002539/* Recent thread time.
2540 On same clock base as bgp_clock (MONOTONIC)
2541 but can be time of last context switch to bgp_read thread. */
2542static time_t
2543bgp_recent_clock (void)
2544{
2545 return recent_relative_time().tv_sec;
2546}
2547
paul718e3742002-12-13 20:15:29 +00002548/* Starting point of packet process function. */
2549int
2550bgp_read (struct thread *thread)
2551{
2552 int ret;
2553 u_char type = 0;
2554 struct peer *peer;
2555 bgp_size_t size;
2556 char notify_data_length[2];
2557
2558 /* Yes first of all get peer pointer. */
2559 peer = THREAD_ARG (thread);
2560 peer->t_read = NULL;
2561
2562 /* For non-blocking IO check. */
2563 if (peer->status == Connect)
2564 {
2565 bgp_connect_check (peer);
2566 goto done;
2567 }
2568 else
2569 {
pauleb821182004-05-01 08:44:08 +00002570 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +00002571 {
pauleb821182004-05-01 08:44:08 +00002572 zlog_err ("bgp_read peer's fd is negative value %d", peer->fd);
paul718e3742002-12-13 20:15:29 +00002573 return -1;
2574 }
pauleb821182004-05-01 08:44:08 +00002575 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
paul718e3742002-12-13 20:15:29 +00002576 }
2577
2578 /* Read packet header to determine type of the packet */
2579 if (peer->packet_size == 0)
2580 peer->packet_size = BGP_HEADER_SIZE;
2581
paul9985f832005-02-09 15:51:56 +00002582 if (stream_get_endp (peer->ibuf) < BGP_HEADER_SIZE)
paul718e3742002-12-13 20:15:29 +00002583 {
2584 ret = bgp_read_packet (peer);
2585
2586 /* Header read error or partial read packet. */
2587 if (ret < 0)
2588 goto done;
2589
2590 /* Get size and type. */
paul9985f832005-02-09 15:51:56 +00002591 stream_forward_getp (peer->ibuf, BGP_MARKER_SIZE);
paul718e3742002-12-13 20:15:29 +00002592 memcpy (notify_data_length, stream_pnt (peer->ibuf), 2);
2593 size = stream_getw (peer->ibuf);
2594 type = stream_getc (peer->ibuf);
2595
2596 if (BGP_DEBUG (normal, NORMAL) && type != 2 && type != 0)
ajs6b514742004-12-08 21:03:23 +00002597 zlog_debug ("%s rcv message type %d, length (excl. header) %d",
paul718e3742002-12-13 20:15:29 +00002598 peer->host, type, size - BGP_HEADER_SIZE);
2599
2600 /* Marker check */
paulf5ba3872004-07-09 12:11:31 +00002601 if (((type == BGP_MSG_OPEN) || (type == BGP_MSG_KEEPALIVE))
paul718e3742002-12-13 20:15:29 +00002602 && ! bgp_marker_all_one (peer->ibuf, BGP_MARKER_SIZE))
2603 {
2604 bgp_notify_send (peer,
2605 BGP_NOTIFY_HEADER_ERR,
2606 BGP_NOTIFY_HEADER_NOT_SYNC);
2607 goto done;
2608 }
2609
2610 /* BGP type check. */
2611 if (type != BGP_MSG_OPEN && type != BGP_MSG_UPDATE
2612 && type != BGP_MSG_NOTIFY && type != BGP_MSG_KEEPALIVE
2613 && type != BGP_MSG_ROUTE_REFRESH_NEW
2614 && type != BGP_MSG_ROUTE_REFRESH_OLD
2615 && type != BGP_MSG_CAPABILITY)
2616 {
2617 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002618 plog_debug (peer->log,
paul718e3742002-12-13 20:15:29 +00002619 "%s unknown message type 0x%02x",
2620 peer->host, type);
2621 bgp_notify_send_with_data (peer,
2622 BGP_NOTIFY_HEADER_ERR,
2623 BGP_NOTIFY_HEADER_BAD_MESTYPE,
2624 &type, 1);
2625 goto done;
2626 }
2627 /* Mimimum packet length check. */
2628 if ((size < BGP_HEADER_SIZE)
2629 || (size > BGP_MAX_PACKET_SIZE)
2630 || (type == BGP_MSG_OPEN && size < BGP_MSG_OPEN_MIN_SIZE)
2631 || (type == BGP_MSG_UPDATE && size < BGP_MSG_UPDATE_MIN_SIZE)
2632 || (type == BGP_MSG_NOTIFY && size < BGP_MSG_NOTIFY_MIN_SIZE)
2633 || (type == BGP_MSG_KEEPALIVE && size != BGP_MSG_KEEPALIVE_MIN_SIZE)
2634 || (type == BGP_MSG_ROUTE_REFRESH_NEW && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
2635 || (type == BGP_MSG_ROUTE_REFRESH_OLD && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
2636 || (type == BGP_MSG_CAPABILITY && size < BGP_MSG_CAPABILITY_MIN_SIZE))
2637 {
2638 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002639 plog_debug (peer->log,
paul718e3742002-12-13 20:15:29 +00002640 "%s bad message length - %d for %s",
2641 peer->host, size,
2642 type == 128 ? "ROUTE-REFRESH" :
2643 bgp_type_str[(int) type]);
2644 bgp_notify_send_with_data (peer,
2645 BGP_NOTIFY_HEADER_ERR,
2646 BGP_NOTIFY_HEADER_BAD_MESLEN,
hassoc9e52be2004-09-26 16:09:34 +00002647 (u_char *) notify_data_length, 2);
paul718e3742002-12-13 20:15:29 +00002648 goto done;
2649 }
2650
2651 /* Adjust size to message length. */
2652 peer->packet_size = size;
2653 }
2654
2655 ret = bgp_read_packet (peer);
2656 if (ret < 0)
2657 goto done;
2658
2659 /* Get size and type again. */
2660 size = stream_getw_from (peer->ibuf, BGP_MARKER_SIZE);
2661 type = stream_getc_from (peer->ibuf, BGP_MARKER_SIZE + 2);
2662
2663 /* BGP packet dump function. */
2664 bgp_dump_packet (peer, type, peer->ibuf);
2665
2666 size = (peer->packet_size - BGP_HEADER_SIZE);
2667
2668 /* Read rest of the packet and call each sort of packet routine */
2669 switch (type)
2670 {
2671 case BGP_MSG_OPEN:
2672 peer->open_in++;
paulf5ba3872004-07-09 12:11:31 +00002673 bgp_open_receive (peer, size); /* XXX return value ignored! */
paul718e3742002-12-13 20:15:29 +00002674 break;
2675 case BGP_MSG_UPDATE:
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002676 peer->readtime = bgp_recent_clock ();
paul718e3742002-12-13 20:15:29 +00002677 bgp_update_receive (peer, size);
2678 break;
2679 case BGP_MSG_NOTIFY:
2680 bgp_notify_receive (peer, size);
2681 break;
2682 case BGP_MSG_KEEPALIVE:
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002683 peer->readtime = bgp_recent_clock ();
paul718e3742002-12-13 20:15:29 +00002684 bgp_keepalive_receive (peer, size);
2685 break;
2686 case BGP_MSG_ROUTE_REFRESH_NEW:
2687 case BGP_MSG_ROUTE_REFRESH_OLD:
2688 peer->refresh_in++;
2689 bgp_route_refresh_receive (peer, size);
2690 break;
2691 case BGP_MSG_CAPABILITY:
2692 peer->dynamic_cap_in++;
2693 bgp_capability_receive (peer, size);
2694 break;
2695 }
2696
2697 /* Clear input buffer. */
2698 peer->packet_size = 0;
2699 if (peer->ibuf)
2700 stream_reset (peer->ibuf);
2701
2702 done:
2703 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2704 {
2705 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +00002706 zlog_debug ("%s [Event] Accepting BGP peer delete", peer->host);
paul718e3742002-12-13 20:15:29 +00002707 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00002708 }
2709 return 0;
2710}