blob: 841eaab88bed62d2d69fcd8eaf10150243d42852 [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"
50#include "bgpd/bgp_advertise.h"
hasso93406d82005-02-02 14:40:33 +000051#include "bgpd/bgp_vty.h"
paul718e3742002-12-13 20:15:29 +000052
53int stream_put_prefix (struct stream *, struct prefix *);
David Lamparter6b0655a2014-06-04 06:53:35 +020054
paul718e3742002-12-13 20:15:29 +000055/* Set up BGP packet marker and packet type. */
56static int
57bgp_packet_set_marker (struct stream *s, u_char type)
58{
59 int i;
60
61 /* Fill in marker. */
62 for (i = 0; i < BGP_MARKER_SIZE; i++)
63 stream_putc (s, 0xff);
64
65 /* Dummy total length. This field is should be filled in later on. */
66 stream_putw (s, 0);
67
68 /* BGP packet type. */
69 stream_putc (s, type);
70
71 /* Return current stream size. */
paul9985f832005-02-09 15:51:56 +000072 return stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +000073}
74
75/* Set BGP packet header size entry. If size is zero then use current
76 stream size. */
77static int
78bgp_packet_set_size (struct stream *s)
79{
80 int cp;
81
82 /* Preserve current pointer. */
paul9985f832005-02-09 15:51:56 +000083 cp = stream_get_endp (s);
84 stream_putw_at (s, BGP_MARKER_SIZE, cp);
paul718e3742002-12-13 20:15:29 +000085
86 return cp;
87}
88
89/* Add new packet to the peer. */
paul94f2b392005-06-28 12:44:16 +000090static void
paul718e3742002-12-13 20:15:29 +000091bgp_packet_add (struct peer *peer, struct stream *s)
92{
93 /* Add packet to the end of list. */
94 stream_fifo_push (peer->obuf, s);
95}
96
97/* Free first packet. */
paul94f2b392005-06-28 12:44:16 +000098static void
paul718e3742002-12-13 20:15:29 +000099bgp_packet_delete (struct peer *peer)
100{
101 stream_free (stream_fifo_pop (peer->obuf));
102}
103
paul718e3742002-12-13 20:15:29 +0000104/* Check file descriptor whether connect is established. */
105static void
106bgp_connect_check (struct peer *peer)
107{
108 int status;
paul5228ad22004-06-04 17:58:18 +0000109 socklen_t slen;
paul718e3742002-12-13 20:15:29 +0000110 int ret;
111
112 /* Anyway I have to reset read and write thread. */
113 BGP_READ_OFF (peer->t_read);
114 BGP_WRITE_OFF (peer->t_write);
115
116 /* Check file descriptor. */
117 slen = sizeof (status);
pauleb821182004-05-01 08:44:08 +0000118 ret = getsockopt(peer->fd, SOL_SOCKET, SO_ERROR, (void *) &status, &slen);
paul718e3742002-12-13 20:15:29 +0000119
120 /* If getsockopt is fail, this is fatal error. */
121 if (ret < 0)
122 {
123 zlog (peer->log, LOG_INFO, "can't get sockopt for nonblocking connect");
124 BGP_EVENT_ADD (peer, TCP_fatal_error);
125 return;
126 }
127
128 /* When status is 0 then TCP connection is established. */
129 if (status == 0)
130 {
131 BGP_EVENT_ADD (peer, TCP_connection_open);
132 }
133 else
134 {
135 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +0000136 plog_debug (peer->log, "%s [Event] Connect failed (%s)",
ajs6099b3b2004-11-20 02:06:59 +0000137 peer->host, safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000138 BGP_EVENT_ADD (peer, TCP_connection_open_failed);
139 }
140}
141
142/* Make BGP update packet. */
paul94f2b392005-06-28 12:44:16 +0000143static struct stream *
paul718e3742002-12-13 20:15:29 +0000144bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
145{
146 struct stream *s;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000147 struct stream *snlri;
paul718e3742002-12-13 20:15:29 +0000148 struct bgp_adj_out *adj;
149 struct bgp_advertise *adv;
150 struct stream *packet;
151 struct bgp_node *rn = NULL;
152 struct bgp_info *binfo = NULL;
153 bgp_size_t total_attr_len = 0;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000154 unsigned long attrlen_pos = 0;
155 size_t mpattrlen_pos = 0;
156 size_t mpattr_pos = 0;
paul718e3742002-12-13 20:15:29 +0000157
158 s = peer->work;
159 stream_reset (s);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000160 snlri = peer->scratch;
161 stream_reset (snlri);
paul718e3742002-12-13 20:15:29 +0000162
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100163 adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->update);
paul718e3742002-12-13 20:15:29 +0000164
165 while (adv)
166 {
Paul Jakmaed3ebfa2006-10-15 23:50:16 +0000167 assert (adv->rn);
168 rn = adv->rn;
paul718e3742002-12-13 20:15:29 +0000169 adj = adv->adj;
170 if (adv->binfo)
171 binfo = adv->binfo;
paul718e3742002-12-13 20:15:29 +0000172
173 /* When remaining space can't include NLRI and it's length. */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000174 if (STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) <=
Lou Berger050defe2016-01-12 13:41:59 -0500175 (BGP_NLRI_LENGTH + bgp_packet_mpattr_prefix_size(afi,safi,&rn->p)))
paul718e3742002-12-13 20:15:29 +0000176 break;
177
178 /* If packet is empty, set attribute. */
179 if (stream_empty (s))
180 {
Lou Berger050defe2016-01-12 13:41:59 -0500181 struct prefix_rd *prd = NULL;
182 u_char *tag = NULL;
Paul Jakmaed3ebfa2006-10-15 23:50:16 +0000183 struct peer *from = NULL;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000184
Lou Berger050defe2016-01-12 13:41:59 -0500185 if (rn->prn)
186 prd = (struct prefix_rd *) &rn->prn->p;
Greg Troxeld3ddb222010-09-17 10:47:49 -0400187 if (binfo)
Lou Berger050defe2016-01-12 13:41:59 -0500188 {
189 from = binfo->peer;
190 if (binfo->extra)
191 tag = binfo->extra->tag;
192 }
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000193
194 /* 1: Write the BGP message header - 16 bytes marker, 2 bytes length,
195 * one byte message type.
196 */
paul718e3742002-12-13 20:15:29 +0000197 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000198
199 /* 2: withdrawn routes length */
paul718e3742002-12-13 20:15:29 +0000200 stream_putw (s, 0);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000201
202 /* 3: total attributes length - attrlen_pos stores the position */
203 attrlen_pos = stream_get_endp (s);
204 stream_putw (s, 0);
205
206 /* 4: if there is MP_REACH_NLRI attribute, that should be the first
207 * attribute, according to draft-ietf-idr-error-handling. Save the
208 * position.
209 */
210 mpattr_pos = stream_get_endp(s);
211
212 /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */
213 total_attr_len = bgp_packet_attribute (NULL, peer, s,
paul5228ad22004-06-04 17:58:18 +0000214 adv->baa->attr,
Lou Berger050defe2016-01-12 13:41:59 -0500215 &rn->p, afi, safi,
216 from, prd, tag);
paul718e3742002-12-13 20:15:29 +0000217 }
218
219 if (afi == AFI_IP && safi == SAFI_UNICAST)
220 stream_put_prefix (s, &rn->p);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000221 else
222 {
223 /* Encode the prefix in MP_REACH_NLRI attribute */
224 struct prefix_rd *prd = NULL;
225 u_char *tag = NULL;
226
227 if (rn->prn)
228 prd = (struct prefix_rd *) &rn->prn->p;
229 if (binfo && binfo->extra)
230 tag = binfo->extra->tag;
231
232 if (stream_empty(snlri))
233 mpattrlen_pos = bgp_packet_mpattr_start(snlri, afi, safi,
234 adv->baa->attr);
235 bgp_packet_mpattr_prefix(snlri, afi, safi, &rn->p, prd, tag);
236 }
paul718e3742002-12-13 20:15:29 +0000237 if (BGP_DEBUG (update, UPDATE_OUT))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000238 {
239 char buf[INET6_BUFSIZ];
240
241 zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d",
242 peer->host,
243 inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ),
244 rn->p.prefixlen);
245 }
paul718e3742002-12-13 20:15:29 +0000246
247 /* Synchnorize attribute. */
248 if (adj->attr)
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000249 bgp_attr_unintern (&adj->attr);
paul718e3742002-12-13 20:15:29 +0000250 else
251 peer->scount[afi][safi]++;
252
253 adj->attr = bgp_attr_intern (adv->baa->attr);
254
255 adv = bgp_advertise_clean (peer, adj, afi, safi);
paul718e3742002-12-13 20:15:29 +0000256 }
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000257
paul718e3742002-12-13 20:15:29 +0000258 if (! stream_empty (s))
259 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000260 if (!stream_empty(snlri))
261 {
262 bgp_packet_mpattr_end(snlri, mpattrlen_pos);
263 total_attr_len += stream_get_endp(snlri);
264 }
265
266 /* set the total attribute length correctly */
267 stream_putw_at (s, attrlen_pos, total_attr_len);
268
269 if (!stream_empty(snlri))
270 packet = stream_dupcat(s, snlri, mpattr_pos);
271 else
272 packet = stream_dup (s);
273 bgp_packet_set_size (packet);
paul718e3742002-12-13 20:15:29 +0000274 bgp_packet_add (peer, packet);
pauleb821182004-05-01 08:44:08 +0000275 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000276 stream_reset (s);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000277 stream_reset (snlri);
paul718e3742002-12-13 20:15:29 +0000278 return packet;
279 }
280 return NULL;
hasso93406d82005-02-02 14:40:33 +0000281}
paul718e3742002-12-13 20:15:29 +0000282
paul94f2b392005-06-28 12:44:16 +0000283static struct stream *
hasso93406d82005-02-02 14:40:33 +0000284bgp_update_packet_eor (struct peer *peer, afi_t afi, safi_t safi)
285{
286 struct stream *s;
hasso93406d82005-02-02 14:40:33 +0000287
Paul Jakma750e8142008-07-22 21:11:48 +0000288 if (DISABLE_BGP_ANNOUNCE)
289 return NULL;
hasso93406d82005-02-02 14:40:33 +0000290
291 if (BGP_DEBUG (normal, NORMAL))
292 zlog_debug ("send End-of-RIB for %s to %s", afi_safi_print (afi, safi), peer->host);
293
294 s = stream_new (BGP_MAX_PACKET_SIZE);
295
296 /* Make BGP update packet. */
297 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
298
299 /* Unfeasible Routes Length */
300 stream_putw (s, 0);
301
302 if (afi == AFI_IP && safi == SAFI_UNICAST)
303 {
304 /* Total Path Attribute Length */
305 stream_putw (s, 0);
306 }
307 else
308 {
309 /* Total Path Attribute Length */
310 stream_putw (s, 6);
311 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
312 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
313 stream_putc (s, 3);
314 stream_putw (s, afi);
315 stream_putc (s, safi);
316 }
317
318 bgp_packet_set_size (s);
Donald Sharpa752c3b2015-08-18 08:48:53 -0400319 bgp_packet_add (peer, s);
320 return s;
paul718e3742002-12-13 20:15:29 +0000321}
322
323/* Make BGP withdraw packet. */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000324/* For ipv4 unicast:
325 16-octet marker | 2-octet length | 1-octet type |
326 2-octet withdrawn route length | withdrawn prefixes | 2-octet attrlen (=0)
327*/
328/* For other afi/safis:
329 16-octet marker | 2-octet length | 1-octet type |
330 2-octet withdrawn route length (=0) | 2-octet attrlen |
331 mp_unreach attr type | attr len | afi | safi | withdrawn prefixes
332*/
paul94f2b392005-06-28 12:44:16 +0000333static struct stream *
paul718e3742002-12-13 20:15:29 +0000334bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi)
335{
336 struct stream *s;
337 struct stream *packet;
338 struct bgp_adj_out *adj;
339 struct bgp_advertise *adv;
340 struct bgp_node *rn;
paul718e3742002-12-13 20:15:29 +0000341 bgp_size_t unfeasible_len;
342 bgp_size_t total_attr_len;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000343 size_t mp_start = 0;
344 size_t attrlen_pos = 0;
345 size_t mplen_pos = 0;
346 u_char first_time = 1;
paul718e3742002-12-13 20:15:29 +0000347
348 s = peer->work;
349 stream_reset (s);
350
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100351 while ((adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->withdraw)) != NULL)
paul718e3742002-12-13 20:15:29 +0000352 {
Paul Jakmaed3ebfa2006-10-15 23:50:16 +0000353 assert (adv->rn);
paul718e3742002-12-13 20:15:29 +0000354 adj = adv->adj;
355 rn = adv->rn;
paul718e3742002-12-13 20:15:29 +0000356
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000357 if (STREAM_REMAIN (s)
hasso4372df72004-05-20 10:20:02 +0000358 < (BGP_NLRI_LENGTH + BGP_TOTAL_ATTR_LEN + PSIZE (rn->p.prefixlen)))
paul718e3742002-12-13 20:15:29 +0000359 break;
360
361 if (stream_empty (s))
362 {
363 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000364 stream_putw (s, 0); /* unfeasible routes length */
paul718e3742002-12-13 20:15:29 +0000365 }
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000366 else
367 first_time = 0;
paul718e3742002-12-13 20:15:29 +0000368
369 if (afi == AFI_IP && safi == SAFI_UNICAST)
370 stream_put_prefix (s, &rn->p);
371 else
372 {
Paul Jakmaa3b6ea52006-05-04 07:52:12 +0000373 struct prefix_rd *prd = NULL;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000374
Paul Jakmaa3b6ea52006-05-04 07:52:12 +0000375 if (rn->prn)
376 prd = (struct prefix_rd *) &rn->prn->p;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000377
378 /* If first time, format the MP_UNREACH header */
379 if (first_time)
380 {
381 attrlen_pos = stream_get_endp (s);
382 /* total attr length = 0 for now. reevaluate later */
383 stream_putw (s, 0);
384 mp_start = stream_get_endp (s);
385 mplen_pos = bgp_packet_mpunreach_start(s, afi, safi);
386 }
387
388 bgp_packet_mpunreach_prefix(s, &rn->p, afi, safi, prd, NULL);
paul718e3742002-12-13 20:15:29 +0000389 }
390
391 if (BGP_DEBUG (update, UPDATE_OUT))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000392 {
393 char buf[INET6_BUFSIZ];
394
395 zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d -- unreachable",
396 peer->host,
397 inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ),
398 rn->p.prefixlen);
399 }
paul718e3742002-12-13 20:15:29 +0000400
401 peer->scount[afi][safi]--;
402
403 bgp_adj_out_remove (rn, adj, peer, afi, safi);
404 bgp_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +0000405 }
406
407 if (! stream_empty (s))
408 {
409 if (afi == AFI_IP && safi == SAFI_UNICAST)
410 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000411 unfeasible_len
paul9985f832005-02-09 15:51:56 +0000412 = stream_get_endp (s) - BGP_HEADER_SIZE - BGP_UNFEASIBLE_LEN;
paul718e3742002-12-13 20:15:29 +0000413 stream_putw_at (s, BGP_HEADER_SIZE, unfeasible_len);
414 stream_putw (s, 0);
415 }
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000416 else
417 {
418 /* Set the mp_unreach attr's length */
419 bgp_packet_mpunreach_end(s, mplen_pos);
420
421 /* Set total path attribute length. */
422 total_attr_len = stream_get_endp(s) - mp_start;
423 stream_putw_at (s, attrlen_pos, total_attr_len);
424 }
paul718e3742002-12-13 20:15:29 +0000425 bgp_packet_set_size (s);
paule83e2082005-05-19 02:12:25 +0000426 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +0000427 bgp_packet_add (peer, packet);
428 stream_reset (s);
429 return packet;
430 }
431
432 return NULL;
433}
434
435void
436bgp_default_update_send (struct peer *peer, struct attr *attr,
437 afi_t afi, safi_t safi, struct peer *from)
438{
439 struct stream *s;
paul718e3742002-12-13 20:15:29 +0000440 struct prefix p;
441 unsigned long pos;
442 bgp_size_t total_attr_len;
paul718e3742002-12-13 20:15:29 +0000443
Paul Jakma750e8142008-07-22 21:11:48 +0000444 if (DISABLE_BGP_ANNOUNCE)
445 return;
paul718e3742002-12-13 20:15:29 +0000446
447 if (afi == AFI_IP)
448 str2prefix ("0.0.0.0/0", &p);
449#ifdef HAVE_IPV6
450 else
451 str2prefix ("::/0", &p);
452#endif /* HAVE_IPV6 */
453
454 /* Logging the attribute. */
455 if (BGP_DEBUG (update, UPDATE_OUT))
456 {
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000457 char attrstr[BUFSIZ];
458 char buf[INET6_BUFSIZ];
459 attrstr[0] = '\0';
460
paul718e3742002-12-13 20:15:29 +0000461 bgp_dump_attr (peer, attr, attrstr, BUFSIZ);
ajs6b514742004-12-08 21:03:23 +0000462 zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d %s",
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000463 peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ),
paul718e3742002-12-13 20:15:29 +0000464 p.prefixlen, attrstr);
465 }
466
467 s = stream_new (BGP_MAX_PACKET_SIZE);
468
469 /* Make BGP update packet. */
470 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
471
472 /* Unfeasible Routes Length. */
473 stream_putw (s, 0);
474
475 /* Make place for total attribute length. */
paul9985f832005-02-09 15:51:56 +0000476 pos = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000477 stream_putw (s, 0);
478 total_attr_len = bgp_packet_attribute (NULL, peer, s, attr, &p, afi, safi, from, NULL, NULL);
479
480 /* Set Total Path Attribute Length. */
481 stream_putw_at (s, pos, total_attr_len);
482
483 /* NLRI set. */
484 if (p.family == AF_INET && safi == SAFI_UNICAST)
485 stream_put_prefix (s, &p);
486
487 /* Set size. */
488 bgp_packet_set_size (s);
489
paul718e3742002-12-13 20:15:29 +0000490 /* Dump packet if debug option is set. */
491#ifdef DEBUG
jardin2d74db52005-10-01 00:07:50 +0000492 /* bgp_packet_dump (packet); */
paul718e3742002-12-13 20:15:29 +0000493#endif /* DEBUG */
494
495 /* Add packet to the peer. */
Donald Sharpa752c3b2015-08-18 08:48:53 -0400496 bgp_packet_add (peer, s);
paul718e3742002-12-13 20:15:29 +0000497
pauleb821182004-05-01 08:44:08 +0000498 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000499}
500
501void
502bgp_default_withdraw_send (struct peer *peer, afi_t afi, safi_t safi)
503{
504 struct stream *s;
paul718e3742002-12-13 20:15:29 +0000505 struct prefix p;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000506 unsigned long attrlen_pos = 0;
paul718e3742002-12-13 20:15:29 +0000507 unsigned long cp;
508 bgp_size_t unfeasible_len;
509 bgp_size_t total_attr_len;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000510 size_t mp_start = 0;
511 size_t mplen_pos = 0;
paul718e3742002-12-13 20:15:29 +0000512
Paul Jakma750e8142008-07-22 21:11:48 +0000513 if (DISABLE_BGP_ANNOUNCE)
514 return;
paul718e3742002-12-13 20:15:29 +0000515
516 if (afi == AFI_IP)
517 str2prefix ("0.0.0.0/0", &p);
518#ifdef HAVE_IPV6
519 else
520 str2prefix ("::/0", &p);
521#endif /* HAVE_IPV6 */
522
523 total_attr_len = 0;
paul718e3742002-12-13 20:15:29 +0000524
525 if (BGP_DEBUG (update, UPDATE_OUT))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000526 {
527 char buf[INET6_BUFSIZ];
528
529 zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d -- unreachable",
530 peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ),
531 p.prefixlen);
532 }
paul718e3742002-12-13 20:15:29 +0000533
534 s = stream_new (BGP_MAX_PACKET_SIZE);
535
536 /* Make BGP update packet. */
537 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
538
539 /* Unfeasible Routes Length. */;
paul9985f832005-02-09 15:51:56 +0000540 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000541 stream_putw (s, 0);
542
543 /* Withdrawn Routes. */
544 if (p.family == AF_INET && safi == SAFI_UNICAST)
545 {
546 stream_put_prefix (s, &p);
547
paul9985f832005-02-09 15:51:56 +0000548 unfeasible_len = stream_get_endp (s) - cp - 2;
paul718e3742002-12-13 20:15:29 +0000549
550 /* Set unfeasible len. */
551 stream_putw_at (s, cp, unfeasible_len);
552
553 /* Set total path attribute length. */
554 stream_putw (s, 0);
555 }
556 else
557 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000558 attrlen_pos = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000559 stream_putw (s, 0);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000560 mp_start = stream_get_endp (s);
561 mplen_pos = bgp_packet_mpunreach_start(s, afi, safi);
562 bgp_packet_mpunreach_prefix(s, &p, afi, safi, NULL, NULL);
563
564 /* Set the mp_unreach attr's length */
565 bgp_packet_mpunreach_end(s, mplen_pos);
paul718e3742002-12-13 20:15:29 +0000566
567 /* Set total path attribute length. */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000568 total_attr_len = stream_get_endp(s) - mp_start;
569 stream_putw_at (s, attrlen_pos, total_attr_len);
paul718e3742002-12-13 20:15:29 +0000570 }
571
572 bgp_packet_set_size (s);
573
paul718e3742002-12-13 20:15:29 +0000574 /* Add packet to the peer. */
Donald Sharpa752c3b2015-08-18 08:48:53 -0400575 bgp_packet_add (peer, s);
paul718e3742002-12-13 20:15:29 +0000576
pauleb821182004-05-01 08:44:08 +0000577 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000578}
579
580/* Get next packet to be written. */
paul94f2b392005-06-28 12:44:16 +0000581static struct stream *
paul718e3742002-12-13 20:15:29 +0000582bgp_write_packet (struct peer *peer)
583{
584 afi_t afi;
585 safi_t safi;
586 struct stream *s = NULL;
587 struct bgp_advertise *adv;
588
589 s = stream_fifo_head (peer->obuf);
590 if (s)
591 return s;
592
593 for (afi = AFI_IP; afi < AFI_MAX; afi++)
594 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
595 {
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100596 adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->withdraw);
paul718e3742002-12-13 20:15:29 +0000597 if (adv)
598 {
599 s = bgp_withdraw_packet (peer, afi, safi);
600 if (s)
601 return s;
602 }
603 }
604
605 for (afi = AFI_IP; afi < AFI_MAX; afi++)
606 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
607 {
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100608 adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->update);
paul718e3742002-12-13 20:15:29 +0000609 if (adv)
610 {
611 if (adv->binfo && adv->binfo->uptime < peer->synctime)
hasso93406d82005-02-02 14:40:33 +0000612 {
613 if (CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_RCV)
614 && CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_ADV)
Vipin Kumardd49eb12014-09-30 14:36:38 -0700615 && ! (CHECK_FLAG (adv->binfo->peer->cap,
616 PEER_CAP_RESTART_BIT_RCV) &&
617 CHECK_FLAG (adv->binfo->peer->cap,
618 PEER_CAP_RESTART_BIT_ADV))
hasso93406d82005-02-02 14:40:33 +0000619 && ! CHECK_FLAG (adv->binfo->flags, BGP_INFO_STALE)
620 && safi != SAFI_MPLS_VPN)
621 {
622 if (CHECK_FLAG (adv->binfo->peer->af_sflags[afi][safi],
623 PEER_STATUS_EOR_RECEIVED))
624 s = bgp_update_packet (peer, afi, safi);
625 }
626 else
627 s = bgp_update_packet (peer, afi, safi);
628 }
paul718e3742002-12-13 20:15:29 +0000629
630 if (s)
631 return s;
632 }
hasso93406d82005-02-02 14:40:33 +0000633
634 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV))
635 {
636 if (peer->afc_nego[afi][safi] && peer->synctime
637 && ! CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND)
638 && safi != SAFI_MPLS_VPN)
639 {
640 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND);
641 return bgp_update_packet_eor (peer, afi, safi);
642 }
643 }
paul718e3742002-12-13 20:15:29 +0000644 }
645
646 return NULL;
647}
648
649/* Is there partially written packet or updates we can send right
650 now. */
paul94f2b392005-06-28 12:44:16 +0000651static int
paul718e3742002-12-13 20:15:29 +0000652bgp_write_proceed (struct peer *peer)
653{
654 afi_t afi;
655 safi_t safi;
656 struct bgp_advertise *adv;
657
658 if (stream_fifo_head (peer->obuf))
659 return 1;
660
661 for (afi = AFI_IP; afi < AFI_MAX; afi++)
662 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
663 if (FIFO_HEAD (&peer->sync[afi][safi]->withdraw))
664 return 1;
665
666 for (afi = AFI_IP; afi < AFI_MAX; afi++)
667 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100668 if ((adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->update)) != NULL)
paul718e3742002-12-13 20:15:29 +0000669 if (adv->binfo->uptime < peer->synctime)
670 return 1;
671
672 return 0;
673}
674
675/* Write packet to the peer. */
676int
677bgp_write (struct thread *thread)
678{
679 struct peer *peer;
680 u_char type;
681 struct stream *s;
682 int num;
paulfd79ac92004-10-13 05:06:08 +0000683 unsigned int count = 0;
paul718e3742002-12-13 20:15:29 +0000684
685 /* Yes first of all get peer pointer. */
686 peer = THREAD_ARG (thread);
687 peer->t_write = NULL;
688
689 /* For non-blocking IO check. */
690 if (peer->status == Connect)
691 {
692 bgp_connect_check (peer);
693 return 0;
694 }
695
Stephen Hemmingereac57022010-08-05 10:26:25 -0700696 s = bgp_write_packet (peer);
697 if (!s)
698 return 0; /* nothing to send */
699
700 sockopt_cork (peer->fd, 1);
701
702 /* Nonblocking write until TCP output buffer is full. */
703 do
paul718e3742002-12-13 20:15:29 +0000704 {
705 int writenum;
paul718e3742002-12-13 20:15:29 +0000706
707 /* Number of bytes to be sent. */
708 writenum = stream_get_endp (s) - stream_get_getp (s);
709
710 /* Call write() system call. */
pauleb821182004-05-01 08:44:08 +0000711 num = write (peer->fd, STREAM_PNT (s), writenum);
Stephen Hemminger35398582010-08-05 10:26:23 -0700712 if (num < 0)
paul718e3742002-12-13 20:15:29 +0000713 {
Stephen Hemmingereac57022010-08-05 10:26:25 -0700714 /* write failed either retry needed or error */
715 if (ERRNO_IO_RETRY(errno))
716 break;
717
718 BGP_EVENT_ADD (peer, TCP_fatal_error);
paul718e3742002-12-13 20:15:29 +0000719 return 0;
720 }
Stephen Hemminger35398582010-08-05 10:26:23 -0700721
paul718e3742002-12-13 20:15:29 +0000722 if (num != writenum)
723 {
Stephen Hemminger35398582010-08-05 10:26:23 -0700724 /* Partial write */
paul9985f832005-02-09 15:51:56 +0000725 stream_forward_getp (s, num);
Stephen Hemmingereac57022010-08-05 10:26:25 -0700726 break;
paul718e3742002-12-13 20:15:29 +0000727 }
728
729 /* Retrieve BGP packet type. */
730 stream_set_getp (s, BGP_MARKER_SIZE + 2);
731 type = stream_getc (s);
732
733 switch (type)
734 {
735 case BGP_MSG_OPEN:
736 peer->open_out++;
737 break;
738 case BGP_MSG_UPDATE:
739 peer->update_out++;
740 break;
741 case BGP_MSG_NOTIFY:
742 peer->notify_out++;
743 /* Double start timer. */
744 peer->v_start *= 2;
745
746 /* Overflow check. */
747 if (peer->v_start >= (60 * 2))
748 peer->v_start = (60 * 2);
749
Paul Jakmaca058a32006-09-14 02:58:49 +0000750 /* Flush any existing events */
Paul Jakmadcdf3992006-10-15 23:39:59 +0000751 BGP_EVENT_ADD (peer, BGP_Stop);
Stephen Hemminger3a69f742013-01-11 18:27:23 +0000752 goto done;
753
paul718e3742002-12-13 20:15:29 +0000754 case BGP_MSG_KEEPALIVE:
755 peer->keepalive_out++;
756 break;
757 case BGP_MSG_ROUTE_REFRESH_NEW:
758 case BGP_MSG_ROUTE_REFRESH_OLD:
759 peer->refresh_out++;
760 break;
761 case BGP_MSG_CAPABILITY:
762 peer->dynamic_cap_out++;
763 break;
764 }
765
766 /* OK we send packet so delete it. */
767 bgp_packet_delete (peer);
paul718e3742002-12-13 20:15:29 +0000768 }
Stephen Hemmingereac57022010-08-05 10:26:25 -0700769 while (++count < BGP_WRITE_PACKET_MAX &&
770 (s = bgp_write_packet (peer)) != NULL);
paul718e3742002-12-13 20:15:29 +0000771
772 if (bgp_write_proceed (peer))
pauleb821182004-05-01 08:44:08 +0000773 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
Stephen Hemminger3a69f742013-01-11 18:27:23 +0000774
775 done:
776 sockopt_cork (peer->fd, 0);
paul718e3742002-12-13 20:15:29 +0000777 return 0;
778}
779
780/* This is only for sending NOTIFICATION message to neighbor. */
paul94f2b392005-06-28 12:44:16 +0000781static int
paul718e3742002-12-13 20:15:29 +0000782bgp_write_notify (struct peer *peer)
783{
Stephen Hemminger35398582010-08-05 10:26:23 -0700784 int ret, val;
paul718e3742002-12-13 20:15:29 +0000785 u_char type;
786 struct stream *s;
787
788 /* There should be at least one packet. */
789 s = stream_fifo_head (peer->obuf);
790 if (!s)
791 return 0;
792 assert (stream_get_endp (s) >= BGP_HEADER_SIZE);
793
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000794 /* Stop collecting data within the socket */
795 sockopt_cork (peer->fd, 0);
796
David Lamparter8ff202e2013-07-31 14:39:41 +0200797 /* socket is in nonblocking mode, if we can't deliver the NOTIFY, well,
798 * we only care about getting a clean shutdown at this point. */
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000799 ret = write (peer->fd, STREAM_DATA (s), stream_get_endp (s));
David Lamparter8ff202e2013-07-31 14:39:41 +0200800
801 /* only connection reset/close gets counted as TCP_fatal_error, failure
802 * to write the entire NOTIFY doesn't get different FSM treatment */
paul718e3742002-12-13 20:15:29 +0000803 if (ret <= 0)
804 {
Paul Jakmadcdf3992006-10-15 23:39:59 +0000805 BGP_EVENT_ADD (peer, TCP_fatal_error);
paul718e3742002-12-13 20:15:29 +0000806 return 0;
807 }
808
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000809 /* Disable Nagle, make NOTIFY packet go out right away */
810 val = 1;
811 (void) setsockopt (peer->fd, IPPROTO_TCP, TCP_NODELAY,
812 (char *) &val, sizeof (val));
813
paul718e3742002-12-13 20:15:29 +0000814 /* Retrieve BGP packet type. */
815 stream_set_getp (s, BGP_MARKER_SIZE + 2);
816 type = stream_getc (s);
817
818 assert (type == BGP_MSG_NOTIFY);
819
820 /* Type should be notify. */
821 peer->notify_out++;
822
823 /* Double start timer. */
824 peer->v_start *= 2;
825
826 /* Overflow check. */
827 if (peer->v_start >= (60 * 2))
828 peer->v_start = (60 * 2);
829
Paul Jakmadcdf3992006-10-15 23:39:59 +0000830 BGP_EVENT_ADD (peer, BGP_Stop);
paul718e3742002-12-13 20:15:29 +0000831
832 return 0;
833}
834
835/* Make keepalive packet and send it to the peer. */
836void
837bgp_keepalive_send (struct peer *peer)
838{
839 struct stream *s;
840 int length;
841
842 s = stream_new (BGP_MAX_PACKET_SIZE);
843
844 /* Make keepalive packet. */
845 bgp_packet_set_marker (s, BGP_MSG_KEEPALIVE);
846
847 /* Set packet size. */
848 length = bgp_packet_set_size (s);
849
850 /* Dump packet if debug option is set. */
851 /* bgp_packet_dump (s); */
852
853 if (BGP_DEBUG (keepalive, KEEPALIVE))
ajs6b514742004-12-08 21:03:23 +0000854 zlog_debug ("%s sending KEEPALIVE", peer->host);
paul718e3742002-12-13 20:15:29 +0000855 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000856 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000857 peer->host, BGP_MSG_KEEPALIVE, length);
858
859 /* Add packet to the peer. */
860 bgp_packet_add (peer, s);
861
pauleb821182004-05-01 08:44:08 +0000862 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000863}
864
865/* Make open packet and send it to the peer. */
866void
867bgp_open_send (struct peer *peer)
868{
869 struct stream *s;
870 int length;
871 u_int16_t send_holdtime;
872 as_t local_as;
873
874 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
875 send_holdtime = peer->holdtime;
876 else
877 send_holdtime = peer->bgp->default_holdtime;
878
879 /* local-as Change */
880 if (peer->change_local_as)
881 local_as = peer->change_local_as;
882 else
883 local_as = peer->local_as;
884
885 s = stream_new (BGP_MAX_PACKET_SIZE);
886
887 /* Make open packet. */
888 bgp_packet_set_marker (s, BGP_MSG_OPEN);
889
890 /* Set open packet values. */
891 stream_putc (s, BGP_VERSION_4); /* BGP version */
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000892 stream_putw (s, (local_as <= BGP_AS_MAX) ? (u_int16_t) local_as
893 : BGP_AS_TRANS);
paul718e3742002-12-13 20:15:29 +0000894 stream_putw (s, send_holdtime); /* Hold Time */
895 stream_put_in_addr (s, &peer->local_id); /* BGP Identifier */
896
897 /* Set capability code. */
898 bgp_open_capability (s, peer);
899
900 /* Set BGP packet length. */
901 length = bgp_packet_set_size (s);
902
903 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +0400904 zlog_debug ("%s sending OPEN, version %d, my as %u, holdtime %d, id %s",
paul718e3742002-12-13 20:15:29 +0000905 peer->host, BGP_VERSION_4, local_as,
906 send_holdtime, inet_ntoa (peer->local_id));
907
908 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000909 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000910 peer->host, BGP_MSG_OPEN, length);
911
912 /* Dump packet if debug option is set. */
913 /* bgp_packet_dump (s); */
914
915 /* Add packet to the peer. */
916 bgp_packet_add (peer, s);
917
pauleb821182004-05-01 08:44:08 +0000918 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000919}
920
921/* Send BGP notify packet with data potion. */
922void
923bgp_notify_send_with_data (struct peer *peer, u_char code, u_char sub_code,
924 u_char *data, size_t datalen)
925{
926 struct stream *s;
927 int length;
928
929 /* Allocate new stream. */
930 s = stream_new (BGP_MAX_PACKET_SIZE);
931
932 /* Make nitify packet. */
933 bgp_packet_set_marker (s, BGP_MSG_NOTIFY);
934
935 /* Set notify packet values. */
936 stream_putc (s, code); /* BGP notify code */
937 stream_putc (s, sub_code); /* BGP notify sub_code */
938
939 /* If notify data is present. */
940 if (data)
941 stream_write (s, data, datalen);
942
943 /* Set BGP packet length. */
944 length = bgp_packet_set_size (s);
945
946 /* Add packet to the peer. */
947 stream_fifo_clean (peer->obuf);
948 bgp_packet_add (peer, s);
949
950 /* For debug */
951 {
952 struct bgp_notify bgp_notify;
953 int first = 0;
954 int i;
955 char c[4];
956
957 bgp_notify.code = code;
958 bgp_notify.subcode = sub_code;
959 bgp_notify.data = NULL;
960 bgp_notify.length = length - BGP_MSG_NOTIFY_MIN_SIZE;
961
962 if (bgp_notify.length)
963 {
964 bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
965 for (i = 0; i < bgp_notify.length; i++)
966 if (first)
967 {
968 sprintf (c, " %02x", data[i]);
969 strcat (bgp_notify.data, c);
970 }
971 else
972 {
973 first = 1;
974 sprintf (c, "%02x", data[i]);
975 strcpy (bgp_notify.data, c);
976 }
977 }
978 bgp_notify_print (peer, &bgp_notify, "sending");
Daniel Walton363c9032015-10-21 06:42:54 -0700979
paul718e3742002-12-13 20:15:29 +0000980 if (bgp_notify.data)
Daniel Walton363c9032015-10-21 06:42:54 -0700981 {
982 XFREE (MTYPE_TMP, bgp_notify.data);
983 bgp_notify.data = NULL;
984 bgp_notify.length = 0;
985 }
paul718e3742002-12-13 20:15:29 +0000986 }
987
988 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000989 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000990 peer->host, BGP_MSG_NOTIFY, length);
991
hassoe0701b72004-05-20 09:19:34 +0000992 /* peer reset cause */
993 if (sub_code != BGP_NOTIFY_CEASE_CONFIG_CHANGE)
994 {
995 if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET)
heasley1212dc12011-09-12 13:27:52 +0400996 {
997 peer->last_reset = PEER_DOWN_USER_RESET;
998 zlog_info ("Notification sent to neighbor %s: User reset", peer->host);
999 }
hassoe0701b72004-05-20 09:19:34 +00001000 else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN)
heasley1212dc12011-09-12 13:27:52 +04001001 {
1002 peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
1003 zlog_info ("Notification sent to neighbor %s: shutdown", peer->host);
1004 }
hassoe0701b72004-05-20 09:19:34 +00001005 else
heasley1212dc12011-09-12 13:27:52 +04001006 {
1007 peer->last_reset = PEER_DOWN_NOTIFY_SEND;
1008 zlog_info ("Notification sent to neighbor %s: type %u/%u",
1009 peer->host, code, sub_code);
1010 }
hassoe0701b72004-05-20 09:19:34 +00001011 }
heasley1212dc12011-09-12 13:27:52 +04001012 else
1013 zlog_info ("Notification sent to neighbor %s: configuration change",
1014 peer->host);
hassoe0701b72004-05-20 09:19:34 +00001015
Denis Ovsienko7ccf5e52011-09-10 16:53:30 +04001016 /* Call immediately. */
paul718e3742002-12-13 20:15:29 +00001017 BGP_WRITE_OFF (peer->t_write);
1018
1019 bgp_write_notify (peer);
1020}
1021
1022/* Send BGP notify packet. */
1023void
1024bgp_notify_send (struct peer *peer, u_char code, u_char sub_code)
1025{
1026 bgp_notify_send_with_data (peer, code, sub_code, NULL, 0);
1027}
1028
paul718e3742002-12-13 20:15:29 +00001029/* Send route refresh message to the peer. */
1030void
1031bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
1032 u_char orf_type, u_char when_to_refresh, int remove)
1033{
1034 struct stream *s;
paul718e3742002-12-13 20:15:29 +00001035 int length;
1036 struct bgp_filter *filter;
1037 int orf_refresh = 0;
1038
Paul Jakma750e8142008-07-22 21:11:48 +00001039 if (DISABLE_BGP_ANNOUNCE)
1040 return;
paul718e3742002-12-13 20:15:29 +00001041
1042 filter = &peer->filter[afi][safi];
1043
1044 /* Adjust safi code. */
1045 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001046 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +00001047
1048 s = stream_new (BGP_MAX_PACKET_SIZE);
1049
1050 /* Make BGP update packet. */
1051 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
1052 bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_NEW);
1053 else
1054 bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_OLD);
1055
1056 /* Encode Route Refresh message. */
1057 stream_putw (s, afi);
1058 stream_putc (s, 0);
1059 stream_putc (s, safi);
1060
1061 if (orf_type == ORF_TYPE_PREFIX
1062 || orf_type == ORF_TYPE_PREFIX_OLD)
1063 if (remove || filter->plist[FILTER_IN].plist)
1064 {
1065 u_int16_t orf_len;
1066 unsigned long orfp;
1067
1068 orf_refresh = 1;
1069 stream_putc (s, when_to_refresh);
1070 stream_putc (s, orf_type);
paul9985f832005-02-09 15:51:56 +00001071 orfp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00001072 stream_putw (s, 0);
1073
1074 if (remove)
1075 {
1076 UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
1077 stream_putc (s, ORF_COMMON_PART_REMOVE_ALL);
1078 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001079 zlog_debug ("%s sending REFRESH_REQ to remove ORF(%d) (%s) for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001080 peer->host, orf_type,
1081 (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
1082 afi, safi);
1083 }
1084 else
1085 {
1086 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
1087 prefix_bgp_orf_entry (s, filter->plist[FILTER_IN].plist,
1088 ORF_COMMON_PART_ADD, ORF_COMMON_PART_PERMIT,
1089 ORF_COMMON_PART_DENY);
1090 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001091 zlog_debug ("%s sending REFRESH_REQ with pfxlist ORF(%d) (%s) for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001092 peer->host, orf_type,
1093 (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
1094 afi, safi);
1095 }
1096
1097 /* Total ORF Entry Len. */
paul9985f832005-02-09 15:51:56 +00001098 orf_len = stream_get_endp (s) - orfp - 2;
paul718e3742002-12-13 20:15:29 +00001099 stream_putw_at (s, orfp, orf_len);
1100 }
1101
1102 /* Set packet size. */
1103 length = bgp_packet_set_size (s);
1104
1105 if (BGP_DEBUG (normal, NORMAL))
1106 {
1107 if (! orf_refresh)
ajs6b514742004-12-08 21:03:23 +00001108 zlog_debug ("%s sending REFRESH_REQ for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001109 peer->host, afi, safi);
ajs6b514742004-12-08 21:03:23 +00001110 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +00001111 peer->host, CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV) ?
1112 BGP_MSG_ROUTE_REFRESH_NEW : BGP_MSG_ROUTE_REFRESH_OLD, length);
1113 }
1114
paul718e3742002-12-13 20:15:29 +00001115 /* Add packet to the peer. */
Donald Sharpa752c3b2015-08-18 08:48:53 -04001116 bgp_packet_add (peer, s);
paul718e3742002-12-13 20:15:29 +00001117
pauleb821182004-05-01 08:44:08 +00001118 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +00001119}
1120
1121/* Send capability message to the peer. */
1122void
1123bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi,
1124 int capability_code, int action)
1125{
1126 struct stream *s;
paul718e3742002-12-13 20:15:29 +00001127 int length;
1128
1129 /* Adjust safi code. */
1130 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001131 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +00001132
1133 s = stream_new (BGP_MAX_PACKET_SIZE);
1134
1135 /* Make BGP update packet. */
1136 bgp_packet_set_marker (s, BGP_MSG_CAPABILITY);
1137
1138 /* Encode MP_EXT capability. */
1139 if (capability_code == CAPABILITY_CODE_MP)
1140 {
1141 stream_putc (s, action);
1142 stream_putc (s, CAPABILITY_CODE_MP);
1143 stream_putc (s, CAPABILITY_CODE_MP_LEN);
1144 stream_putw (s, afi);
1145 stream_putc (s, 0);
1146 stream_putc (s, safi);
1147
1148 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001149 zlog_debug ("%s sending CAPABILITY has %s MP_EXT CAP for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001150 peer->host, action == CAPABILITY_ACTION_SET ?
1151 "Advertising" : "Removing", afi, safi);
1152 }
1153
paul718e3742002-12-13 20:15:29 +00001154 /* Set packet size. */
1155 length = bgp_packet_set_size (s);
1156
paul718e3742002-12-13 20:15:29 +00001157
1158 /* Add packet to the peer. */
Donald Sharpa752c3b2015-08-18 08:48:53 -04001159 bgp_packet_add (peer, s);
paul718e3742002-12-13 20:15:29 +00001160
1161 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001162 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +00001163 peer->host, BGP_MSG_CAPABILITY, length);
1164
pauleb821182004-05-01 08:44:08 +00001165 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +00001166}
David Lamparter6b0655a2014-06-04 06:53:35 +02001167
paul718e3742002-12-13 20:15:29 +00001168/* RFC1771 6.8 Connection collision detection. */
paul94f2b392005-06-28 12:44:16 +00001169static int
pauleb821182004-05-01 08:44:08 +00001170bgp_collision_detect (struct peer *new, struct in_addr remote_id)
paul718e3742002-12-13 20:15:29 +00001171{
pauleb821182004-05-01 08:44:08 +00001172 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001173 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001174 struct bgp *bgp;
1175
1176 bgp = bgp_get_default ();
1177 if (! bgp)
1178 return 0;
1179
1180 /* Upon receipt of an OPEN message, the local system must examine
1181 all of its connections that are in the OpenConfirm state. A BGP
1182 speaker may also examine connections in an OpenSent state if it
1183 knows the BGP Identifier of the peer by means outside of the
1184 protocol. If among these connections there is a connection to a
1185 remote BGP speaker whose BGP Identifier equals the one in the
1186 OPEN message, then the local system performs the following
1187 collision resolution procedure: */
1188
paul1eb8ef22005-04-07 07:30:20 +00001189 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001190 {
1191 /* Under OpenConfirm status, local peer structure already hold
1192 remote router ID. */
pauleb821182004-05-01 08:44:08 +00001193
1194 if (peer != new
1195 && (peer->status == OpenConfirm || peer->status == OpenSent)
1196 && sockunion_same (&peer->su, &new->su))
1197 {
paul718e3742002-12-13 20:15:29 +00001198 /* 1. The BGP Identifier of the local system is compared to
1199 the BGP Identifier of the remote system (as specified in
1200 the OPEN message). */
1201
1202 if (ntohl (peer->local_id.s_addr) < ntohl (remote_id.s_addr))
1203 {
1204 /* 2. If the value of the local BGP Identifier is less
1205 than the remote one, the local system closes BGP
1206 connection that already exists (the one that is
1207 already in the OpenConfirm state), and accepts BGP
1208 connection initiated by the remote system. */
1209
pauleb821182004-05-01 08:44:08 +00001210 if (peer->fd >= 0)
hassoe0701b72004-05-20 09:19:34 +00001211 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
paul718e3742002-12-13 20:15:29 +00001212 return 1;
1213 }
1214 else
1215 {
1216 /* 3. Otherwise, the local system closes newly created
1217 BGP connection (the one associated with the newly
1218 received OPEN message), and continues to use the
1219 existing one (the one that is already in the
1220 OpenConfirm state). */
1221
pauleb821182004-05-01 08:44:08 +00001222 if (new->fd >= 0)
paulf5ba3872004-07-09 12:11:31 +00001223 bgp_notify_send (new, BGP_NOTIFY_CEASE,
1224 BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
paul718e3742002-12-13 20:15:29 +00001225 return -1;
1226 }
pauleb821182004-05-01 08:44:08 +00001227 }
1228 }
paul718e3742002-12-13 20:15:29 +00001229 return 0;
1230}
1231
paul94f2b392005-06-28 12:44:16 +00001232static int
paul718e3742002-12-13 20:15:29 +00001233bgp_open_receive (struct peer *peer, bgp_size_t size)
1234{
1235 int ret;
1236 u_char version;
1237 u_char optlen;
1238 u_int16_t holdtime;
1239 u_int16_t send_holdtime;
1240 as_t remote_as;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001241 as_t as4 = 0;
paul718e3742002-12-13 20:15:29 +00001242 struct peer *realpeer;
1243 struct in_addr remote_id;
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001244 int mp_capability;
paul5228ad22004-06-04 17:58:18 +00001245 u_int8_t notify_data_remote_as[2];
1246 u_int8_t notify_data_remote_id[4];
paul718e3742002-12-13 20:15:29 +00001247
1248 realpeer = NULL;
1249
1250 /* Parse open packet. */
1251 version = stream_getc (peer->ibuf);
1252 memcpy (notify_data_remote_as, stream_pnt (peer->ibuf), 2);
1253 remote_as = stream_getw (peer->ibuf);
1254 holdtime = stream_getw (peer->ibuf);
1255 memcpy (notify_data_remote_id, stream_pnt (peer->ibuf), 4);
1256 remote_id.s_addr = stream_get_ipv4 (peer->ibuf);
1257
1258 /* Receive OPEN message log */
1259 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001260 zlog_debug ("%s rcv OPEN, version %d, remote-as (in open) %u,"
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001261 " holdtime %d, id %s",
1262 peer->host, version, remote_as, holdtime,
1263 inet_ntoa (remote_id));
1264
1265 /* BEGIN to read the capability here, but dont do it yet */
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001266 mp_capability = 0;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001267 optlen = stream_getc (peer->ibuf);
1268
1269 if (optlen != 0)
1270 {
1271 /* We need the as4 capability value *right now* because
1272 * if it is there, we have not got the remote_as yet, and without
1273 * that we do not know which peer is connecting to us now.
1274 */
1275 as4 = peek_for_as4_capability (peer, optlen);
1276 }
1277
1278 /* Just in case we have a silly peer who sends AS4 capability set to 0 */
1279 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) && !as4)
1280 {
1281 zlog_err ("%s bad OPEN, got AS4 capability, but AS4 set to 0",
1282 peer->host);
1283 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1284 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1285 return -1;
1286 }
1287
1288 if (remote_as == BGP_AS_TRANS)
1289 {
1290 /* Take the AS4 from the capability. We must have received the
1291 * capability now! Otherwise we have a asn16 peer who uses
1292 * BGP_AS_TRANS, for some unknown reason.
1293 */
1294 if (as4 == BGP_AS_TRANS)
1295 {
1296 zlog_err ("%s [AS4] NEW speaker using AS_TRANS for AS4, not allowed",
1297 peer->host);
1298 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1299 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1300 return -1;
1301 }
1302
1303 if (!as4 && BGP_DEBUG (as4, AS4))
1304 zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but no AS4."
1305 " Odd, but proceeding.", peer->host);
1306 else if (as4 < BGP_AS_MAX && BGP_DEBUG (as4, AS4))
Paul Jakma0df7c912008-07-21 21:02:49 +00001307 zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but AS4 (%u) fits "
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001308 "in 2-bytes, very odd peer.", peer->host, as4);
1309 if (as4)
1310 remote_as = as4;
1311 }
1312 else
1313 {
1314 /* We may have a partner with AS4 who has an asno < BGP_AS_MAX */
1315 /* If we have got the capability, peer->as4cap must match remote_as */
1316 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)
1317 && as4 != remote_as)
1318 {
1319 /* raise error, log this, close session */
1320 zlog_err ("%s bad OPEN, got AS4 capability, but remote_as %u"
1321 " mismatch with 16bit 'myasn' %u in open",
1322 peer->host, as4, remote_as);
1323 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1324 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1325 return -1;
1326 }
1327 }
1328
paul718e3742002-12-13 20:15:29 +00001329 /* Lookup peer from Open packet. */
1330 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1331 {
1332 int as = 0;
1333
1334 realpeer = peer_lookup_with_open (&peer->su, remote_as, &remote_id, &as);
1335
1336 if (! realpeer)
1337 {
1338 /* Peer's source IP address is check in bgp_accept(), so this
1339 must be AS number mismatch or remote-id configuration
1340 mismatch. */
1341 if (as)
1342 {
1343 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001344 zlog_debug ("%s bad OPEN, wrong router identifier %s",
1345 peer->host, inet_ntoa (remote_id));
1346 bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
1347 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
1348 notify_data_remote_id, 4);
paul718e3742002-12-13 20:15:29 +00001349 }
1350 else
1351 {
1352 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001353 zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
ajs6b514742004-12-08 21:03:23 +00001354 peer->host, remote_as, peer->as);
1355 bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
1356 BGP_NOTIFY_OPEN_BAD_PEER_AS,
1357 notify_data_remote_as, 2);
paul718e3742002-12-13 20:15:29 +00001358 }
1359 return -1;
1360 }
1361 }
1362
1363 /* When collision is detected and this peer is closed. Retrun
1364 immidiately. */
1365 ret = bgp_collision_detect (peer, remote_id);
1366 if (ret < 0)
1367 return ret;
1368
pauleb821182004-05-01 08:44:08 +00001369 /* Hack part. */
1370 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1371 {
hasso93406d82005-02-02 14:40:33 +00001372 if (realpeer->status == Established
1373 && CHECK_FLAG (realpeer->sflags, PEER_STATUS_NSF_MODE))
1374 {
1375 realpeer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
1376 SET_FLAG (realpeer->sflags, PEER_STATUS_NSF_WAIT);
1377 }
1378 else if (ret == 0 && realpeer->status != Active
1379 && realpeer->status != OpenSent
Paul Jakma6e199262008-09-09 17:14:33 +01001380 && realpeer->status != OpenConfirm
1381 && realpeer->status != Connect)
pauleb821182004-05-01 08:44:08 +00001382 {
Paul Jakma2b2fc562008-09-06 13:09:35 +01001383 /* XXX: This is an awful problem..
1384 *
1385 * According to the RFC we should just let this connection (of the
1386 * accepted 'peer') continue on to Established if the other
1387 * connection (the 'realpeer' one) is in state Connect, and deal
1388 * with the more larval FSM as/when it gets far enough to receive
1389 * an Open. We don't do that though, we instead close the (more
1390 * developed) accepted connection.
1391 *
1392 * This means there's a race, which if hit, can loop:
1393 *
1394 * FSM for A FSM for B
1395 * realpeer accept-peer realpeer accept-peer
1396 *
1397 * Connect Connect
1398 * Active
1399 * OpenSent OpenSent
1400 * <arrive here,
1401 * Notify, delete>
1402 * Idle Active
1403 * OpenSent OpenSent
1404 * <arrive here,
1405 * Notify, delete>
1406 * Idle
1407 * <wait> <wait>
1408 * Connect Connect
1409 *
1410 *
1411 * If both sides are Quagga, they're almost certain to wait for
1412 * the same amount of time of course (which doesn't preclude other
1413 * implementations also waiting for same time). The race is
1414 * exacerbated by high-latency (in bgpd and/or the network).
1415 *
1416 * The reason we do this is because our FSM is tied to our peer
1417 * structure, which carries our configuration information, etc.
1418 * I.e. we can't let the accepted-peer FSM continue on as it is,
1419 * cause it's not associated with any actual peer configuration -
1420 * it's just a dummy.
1421 *
1422 * It's possible we could hack-fix this by just bgp_stop'ing the
1423 * realpeer and continueing on with the 'transfer FSM' below.
1424 * Ideally, we need to seperate FSMs from struct peer.
1425 *
1426 * Setting one side to passive avoids the race, as a workaround.
1427 */
pauleb821182004-05-01 08:44:08 +00001428 if (BGP_DEBUG (events, EVENTS))
hasso93406d82005-02-02 14:40:33 +00001429 zlog_debug ("%s peer status is %s close connection",
1430 realpeer->host, LOOKUP (bgp_status_msg,
1431 realpeer->status));
1432 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1433 BGP_NOTIFY_CEASE_CONNECT_REJECT);
1434
pauleb821182004-05-01 08:44:08 +00001435 return -1;
1436 }
1437
1438 if (BGP_DEBUG (events, EVENTS))
Paul Jakma6e199262008-09-09 17:14:33 +01001439 zlog_debug ("%s [Event] Transfer accept BGP peer to real (state %s)",
1440 peer->host,
1441 LOOKUP (bgp_status_msg, realpeer->status));
pauleb821182004-05-01 08:44:08 +00001442
1443 bgp_stop (realpeer);
1444
1445 /* Transfer file descriptor. */
1446 realpeer->fd = peer->fd;
1447 peer->fd = -1;
1448
1449 /* Transfer input buffer. */
1450 stream_free (realpeer->ibuf);
1451 realpeer->ibuf = peer->ibuf;
1452 realpeer->packet_size = peer->packet_size;
1453 peer->ibuf = NULL;
1454
1455 /* Transfer status. */
1456 realpeer->status = peer->status;
1457 bgp_stop (peer);
paul200df112005-06-01 11:17:05 +00001458
pauleb821182004-05-01 08:44:08 +00001459 /* peer pointer change. Open packet send to neighbor. */
1460 peer = realpeer;
1461 bgp_open_send (peer);
1462 if (peer->fd < 0)
1463 {
1464 zlog_err ("bgp_open_receive peer's fd is negative value %d",
1465 peer->fd);
1466 return -1;
1467 }
1468 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
1469 }
1470
paul718e3742002-12-13 20:15:29 +00001471 /* remote router-id check. */
1472 if (remote_id.s_addr == 0
Denis Ovsienko733cd9e2011-12-17 19:39:30 +04001473 || IPV4_CLASS_DE (ntohl (remote_id.s_addr))
paul718e3742002-12-13 20:15:29 +00001474 || ntohl (peer->local_id.s_addr) == ntohl (remote_id.s_addr))
1475 {
1476 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001477 zlog_debug ("%s bad OPEN, wrong router identifier %s",
paul718e3742002-12-13 20:15:29 +00001478 peer->host, inet_ntoa (remote_id));
1479 bgp_notify_send_with_data (peer,
1480 BGP_NOTIFY_OPEN_ERR,
1481 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
1482 notify_data_remote_id, 4);
1483 return -1;
1484 }
1485
1486 /* Set remote router-id */
1487 peer->remote_id = remote_id;
1488
1489 /* Peer BGP version check. */
1490 if (version != BGP_VERSION_4)
1491 {
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001492 u_int16_t maxver = htons(BGP_VERSION_4);
1493 /* XXX this reply may not be correct if version < 4 XXX */
paul718e3742002-12-13 20:15:29 +00001494 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001495 zlog_debug ("%s bad protocol version, remote requested %d, local request %d",
paul718e3742002-12-13 20:15:29 +00001496 peer->host, version, BGP_VERSION_4);
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001497 /* Data must be in network byte order here */
paul718e3742002-12-13 20:15:29 +00001498 bgp_notify_send_with_data (peer,
1499 BGP_NOTIFY_OPEN_ERR,
1500 BGP_NOTIFY_OPEN_UNSUP_VERSION,
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001501 (u_int8_t *) &maxver, 2);
paul718e3742002-12-13 20:15:29 +00001502 return -1;
1503 }
1504
1505 /* Check neighbor as number. */
1506 if (remote_as != peer->as)
1507 {
1508 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001509 zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
paul718e3742002-12-13 20:15:29 +00001510 peer->host, remote_as, peer->as);
1511 bgp_notify_send_with_data (peer,
1512 BGP_NOTIFY_OPEN_ERR,
1513 BGP_NOTIFY_OPEN_BAD_PEER_AS,
1514 notify_data_remote_as, 2);
1515 return -1;
1516 }
1517
1518 /* From the rfc: Upon receipt of an OPEN message, a BGP speaker MUST
1519 calculate the value of the Hold Timer by using the smaller of its
1520 configured Hold Time and the Hold Time received in the OPEN message.
1521 The Hold Time MUST be either zero or at least three seconds. An
1522 implementation may reject connections on the basis of the Hold Time. */
1523
1524 if (holdtime < 3 && holdtime != 0)
1525 {
1526 bgp_notify_send (peer,
1527 BGP_NOTIFY_OPEN_ERR,
1528 BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
1529 return -1;
1530 }
1531
1532 /* From the rfc: A reasonable maximum time between KEEPALIVE messages
1533 would be one third of the Hold Time interval. KEEPALIVE messages
1534 MUST NOT be sent more frequently than one per second. An
1535 implementation MAY adjust the rate at which it sends KEEPALIVE
1536 messages as a function of the Hold Time interval. */
1537
1538 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
1539 send_holdtime = peer->holdtime;
1540 else
1541 send_holdtime = peer->bgp->default_holdtime;
1542
1543 if (holdtime < send_holdtime)
1544 peer->v_holdtime = holdtime;
1545 else
1546 peer->v_holdtime = send_holdtime;
1547
1548 peer->v_keepalive = peer->v_holdtime / 3;
1549
1550 /* Open option part parse. */
paul718e3742002-12-13 20:15:29 +00001551 if (optlen != 0)
1552 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001553 if ((ret = bgp_open_option_parse (peer, optlen, &mp_capability)) < 0)
Paul Jakma58617392012-01-09 20:59:26 +00001554 {
1555 bgp_notify_send (peer,
1556 BGP_NOTIFY_OPEN_ERR,
Paul Jakma68ec4242015-11-25 17:14:34 +00001557 BGP_NOTIFY_OPEN_UNSPECIFIC);
Paul Jakma58617392012-01-09 20:59:26 +00001558 return ret;
1559 }
paul718e3742002-12-13 20:15:29 +00001560 }
1561 else
1562 {
1563 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001564 zlog_debug ("%s rcvd OPEN w/ OPTION parameter len: 0",
paul718e3742002-12-13 20:15:29 +00001565 peer->host);
1566 }
1567
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001568 /*
1569 * Assume that the peer supports the locally configured set of
1570 * AFI/SAFIs if the peer did not send us any Mulitiprotocol
1571 * capabilities, or if 'override-capability' is configured.
1572 */
1573 if (! mp_capability ||
1574 CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
paul718e3742002-12-13 20:15:29 +00001575 {
1576 peer->afc_nego[AFI_IP][SAFI_UNICAST] = peer->afc[AFI_IP][SAFI_UNICAST];
1577 peer->afc_nego[AFI_IP][SAFI_MULTICAST] = peer->afc[AFI_IP][SAFI_MULTICAST];
1578 peer->afc_nego[AFI_IP6][SAFI_UNICAST] = peer->afc[AFI_IP6][SAFI_UNICAST];
1579 peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = peer->afc[AFI_IP6][SAFI_MULTICAST];
1580 }
1581
1582 /* Get sockname. */
1583 bgp_getsockname (peer);
Timo Teräs0edba8b2015-10-22 11:35:17 +03001584 peer->rtt = sockopt_tcp_rtt (peer->fd);
paul718e3742002-12-13 20:15:29 +00001585
1586 BGP_EVENT_ADD (peer, Receive_OPEN_message);
1587
1588 peer->packet_size = 0;
1589 if (peer->ibuf)
1590 stream_reset (peer->ibuf);
1591
1592 return 0;
1593}
1594
1595/* Parse BGP Update packet and make attribute object. */
paul94f2b392005-06-28 12:44:16 +00001596static int
paul718e3742002-12-13 20:15:29 +00001597bgp_update_receive (struct peer *peer, bgp_size_t size)
1598{
1599 int ret;
1600 u_char *end;
1601 struct stream *s;
1602 struct attr attr;
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001603 struct attr_extra extra;
paul718e3742002-12-13 20:15:29 +00001604 bgp_size_t attribute_len;
1605 bgp_size_t update_len;
1606 bgp_size_t withdraw_len;
1607 struct bgp_nlri update;
1608 struct bgp_nlri withdraw;
1609 struct bgp_nlri mp_update;
1610 struct bgp_nlri mp_withdraw;
paul718e3742002-12-13 20:15:29 +00001611
1612 /* Status must be Established. */
1613 if (peer->status != Established)
1614 {
1615 zlog_err ("%s [FSM] Update packet received under status %s",
1616 peer->host, LOOKUP (bgp_status_msg, peer->status));
1617 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
1618 return -1;
1619 }
1620
1621 /* Set initial values. */
1622 memset (&attr, 0, sizeof (struct attr));
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001623 memset (&extra, 0, sizeof (struct attr_extra));
paul718e3742002-12-13 20:15:29 +00001624 memset (&update, 0, sizeof (struct bgp_nlri));
1625 memset (&withdraw, 0, sizeof (struct bgp_nlri));
1626 memset (&mp_update, 0, sizeof (struct bgp_nlri));
1627 memset (&mp_withdraw, 0, sizeof (struct bgp_nlri));
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001628 attr.extra = &extra;
paul718e3742002-12-13 20:15:29 +00001629
1630 s = peer->ibuf;
1631 end = stream_pnt (s) + size;
1632
1633 /* RFC1771 6.3 If the Unfeasible Routes Length or Total Attribute
1634 Length is too large (i.e., if Unfeasible Routes Length + Total
1635 Attribute Length + 23 exceeds the message Length), then the Error
1636 Subcode is set to Malformed Attribute List. */
1637 if (stream_pnt (s) + 2 > end)
1638 {
1639 zlog_err ("%s [Error] Update packet error"
1640 " (packet length is short for unfeasible length)",
1641 peer->host);
1642 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1643 BGP_NOTIFY_UPDATE_MAL_ATTR);
1644 return -1;
1645 }
1646
1647 /* Unfeasible Route Length. */
1648 withdraw_len = stream_getw (s);
1649
1650 /* Unfeasible Route Length check. */
1651 if (stream_pnt (s) + withdraw_len > end)
1652 {
1653 zlog_err ("%s [Error] Update packet error"
1654 " (packet unfeasible length overflow %d)",
1655 peer->host, withdraw_len);
1656 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1657 BGP_NOTIFY_UPDATE_MAL_ATTR);
1658 return -1;
1659 }
1660
1661 /* Unfeasible Route packet format check. */
1662 if (withdraw_len > 0)
1663 {
Lou Berger050defe2016-01-12 13:41:59 -05001664 ret = bgp_nlri_sanity_check (peer, AFI_IP, SAFI_UNICAST, stream_pnt (s), withdraw_len);
paul718e3742002-12-13 20:15:29 +00001665 if (ret < 0)
1666 return -1;
1667
1668 if (BGP_DEBUG (packet, PACKET_RECV))
ajs6b514742004-12-08 21:03:23 +00001669 zlog_debug ("%s [Update:RECV] Unfeasible NLRI received", peer->host);
paul718e3742002-12-13 20:15:29 +00001670
1671 withdraw.afi = AFI_IP;
1672 withdraw.safi = SAFI_UNICAST;
1673 withdraw.nlri = stream_pnt (s);
1674 withdraw.length = withdraw_len;
paul9985f832005-02-09 15:51:56 +00001675 stream_forward_getp (s, withdraw_len);
paul718e3742002-12-13 20:15:29 +00001676 }
1677
1678 /* Attribute total length check. */
1679 if (stream_pnt (s) + 2 > end)
1680 {
1681 zlog_warn ("%s [Error] Packet Error"
1682 " (update packet is short for attribute length)",
1683 peer->host);
1684 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1685 BGP_NOTIFY_UPDATE_MAL_ATTR);
1686 return -1;
1687 }
1688
1689 /* Fetch attribute total length. */
1690 attribute_len = stream_getw (s);
1691
1692 /* Attribute length check. */
1693 if (stream_pnt (s) + attribute_len > end)
1694 {
1695 zlog_warn ("%s [Error] Packet Error"
1696 " (update packet attribute length overflow %d)",
1697 peer->host, attribute_len);
1698 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1699 BGP_NOTIFY_UPDATE_MAL_ATTR);
1700 return -1;
1701 }
Paul Jakmab881c702010-11-23 16:35:42 +00001702
1703 /* Certain attribute parsing errors should not be considered bad enough
1704 * to reset the session for, most particularly any partial/optional
1705 * attributes that have 'tunneled' over speakers that don't understand
1706 * them. Instead we withdraw only the prefix concerned.
1707 *
1708 * Complicates the flow a little though..
1709 */
1710 bgp_attr_parse_ret_t attr_parse_ret = BGP_ATTR_PARSE_PROCEED;
1711 /* This define morphs the update case into a withdraw when lower levels
1712 * have signalled an error condition where this is best.
1713 */
1714#define NLRI_ATTR_ARG (attr_parse_ret != BGP_ATTR_PARSE_WITHDRAW ? &attr : NULL)
paul718e3742002-12-13 20:15:29 +00001715
1716 /* Parse attribute when it exists. */
1717 if (attribute_len)
1718 {
Paul Jakmab881c702010-11-23 16:35:42 +00001719 attr_parse_ret = bgp_attr_parse (peer, &attr, attribute_len,
paul718e3742002-12-13 20:15:29 +00001720 &mp_update, &mp_withdraw);
Paul Jakmab881c702010-11-23 16:35:42 +00001721 if (attr_parse_ret == BGP_ATTR_PARSE_ERROR)
David Lamparterf80f8382014-06-04 01:00:51 +02001722 {
1723 bgp_attr_unintern_sub (&attr);
Lou Berger050defe2016-01-12 13:41:59 -05001724 bgp_attr_flush (&attr);
David Lamparterf80f8382014-06-04 01:00:51 +02001725 return -1;
1726 }
paul718e3742002-12-13 20:15:29 +00001727 }
Paul Jakmab881c702010-11-23 16:35:42 +00001728
paul718e3742002-12-13 20:15:29 +00001729 /* Logging the attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001730 if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW
1731 || BGP_DEBUG (update, UPDATE_IN))
paul718e3742002-12-13 20:15:29 +00001732 {
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +00001733 char attrstr[BUFSIZ];
1734 attrstr[0] = '\0';
1735
paule01f9cb2004-07-09 17:48:53 +00001736 ret= bgp_dump_attr (peer, &attr, attrstr, BUFSIZ);
Paul Jakmab881c702010-11-23 16:35:42 +00001737 int lvl = (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
1738 ? LOG_ERR : LOG_DEBUG;
1739
1740 if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
1741 zlog (peer->log, LOG_ERR,
1742 "%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.",
1743 peer->host);
paule01f9cb2004-07-09 17:48:53 +00001744
1745 if (ret)
Paul Jakmab881c702010-11-23 16:35:42 +00001746 zlog (peer->log, lvl, "%s rcvd UPDATE w/ attr: %s",
paule01f9cb2004-07-09 17:48:53 +00001747 peer->host, attrstr);
paul718e3742002-12-13 20:15:29 +00001748 }
Paul Jakmab881c702010-11-23 16:35:42 +00001749
paul718e3742002-12-13 20:15:29 +00001750 /* Network Layer Reachability Information. */
1751 update_len = end - stream_pnt (s);
1752
1753 if (update_len)
1754 {
1755 /* Check NLRI packet format and prefix length. */
Lou Berger050defe2016-01-12 13:41:59 -05001756 ret = bgp_nlri_sanity_check (peer, AFI_IP, SAFI_UNICAST, stream_pnt (s), update_len);
paul718e3742002-12-13 20:15:29 +00001757 if (ret < 0)
Paul Jakmab881c702010-11-23 16:35:42 +00001758 {
1759 bgp_attr_unintern_sub (&attr);
Lou Berger050defe2016-01-12 13:41:59 -05001760 bgp_attr_flush (&attr);
Paul Jakmab881c702010-11-23 16:35:42 +00001761 return -1;
1762 }
paul718e3742002-12-13 20:15:29 +00001763
1764 /* Set NLRI portion to structure. */
1765 update.afi = AFI_IP;
1766 update.safi = SAFI_UNICAST;
1767 update.nlri = stream_pnt (s);
1768 update.length = update_len;
paul9985f832005-02-09 15:51:56 +00001769 stream_forward_getp (s, update_len);
paul718e3742002-12-13 20:15:29 +00001770 }
1771
1772 /* NLRI is processed only when the peer is configured specific
1773 Address Family and Subsequent Address Family. */
1774 if (peer->afc[AFI_IP][SAFI_UNICAST])
1775 {
1776 if (withdraw.length)
1777 bgp_nlri_parse (peer, NULL, &withdraw);
1778
1779 if (update.length)
Paul Jakmab881c702010-11-23 16:35:42 +00001780 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &update);
paule01f9cb2004-07-09 17:48:53 +00001781
hassof4184462005-02-01 20:13:16 +00001782 if (mp_update.length
1783 && mp_update.afi == AFI_IP
1784 && mp_update.safi == SAFI_UNICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001785 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
hassof4184462005-02-01 20:13:16 +00001786
1787 if (mp_withdraw.length
1788 && mp_withdraw.afi == AFI_IP
1789 && mp_withdraw.safi == SAFI_UNICAST)
1790 bgp_nlri_parse (peer, NULL, &mp_withdraw);
1791
paule01f9cb2004-07-09 17:48:53 +00001792 if (! attribute_len && ! withdraw_len)
1793 {
1794 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001795 SET_FLAG (peer->af_sflags[AFI_IP][SAFI_UNICAST],
1796 PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001797
hasso93406d82005-02-02 14:40:33 +00001798 /* NSF delete stale route */
1799 if (peer->nsf[AFI_IP][SAFI_UNICAST])
1800 bgp_clear_stale_route (peer, AFI_IP, SAFI_UNICAST);
1801
1802 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001803 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001804 peer->host);
1805 }
paul718e3742002-12-13 20:15:29 +00001806 }
1807 if (peer->afc[AFI_IP][SAFI_MULTICAST])
1808 {
1809 if (mp_update.length
Lou Berger9da04bc2016-01-12 13:41:55 -05001810 && mp_update.afi == AFI_IP
paul718e3742002-12-13 20:15:29 +00001811 && mp_update.safi == SAFI_MULTICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001812 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001813
1814 if (mp_withdraw.length
Lou Berger9da04bc2016-01-12 13:41:55 -05001815 && mp_withdraw.afi == AFI_IP
paul718e3742002-12-13 20:15:29 +00001816 && mp_withdraw.safi == SAFI_MULTICAST)
1817 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001818
hasso93406d82005-02-02 14:40:33 +00001819 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001820 && mp_withdraw.afi == AFI_IP
1821 && mp_withdraw.safi == SAFI_MULTICAST
1822 && mp_withdraw.length == 0)
1823 {
1824 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001825 SET_FLAG (peer->af_sflags[AFI_IP][SAFI_MULTICAST],
1826 PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001827
hasso93406d82005-02-02 14:40:33 +00001828 /* NSF delete stale route */
1829 if (peer->nsf[AFI_IP][SAFI_MULTICAST])
1830 bgp_clear_stale_route (peer, AFI_IP, SAFI_MULTICAST);
1831
1832 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001833 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Multicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001834 peer->host);
1835 }
paul718e3742002-12-13 20:15:29 +00001836 }
1837 if (peer->afc[AFI_IP6][SAFI_UNICAST])
1838 {
1839 if (mp_update.length
1840 && mp_update.afi == AFI_IP6
1841 && mp_update.safi == SAFI_UNICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001842 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001843
1844 if (mp_withdraw.length
1845 && mp_withdraw.afi == AFI_IP6
1846 && mp_withdraw.safi == SAFI_UNICAST)
1847 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001848
hasso93406d82005-02-02 14:40:33 +00001849 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001850 && mp_withdraw.afi == AFI_IP6
1851 && mp_withdraw.safi == SAFI_UNICAST
1852 && mp_withdraw.length == 0)
1853 {
1854 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001855 SET_FLAG (peer->af_sflags[AFI_IP6][SAFI_UNICAST], PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001856
hasso93406d82005-02-02 14:40:33 +00001857 /* NSF delete stale route */
1858 if (peer->nsf[AFI_IP6][SAFI_UNICAST])
1859 bgp_clear_stale_route (peer, AFI_IP6, SAFI_UNICAST);
1860
1861 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001862 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001863 peer->host);
1864 }
paul718e3742002-12-13 20:15:29 +00001865 }
1866 if (peer->afc[AFI_IP6][SAFI_MULTICAST])
1867 {
1868 if (mp_update.length
1869 && mp_update.afi == AFI_IP6
1870 && mp_update.safi == SAFI_MULTICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001871 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001872
1873 if (mp_withdraw.length
1874 && mp_withdraw.afi == AFI_IP6
1875 && mp_withdraw.safi == SAFI_MULTICAST)
1876 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001877
hasso93406d82005-02-02 14:40:33 +00001878 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001879 && mp_withdraw.afi == AFI_IP6
1880 && mp_withdraw.safi == SAFI_MULTICAST
1881 && mp_withdraw.length == 0)
1882 {
1883 /* End-of-RIB received */
1884
hasso93406d82005-02-02 14:40:33 +00001885 /* NSF delete stale route */
1886 if (peer->nsf[AFI_IP6][SAFI_MULTICAST])
1887 bgp_clear_stale_route (peer, AFI_IP6, SAFI_MULTICAST);
1888
paule01f9cb2004-07-09 17:48:53 +00001889 if (BGP_DEBUG (update, UPDATE_IN))
ajs6b514742004-12-08 21:03:23 +00001890 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Multicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001891 peer->host);
1892 }
paul718e3742002-12-13 20:15:29 +00001893 }
1894 if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
1895 {
1896 if (mp_update.length
1897 && mp_update.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001898 && mp_update.safi == SAFI_MPLS_LABELED_VPN)
Lou Berger9da04bc2016-01-12 13:41:55 -05001899 bgp_nlri_parse_vpn (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001900
1901 if (mp_withdraw.length
1902 && mp_withdraw.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001903 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN)
Lou Berger9da04bc2016-01-12 13:41:55 -05001904 bgp_nlri_parse_vpn (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001905
hasso93406d82005-02-02 14:40:33 +00001906 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001907 && mp_withdraw.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001908 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN
paule01f9cb2004-07-09 17:48:53 +00001909 && mp_withdraw.length == 0)
1910 {
1911 /* End-of-RIB received */
1912
1913 if (BGP_DEBUG (update, UPDATE_IN))
ajs6b514742004-12-08 21:03:23 +00001914 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for VPNv4 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001915 peer->host);
1916 }
paul718e3742002-12-13 20:15:29 +00001917 }
Lou Berger9da04bc2016-01-12 13:41:55 -05001918 if (peer->afc[AFI_IP6][SAFI_MPLS_VPN])
1919 {
1920 if (mp_update.length
1921 && mp_update.afi == AFI_IP6
1922 && mp_update.safi == SAFI_MPLS_LABELED_VPN)
1923 bgp_nlri_parse_vpn (peer, NLRI_ATTR_ARG, &mp_update);
1924
1925 if (mp_withdraw.length
1926 && mp_withdraw.afi == AFI_IP6
1927 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN)
1928 bgp_nlri_parse_vpn (peer, NULL, &mp_withdraw);
1929
1930 if (! withdraw_len
1931 && mp_withdraw.afi == AFI_IP6
1932 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN
1933 && mp_withdraw.length == 0)
1934 {
1935 /* End-of-RIB received */
1936
1937 if (BGP_DEBUG (update, UPDATE_IN))
1938 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for VPNv4 Unicast from %s",
1939 peer->host);
1940 }
1941 }
paul718e3742002-12-13 20:15:29 +00001942
1943 /* Everything is done. We unintern temporary structures which
1944 interned in bgp_attr_parse(). */
Paul Jakmab881c702010-11-23 16:35:42 +00001945 bgp_attr_unintern_sub (&attr);
Lou Berger050defe2016-01-12 13:41:59 -05001946 bgp_attr_flush (&attr);
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001947
paul718e3742002-12-13 20:15:29 +00001948 /* If peering is stopped due to some reason, do not generate BGP
1949 event. */
1950 if (peer->status != Established)
1951 return 0;
1952
1953 /* Increment packet counter. */
1954 peer->update_in++;
Stephen Hemminger65957882010-01-15 16:22:10 +03001955 peer->update_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00001956
Jorge Boncompte [DTI2]e2c38e62012-06-20 17:45:50 +02001957 /* Rearm holdtime timer */
Jorge Boncompte [DTI2]6a4677b2012-05-07 16:53:07 +00001958 BGP_TIMER_OFF (peer->t_holdtime);
Jorge Boncompte [DTI2]e2c38e62012-06-20 17:45:50 +02001959 bgp_timer_set (peer);
paul718e3742002-12-13 20:15:29 +00001960
1961 return 0;
1962}
1963
1964/* Notify message treatment function. */
paul94f2b392005-06-28 12:44:16 +00001965static void
paul718e3742002-12-13 20:15:29 +00001966bgp_notify_receive (struct peer *peer, bgp_size_t size)
1967{
1968 struct bgp_notify bgp_notify;
1969
1970 if (peer->notify.data)
1971 {
1972 XFREE (MTYPE_TMP, peer->notify.data);
1973 peer->notify.data = NULL;
1974 peer->notify.length = 0;
1975 }
1976
1977 bgp_notify.code = stream_getc (peer->ibuf);
1978 bgp_notify.subcode = stream_getc (peer->ibuf);
1979 bgp_notify.length = size - 2;
1980 bgp_notify.data = NULL;
1981
1982 /* Preserv notify code and sub code. */
1983 peer->notify.code = bgp_notify.code;
1984 peer->notify.subcode = bgp_notify.subcode;
1985 /* For further diagnostic record returned Data. */
1986 if (bgp_notify.length)
1987 {
1988 peer->notify.length = size - 2;
1989 peer->notify.data = XMALLOC (MTYPE_TMP, size - 2);
1990 memcpy (peer->notify.data, stream_pnt (peer->ibuf), size - 2);
1991 }
1992
1993 /* For debug */
1994 {
1995 int i;
1996 int first = 0;
1997 char c[4];
1998
1999 if (bgp_notify.length)
2000 {
2001 bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
2002 for (i = 0; i < bgp_notify.length; i++)
2003 if (first)
2004 {
2005 sprintf (c, " %02x", stream_getc (peer->ibuf));
2006 strcat (bgp_notify.data, c);
2007 }
2008 else
2009 {
2010 first = 1;
2011 sprintf (c, "%02x", stream_getc (peer->ibuf));
2012 strcpy (bgp_notify.data, c);
2013 }
2014 }
2015
2016 bgp_notify_print(peer, &bgp_notify, "received");
2017 if (bgp_notify.data)
Daniel Walton363c9032015-10-21 06:42:54 -07002018 {
2019 XFREE (MTYPE_TMP, bgp_notify.data);
2020 bgp_notify.data = NULL;
2021 bgp_notify.length = 0;
2022 }
paul718e3742002-12-13 20:15:29 +00002023 }
2024
2025 /* peer count update */
2026 peer->notify_in++;
2027
hassoe0701b72004-05-20 09:19:34 +00002028 if (peer->status == Established)
2029 peer->last_reset = PEER_DOWN_NOTIFY_RECEIVED;
2030
paul718e3742002-12-13 20:15:29 +00002031 /* We have to check for Notify with Unsupported Optional Parameter.
2032 in that case we fallback to open without the capability option.
2033 But this done in bgp_stop. We just mark it here to avoid changing
2034 the fsm tables. */
2035 if (bgp_notify.code == BGP_NOTIFY_OPEN_ERR &&
2036 bgp_notify.subcode == BGP_NOTIFY_OPEN_UNSUP_PARAM )
2037 UNSET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
2038
paul718e3742002-12-13 20:15:29 +00002039 BGP_EVENT_ADD (peer, Receive_NOTIFICATION_message);
2040}
2041
2042/* Keepalive treatment function -- get keepalive send keepalive */
paul94f2b392005-06-28 12:44:16 +00002043static void
paul718e3742002-12-13 20:15:29 +00002044bgp_keepalive_receive (struct peer *peer, bgp_size_t size)
2045{
2046 if (BGP_DEBUG (keepalive, KEEPALIVE))
ajs6b514742004-12-08 21:03:23 +00002047 zlog_debug ("%s KEEPALIVE rcvd", peer->host);
paul718e3742002-12-13 20:15:29 +00002048
2049 BGP_EVENT_ADD (peer, Receive_KEEPALIVE_message);
2050}
2051
2052/* Route refresh message is received. */
paul94f2b392005-06-28 12:44:16 +00002053static void
paul718e3742002-12-13 20:15:29 +00002054bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
2055{
2056 afi_t afi;
2057 safi_t safi;
paul718e3742002-12-13 20:15:29 +00002058 struct stream *s;
2059
2060 /* If peer does not have the capability, send notification. */
2061 if (! CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_ADV))
2062 {
2063 plog_err (peer->log, "%s [Error] BGP route refresh is not enabled",
2064 peer->host);
2065 bgp_notify_send (peer,
2066 BGP_NOTIFY_HEADER_ERR,
2067 BGP_NOTIFY_HEADER_BAD_MESTYPE);
2068 return;
2069 }
2070
2071 /* Status must be Established. */
2072 if (peer->status != Established)
2073 {
2074 plog_err (peer->log,
2075 "%s [Error] Route refresh packet received under status %s",
2076 peer->host, LOOKUP (bgp_status_msg, peer->status));
2077 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
2078 return;
2079 }
2080
2081 s = peer->ibuf;
2082
2083 /* Parse packet. */
2084 afi = stream_getw (s);
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002085 /* reserved byte */
2086 stream_getc (s);
paul718e3742002-12-13 20:15:29 +00002087 safi = stream_getc (s);
2088
2089 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002090 zlog_debug ("%s rcvd REFRESH_REQ for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00002091 peer->host, afi, safi);
2092
2093 /* Check AFI and SAFI. */
2094 if ((afi != AFI_IP && afi != AFI_IP6)
2095 || (safi != SAFI_UNICAST && safi != SAFI_MULTICAST
Denis Ovsienko42e6d742011-07-14 12:36:19 +04002096 && safi != SAFI_MPLS_LABELED_VPN))
paul718e3742002-12-13 20:15:29 +00002097 {
2098 if (BGP_DEBUG (normal, NORMAL))
2099 {
ajs6b514742004-12-08 21:03:23 +00002100 zlog_debug ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored",
paul718e3742002-12-13 20:15:29 +00002101 peer->host, afi, safi);
2102 }
2103 return;
2104 }
2105
2106 /* Adjust safi code. */
Denis Ovsienko42e6d742011-07-14 12:36:19 +04002107 if (safi == SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00002108 safi = SAFI_MPLS_VPN;
2109
2110 if (size != BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE)
2111 {
2112 u_char *end;
2113 u_char when_to_refresh;
2114 u_char orf_type;
2115 u_int16_t orf_len;
2116
2117 if (size - (BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE) < 5)
2118 {
2119 zlog_info ("%s ORF route refresh length error", peer->host);
2120 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2121 return;
2122 }
2123
2124 when_to_refresh = stream_getc (s);
2125 end = stream_pnt (s) + (size - 5);
2126
Paul Jakma370b64a2007-12-22 16:49:52 +00002127 while ((stream_pnt (s) + 2) < end)
paul718e3742002-12-13 20:15:29 +00002128 {
2129 orf_type = stream_getc (s);
2130 orf_len = stream_getw (s);
Paul Jakma370b64a2007-12-22 16:49:52 +00002131
2132 /* orf_len in bounds? */
2133 if ((stream_pnt (s) + orf_len) > end)
2134 break; /* XXX: Notify instead?? */
paul718e3742002-12-13 20:15:29 +00002135 if (orf_type == ORF_TYPE_PREFIX
2136 || orf_type == ORF_TYPE_PREFIX_OLD)
2137 {
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002138 uint8_t *p_pnt = stream_pnt (s);
2139 uint8_t *p_end = stream_pnt (s) + orf_len;
paul718e3742002-12-13 20:15:29 +00002140 struct orf_prefix orfp;
2141 u_char common = 0;
2142 u_int32_t seq;
2143 int psize;
2144 char name[BUFSIZ];
paul718e3742002-12-13 20:15:29 +00002145 int ret;
2146
2147 if (BGP_DEBUG (normal, NORMAL))
2148 {
ajs6b514742004-12-08 21:03:23 +00002149 zlog_debug ("%s rcvd Prefixlist ORF(%d) length %d",
paul718e3742002-12-13 20:15:29 +00002150 peer->host, orf_type, orf_len);
2151 }
2152
Paul Jakma370b64a2007-12-22 16:49:52 +00002153 /* we're going to read at least 1 byte of common ORF header,
2154 * and 7 bytes of ORF Address-filter entry from the stream
2155 */
2156 if (orf_len < 7)
2157 break;
2158
paul718e3742002-12-13 20:15:29 +00002159 /* ORF prefix-list name */
2160 sprintf (name, "%s.%d.%d", peer->host, afi, safi);
2161
2162 while (p_pnt < p_end)
2163 {
Chris Halld64379e2010-05-14 16:38:39 +04002164 /* If the ORF entry is malformed, want to read as much of it
2165 * as possible without going beyond the bounds of the entry,
2166 * to maximise debug information.
2167 */
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002168 int ok;
paul718e3742002-12-13 20:15:29 +00002169 memset (&orfp, 0, sizeof (struct orf_prefix));
2170 common = *p_pnt++;
Chris Halld64379e2010-05-14 16:38:39 +04002171 /* after ++: p_pnt <= p_end */
paul718e3742002-12-13 20:15:29 +00002172 if (common & ORF_COMMON_PART_REMOVE_ALL)
2173 {
2174 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002175 zlog_debug ("%s rcvd Remove-All pfxlist ORF request", peer->host);
David Lamparterc9c06d02015-04-13 10:21:35 +02002176 prefix_bgp_orf_remove_all (afi, name);
paul718e3742002-12-13 20:15:29 +00002177 break;
2178 }
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002179 ok = ((size_t)(p_end - p_pnt) >= sizeof(u_int32_t)) ;
Denis Ovsienkobb915f52011-12-13 21:11:39 +04002180 if (ok)
Chris Halld64379e2010-05-14 16:38:39 +04002181 {
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002182 memcpy (&seq, p_pnt, sizeof (u_int32_t));
2183 p_pnt += sizeof (u_int32_t);
2184 orfp.seq = ntohl (seq);
Chris Halld64379e2010-05-14 16:38:39 +04002185 }
2186 else
2187 p_pnt = p_end ;
2188
2189 if ((ok = (p_pnt < p_end)))
2190 orfp.ge = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */
2191 if ((ok = (p_pnt < p_end)))
2192 orfp.le = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */
2193 if ((ok = (p_pnt < p_end)))
2194 orfp.p.prefixlen = *p_pnt++ ;
2195 orfp.p.family = afi2family (afi); /* afi checked already */
2196
2197 psize = PSIZE (orfp.p.prefixlen); /* 0 if not ok */
2198 if (psize > prefix_blen(&orfp.p)) /* valid for family ? */
2199 {
2200 ok = 0 ;
2201 psize = prefix_blen(&orfp.p) ;
2202 }
2203 if (psize > (p_end - p_pnt)) /* valid for packet ? */
2204 {
2205 ok = 0 ;
2206 psize = p_end - p_pnt ;
2207 }
2208
2209 if (psize > 0)
2210 memcpy (&orfp.p.u.prefix, p_pnt, psize);
paul718e3742002-12-13 20:15:29 +00002211 p_pnt += psize;
2212
2213 if (BGP_DEBUG (normal, NORMAL))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +00002214 {
2215 char buf[INET6_BUFSIZ];
2216
2217 zlog_debug ("%s rcvd %s %s seq %u %s/%d ge %d le %d%s",
2218 peer->host,
2219 (common & ORF_COMMON_PART_REMOVE ? "Remove" : "Add"),
2220 (common & ORF_COMMON_PART_DENY ? "deny" : "permit"),
2221 orfp.seq,
2222 inet_ntop (orfp.p.family, &orfp.p.u.prefix, buf, INET6_BUFSIZ),
2223 orfp.p.prefixlen, orfp.ge, orfp.le,
2224 ok ? "" : " MALFORMED");
2225 }
2226
Chris Halld64379e2010-05-14 16:38:39 +04002227 if (ok)
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002228 ret = prefix_bgp_orf_set (name, afi, &orfp,
2229 (common & ORF_COMMON_PART_DENY ? 0 : 1 ),
2230 (common & ORF_COMMON_PART_REMOVE ? 0 : 1));
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002231
2232 if (!ok || (ok && ret != CMD_SUCCESS))
paul718e3742002-12-13 20:15:29 +00002233 {
2234 if (BGP_DEBUG (normal, NORMAL))
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002235 zlog_debug ("%s Received misformatted prefixlist ORF."
2236 " Remove All pfxlist", peer->host);
David Lamparterc9c06d02015-04-13 10:21:35 +02002237 prefix_bgp_orf_remove_all (afi, name);
paul718e3742002-12-13 20:15:29 +00002238 break;
2239 }
2240 }
2241 peer->orf_plist[afi][safi] =
David Lamparterc9c06d02015-04-13 10:21:35 +02002242 prefix_bgp_orf_lookup (afi, name);
paul718e3742002-12-13 20:15:29 +00002243 }
paul9985f832005-02-09 15:51:56 +00002244 stream_forward_getp (s, orf_len);
paul718e3742002-12-13 20:15:29 +00002245 }
2246 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002247 zlog_debug ("%s rcvd Refresh %s ORF request", peer->host,
paul718e3742002-12-13 20:15:29 +00002248 when_to_refresh == REFRESH_DEFER ? "Defer" : "Immediate");
2249 if (when_to_refresh == REFRESH_DEFER)
2250 return;
2251 }
2252
2253 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2254 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH))
2255 UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
2256
2257 /* Perform route refreshment to the peer */
2258 bgp_announce_route (peer, afi, safi);
2259}
2260
paul94f2b392005-06-28 12:44:16 +00002261static int
paul718e3742002-12-13 20:15:29 +00002262bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
2263{
2264 u_char *end;
Paul Jakma6d582722007-08-06 15:21:45 +00002265 struct capability_mp_data mpc;
2266 struct capability_header *hdr;
paul718e3742002-12-13 20:15:29 +00002267 u_char action;
paul718e3742002-12-13 20:15:29 +00002268 afi_t afi;
2269 safi_t safi;
2270
paul718e3742002-12-13 20:15:29 +00002271 end = pnt + length;
2272
2273 while (pnt < end)
Paul Jakma6d582722007-08-06 15:21:45 +00002274 {
paul718e3742002-12-13 20:15:29 +00002275 /* We need at least action, capability code and capability length. */
2276 if (pnt + 3 > end)
2277 {
2278 zlog_info ("%s Capability length error", peer->host);
2279 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2280 return -1;
2281 }
paul718e3742002-12-13 20:15:29 +00002282 action = *pnt;
Paul Jakma6d582722007-08-06 15:21:45 +00002283 hdr = (struct capability_header *)(pnt + 1);
2284
paul718e3742002-12-13 20:15:29 +00002285 /* Action value check. */
2286 if (action != CAPABILITY_ACTION_SET
2287 && action != CAPABILITY_ACTION_UNSET)
2288 {
2289 zlog_info ("%s Capability Action Value error %d",
2290 peer->host, action);
2291 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2292 return -1;
2293 }
2294
2295 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002296 zlog_debug ("%s CAPABILITY has action: %d, code: %u, length %u",
Paul Jakma6d582722007-08-06 15:21:45 +00002297 peer->host, action, hdr->code, hdr->length);
paul718e3742002-12-13 20:15:29 +00002298
2299 /* Capability length check. */
Paul Jakma6d582722007-08-06 15:21:45 +00002300 if ((pnt + hdr->length + 3) > end)
paul718e3742002-12-13 20:15:29 +00002301 {
2302 zlog_info ("%s Capability length error", peer->host);
2303 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2304 return -1;
2305 }
2306
Paul Jakma6d582722007-08-06 15:21:45 +00002307 /* Fetch structure to the byte stream. */
2308 memcpy (&mpc, pnt + 3, sizeof (struct capability_mp_data));
2309
paul718e3742002-12-13 20:15:29 +00002310 /* We know MP Capability Code. */
Paul Jakma6d582722007-08-06 15:21:45 +00002311 if (hdr->code == CAPABILITY_CODE_MP)
paul718e3742002-12-13 20:15:29 +00002312 {
Paul Jakma6d582722007-08-06 15:21:45 +00002313 afi = ntohs (mpc.afi);
2314 safi = mpc.safi;
paul718e3742002-12-13 20:15:29 +00002315
2316 /* Ignore capability when override-capability is set. */
2317 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
2318 continue;
Paul Jakma6d582722007-08-06 15:21:45 +00002319
2320 if (!bgp_afi_safi_valid_indices (afi, &safi))
2321 {
2322 if (BGP_DEBUG (normal, NORMAL))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002323 zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid "
2324 "(%u/%u)", peer->host, afi, safi);
Paul Jakma6d582722007-08-06 15:21:45 +00002325 continue;
2326 }
2327
paul718e3742002-12-13 20:15:29 +00002328 /* Address family check. */
Paul Jakma6d582722007-08-06 15:21:45 +00002329 if (BGP_DEBUG (normal, NORMAL))
2330 zlog_debug ("%s CAPABILITY has %s MP_EXT CAP for afi/safi: %u/%u",
2331 peer->host,
2332 action == CAPABILITY_ACTION_SET
2333 ? "Advertising" : "Removing",
2334 ntohs(mpc.afi) , mpc.safi);
2335
2336 if (action == CAPABILITY_ACTION_SET)
2337 {
2338 peer->afc_recv[afi][safi] = 1;
2339 if (peer->afc[afi][safi])
2340 {
2341 peer->afc_nego[afi][safi] = 1;
2342 bgp_announce_route (peer, afi, safi);
2343 }
2344 }
2345 else
2346 {
2347 peer->afc_recv[afi][safi] = 0;
2348 peer->afc_nego[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00002349
Paul Jakma6d582722007-08-06 15:21:45 +00002350 if (peer_active_nego (peer))
Chris Caputo228da422009-07-18 05:44:03 +00002351 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
Paul Jakma6d582722007-08-06 15:21:45 +00002352 else
2353 BGP_EVENT_ADD (peer, BGP_Stop);
2354 }
paul718e3742002-12-13 20:15:29 +00002355 }
paul718e3742002-12-13 20:15:29 +00002356 else
2357 {
2358 zlog_warn ("%s unrecognized capability code: %d - ignored",
Paul Jakma6d582722007-08-06 15:21:45 +00002359 peer->host, hdr->code);
paul718e3742002-12-13 20:15:29 +00002360 }
Paul Jakma6d582722007-08-06 15:21:45 +00002361 pnt += hdr->length + 3;
paul718e3742002-12-13 20:15:29 +00002362 }
2363 return 0;
2364}
2365
Paul Jakma01b7ce22009-06-18 12:34:43 +01002366/* Dynamic Capability is received.
2367 *
2368 * This is exported for unit-test purposes
2369 */
Paul Jakma6d582722007-08-06 15:21:45 +00002370int
paul718e3742002-12-13 20:15:29 +00002371bgp_capability_receive (struct peer *peer, bgp_size_t size)
2372{
2373 u_char *pnt;
paul718e3742002-12-13 20:15:29 +00002374
2375 /* Fetch pointer. */
2376 pnt = stream_pnt (peer->ibuf);
2377
2378 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002379 zlog_debug ("%s rcv CAPABILITY", peer->host);
paul718e3742002-12-13 20:15:29 +00002380
2381 /* If peer does not have the capability, send notification. */
2382 if (! CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV))
2383 {
2384 plog_err (peer->log, "%s [Error] BGP dynamic capability is not enabled",
2385 peer->host);
2386 bgp_notify_send (peer,
2387 BGP_NOTIFY_HEADER_ERR,
2388 BGP_NOTIFY_HEADER_BAD_MESTYPE);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002389 return -1;
paul718e3742002-12-13 20:15:29 +00002390 }
2391
2392 /* Status must be Established. */
2393 if (peer->status != Established)
2394 {
2395 plog_err (peer->log,
2396 "%s [Error] Dynamic capability packet received under status %s", peer->host, LOOKUP (bgp_status_msg, peer->status));
2397 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002398 return -1;
paul718e3742002-12-13 20:15:29 +00002399 }
2400
2401 /* Parse packet. */
Paul Jakma6d582722007-08-06 15:21:45 +00002402 return bgp_capability_msg_parse (peer, pnt, size);
paul718e3742002-12-13 20:15:29 +00002403}
David Lamparter6b0655a2014-06-04 06:53:35 +02002404
paul718e3742002-12-13 20:15:29 +00002405/* BGP read utility function. */
paul94f2b392005-06-28 12:44:16 +00002406static int
paul718e3742002-12-13 20:15:29 +00002407bgp_read_packet (struct peer *peer)
2408{
2409 int nbytes;
2410 int readsize;
2411
paul9985f832005-02-09 15:51:56 +00002412 readsize = peer->packet_size - stream_get_endp (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00002413
2414 /* If size is zero then return. */
2415 if (! readsize)
2416 return 0;
2417
2418 /* Read packet from fd. */
Stephen Hemminger35398582010-08-05 10:26:23 -07002419 nbytes = stream_read_try (peer->ibuf, peer->fd, readsize);
paul718e3742002-12-13 20:15:29 +00002420
2421 /* If read byte is smaller than zero then error occured. */
2422 if (nbytes < 0)
2423 {
Stephen Hemminger35398582010-08-05 10:26:23 -07002424 /* Transient error should retry */
2425 if (nbytes == -2)
paul718e3742002-12-13 20:15:29 +00002426 return -1;
2427
2428 plog_err (peer->log, "%s [Error] bgp_read_packet error: %s",
ajs6099b3b2004-11-20 02:06:59 +00002429 peer->host, safe_strerror (errno));
hasso93406d82005-02-02 14:40:33 +00002430
2431 if (peer->status == Established)
2432 {
2433 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
2434 {
2435 peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
2436 SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
2437 }
2438 else
2439 peer->last_reset = PEER_DOWN_CLOSE_SESSION;
2440 }
2441
paul718e3742002-12-13 20:15:29 +00002442 BGP_EVENT_ADD (peer, TCP_fatal_error);
2443 return -1;
2444 }
2445
2446 /* When read byte is zero : clear bgp peer and return */
2447 if (nbytes == 0)
2448 {
2449 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +00002450 plog_debug (peer->log, "%s [Event] BGP connection closed fd %d",
pauleb821182004-05-01 08:44:08 +00002451 peer->host, peer->fd);
hassoe0701b72004-05-20 09:19:34 +00002452
2453 if (peer->status == Established)
hasso93406d82005-02-02 14:40:33 +00002454 {
2455 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
2456 {
2457 peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
2458 SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
2459 }
2460 else
2461 peer->last_reset = PEER_DOWN_CLOSE_SESSION;
2462 }
hassoe0701b72004-05-20 09:19:34 +00002463
paul718e3742002-12-13 20:15:29 +00002464 BGP_EVENT_ADD (peer, TCP_connection_closed);
2465 return -1;
2466 }
2467
2468 /* We read partial packet. */
paul9985f832005-02-09 15:51:56 +00002469 if (stream_get_endp (peer->ibuf) != peer->packet_size)
paul718e3742002-12-13 20:15:29 +00002470 return -1;
2471
2472 return 0;
2473}
2474
2475/* Marker check. */
paul94f2b392005-06-28 12:44:16 +00002476static int
paul718e3742002-12-13 20:15:29 +00002477bgp_marker_all_one (struct stream *s, int length)
2478{
2479 int i;
2480
2481 for (i = 0; i < length; i++)
2482 if (s->data[i] != 0xff)
2483 return 0;
2484
2485 return 1;
2486}
2487
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002488/* Recent thread time.
2489 On same clock base as bgp_clock (MONOTONIC)
2490 but can be time of last context switch to bgp_read thread. */
2491static time_t
2492bgp_recent_clock (void)
2493{
2494 return recent_relative_time().tv_sec;
2495}
2496
paul718e3742002-12-13 20:15:29 +00002497/* Starting point of packet process function. */
2498int
2499bgp_read (struct thread *thread)
2500{
2501 int ret;
2502 u_char type = 0;
2503 struct peer *peer;
2504 bgp_size_t size;
2505 char notify_data_length[2];
2506
2507 /* Yes first of all get peer pointer. */
2508 peer = THREAD_ARG (thread);
2509 peer->t_read = NULL;
2510
2511 /* For non-blocking IO check. */
2512 if (peer->status == Connect)
2513 {
2514 bgp_connect_check (peer);
2515 goto done;
2516 }
2517 else
2518 {
pauleb821182004-05-01 08:44:08 +00002519 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +00002520 {
pauleb821182004-05-01 08:44:08 +00002521 zlog_err ("bgp_read peer's fd is negative value %d", peer->fd);
paul718e3742002-12-13 20:15:29 +00002522 return -1;
2523 }
pauleb821182004-05-01 08:44:08 +00002524 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
paul718e3742002-12-13 20:15:29 +00002525 }
2526
2527 /* Read packet header to determine type of the packet */
2528 if (peer->packet_size == 0)
2529 peer->packet_size = BGP_HEADER_SIZE;
2530
paul9985f832005-02-09 15:51:56 +00002531 if (stream_get_endp (peer->ibuf) < BGP_HEADER_SIZE)
paul718e3742002-12-13 20:15:29 +00002532 {
2533 ret = bgp_read_packet (peer);
2534
2535 /* Header read error or partial read packet. */
2536 if (ret < 0)
2537 goto done;
2538
2539 /* Get size and type. */
paul9985f832005-02-09 15:51:56 +00002540 stream_forward_getp (peer->ibuf, BGP_MARKER_SIZE);
paul718e3742002-12-13 20:15:29 +00002541 memcpy (notify_data_length, stream_pnt (peer->ibuf), 2);
2542 size = stream_getw (peer->ibuf);
2543 type = stream_getc (peer->ibuf);
2544
2545 if (BGP_DEBUG (normal, NORMAL) && type != 2 && type != 0)
ajs6b514742004-12-08 21:03:23 +00002546 zlog_debug ("%s rcv message type %d, length (excl. header) %d",
paul718e3742002-12-13 20:15:29 +00002547 peer->host, type, size - BGP_HEADER_SIZE);
2548
2549 /* Marker check */
paulf5ba3872004-07-09 12:11:31 +00002550 if (((type == BGP_MSG_OPEN) || (type == BGP_MSG_KEEPALIVE))
paul718e3742002-12-13 20:15:29 +00002551 && ! bgp_marker_all_one (peer->ibuf, BGP_MARKER_SIZE))
2552 {
2553 bgp_notify_send (peer,
2554 BGP_NOTIFY_HEADER_ERR,
2555 BGP_NOTIFY_HEADER_NOT_SYNC);
2556 goto done;
2557 }
2558
2559 /* BGP type check. */
2560 if (type != BGP_MSG_OPEN && type != BGP_MSG_UPDATE
2561 && type != BGP_MSG_NOTIFY && type != BGP_MSG_KEEPALIVE
2562 && type != BGP_MSG_ROUTE_REFRESH_NEW
2563 && type != BGP_MSG_ROUTE_REFRESH_OLD
2564 && type != BGP_MSG_CAPABILITY)
2565 {
2566 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002567 plog_debug (peer->log,
paul718e3742002-12-13 20:15:29 +00002568 "%s unknown message type 0x%02x",
2569 peer->host, type);
2570 bgp_notify_send_with_data (peer,
2571 BGP_NOTIFY_HEADER_ERR,
2572 BGP_NOTIFY_HEADER_BAD_MESTYPE,
2573 &type, 1);
2574 goto done;
2575 }
2576 /* Mimimum packet length check. */
2577 if ((size < BGP_HEADER_SIZE)
2578 || (size > BGP_MAX_PACKET_SIZE)
2579 || (type == BGP_MSG_OPEN && size < BGP_MSG_OPEN_MIN_SIZE)
2580 || (type == BGP_MSG_UPDATE && size < BGP_MSG_UPDATE_MIN_SIZE)
2581 || (type == BGP_MSG_NOTIFY && size < BGP_MSG_NOTIFY_MIN_SIZE)
2582 || (type == BGP_MSG_KEEPALIVE && size != BGP_MSG_KEEPALIVE_MIN_SIZE)
2583 || (type == BGP_MSG_ROUTE_REFRESH_NEW && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
2584 || (type == BGP_MSG_ROUTE_REFRESH_OLD && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
2585 || (type == BGP_MSG_CAPABILITY && size < BGP_MSG_CAPABILITY_MIN_SIZE))
2586 {
2587 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002588 plog_debug (peer->log,
paul718e3742002-12-13 20:15:29 +00002589 "%s bad message length - %d for %s",
2590 peer->host, size,
2591 type == 128 ? "ROUTE-REFRESH" :
2592 bgp_type_str[(int) type]);
2593 bgp_notify_send_with_data (peer,
2594 BGP_NOTIFY_HEADER_ERR,
2595 BGP_NOTIFY_HEADER_BAD_MESLEN,
hassoc9e52be2004-09-26 16:09:34 +00002596 (u_char *) notify_data_length, 2);
paul718e3742002-12-13 20:15:29 +00002597 goto done;
2598 }
2599
2600 /* Adjust size to message length. */
2601 peer->packet_size = size;
2602 }
2603
2604 ret = bgp_read_packet (peer);
2605 if (ret < 0)
2606 goto done;
2607
2608 /* Get size and type again. */
2609 size = stream_getw_from (peer->ibuf, BGP_MARKER_SIZE);
2610 type = stream_getc_from (peer->ibuf, BGP_MARKER_SIZE + 2);
2611
2612 /* BGP packet dump function. */
2613 bgp_dump_packet (peer, type, peer->ibuf);
2614
2615 size = (peer->packet_size - BGP_HEADER_SIZE);
2616
2617 /* Read rest of the packet and call each sort of packet routine */
2618 switch (type)
2619 {
2620 case BGP_MSG_OPEN:
2621 peer->open_in++;
paulf5ba3872004-07-09 12:11:31 +00002622 bgp_open_receive (peer, size); /* XXX return value ignored! */
paul718e3742002-12-13 20:15:29 +00002623 break;
2624 case BGP_MSG_UPDATE:
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002625 peer->readtime = bgp_recent_clock ();
paul718e3742002-12-13 20:15:29 +00002626 bgp_update_receive (peer, size);
2627 break;
2628 case BGP_MSG_NOTIFY:
2629 bgp_notify_receive (peer, size);
2630 break;
2631 case BGP_MSG_KEEPALIVE:
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002632 peer->readtime = bgp_recent_clock ();
paul718e3742002-12-13 20:15:29 +00002633 bgp_keepalive_receive (peer, size);
2634 break;
2635 case BGP_MSG_ROUTE_REFRESH_NEW:
2636 case BGP_MSG_ROUTE_REFRESH_OLD:
2637 peer->refresh_in++;
2638 bgp_route_refresh_receive (peer, size);
2639 break;
2640 case BGP_MSG_CAPABILITY:
2641 peer->dynamic_cap_in++;
2642 bgp_capability_receive (peer, size);
2643 break;
2644 }
2645
2646 /* Clear input buffer. */
2647 peer->packet_size = 0;
2648 if (peer->ibuf)
2649 stream_reset (peer->ibuf);
2650
2651 done:
2652 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2653 {
2654 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +00002655 zlog_debug ("%s [Event] Accepting BGP peer delete", peer->host);
paul718e3742002-12-13 20:15:29 +00002656 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00002657 }
2658 return 0;
2659}