blob: 4ab5b064080026d65a512c91d41738e9b288e145 [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"
34
35#include "bgpd/bgpd.h"
36#include "bgpd/bgp_table.h"
37#include "bgpd/bgp_dump.h"
38#include "bgpd/bgp_attr.h"
39#include "bgpd/bgp_debug.h"
40#include "bgpd/bgp_fsm.h"
41#include "bgpd/bgp_route.h"
42#include "bgpd/bgp_packet.h"
43#include "bgpd/bgp_open.h"
44#include "bgpd/bgp_aspath.h"
45#include "bgpd/bgp_community.h"
46#include "bgpd/bgp_ecommunity.h"
47#include "bgpd/bgp_network.h"
48#include "bgpd/bgp_mplsvpn.h"
49#include "bgpd/bgp_advertise.h"
hasso93406d82005-02-02 14:40:33 +000050#include "bgpd/bgp_vty.h"
paul718e3742002-12-13 20:15:29 +000051
52int stream_put_prefix (struct stream *, struct prefix *);
David Lamparter6b0655a2014-06-04 06:53:35 +020053
paul718e3742002-12-13 20:15:29 +000054/* Set up BGP packet marker and packet type. */
55static int
56bgp_packet_set_marker (struct stream *s, u_char type)
57{
58 int i;
59
60 /* Fill in marker. */
61 for (i = 0; i < BGP_MARKER_SIZE; i++)
62 stream_putc (s, 0xff);
63
64 /* Dummy total length. This field is should be filled in later on. */
65 stream_putw (s, 0);
66
67 /* BGP packet type. */
68 stream_putc (s, type);
69
70 /* Return current stream size. */
paul9985f832005-02-09 15:51:56 +000071 return stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +000072}
73
74/* Set BGP packet header size entry. If size is zero then use current
75 stream size. */
76static int
77bgp_packet_set_size (struct stream *s)
78{
79 int cp;
80
81 /* Preserve current pointer. */
paul9985f832005-02-09 15:51:56 +000082 cp = stream_get_endp (s);
83 stream_putw_at (s, BGP_MARKER_SIZE, cp);
paul718e3742002-12-13 20:15:29 +000084
85 return cp;
86}
87
88/* Add new packet to the peer. */
paul94f2b392005-06-28 12:44:16 +000089static void
paul718e3742002-12-13 20:15:29 +000090bgp_packet_add (struct peer *peer, struct stream *s)
91{
92 /* Add packet to the end of list. */
93 stream_fifo_push (peer->obuf, s);
94}
95
96/* Free first packet. */
paul94f2b392005-06-28 12:44:16 +000097static void
paul718e3742002-12-13 20:15:29 +000098bgp_packet_delete (struct peer *peer)
99{
100 stream_free (stream_fifo_pop (peer->obuf));
101}
102
paul718e3742002-12-13 20:15:29 +0000103/* Check file descriptor whether connect is established. */
104static void
105bgp_connect_check (struct peer *peer)
106{
107 int status;
paul5228ad22004-06-04 17:58:18 +0000108 socklen_t slen;
paul718e3742002-12-13 20:15:29 +0000109 int ret;
110
111 /* Anyway I have to reset read and write thread. */
112 BGP_READ_OFF (peer->t_read);
113 BGP_WRITE_OFF (peer->t_write);
114
115 /* Check file descriptor. */
116 slen = sizeof (status);
pauleb821182004-05-01 08:44:08 +0000117 ret = getsockopt(peer->fd, SOL_SOCKET, SO_ERROR, (void *) &status, &slen);
paul718e3742002-12-13 20:15:29 +0000118
119 /* If getsockopt is fail, this is fatal error. */
120 if (ret < 0)
121 {
122 zlog (peer->log, LOG_INFO, "can't get sockopt for nonblocking connect");
123 BGP_EVENT_ADD (peer, TCP_fatal_error);
124 return;
125 }
126
127 /* When status is 0 then TCP connection is established. */
128 if (status == 0)
129 {
130 BGP_EVENT_ADD (peer, TCP_connection_open);
131 }
132 else
133 {
134 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +0000135 plog_debug (peer->log, "%s [Event] Connect failed (%s)",
ajs6099b3b2004-11-20 02:06:59 +0000136 peer->host, safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000137 BGP_EVENT_ADD (peer, TCP_connection_open_failed);
138 }
139}
140
141/* Make BGP update packet. */
paul94f2b392005-06-28 12:44:16 +0000142static struct stream *
paul718e3742002-12-13 20:15:29 +0000143bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
144{
145 struct stream *s;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000146 struct stream *snlri;
paul718e3742002-12-13 20:15:29 +0000147 struct bgp_adj_out *adj;
148 struct bgp_advertise *adv;
149 struct stream *packet;
150 struct bgp_node *rn = NULL;
151 struct bgp_info *binfo = NULL;
152 bgp_size_t total_attr_len = 0;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000153 unsigned long attrlen_pos = 0;
154 size_t mpattrlen_pos = 0;
155 size_t mpattr_pos = 0;
paul718e3742002-12-13 20:15:29 +0000156
157 s = peer->work;
158 stream_reset (s);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000159 snlri = peer->scratch;
160 stream_reset (snlri);
paul718e3742002-12-13 20:15:29 +0000161
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100162 adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->update);
paul718e3742002-12-13 20:15:29 +0000163
164 while (adv)
165 {
Paul Jakmaed3ebfa2006-10-15 23:50:16 +0000166 assert (adv->rn);
167 rn = adv->rn;
paul718e3742002-12-13 20:15:29 +0000168 adj = adv->adj;
169 if (adv->binfo)
170 binfo = adv->binfo;
paul718e3742002-12-13 20:15:29 +0000171
172 /* When remaining space can't include NLRI and it's length. */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000173 if (STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) <=
174 (BGP_NLRI_LENGTH + PSIZE (rn->p.prefixlen)))
paul718e3742002-12-13 20:15:29 +0000175 break;
176
177 /* If packet is empty, set attribute. */
178 if (stream_empty (s))
179 {
Paul Jakmaed3ebfa2006-10-15 23:50:16 +0000180 struct peer *from = NULL;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000181
Greg Troxeld3ddb222010-09-17 10:47:49 -0400182 if (binfo)
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000183 from = binfo->peer;
184
185 /* 1: Write the BGP message header - 16 bytes marker, 2 bytes length,
186 * one byte message type.
187 */
paul718e3742002-12-13 20:15:29 +0000188 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000189
190 /* 2: withdrawn routes length */
paul718e3742002-12-13 20:15:29 +0000191 stream_putw (s, 0);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000192
193 /* 3: total attributes length - attrlen_pos stores the position */
194 attrlen_pos = stream_get_endp (s);
195 stream_putw (s, 0);
196
197 /* 4: if there is MP_REACH_NLRI attribute, that should be the first
198 * attribute, according to draft-ietf-idr-error-handling. Save the
199 * position.
200 */
201 mpattr_pos = stream_get_endp(s);
202
203 /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */
204 total_attr_len = bgp_packet_attribute (NULL, peer, s,
paul5228ad22004-06-04 17:58:18 +0000205 adv->baa->attr,
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000206 NULL, afi, safi,
207 from, NULL, NULL);
paul718e3742002-12-13 20:15:29 +0000208 }
209
210 if (afi == AFI_IP && safi == SAFI_UNICAST)
211 stream_put_prefix (s, &rn->p);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000212 else
213 {
214 /* Encode the prefix in MP_REACH_NLRI attribute */
215 struct prefix_rd *prd = NULL;
216 u_char *tag = NULL;
217
218 if (rn->prn)
219 prd = (struct prefix_rd *) &rn->prn->p;
220 if (binfo && binfo->extra)
221 tag = binfo->extra->tag;
222
223 if (stream_empty(snlri))
224 mpattrlen_pos = bgp_packet_mpattr_start(snlri, afi, safi,
225 adv->baa->attr);
226 bgp_packet_mpattr_prefix(snlri, afi, safi, &rn->p, prd, tag);
227 }
paul718e3742002-12-13 20:15:29 +0000228 if (BGP_DEBUG (update, UPDATE_OUT))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000229 {
230 char buf[INET6_BUFSIZ];
231
232 zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d",
233 peer->host,
234 inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ),
235 rn->p.prefixlen);
236 }
paul718e3742002-12-13 20:15:29 +0000237
238 /* Synchnorize attribute. */
239 if (adj->attr)
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000240 bgp_attr_unintern (&adj->attr);
paul718e3742002-12-13 20:15:29 +0000241 else
242 peer->scount[afi][safi]++;
243
244 adj->attr = bgp_attr_intern (adv->baa->attr);
245
246 adv = bgp_advertise_clean (peer, adj, afi, safi);
paul718e3742002-12-13 20:15:29 +0000247 }
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000248
paul718e3742002-12-13 20:15:29 +0000249 if (! stream_empty (s))
250 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000251 if (!stream_empty(snlri))
252 {
253 bgp_packet_mpattr_end(snlri, mpattrlen_pos);
254 total_attr_len += stream_get_endp(snlri);
255 }
256
257 /* set the total attribute length correctly */
258 stream_putw_at (s, attrlen_pos, total_attr_len);
259
260 if (!stream_empty(snlri))
261 packet = stream_dupcat(s, snlri, mpattr_pos);
262 else
263 packet = stream_dup (s);
264 bgp_packet_set_size (packet);
paul718e3742002-12-13 20:15:29 +0000265 bgp_packet_add (peer, packet);
pauleb821182004-05-01 08:44:08 +0000266 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000267 stream_reset (s);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000268 stream_reset (snlri);
paul718e3742002-12-13 20:15:29 +0000269 return packet;
270 }
271 return NULL;
hasso93406d82005-02-02 14:40:33 +0000272}
paul718e3742002-12-13 20:15:29 +0000273
paul94f2b392005-06-28 12:44:16 +0000274static struct stream *
hasso93406d82005-02-02 14:40:33 +0000275bgp_update_packet_eor (struct peer *peer, afi_t afi, safi_t safi)
276{
277 struct stream *s;
hasso93406d82005-02-02 14:40:33 +0000278
Paul Jakma750e8142008-07-22 21:11:48 +0000279 if (DISABLE_BGP_ANNOUNCE)
280 return NULL;
hasso93406d82005-02-02 14:40:33 +0000281
282 if (BGP_DEBUG (normal, NORMAL))
283 zlog_debug ("send End-of-RIB for %s to %s", afi_safi_print (afi, safi), peer->host);
284
285 s = stream_new (BGP_MAX_PACKET_SIZE);
286
287 /* Make BGP update packet. */
288 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
289
290 /* Unfeasible Routes Length */
291 stream_putw (s, 0);
292
293 if (afi == AFI_IP && safi == SAFI_UNICAST)
294 {
295 /* Total Path Attribute Length */
296 stream_putw (s, 0);
297 }
298 else
299 {
300 /* Total Path Attribute Length */
301 stream_putw (s, 6);
302 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
303 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
304 stream_putc (s, 3);
305 stream_putw (s, afi);
306 stream_putc (s, safi);
307 }
308
309 bgp_packet_set_size (s);
Donald Sharpa752c3b2015-08-18 08:48:53 -0400310 bgp_packet_add (peer, s);
311 return s;
paul718e3742002-12-13 20:15:29 +0000312}
313
314/* Make BGP withdraw packet. */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000315/* For ipv4 unicast:
316 16-octet marker | 2-octet length | 1-octet type |
317 2-octet withdrawn route length | withdrawn prefixes | 2-octet attrlen (=0)
318*/
319/* For other afi/safis:
320 16-octet marker | 2-octet length | 1-octet type |
321 2-octet withdrawn route length (=0) | 2-octet attrlen |
322 mp_unreach attr type | attr len | afi | safi | withdrawn prefixes
323*/
paul94f2b392005-06-28 12:44:16 +0000324static struct stream *
paul718e3742002-12-13 20:15:29 +0000325bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi)
326{
327 struct stream *s;
328 struct stream *packet;
329 struct bgp_adj_out *adj;
330 struct bgp_advertise *adv;
331 struct bgp_node *rn;
paul718e3742002-12-13 20:15:29 +0000332 bgp_size_t unfeasible_len;
333 bgp_size_t total_attr_len;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000334 size_t mp_start = 0;
335 size_t attrlen_pos = 0;
336 size_t mplen_pos = 0;
337 u_char first_time = 1;
paul718e3742002-12-13 20:15:29 +0000338
339 s = peer->work;
340 stream_reset (s);
341
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100342 while ((adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->withdraw)) != NULL)
paul718e3742002-12-13 20:15:29 +0000343 {
Paul Jakmaed3ebfa2006-10-15 23:50:16 +0000344 assert (adv->rn);
paul718e3742002-12-13 20:15:29 +0000345 adj = adv->adj;
346 rn = adv->rn;
paul718e3742002-12-13 20:15:29 +0000347
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000348 if (STREAM_REMAIN (s)
hasso4372df72004-05-20 10:20:02 +0000349 < (BGP_NLRI_LENGTH + BGP_TOTAL_ATTR_LEN + PSIZE (rn->p.prefixlen)))
paul718e3742002-12-13 20:15:29 +0000350 break;
351
352 if (stream_empty (s))
353 {
354 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000355 stream_putw (s, 0); /* unfeasible routes length */
paul718e3742002-12-13 20:15:29 +0000356 }
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000357 else
358 first_time = 0;
paul718e3742002-12-13 20:15:29 +0000359
360 if (afi == AFI_IP && safi == SAFI_UNICAST)
361 stream_put_prefix (s, &rn->p);
362 else
363 {
Paul Jakmaa3b6ea52006-05-04 07:52:12 +0000364 struct prefix_rd *prd = NULL;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000365
Paul Jakmaa3b6ea52006-05-04 07:52:12 +0000366 if (rn->prn)
367 prd = (struct prefix_rd *) &rn->prn->p;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000368
369 /* If first time, format the MP_UNREACH header */
370 if (first_time)
371 {
372 attrlen_pos = stream_get_endp (s);
373 /* total attr length = 0 for now. reevaluate later */
374 stream_putw (s, 0);
375 mp_start = stream_get_endp (s);
376 mplen_pos = bgp_packet_mpunreach_start(s, afi, safi);
377 }
378
379 bgp_packet_mpunreach_prefix(s, &rn->p, afi, safi, prd, NULL);
paul718e3742002-12-13 20:15:29 +0000380 }
381
382 if (BGP_DEBUG (update, UPDATE_OUT))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000383 {
384 char buf[INET6_BUFSIZ];
385
386 zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d -- unreachable",
387 peer->host,
388 inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ),
389 rn->p.prefixlen);
390 }
paul718e3742002-12-13 20:15:29 +0000391
392 peer->scount[afi][safi]--;
393
394 bgp_adj_out_remove (rn, adj, peer, afi, safi);
395 bgp_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +0000396 }
397
398 if (! stream_empty (s))
399 {
400 if (afi == AFI_IP && safi == SAFI_UNICAST)
401 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000402 unfeasible_len
paul9985f832005-02-09 15:51:56 +0000403 = stream_get_endp (s) - BGP_HEADER_SIZE - BGP_UNFEASIBLE_LEN;
paul718e3742002-12-13 20:15:29 +0000404 stream_putw_at (s, BGP_HEADER_SIZE, unfeasible_len);
405 stream_putw (s, 0);
406 }
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000407 else
408 {
409 /* Set the mp_unreach attr's length */
410 bgp_packet_mpunreach_end(s, mplen_pos);
411
412 /* Set total path attribute length. */
413 total_attr_len = stream_get_endp(s) - mp_start;
414 stream_putw_at (s, attrlen_pos, total_attr_len);
415 }
paul718e3742002-12-13 20:15:29 +0000416 bgp_packet_set_size (s);
paule83e2082005-05-19 02:12:25 +0000417 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +0000418 bgp_packet_add (peer, packet);
419 stream_reset (s);
420 return packet;
421 }
422
423 return NULL;
424}
425
426void
427bgp_default_update_send (struct peer *peer, struct attr *attr,
428 afi_t afi, safi_t safi, struct peer *from)
429{
430 struct stream *s;
paul718e3742002-12-13 20:15:29 +0000431 struct prefix p;
432 unsigned long pos;
433 bgp_size_t total_attr_len;
paul718e3742002-12-13 20:15:29 +0000434
Paul Jakma750e8142008-07-22 21:11:48 +0000435 if (DISABLE_BGP_ANNOUNCE)
436 return;
paul718e3742002-12-13 20:15:29 +0000437
438 if (afi == AFI_IP)
439 str2prefix ("0.0.0.0/0", &p);
440#ifdef HAVE_IPV6
441 else
442 str2prefix ("::/0", &p);
443#endif /* HAVE_IPV6 */
444
445 /* Logging the attribute. */
446 if (BGP_DEBUG (update, UPDATE_OUT))
447 {
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000448 char attrstr[BUFSIZ];
449 char buf[INET6_BUFSIZ];
450 attrstr[0] = '\0';
451
paul718e3742002-12-13 20:15:29 +0000452 bgp_dump_attr (peer, attr, attrstr, BUFSIZ);
ajs6b514742004-12-08 21:03:23 +0000453 zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d %s",
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000454 peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ),
paul718e3742002-12-13 20:15:29 +0000455 p.prefixlen, attrstr);
456 }
457
458 s = stream_new (BGP_MAX_PACKET_SIZE);
459
460 /* Make BGP update packet. */
461 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
462
463 /* Unfeasible Routes Length. */
464 stream_putw (s, 0);
465
466 /* Make place for total attribute length. */
paul9985f832005-02-09 15:51:56 +0000467 pos = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000468 stream_putw (s, 0);
469 total_attr_len = bgp_packet_attribute (NULL, peer, s, attr, &p, afi, safi, from, NULL, NULL);
470
471 /* Set Total Path Attribute Length. */
472 stream_putw_at (s, pos, total_attr_len);
473
474 /* NLRI set. */
475 if (p.family == AF_INET && safi == SAFI_UNICAST)
476 stream_put_prefix (s, &p);
477
478 /* Set size. */
479 bgp_packet_set_size (s);
480
paul718e3742002-12-13 20:15:29 +0000481 /* Dump packet if debug option is set. */
482#ifdef DEBUG
jardin2d74db52005-10-01 00:07:50 +0000483 /* bgp_packet_dump (packet); */
paul718e3742002-12-13 20:15:29 +0000484#endif /* DEBUG */
485
486 /* Add packet to the peer. */
Donald Sharpa752c3b2015-08-18 08:48:53 -0400487 bgp_packet_add (peer, s);
paul718e3742002-12-13 20:15:29 +0000488
pauleb821182004-05-01 08:44:08 +0000489 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000490}
491
492void
493bgp_default_withdraw_send (struct peer *peer, afi_t afi, safi_t safi)
494{
495 struct stream *s;
paul718e3742002-12-13 20:15:29 +0000496 struct prefix p;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000497 unsigned long attrlen_pos = 0;
paul718e3742002-12-13 20:15:29 +0000498 unsigned long cp;
499 bgp_size_t unfeasible_len;
500 bgp_size_t total_attr_len;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000501 size_t mp_start = 0;
502 size_t mplen_pos = 0;
paul718e3742002-12-13 20:15:29 +0000503
Paul Jakma750e8142008-07-22 21:11:48 +0000504 if (DISABLE_BGP_ANNOUNCE)
505 return;
paul718e3742002-12-13 20:15:29 +0000506
507 if (afi == AFI_IP)
508 str2prefix ("0.0.0.0/0", &p);
509#ifdef HAVE_IPV6
510 else
511 str2prefix ("::/0", &p);
512#endif /* HAVE_IPV6 */
513
514 total_attr_len = 0;
paul718e3742002-12-13 20:15:29 +0000515
516 if (BGP_DEBUG (update, UPDATE_OUT))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000517 {
518 char buf[INET6_BUFSIZ];
519
520 zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d -- unreachable",
521 peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ),
522 p.prefixlen);
523 }
paul718e3742002-12-13 20:15:29 +0000524
525 s = stream_new (BGP_MAX_PACKET_SIZE);
526
527 /* Make BGP update packet. */
528 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
529
530 /* Unfeasible Routes Length. */;
paul9985f832005-02-09 15:51:56 +0000531 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000532 stream_putw (s, 0);
533
534 /* Withdrawn Routes. */
535 if (p.family == AF_INET && safi == SAFI_UNICAST)
536 {
537 stream_put_prefix (s, &p);
538
paul9985f832005-02-09 15:51:56 +0000539 unfeasible_len = stream_get_endp (s) - cp - 2;
paul718e3742002-12-13 20:15:29 +0000540
541 /* Set unfeasible len. */
542 stream_putw_at (s, cp, unfeasible_len);
543
544 /* Set total path attribute length. */
545 stream_putw (s, 0);
546 }
547 else
548 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000549 attrlen_pos = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000550 stream_putw (s, 0);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000551 mp_start = stream_get_endp (s);
552 mplen_pos = bgp_packet_mpunreach_start(s, afi, safi);
553 bgp_packet_mpunreach_prefix(s, &p, afi, safi, NULL, NULL);
554
555 /* Set the mp_unreach attr's length */
556 bgp_packet_mpunreach_end(s, mplen_pos);
paul718e3742002-12-13 20:15:29 +0000557
558 /* Set total path attribute length. */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000559 total_attr_len = stream_get_endp(s) - mp_start;
560 stream_putw_at (s, attrlen_pos, total_attr_len);
paul718e3742002-12-13 20:15:29 +0000561 }
562
563 bgp_packet_set_size (s);
564
paul718e3742002-12-13 20:15:29 +0000565 /* Add packet to the peer. */
Donald Sharpa752c3b2015-08-18 08:48:53 -0400566 bgp_packet_add (peer, s);
paul718e3742002-12-13 20:15:29 +0000567
pauleb821182004-05-01 08:44:08 +0000568 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000569}
570
571/* Get next packet to be written. */
paul94f2b392005-06-28 12:44:16 +0000572static struct stream *
paul718e3742002-12-13 20:15:29 +0000573bgp_write_packet (struct peer *peer)
574{
575 afi_t afi;
576 safi_t safi;
577 struct stream *s = NULL;
578 struct bgp_advertise *adv;
579
580 s = stream_fifo_head (peer->obuf);
581 if (s)
582 return s;
583
584 for (afi = AFI_IP; afi < AFI_MAX; afi++)
585 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
586 {
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100587 adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->withdraw);
paul718e3742002-12-13 20:15:29 +0000588 if (adv)
589 {
590 s = bgp_withdraw_packet (peer, afi, safi);
591 if (s)
592 return s;
593 }
594 }
595
596 for (afi = AFI_IP; afi < AFI_MAX; afi++)
597 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
598 {
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100599 adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->update);
paul718e3742002-12-13 20:15:29 +0000600 if (adv)
601 {
602 if (adv->binfo && adv->binfo->uptime < peer->synctime)
hasso93406d82005-02-02 14:40:33 +0000603 {
604 if (CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_RCV)
605 && CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_ADV)
Vipin Kumardd49eb12014-09-30 14:36:38 -0700606 && ! (CHECK_FLAG (adv->binfo->peer->cap,
607 PEER_CAP_RESTART_BIT_RCV) &&
608 CHECK_FLAG (adv->binfo->peer->cap,
609 PEER_CAP_RESTART_BIT_ADV))
hasso93406d82005-02-02 14:40:33 +0000610 && ! CHECK_FLAG (adv->binfo->flags, BGP_INFO_STALE)
611 && safi != SAFI_MPLS_VPN)
612 {
613 if (CHECK_FLAG (adv->binfo->peer->af_sflags[afi][safi],
614 PEER_STATUS_EOR_RECEIVED))
615 s = bgp_update_packet (peer, afi, safi);
616 }
617 else
618 s = bgp_update_packet (peer, afi, safi);
619 }
paul718e3742002-12-13 20:15:29 +0000620
621 if (s)
622 return s;
623 }
hasso93406d82005-02-02 14:40:33 +0000624
625 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV))
626 {
627 if (peer->afc_nego[afi][safi] && peer->synctime
628 && ! CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND)
629 && safi != SAFI_MPLS_VPN)
630 {
631 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND);
632 return bgp_update_packet_eor (peer, afi, safi);
633 }
634 }
paul718e3742002-12-13 20:15:29 +0000635 }
636
637 return NULL;
638}
639
640/* Is there partially written packet or updates we can send right
641 now. */
paul94f2b392005-06-28 12:44:16 +0000642static int
paul718e3742002-12-13 20:15:29 +0000643bgp_write_proceed (struct peer *peer)
644{
645 afi_t afi;
646 safi_t safi;
647 struct bgp_advertise *adv;
648
649 if (stream_fifo_head (peer->obuf))
650 return 1;
651
652 for (afi = AFI_IP; afi < AFI_MAX; afi++)
653 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
654 if (FIFO_HEAD (&peer->sync[afi][safi]->withdraw))
655 return 1;
656
657 for (afi = AFI_IP; afi < AFI_MAX; afi++)
658 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100659 if ((adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->update)) != NULL)
paul718e3742002-12-13 20:15:29 +0000660 if (adv->binfo->uptime < peer->synctime)
661 return 1;
662
663 return 0;
664}
665
666/* Write packet to the peer. */
667int
668bgp_write (struct thread *thread)
669{
670 struct peer *peer;
671 u_char type;
672 struct stream *s;
673 int num;
paulfd79ac92004-10-13 05:06:08 +0000674 unsigned int count = 0;
paul718e3742002-12-13 20:15:29 +0000675
676 /* Yes first of all get peer pointer. */
677 peer = THREAD_ARG (thread);
678 peer->t_write = NULL;
679
680 /* For non-blocking IO check. */
681 if (peer->status == Connect)
682 {
683 bgp_connect_check (peer);
684 return 0;
685 }
686
Stephen Hemmingereac57022010-08-05 10:26:25 -0700687 s = bgp_write_packet (peer);
688 if (!s)
689 return 0; /* nothing to send */
690
691 sockopt_cork (peer->fd, 1);
692
693 /* Nonblocking write until TCP output buffer is full. */
694 do
paul718e3742002-12-13 20:15:29 +0000695 {
696 int writenum;
paul718e3742002-12-13 20:15:29 +0000697
698 /* Number of bytes to be sent. */
699 writenum = stream_get_endp (s) - stream_get_getp (s);
700
701 /* Call write() system call. */
pauleb821182004-05-01 08:44:08 +0000702 num = write (peer->fd, STREAM_PNT (s), writenum);
Stephen Hemminger35398582010-08-05 10:26:23 -0700703 if (num < 0)
paul718e3742002-12-13 20:15:29 +0000704 {
Stephen Hemmingereac57022010-08-05 10:26:25 -0700705 /* write failed either retry needed or error */
706 if (ERRNO_IO_RETRY(errno))
707 break;
708
709 BGP_EVENT_ADD (peer, TCP_fatal_error);
paul718e3742002-12-13 20:15:29 +0000710 return 0;
711 }
Stephen Hemminger35398582010-08-05 10:26:23 -0700712
paul718e3742002-12-13 20:15:29 +0000713 if (num != writenum)
714 {
Stephen Hemminger35398582010-08-05 10:26:23 -0700715 /* Partial write */
paul9985f832005-02-09 15:51:56 +0000716 stream_forward_getp (s, num);
Stephen Hemmingereac57022010-08-05 10:26:25 -0700717 break;
paul718e3742002-12-13 20:15:29 +0000718 }
719
720 /* Retrieve BGP packet type. */
721 stream_set_getp (s, BGP_MARKER_SIZE + 2);
722 type = stream_getc (s);
723
724 switch (type)
725 {
726 case BGP_MSG_OPEN:
727 peer->open_out++;
728 break;
729 case BGP_MSG_UPDATE:
730 peer->update_out++;
731 break;
732 case BGP_MSG_NOTIFY:
733 peer->notify_out++;
734 /* Double start timer. */
735 peer->v_start *= 2;
736
737 /* Overflow check. */
738 if (peer->v_start >= (60 * 2))
739 peer->v_start = (60 * 2);
740
Paul Jakmaca058a32006-09-14 02:58:49 +0000741 /* Flush any existing events */
Paul Jakmadcdf3992006-10-15 23:39:59 +0000742 BGP_EVENT_ADD (peer, BGP_Stop);
Stephen Hemminger3a69f742013-01-11 18:27:23 +0000743 goto done;
744
paul718e3742002-12-13 20:15:29 +0000745 case BGP_MSG_KEEPALIVE:
746 peer->keepalive_out++;
747 break;
748 case BGP_MSG_ROUTE_REFRESH_NEW:
749 case BGP_MSG_ROUTE_REFRESH_OLD:
750 peer->refresh_out++;
751 break;
752 case BGP_MSG_CAPABILITY:
753 peer->dynamic_cap_out++;
754 break;
755 }
756
757 /* OK we send packet so delete it. */
758 bgp_packet_delete (peer);
paul718e3742002-12-13 20:15:29 +0000759 }
Stephen Hemmingereac57022010-08-05 10:26:25 -0700760 while (++count < BGP_WRITE_PACKET_MAX &&
761 (s = bgp_write_packet (peer)) != NULL);
paul718e3742002-12-13 20:15:29 +0000762
763 if (bgp_write_proceed (peer))
pauleb821182004-05-01 08:44:08 +0000764 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
Stephen Hemminger3a69f742013-01-11 18:27:23 +0000765
766 done:
767 sockopt_cork (peer->fd, 0);
paul718e3742002-12-13 20:15:29 +0000768 return 0;
769}
770
771/* This is only for sending NOTIFICATION message to neighbor. */
paul94f2b392005-06-28 12:44:16 +0000772static int
paul718e3742002-12-13 20:15:29 +0000773bgp_write_notify (struct peer *peer)
774{
Stephen Hemminger35398582010-08-05 10:26:23 -0700775 int ret, val;
paul718e3742002-12-13 20:15:29 +0000776 u_char type;
777 struct stream *s;
778
779 /* There should be at least one packet. */
780 s = stream_fifo_head (peer->obuf);
781 if (!s)
782 return 0;
783 assert (stream_get_endp (s) >= BGP_HEADER_SIZE);
784
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000785 /* Stop collecting data within the socket */
786 sockopt_cork (peer->fd, 0);
787
David Lamparter8ff202e2013-07-31 14:39:41 +0200788 /* socket is in nonblocking mode, if we can't deliver the NOTIFY, well,
789 * we only care about getting a clean shutdown at this point. */
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000790 ret = write (peer->fd, STREAM_DATA (s), stream_get_endp (s));
David Lamparter8ff202e2013-07-31 14:39:41 +0200791
792 /* only connection reset/close gets counted as TCP_fatal_error, failure
793 * to write the entire NOTIFY doesn't get different FSM treatment */
paul718e3742002-12-13 20:15:29 +0000794 if (ret <= 0)
795 {
Paul Jakmadcdf3992006-10-15 23:39:59 +0000796 BGP_EVENT_ADD (peer, TCP_fatal_error);
paul718e3742002-12-13 20:15:29 +0000797 return 0;
798 }
799
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000800 /* Disable Nagle, make NOTIFY packet go out right away */
801 val = 1;
802 (void) setsockopt (peer->fd, IPPROTO_TCP, TCP_NODELAY,
803 (char *) &val, sizeof (val));
804
paul718e3742002-12-13 20:15:29 +0000805 /* Retrieve BGP packet type. */
806 stream_set_getp (s, BGP_MARKER_SIZE + 2);
807 type = stream_getc (s);
808
809 assert (type == BGP_MSG_NOTIFY);
810
811 /* Type should be notify. */
812 peer->notify_out++;
813
814 /* Double start timer. */
815 peer->v_start *= 2;
816
817 /* Overflow check. */
818 if (peer->v_start >= (60 * 2))
819 peer->v_start = (60 * 2);
820
Paul Jakmadcdf3992006-10-15 23:39:59 +0000821 BGP_EVENT_ADD (peer, BGP_Stop);
paul718e3742002-12-13 20:15:29 +0000822
823 return 0;
824}
825
826/* Make keepalive packet and send it to the peer. */
827void
828bgp_keepalive_send (struct peer *peer)
829{
830 struct stream *s;
831 int length;
832
833 s = stream_new (BGP_MAX_PACKET_SIZE);
834
835 /* Make keepalive packet. */
836 bgp_packet_set_marker (s, BGP_MSG_KEEPALIVE);
837
838 /* Set packet size. */
839 length = bgp_packet_set_size (s);
840
841 /* Dump packet if debug option is set. */
842 /* bgp_packet_dump (s); */
843
844 if (BGP_DEBUG (keepalive, KEEPALIVE))
ajs6b514742004-12-08 21:03:23 +0000845 zlog_debug ("%s sending KEEPALIVE", peer->host);
paul718e3742002-12-13 20:15:29 +0000846 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000847 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000848 peer->host, BGP_MSG_KEEPALIVE, length);
849
850 /* Add packet to the peer. */
851 bgp_packet_add (peer, s);
852
pauleb821182004-05-01 08:44:08 +0000853 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000854}
855
856/* Make open packet and send it to the peer. */
857void
858bgp_open_send (struct peer *peer)
859{
860 struct stream *s;
861 int length;
862 u_int16_t send_holdtime;
863 as_t local_as;
864
865 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
866 send_holdtime = peer->holdtime;
867 else
868 send_holdtime = peer->bgp->default_holdtime;
869
870 /* local-as Change */
871 if (peer->change_local_as)
872 local_as = peer->change_local_as;
873 else
874 local_as = peer->local_as;
875
876 s = stream_new (BGP_MAX_PACKET_SIZE);
877
878 /* Make open packet. */
879 bgp_packet_set_marker (s, BGP_MSG_OPEN);
880
881 /* Set open packet values. */
882 stream_putc (s, BGP_VERSION_4); /* BGP version */
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000883 stream_putw (s, (local_as <= BGP_AS_MAX) ? (u_int16_t) local_as
884 : BGP_AS_TRANS);
paul718e3742002-12-13 20:15:29 +0000885 stream_putw (s, send_holdtime); /* Hold Time */
886 stream_put_in_addr (s, &peer->local_id); /* BGP Identifier */
887
888 /* Set capability code. */
889 bgp_open_capability (s, peer);
890
891 /* Set BGP packet length. */
892 length = bgp_packet_set_size (s);
893
894 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +0400895 zlog_debug ("%s sending OPEN, version %d, my as %u, holdtime %d, id %s",
paul718e3742002-12-13 20:15:29 +0000896 peer->host, BGP_VERSION_4, local_as,
897 send_holdtime, inet_ntoa (peer->local_id));
898
899 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000900 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000901 peer->host, BGP_MSG_OPEN, length);
902
903 /* Dump packet if debug option is set. */
904 /* bgp_packet_dump (s); */
905
906 /* Add packet to the peer. */
907 bgp_packet_add (peer, s);
908
pauleb821182004-05-01 08:44:08 +0000909 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000910}
911
912/* Send BGP notify packet with data potion. */
913void
914bgp_notify_send_with_data (struct peer *peer, u_char code, u_char sub_code,
915 u_char *data, size_t datalen)
916{
917 struct stream *s;
918 int length;
919
920 /* Allocate new stream. */
921 s = stream_new (BGP_MAX_PACKET_SIZE);
922
923 /* Make nitify packet. */
924 bgp_packet_set_marker (s, BGP_MSG_NOTIFY);
925
926 /* Set notify packet values. */
927 stream_putc (s, code); /* BGP notify code */
928 stream_putc (s, sub_code); /* BGP notify sub_code */
929
930 /* If notify data is present. */
931 if (data)
932 stream_write (s, data, datalen);
933
934 /* Set BGP packet length. */
935 length = bgp_packet_set_size (s);
936
937 /* Add packet to the peer. */
938 stream_fifo_clean (peer->obuf);
939 bgp_packet_add (peer, s);
940
941 /* For debug */
942 {
943 struct bgp_notify bgp_notify;
944 int first = 0;
945 int i;
946 char c[4];
947
948 bgp_notify.code = code;
949 bgp_notify.subcode = sub_code;
950 bgp_notify.data = NULL;
951 bgp_notify.length = length - BGP_MSG_NOTIFY_MIN_SIZE;
952
953 if (bgp_notify.length)
954 {
955 bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
956 for (i = 0; i < bgp_notify.length; i++)
957 if (first)
958 {
959 sprintf (c, " %02x", data[i]);
960 strcat (bgp_notify.data, c);
961 }
962 else
963 {
964 first = 1;
965 sprintf (c, "%02x", data[i]);
966 strcpy (bgp_notify.data, c);
967 }
968 }
969 bgp_notify_print (peer, &bgp_notify, "sending");
Daniel Walton363c9032015-10-21 06:42:54 -0700970
paul718e3742002-12-13 20:15:29 +0000971 if (bgp_notify.data)
Daniel Walton363c9032015-10-21 06:42:54 -0700972 {
973 XFREE (MTYPE_TMP, bgp_notify.data);
974 bgp_notify.data = NULL;
975 bgp_notify.length = 0;
976 }
paul718e3742002-12-13 20:15:29 +0000977 }
978
979 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000980 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000981 peer->host, BGP_MSG_NOTIFY, length);
982
hassoe0701b72004-05-20 09:19:34 +0000983 /* peer reset cause */
984 if (sub_code != BGP_NOTIFY_CEASE_CONFIG_CHANGE)
985 {
986 if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET)
heasley1212dc12011-09-12 13:27:52 +0400987 {
988 peer->last_reset = PEER_DOWN_USER_RESET;
989 zlog_info ("Notification sent to neighbor %s: User reset", peer->host);
990 }
hassoe0701b72004-05-20 09:19:34 +0000991 else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN)
heasley1212dc12011-09-12 13:27:52 +0400992 {
993 peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
994 zlog_info ("Notification sent to neighbor %s: shutdown", peer->host);
995 }
hassoe0701b72004-05-20 09:19:34 +0000996 else
heasley1212dc12011-09-12 13:27:52 +0400997 {
998 peer->last_reset = PEER_DOWN_NOTIFY_SEND;
999 zlog_info ("Notification sent to neighbor %s: type %u/%u",
1000 peer->host, code, sub_code);
1001 }
hassoe0701b72004-05-20 09:19:34 +00001002 }
heasley1212dc12011-09-12 13:27:52 +04001003 else
1004 zlog_info ("Notification sent to neighbor %s: configuration change",
1005 peer->host);
hassoe0701b72004-05-20 09:19:34 +00001006
Denis Ovsienko7ccf5e52011-09-10 16:53:30 +04001007 /* Call immediately. */
paul718e3742002-12-13 20:15:29 +00001008 BGP_WRITE_OFF (peer->t_write);
1009
1010 bgp_write_notify (peer);
1011}
1012
1013/* Send BGP notify packet. */
1014void
1015bgp_notify_send (struct peer *peer, u_char code, u_char sub_code)
1016{
1017 bgp_notify_send_with_data (peer, code, sub_code, NULL, 0);
1018}
1019
paul718e3742002-12-13 20:15:29 +00001020/* Send route refresh message to the peer. */
1021void
1022bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
1023 u_char orf_type, u_char when_to_refresh, int remove)
1024{
1025 struct stream *s;
paul718e3742002-12-13 20:15:29 +00001026 int length;
1027 struct bgp_filter *filter;
1028 int orf_refresh = 0;
1029
Paul Jakma750e8142008-07-22 21:11:48 +00001030 if (DISABLE_BGP_ANNOUNCE)
1031 return;
paul718e3742002-12-13 20:15:29 +00001032
1033 filter = &peer->filter[afi][safi];
1034
1035 /* Adjust safi code. */
1036 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001037 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +00001038
1039 s = stream_new (BGP_MAX_PACKET_SIZE);
1040
1041 /* Make BGP update packet. */
1042 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
1043 bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_NEW);
1044 else
1045 bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_OLD);
1046
1047 /* Encode Route Refresh message. */
1048 stream_putw (s, afi);
1049 stream_putc (s, 0);
1050 stream_putc (s, safi);
1051
1052 if (orf_type == ORF_TYPE_PREFIX
1053 || orf_type == ORF_TYPE_PREFIX_OLD)
1054 if (remove || filter->plist[FILTER_IN].plist)
1055 {
1056 u_int16_t orf_len;
1057 unsigned long orfp;
1058
1059 orf_refresh = 1;
1060 stream_putc (s, when_to_refresh);
1061 stream_putc (s, orf_type);
paul9985f832005-02-09 15:51:56 +00001062 orfp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00001063 stream_putw (s, 0);
1064
1065 if (remove)
1066 {
1067 UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
1068 stream_putc (s, ORF_COMMON_PART_REMOVE_ALL);
1069 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001070 zlog_debug ("%s sending REFRESH_REQ to remove ORF(%d) (%s) for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001071 peer->host, orf_type,
1072 (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
1073 afi, safi);
1074 }
1075 else
1076 {
1077 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
1078 prefix_bgp_orf_entry (s, filter->plist[FILTER_IN].plist,
1079 ORF_COMMON_PART_ADD, ORF_COMMON_PART_PERMIT,
1080 ORF_COMMON_PART_DENY);
1081 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001082 zlog_debug ("%s sending REFRESH_REQ with pfxlist ORF(%d) (%s) for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001083 peer->host, orf_type,
1084 (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
1085 afi, safi);
1086 }
1087
1088 /* Total ORF Entry Len. */
paul9985f832005-02-09 15:51:56 +00001089 orf_len = stream_get_endp (s) - orfp - 2;
paul718e3742002-12-13 20:15:29 +00001090 stream_putw_at (s, orfp, orf_len);
1091 }
1092
1093 /* Set packet size. */
1094 length = bgp_packet_set_size (s);
1095
1096 if (BGP_DEBUG (normal, NORMAL))
1097 {
1098 if (! orf_refresh)
ajs6b514742004-12-08 21:03:23 +00001099 zlog_debug ("%s sending REFRESH_REQ for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001100 peer->host, afi, safi);
ajs6b514742004-12-08 21:03:23 +00001101 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +00001102 peer->host, CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV) ?
1103 BGP_MSG_ROUTE_REFRESH_NEW : BGP_MSG_ROUTE_REFRESH_OLD, length);
1104 }
1105
paul718e3742002-12-13 20:15:29 +00001106 /* Add packet to the peer. */
Donald Sharpa752c3b2015-08-18 08:48:53 -04001107 bgp_packet_add (peer, s);
paul718e3742002-12-13 20:15:29 +00001108
pauleb821182004-05-01 08:44:08 +00001109 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +00001110}
1111
1112/* Send capability message to the peer. */
1113void
1114bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi,
1115 int capability_code, int action)
1116{
1117 struct stream *s;
paul718e3742002-12-13 20:15:29 +00001118 int length;
1119
1120 /* Adjust safi code. */
1121 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001122 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +00001123
1124 s = stream_new (BGP_MAX_PACKET_SIZE);
1125
1126 /* Make BGP update packet. */
1127 bgp_packet_set_marker (s, BGP_MSG_CAPABILITY);
1128
1129 /* Encode MP_EXT capability. */
1130 if (capability_code == CAPABILITY_CODE_MP)
1131 {
1132 stream_putc (s, action);
1133 stream_putc (s, CAPABILITY_CODE_MP);
1134 stream_putc (s, CAPABILITY_CODE_MP_LEN);
1135 stream_putw (s, afi);
1136 stream_putc (s, 0);
1137 stream_putc (s, safi);
1138
1139 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001140 zlog_debug ("%s sending CAPABILITY has %s MP_EXT CAP for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001141 peer->host, action == CAPABILITY_ACTION_SET ?
1142 "Advertising" : "Removing", afi, safi);
1143 }
1144
paul718e3742002-12-13 20:15:29 +00001145 /* Set packet size. */
1146 length = bgp_packet_set_size (s);
1147
paul718e3742002-12-13 20:15:29 +00001148
1149 /* Add packet to the peer. */
Donald Sharpa752c3b2015-08-18 08:48:53 -04001150 bgp_packet_add (peer, s);
paul718e3742002-12-13 20:15:29 +00001151
1152 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001153 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +00001154 peer->host, BGP_MSG_CAPABILITY, length);
1155
pauleb821182004-05-01 08:44:08 +00001156 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +00001157}
David Lamparter6b0655a2014-06-04 06:53:35 +02001158
paul718e3742002-12-13 20:15:29 +00001159/* RFC1771 6.8 Connection collision detection. */
paul94f2b392005-06-28 12:44:16 +00001160static int
pauleb821182004-05-01 08:44:08 +00001161bgp_collision_detect (struct peer *new, struct in_addr remote_id)
paul718e3742002-12-13 20:15:29 +00001162{
pauleb821182004-05-01 08:44:08 +00001163 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001164 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001165 struct bgp *bgp;
1166
1167 bgp = bgp_get_default ();
1168 if (! bgp)
1169 return 0;
1170
1171 /* Upon receipt of an OPEN message, the local system must examine
1172 all of its connections that are in the OpenConfirm state. A BGP
1173 speaker may also examine connections in an OpenSent state if it
1174 knows the BGP Identifier of the peer by means outside of the
1175 protocol. If among these connections there is a connection to a
1176 remote BGP speaker whose BGP Identifier equals the one in the
1177 OPEN message, then the local system performs the following
1178 collision resolution procedure: */
1179
paul1eb8ef22005-04-07 07:30:20 +00001180 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001181 {
1182 /* Under OpenConfirm status, local peer structure already hold
1183 remote router ID. */
pauleb821182004-05-01 08:44:08 +00001184
1185 if (peer != new
1186 && (peer->status == OpenConfirm || peer->status == OpenSent)
1187 && sockunion_same (&peer->su, &new->su))
1188 {
paul718e3742002-12-13 20:15:29 +00001189 /* 1. The BGP Identifier of the local system is compared to
1190 the BGP Identifier of the remote system (as specified in
1191 the OPEN message). */
1192
1193 if (ntohl (peer->local_id.s_addr) < ntohl (remote_id.s_addr))
1194 {
1195 /* 2. If the value of the local BGP Identifier is less
1196 than the remote one, the local system closes BGP
1197 connection that already exists (the one that is
1198 already in the OpenConfirm state), and accepts BGP
1199 connection initiated by the remote system. */
1200
pauleb821182004-05-01 08:44:08 +00001201 if (peer->fd >= 0)
hassoe0701b72004-05-20 09:19:34 +00001202 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
paul718e3742002-12-13 20:15:29 +00001203 return 1;
1204 }
1205 else
1206 {
1207 /* 3. Otherwise, the local system closes newly created
1208 BGP connection (the one associated with the newly
1209 received OPEN message), and continues to use the
1210 existing one (the one that is already in the
1211 OpenConfirm state). */
1212
pauleb821182004-05-01 08:44:08 +00001213 if (new->fd >= 0)
paulf5ba3872004-07-09 12:11:31 +00001214 bgp_notify_send (new, BGP_NOTIFY_CEASE,
1215 BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
paul718e3742002-12-13 20:15:29 +00001216 return -1;
1217 }
pauleb821182004-05-01 08:44:08 +00001218 }
1219 }
paul718e3742002-12-13 20:15:29 +00001220 return 0;
1221}
1222
paul94f2b392005-06-28 12:44:16 +00001223static int
paul718e3742002-12-13 20:15:29 +00001224bgp_open_receive (struct peer *peer, bgp_size_t size)
1225{
1226 int ret;
1227 u_char version;
1228 u_char optlen;
1229 u_int16_t holdtime;
1230 u_int16_t send_holdtime;
1231 as_t remote_as;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001232 as_t as4 = 0;
paul718e3742002-12-13 20:15:29 +00001233 struct peer *realpeer;
1234 struct in_addr remote_id;
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001235 int mp_capability;
paul5228ad22004-06-04 17:58:18 +00001236 u_int8_t notify_data_remote_as[2];
1237 u_int8_t notify_data_remote_id[4];
paul718e3742002-12-13 20:15:29 +00001238
1239 realpeer = NULL;
1240
1241 /* Parse open packet. */
1242 version = stream_getc (peer->ibuf);
1243 memcpy (notify_data_remote_as, stream_pnt (peer->ibuf), 2);
1244 remote_as = stream_getw (peer->ibuf);
1245 holdtime = stream_getw (peer->ibuf);
1246 memcpy (notify_data_remote_id, stream_pnt (peer->ibuf), 4);
1247 remote_id.s_addr = stream_get_ipv4 (peer->ibuf);
1248
1249 /* Receive OPEN message log */
1250 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001251 zlog_debug ("%s rcv OPEN, version %d, remote-as (in open) %u,"
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001252 " holdtime %d, id %s",
1253 peer->host, version, remote_as, holdtime,
1254 inet_ntoa (remote_id));
1255
1256 /* BEGIN to read the capability here, but dont do it yet */
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001257 mp_capability = 0;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001258 optlen = stream_getc (peer->ibuf);
1259
1260 if (optlen != 0)
1261 {
1262 /* We need the as4 capability value *right now* because
1263 * if it is there, we have not got the remote_as yet, and without
1264 * that we do not know which peer is connecting to us now.
1265 */
1266 as4 = peek_for_as4_capability (peer, optlen);
1267 }
1268
1269 /* Just in case we have a silly peer who sends AS4 capability set to 0 */
1270 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) && !as4)
1271 {
1272 zlog_err ("%s bad OPEN, got AS4 capability, but AS4 set to 0",
1273 peer->host);
1274 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1275 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1276 return -1;
1277 }
1278
1279 if (remote_as == BGP_AS_TRANS)
1280 {
1281 /* Take the AS4 from the capability. We must have received the
1282 * capability now! Otherwise we have a asn16 peer who uses
1283 * BGP_AS_TRANS, for some unknown reason.
1284 */
1285 if (as4 == BGP_AS_TRANS)
1286 {
1287 zlog_err ("%s [AS4] NEW speaker using AS_TRANS for AS4, not allowed",
1288 peer->host);
1289 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1290 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1291 return -1;
1292 }
1293
1294 if (!as4 && BGP_DEBUG (as4, AS4))
1295 zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but no AS4."
1296 " Odd, but proceeding.", peer->host);
1297 else if (as4 < BGP_AS_MAX && BGP_DEBUG (as4, AS4))
Paul Jakma0df7c912008-07-21 21:02:49 +00001298 zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but AS4 (%u) fits "
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001299 "in 2-bytes, very odd peer.", peer->host, as4);
1300 if (as4)
1301 remote_as = as4;
1302 }
1303 else
1304 {
1305 /* We may have a partner with AS4 who has an asno < BGP_AS_MAX */
1306 /* If we have got the capability, peer->as4cap must match remote_as */
1307 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)
1308 && as4 != remote_as)
1309 {
1310 /* raise error, log this, close session */
1311 zlog_err ("%s bad OPEN, got AS4 capability, but remote_as %u"
1312 " mismatch with 16bit 'myasn' %u in open",
1313 peer->host, as4, remote_as);
1314 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1315 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1316 return -1;
1317 }
1318 }
1319
paul718e3742002-12-13 20:15:29 +00001320 /* Lookup peer from Open packet. */
1321 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1322 {
1323 int as = 0;
1324
1325 realpeer = peer_lookup_with_open (&peer->su, remote_as, &remote_id, &as);
1326
1327 if (! realpeer)
1328 {
1329 /* Peer's source IP address is check in bgp_accept(), so this
1330 must be AS number mismatch or remote-id configuration
1331 mismatch. */
1332 if (as)
1333 {
1334 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001335 zlog_debug ("%s bad OPEN, wrong router identifier %s",
1336 peer->host, inet_ntoa (remote_id));
1337 bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
1338 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
1339 notify_data_remote_id, 4);
paul718e3742002-12-13 20:15:29 +00001340 }
1341 else
1342 {
1343 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001344 zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
ajs6b514742004-12-08 21:03:23 +00001345 peer->host, remote_as, peer->as);
1346 bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
1347 BGP_NOTIFY_OPEN_BAD_PEER_AS,
1348 notify_data_remote_as, 2);
paul718e3742002-12-13 20:15:29 +00001349 }
1350 return -1;
1351 }
1352 }
1353
1354 /* When collision is detected and this peer is closed. Retrun
1355 immidiately. */
1356 ret = bgp_collision_detect (peer, remote_id);
1357 if (ret < 0)
1358 return ret;
1359
pauleb821182004-05-01 08:44:08 +00001360 /* Hack part. */
1361 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1362 {
hasso93406d82005-02-02 14:40:33 +00001363 if (realpeer->status == Established
1364 && CHECK_FLAG (realpeer->sflags, PEER_STATUS_NSF_MODE))
1365 {
1366 realpeer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
1367 SET_FLAG (realpeer->sflags, PEER_STATUS_NSF_WAIT);
1368 }
1369 else if (ret == 0 && realpeer->status != Active
1370 && realpeer->status != OpenSent
Paul Jakma6e199262008-09-09 17:14:33 +01001371 && realpeer->status != OpenConfirm
1372 && realpeer->status != Connect)
pauleb821182004-05-01 08:44:08 +00001373 {
Paul Jakma2b2fc562008-09-06 13:09:35 +01001374 /* XXX: This is an awful problem..
1375 *
1376 * According to the RFC we should just let this connection (of the
1377 * accepted 'peer') continue on to Established if the other
1378 * connection (the 'realpeer' one) is in state Connect, and deal
1379 * with the more larval FSM as/when it gets far enough to receive
1380 * an Open. We don't do that though, we instead close the (more
1381 * developed) accepted connection.
1382 *
1383 * This means there's a race, which if hit, can loop:
1384 *
1385 * FSM for A FSM for B
1386 * realpeer accept-peer realpeer accept-peer
1387 *
1388 * Connect Connect
1389 * Active
1390 * OpenSent OpenSent
1391 * <arrive here,
1392 * Notify, delete>
1393 * Idle Active
1394 * OpenSent OpenSent
1395 * <arrive here,
1396 * Notify, delete>
1397 * Idle
1398 * <wait> <wait>
1399 * Connect Connect
1400 *
1401 *
1402 * If both sides are Quagga, they're almost certain to wait for
1403 * the same amount of time of course (which doesn't preclude other
1404 * implementations also waiting for same time). The race is
1405 * exacerbated by high-latency (in bgpd and/or the network).
1406 *
1407 * The reason we do this is because our FSM is tied to our peer
1408 * structure, which carries our configuration information, etc.
1409 * I.e. we can't let the accepted-peer FSM continue on as it is,
1410 * cause it's not associated with any actual peer configuration -
1411 * it's just a dummy.
1412 *
1413 * It's possible we could hack-fix this by just bgp_stop'ing the
1414 * realpeer and continueing on with the 'transfer FSM' below.
1415 * Ideally, we need to seperate FSMs from struct peer.
1416 *
1417 * Setting one side to passive avoids the race, as a workaround.
1418 */
pauleb821182004-05-01 08:44:08 +00001419 if (BGP_DEBUG (events, EVENTS))
hasso93406d82005-02-02 14:40:33 +00001420 zlog_debug ("%s peer status is %s close connection",
1421 realpeer->host, LOOKUP (bgp_status_msg,
1422 realpeer->status));
1423 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1424 BGP_NOTIFY_CEASE_CONNECT_REJECT);
1425
pauleb821182004-05-01 08:44:08 +00001426 return -1;
1427 }
1428
1429 if (BGP_DEBUG (events, EVENTS))
Paul Jakma6e199262008-09-09 17:14:33 +01001430 zlog_debug ("%s [Event] Transfer accept BGP peer to real (state %s)",
1431 peer->host,
1432 LOOKUP (bgp_status_msg, realpeer->status));
pauleb821182004-05-01 08:44:08 +00001433
1434 bgp_stop (realpeer);
1435
1436 /* Transfer file descriptor. */
1437 realpeer->fd = peer->fd;
1438 peer->fd = -1;
1439
1440 /* Transfer input buffer. */
1441 stream_free (realpeer->ibuf);
1442 realpeer->ibuf = peer->ibuf;
1443 realpeer->packet_size = peer->packet_size;
1444 peer->ibuf = NULL;
1445
1446 /* Transfer status. */
1447 realpeer->status = peer->status;
1448 bgp_stop (peer);
paul200df112005-06-01 11:17:05 +00001449
pauleb821182004-05-01 08:44:08 +00001450 /* peer pointer change. Open packet send to neighbor. */
1451 peer = realpeer;
1452 bgp_open_send (peer);
1453 if (peer->fd < 0)
1454 {
1455 zlog_err ("bgp_open_receive peer's fd is negative value %d",
1456 peer->fd);
1457 return -1;
1458 }
1459 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
1460 }
1461
paul718e3742002-12-13 20:15:29 +00001462 /* remote router-id check. */
1463 if (remote_id.s_addr == 0
Denis Ovsienko733cd9e2011-12-17 19:39:30 +04001464 || IPV4_CLASS_DE (ntohl (remote_id.s_addr))
paul718e3742002-12-13 20:15:29 +00001465 || ntohl (peer->local_id.s_addr) == ntohl (remote_id.s_addr))
1466 {
1467 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001468 zlog_debug ("%s bad OPEN, wrong router identifier %s",
paul718e3742002-12-13 20:15:29 +00001469 peer->host, inet_ntoa (remote_id));
1470 bgp_notify_send_with_data (peer,
1471 BGP_NOTIFY_OPEN_ERR,
1472 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
1473 notify_data_remote_id, 4);
1474 return -1;
1475 }
1476
1477 /* Set remote router-id */
1478 peer->remote_id = remote_id;
1479
1480 /* Peer BGP version check. */
1481 if (version != BGP_VERSION_4)
1482 {
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001483 u_int16_t maxver = htons(BGP_VERSION_4);
1484 /* XXX this reply may not be correct if version < 4 XXX */
paul718e3742002-12-13 20:15:29 +00001485 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001486 zlog_debug ("%s bad protocol version, remote requested %d, local request %d",
paul718e3742002-12-13 20:15:29 +00001487 peer->host, version, BGP_VERSION_4);
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001488 /* Data must be in network byte order here */
paul718e3742002-12-13 20:15:29 +00001489 bgp_notify_send_with_data (peer,
1490 BGP_NOTIFY_OPEN_ERR,
1491 BGP_NOTIFY_OPEN_UNSUP_VERSION,
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001492 (u_int8_t *) &maxver, 2);
paul718e3742002-12-13 20:15:29 +00001493 return -1;
1494 }
1495
1496 /* Check neighbor as number. */
1497 if (remote_as != peer->as)
1498 {
1499 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001500 zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
paul718e3742002-12-13 20:15:29 +00001501 peer->host, remote_as, peer->as);
1502 bgp_notify_send_with_data (peer,
1503 BGP_NOTIFY_OPEN_ERR,
1504 BGP_NOTIFY_OPEN_BAD_PEER_AS,
1505 notify_data_remote_as, 2);
1506 return -1;
1507 }
1508
1509 /* From the rfc: Upon receipt of an OPEN message, a BGP speaker MUST
1510 calculate the value of the Hold Timer by using the smaller of its
1511 configured Hold Time and the Hold Time received in the OPEN message.
1512 The Hold Time MUST be either zero or at least three seconds. An
1513 implementation may reject connections on the basis of the Hold Time. */
1514
1515 if (holdtime < 3 && holdtime != 0)
1516 {
1517 bgp_notify_send (peer,
1518 BGP_NOTIFY_OPEN_ERR,
1519 BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
1520 return -1;
1521 }
1522
1523 /* From the rfc: A reasonable maximum time between KEEPALIVE messages
1524 would be one third of the Hold Time interval. KEEPALIVE messages
1525 MUST NOT be sent more frequently than one per second. An
1526 implementation MAY adjust the rate at which it sends KEEPALIVE
1527 messages as a function of the Hold Time interval. */
1528
1529 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
1530 send_holdtime = peer->holdtime;
1531 else
1532 send_holdtime = peer->bgp->default_holdtime;
1533
1534 if (holdtime < send_holdtime)
1535 peer->v_holdtime = holdtime;
1536 else
1537 peer->v_holdtime = send_holdtime;
1538
1539 peer->v_keepalive = peer->v_holdtime / 3;
1540
1541 /* Open option part parse. */
paul718e3742002-12-13 20:15:29 +00001542 if (optlen != 0)
1543 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001544 if ((ret = bgp_open_option_parse (peer, optlen, &mp_capability)) < 0)
Paul Jakma58617392012-01-09 20:59:26 +00001545 {
1546 bgp_notify_send (peer,
1547 BGP_NOTIFY_OPEN_ERR,
1548 BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
1549 return ret;
1550 }
paul718e3742002-12-13 20:15:29 +00001551 }
1552 else
1553 {
1554 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001555 zlog_debug ("%s rcvd OPEN w/ OPTION parameter len: 0",
paul718e3742002-12-13 20:15:29 +00001556 peer->host);
1557 }
1558
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001559 /*
1560 * Assume that the peer supports the locally configured set of
1561 * AFI/SAFIs if the peer did not send us any Mulitiprotocol
1562 * capabilities, or if 'override-capability' is configured.
1563 */
1564 if (! mp_capability ||
1565 CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
paul718e3742002-12-13 20:15:29 +00001566 {
1567 peer->afc_nego[AFI_IP][SAFI_UNICAST] = peer->afc[AFI_IP][SAFI_UNICAST];
1568 peer->afc_nego[AFI_IP][SAFI_MULTICAST] = peer->afc[AFI_IP][SAFI_MULTICAST];
1569 peer->afc_nego[AFI_IP6][SAFI_UNICAST] = peer->afc[AFI_IP6][SAFI_UNICAST];
1570 peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = peer->afc[AFI_IP6][SAFI_MULTICAST];
1571 }
1572
1573 /* Get sockname. */
1574 bgp_getsockname (peer);
1575
1576 BGP_EVENT_ADD (peer, Receive_OPEN_message);
1577
1578 peer->packet_size = 0;
1579 if (peer->ibuf)
1580 stream_reset (peer->ibuf);
1581
1582 return 0;
1583}
1584
1585/* Parse BGP Update packet and make attribute object. */
paul94f2b392005-06-28 12:44:16 +00001586static int
paul718e3742002-12-13 20:15:29 +00001587bgp_update_receive (struct peer *peer, bgp_size_t size)
1588{
1589 int ret;
1590 u_char *end;
1591 struct stream *s;
1592 struct attr attr;
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001593 struct attr_extra extra;
paul718e3742002-12-13 20:15:29 +00001594 bgp_size_t attribute_len;
1595 bgp_size_t update_len;
1596 bgp_size_t withdraw_len;
1597 struct bgp_nlri update;
1598 struct bgp_nlri withdraw;
1599 struct bgp_nlri mp_update;
1600 struct bgp_nlri mp_withdraw;
paul718e3742002-12-13 20:15:29 +00001601
1602 /* Status must be Established. */
1603 if (peer->status != Established)
1604 {
1605 zlog_err ("%s [FSM] Update packet received under status %s",
1606 peer->host, LOOKUP (bgp_status_msg, peer->status));
1607 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
1608 return -1;
1609 }
1610
1611 /* Set initial values. */
1612 memset (&attr, 0, sizeof (struct attr));
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001613 memset (&extra, 0, sizeof (struct attr_extra));
paul718e3742002-12-13 20:15:29 +00001614 memset (&update, 0, sizeof (struct bgp_nlri));
1615 memset (&withdraw, 0, sizeof (struct bgp_nlri));
1616 memset (&mp_update, 0, sizeof (struct bgp_nlri));
1617 memset (&mp_withdraw, 0, sizeof (struct bgp_nlri));
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001618 attr.extra = &extra;
paul718e3742002-12-13 20:15:29 +00001619
1620 s = peer->ibuf;
1621 end = stream_pnt (s) + size;
1622
1623 /* RFC1771 6.3 If the Unfeasible Routes Length or Total Attribute
1624 Length is too large (i.e., if Unfeasible Routes Length + Total
1625 Attribute Length + 23 exceeds the message Length), then the Error
1626 Subcode is set to Malformed Attribute List. */
1627 if (stream_pnt (s) + 2 > end)
1628 {
1629 zlog_err ("%s [Error] Update packet error"
1630 " (packet length is short for unfeasible length)",
1631 peer->host);
1632 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1633 BGP_NOTIFY_UPDATE_MAL_ATTR);
1634 return -1;
1635 }
1636
1637 /* Unfeasible Route Length. */
1638 withdraw_len = stream_getw (s);
1639
1640 /* Unfeasible Route Length check. */
1641 if (stream_pnt (s) + withdraw_len > end)
1642 {
1643 zlog_err ("%s [Error] Update packet error"
1644 " (packet unfeasible length overflow %d)",
1645 peer->host, withdraw_len);
1646 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1647 BGP_NOTIFY_UPDATE_MAL_ATTR);
1648 return -1;
1649 }
1650
1651 /* Unfeasible Route packet format check. */
1652 if (withdraw_len > 0)
1653 {
1654 ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), withdraw_len);
1655 if (ret < 0)
1656 return -1;
1657
1658 if (BGP_DEBUG (packet, PACKET_RECV))
ajs6b514742004-12-08 21:03:23 +00001659 zlog_debug ("%s [Update:RECV] Unfeasible NLRI received", peer->host);
paul718e3742002-12-13 20:15:29 +00001660
1661 withdraw.afi = AFI_IP;
1662 withdraw.safi = SAFI_UNICAST;
1663 withdraw.nlri = stream_pnt (s);
1664 withdraw.length = withdraw_len;
paul9985f832005-02-09 15:51:56 +00001665 stream_forward_getp (s, withdraw_len);
paul718e3742002-12-13 20:15:29 +00001666 }
1667
1668 /* Attribute total length check. */
1669 if (stream_pnt (s) + 2 > end)
1670 {
1671 zlog_warn ("%s [Error] Packet Error"
1672 " (update packet is short for attribute length)",
1673 peer->host);
1674 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1675 BGP_NOTIFY_UPDATE_MAL_ATTR);
1676 return -1;
1677 }
1678
1679 /* Fetch attribute total length. */
1680 attribute_len = stream_getw (s);
1681
1682 /* Attribute length check. */
1683 if (stream_pnt (s) + attribute_len > end)
1684 {
1685 zlog_warn ("%s [Error] Packet Error"
1686 " (update packet attribute length overflow %d)",
1687 peer->host, attribute_len);
1688 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1689 BGP_NOTIFY_UPDATE_MAL_ATTR);
1690 return -1;
1691 }
Paul Jakmab881c702010-11-23 16:35:42 +00001692
1693 /* Certain attribute parsing errors should not be considered bad enough
1694 * to reset the session for, most particularly any partial/optional
1695 * attributes that have 'tunneled' over speakers that don't understand
1696 * them. Instead we withdraw only the prefix concerned.
1697 *
1698 * Complicates the flow a little though..
1699 */
1700 bgp_attr_parse_ret_t attr_parse_ret = BGP_ATTR_PARSE_PROCEED;
1701 /* This define morphs the update case into a withdraw when lower levels
1702 * have signalled an error condition where this is best.
1703 */
1704#define NLRI_ATTR_ARG (attr_parse_ret != BGP_ATTR_PARSE_WITHDRAW ? &attr : NULL)
paul718e3742002-12-13 20:15:29 +00001705
1706 /* Parse attribute when it exists. */
1707 if (attribute_len)
1708 {
Paul Jakmab881c702010-11-23 16:35:42 +00001709 attr_parse_ret = bgp_attr_parse (peer, &attr, attribute_len,
paul718e3742002-12-13 20:15:29 +00001710 &mp_update, &mp_withdraw);
Paul Jakmab881c702010-11-23 16:35:42 +00001711 if (attr_parse_ret == BGP_ATTR_PARSE_ERROR)
David Lamparterf80f8382014-06-04 01:00:51 +02001712 {
1713 bgp_attr_unintern_sub (&attr);
1714 return -1;
1715 }
paul718e3742002-12-13 20:15:29 +00001716 }
Paul Jakmab881c702010-11-23 16:35:42 +00001717
paul718e3742002-12-13 20:15:29 +00001718 /* Logging the attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001719 if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW
1720 || BGP_DEBUG (update, UPDATE_IN))
paul718e3742002-12-13 20:15:29 +00001721 {
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +00001722 char attrstr[BUFSIZ];
1723 attrstr[0] = '\0';
1724
paule01f9cb2004-07-09 17:48:53 +00001725 ret= bgp_dump_attr (peer, &attr, attrstr, BUFSIZ);
Paul Jakmab881c702010-11-23 16:35:42 +00001726 int lvl = (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
1727 ? LOG_ERR : LOG_DEBUG;
1728
1729 if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
1730 zlog (peer->log, LOG_ERR,
1731 "%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.",
1732 peer->host);
paule01f9cb2004-07-09 17:48:53 +00001733
1734 if (ret)
Paul Jakmab881c702010-11-23 16:35:42 +00001735 zlog (peer->log, lvl, "%s rcvd UPDATE w/ attr: %s",
paule01f9cb2004-07-09 17:48:53 +00001736 peer->host, attrstr);
paul718e3742002-12-13 20:15:29 +00001737 }
Paul Jakmab881c702010-11-23 16:35:42 +00001738
paul718e3742002-12-13 20:15:29 +00001739 /* Network Layer Reachability Information. */
1740 update_len = end - stream_pnt (s);
1741
1742 if (update_len)
1743 {
1744 /* Check NLRI packet format and prefix length. */
1745 ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), update_len);
1746 if (ret < 0)
Paul Jakmab881c702010-11-23 16:35:42 +00001747 {
1748 bgp_attr_unintern_sub (&attr);
Paul Jakmab881c702010-11-23 16:35:42 +00001749 return -1;
1750 }
paul718e3742002-12-13 20:15:29 +00001751
1752 /* Set NLRI portion to structure. */
1753 update.afi = AFI_IP;
1754 update.safi = SAFI_UNICAST;
1755 update.nlri = stream_pnt (s);
1756 update.length = update_len;
paul9985f832005-02-09 15:51:56 +00001757 stream_forward_getp (s, update_len);
paul718e3742002-12-13 20:15:29 +00001758 }
1759
1760 /* NLRI is processed only when the peer is configured specific
1761 Address Family and Subsequent Address Family. */
1762 if (peer->afc[AFI_IP][SAFI_UNICAST])
1763 {
1764 if (withdraw.length)
1765 bgp_nlri_parse (peer, NULL, &withdraw);
1766
1767 if (update.length)
Paul Jakmab881c702010-11-23 16:35:42 +00001768 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &update);
paule01f9cb2004-07-09 17:48:53 +00001769
hassof4184462005-02-01 20:13:16 +00001770 if (mp_update.length
1771 && mp_update.afi == AFI_IP
1772 && mp_update.safi == SAFI_UNICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001773 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
hassof4184462005-02-01 20:13:16 +00001774
1775 if (mp_withdraw.length
1776 && mp_withdraw.afi == AFI_IP
1777 && mp_withdraw.safi == SAFI_UNICAST)
1778 bgp_nlri_parse (peer, NULL, &mp_withdraw);
1779
paule01f9cb2004-07-09 17:48:53 +00001780 if (! attribute_len && ! withdraw_len)
1781 {
1782 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001783 SET_FLAG (peer->af_sflags[AFI_IP][SAFI_UNICAST],
1784 PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001785
hasso93406d82005-02-02 14:40:33 +00001786 /* NSF delete stale route */
1787 if (peer->nsf[AFI_IP][SAFI_UNICAST])
1788 bgp_clear_stale_route (peer, AFI_IP, SAFI_UNICAST);
1789
1790 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001791 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001792 peer->host);
1793 }
paul718e3742002-12-13 20:15:29 +00001794 }
1795 if (peer->afc[AFI_IP][SAFI_MULTICAST])
1796 {
1797 if (mp_update.length
1798 && mp_update.afi == AFI_IP
1799 && mp_update.safi == SAFI_MULTICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001800 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001801
1802 if (mp_withdraw.length
1803 && mp_withdraw.afi == AFI_IP
1804 && mp_withdraw.safi == SAFI_MULTICAST)
1805 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001806
hasso93406d82005-02-02 14:40:33 +00001807 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001808 && mp_withdraw.afi == AFI_IP
1809 && mp_withdraw.safi == SAFI_MULTICAST
1810 && mp_withdraw.length == 0)
1811 {
1812 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001813 SET_FLAG (peer->af_sflags[AFI_IP][SAFI_MULTICAST],
1814 PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001815
hasso93406d82005-02-02 14:40:33 +00001816 /* NSF delete stale route */
1817 if (peer->nsf[AFI_IP][SAFI_MULTICAST])
1818 bgp_clear_stale_route (peer, AFI_IP, SAFI_MULTICAST);
1819
1820 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001821 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Multicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001822 peer->host);
1823 }
paul718e3742002-12-13 20:15:29 +00001824 }
1825 if (peer->afc[AFI_IP6][SAFI_UNICAST])
1826 {
1827 if (mp_update.length
1828 && mp_update.afi == AFI_IP6
1829 && mp_update.safi == SAFI_UNICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001830 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001831
1832 if (mp_withdraw.length
1833 && mp_withdraw.afi == AFI_IP6
1834 && mp_withdraw.safi == SAFI_UNICAST)
1835 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001836
hasso93406d82005-02-02 14:40:33 +00001837 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001838 && mp_withdraw.afi == AFI_IP6
1839 && mp_withdraw.safi == SAFI_UNICAST
1840 && mp_withdraw.length == 0)
1841 {
1842 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001843 SET_FLAG (peer->af_sflags[AFI_IP6][SAFI_UNICAST], PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001844
hasso93406d82005-02-02 14:40:33 +00001845 /* NSF delete stale route */
1846 if (peer->nsf[AFI_IP6][SAFI_UNICAST])
1847 bgp_clear_stale_route (peer, AFI_IP6, SAFI_UNICAST);
1848
1849 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001850 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001851 peer->host);
1852 }
paul718e3742002-12-13 20:15:29 +00001853 }
1854 if (peer->afc[AFI_IP6][SAFI_MULTICAST])
1855 {
1856 if (mp_update.length
1857 && mp_update.afi == AFI_IP6
1858 && mp_update.safi == SAFI_MULTICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001859 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001860
1861 if (mp_withdraw.length
1862 && mp_withdraw.afi == AFI_IP6
1863 && mp_withdraw.safi == SAFI_MULTICAST)
1864 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001865
hasso93406d82005-02-02 14:40:33 +00001866 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001867 && mp_withdraw.afi == AFI_IP6
1868 && mp_withdraw.safi == SAFI_MULTICAST
1869 && mp_withdraw.length == 0)
1870 {
1871 /* End-of-RIB received */
1872
hasso93406d82005-02-02 14:40:33 +00001873 /* NSF delete stale route */
1874 if (peer->nsf[AFI_IP6][SAFI_MULTICAST])
1875 bgp_clear_stale_route (peer, AFI_IP6, SAFI_MULTICAST);
1876
paule01f9cb2004-07-09 17:48:53 +00001877 if (BGP_DEBUG (update, UPDATE_IN))
ajs6b514742004-12-08 21:03:23 +00001878 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Multicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001879 peer->host);
1880 }
paul718e3742002-12-13 20:15:29 +00001881 }
1882 if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
1883 {
1884 if (mp_update.length
1885 && mp_update.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001886 && mp_update.safi == SAFI_MPLS_LABELED_VPN)
Paul Jakmab881c702010-11-23 16:35:42 +00001887 bgp_nlri_parse_vpnv4 (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001888
1889 if (mp_withdraw.length
1890 && mp_withdraw.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001891 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00001892 bgp_nlri_parse_vpnv4 (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001893
hasso93406d82005-02-02 14:40:33 +00001894 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001895 && mp_withdraw.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001896 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN
paule01f9cb2004-07-09 17:48:53 +00001897 && mp_withdraw.length == 0)
1898 {
1899 /* End-of-RIB received */
1900
1901 if (BGP_DEBUG (update, UPDATE_IN))
ajs6b514742004-12-08 21:03:23 +00001902 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for VPNv4 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001903 peer->host);
1904 }
paul718e3742002-12-13 20:15:29 +00001905 }
1906
1907 /* Everything is done. We unintern temporary structures which
1908 interned in bgp_attr_parse(). */
Paul Jakmab881c702010-11-23 16:35:42 +00001909 bgp_attr_unintern_sub (&attr);
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001910
paul718e3742002-12-13 20:15:29 +00001911 /* If peering is stopped due to some reason, do not generate BGP
1912 event. */
1913 if (peer->status != Established)
1914 return 0;
1915
1916 /* Increment packet counter. */
1917 peer->update_in++;
Stephen Hemminger65957882010-01-15 16:22:10 +03001918 peer->update_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00001919
Jorge Boncompte [DTI2]e2c38e62012-06-20 17:45:50 +02001920 /* Rearm holdtime timer */
Jorge Boncompte [DTI2]6a4677b2012-05-07 16:53:07 +00001921 BGP_TIMER_OFF (peer->t_holdtime);
Jorge Boncompte [DTI2]e2c38e62012-06-20 17:45:50 +02001922 bgp_timer_set (peer);
paul718e3742002-12-13 20:15:29 +00001923
1924 return 0;
1925}
1926
1927/* Notify message treatment function. */
paul94f2b392005-06-28 12:44:16 +00001928static void
paul718e3742002-12-13 20:15:29 +00001929bgp_notify_receive (struct peer *peer, bgp_size_t size)
1930{
1931 struct bgp_notify bgp_notify;
1932
1933 if (peer->notify.data)
1934 {
1935 XFREE (MTYPE_TMP, peer->notify.data);
1936 peer->notify.data = NULL;
1937 peer->notify.length = 0;
1938 }
1939
1940 bgp_notify.code = stream_getc (peer->ibuf);
1941 bgp_notify.subcode = stream_getc (peer->ibuf);
1942 bgp_notify.length = size - 2;
1943 bgp_notify.data = NULL;
1944
1945 /* Preserv notify code and sub code. */
1946 peer->notify.code = bgp_notify.code;
1947 peer->notify.subcode = bgp_notify.subcode;
1948 /* For further diagnostic record returned Data. */
1949 if (bgp_notify.length)
1950 {
1951 peer->notify.length = size - 2;
1952 peer->notify.data = XMALLOC (MTYPE_TMP, size - 2);
1953 memcpy (peer->notify.data, stream_pnt (peer->ibuf), size - 2);
1954 }
1955
1956 /* For debug */
1957 {
1958 int i;
1959 int first = 0;
1960 char c[4];
1961
1962 if (bgp_notify.length)
1963 {
1964 bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
1965 for (i = 0; i < bgp_notify.length; i++)
1966 if (first)
1967 {
1968 sprintf (c, " %02x", stream_getc (peer->ibuf));
1969 strcat (bgp_notify.data, c);
1970 }
1971 else
1972 {
1973 first = 1;
1974 sprintf (c, "%02x", stream_getc (peer->ibuf));
1975 strcpy (bgp_notify.data, c);
1976 }
1977 }
1978
1979 bgp_notify_print(peer, &bgp_notify, "received");
1980 if (bgp_notify.data)
Daniel Walton363c9032015-10-21 06:42:54 -07001981 {
1982 XFREE (MTYPE_TMP, bgp_notify.data);
1983 bgp_notify.data = NULL;
1984 bgp_notify.length = 0;
1985 }
paul718e3742002-12-13 20:15:29 +00001986 }
1987
1988 /* peer count update */
1989 peer->notify_in++;
1990
hassoe0701b72004-05-20 09:19:34 +00001991 if (peer->status == Established)
1992 peer->last_reset = PEER_DOWN_NOTIFY_RECEIVED;
1993
paul718e3742002-12-13 20:15:29 +00001994 /* We have to check for Notify with Unsupported Optional Parameter.
1995 in that case we fallback to open without the capability option.
1996 But this done in bgp_stop. We just mark it here to avoid changing
1997 the fsm tables. */
1998 if (bgp_notify.code == BGP_NOTIFY_OPEN_ERR &&
1999 bgp_notify.subcode == BGP_NOTIFY_OPEN_UNSUP_PARAM )
2000 UNSET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
2001
paul718e3742002-12-13 20:15:29 +00002002 BGP_EVENT_ADD (peer, Receive_NOTIFICATION_message);
2003}
2004
2005/* Keepalive treatment function -- get keepalive send keepalive */
paul94f2b392005-06-28 12:44:16 +00002006static void
paul718e3742002-12-13 20:15:29 +00002007bgp_keepalive_receive (struct peer *peer, bgp_size_t size)
2008{
2009 if (BGP_DEBUG (keepalive, KEEPALIVE))
ajs6b514742004-12-08 21:03:23 +00002010 zlog_debug ("%s KEEPALIVE rcvd", peer->host);
paul718e3742002-12-13 20:15:29 +00002011
2012 BGP_EVENT_ADD (peer, Receive_KEEPALIVE_message);
2013}
2014
2015/* Route refresh message is received. */
paul94f2b392005-06-28 12:44:16 +00002016static void
paul718e3742002-12-13 20:15:29 +00002017bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
2018{
2019 afi_t afi;
2020 safi_t safi;
paul718e3742002-12-13 20:15:29 +00002021 struct stream *s;
2022
2023 /* If peer does not have the capability, send notification. */
2024 if (! CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_ADV))
2025 {
2026 plog_err (peer->log, "%s [Error] BGP route refresh is not enabled",
2027 peer->host);
2028 bgp_notify_send (peer,
2029 BGP_NOTIFY_HEADER_ERR,
2030 BGP_NOTIFY_HEADER_BAD_MESTYPE);
2031 return;
2032 }
2033
2034 /* Status must be Established. */
2035 if (peer->status != Established)
2036 {
2037 plog_err (peer->log,
2038 "%s [Error] Route refresh packet received under status %s",
2039 peer->host, LOOKUP (bgp_status_msg, peer->status));
2040 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
2041 return;
2042 }
2043
2044 s = peer->ibuf;
2045
2046 /* Parse packet. */
2047 afi = stream_getw (s);
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002048 /* reserved byte */
2049 stream_getc (s);
paul718e3742002-12-13 20:15:29 +00002050 safi = stream_getc (s);
2051
2052 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002053 zlog_debug ("%s rcvd REFRESH_REQ for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00002054 peer->host, afi, safi);
2055
2056 /* Check AFI and SAFI. */
2057 if ((afi != AFI_IP && afi != AFI_IP6)
2058 || (safi != SAFI_UNICAST && safi != SAFI_MULTICAST
Denis Ovsienko42e6d742011-07-14 12:36:19 +04002059 && safi != SAFI_MPLS_LABELED_VPN))
paul718e3742002-12-13 20:15:29 +00002060 {
2061 if (BGP_DEBUG (normal, NORMAL))
2062 {
ajs6b514742004-12-08 21:03:23 +00002063 zlog_debug ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored",
paul718e3742002-12-13 20:15:29 +00002064 peer->host, afi, safi);
2065 }
2066 return;
2067 }
2068
2069 /* Adjust safi code. */
Denis Ovsienko42e6d742011-07-14 12:36:19 +04002070 if (safi == SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00002071 safi = SAFI_MPLS_VPN;
2072
2073 if (size != BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE)
2074 {
2075 u_char *end;
2076 u_char when_to_refresh;
2077 u_char orf_type;
2078 u_int16_t orf_len;
2079
2080 if (size - (BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE) < 5)
2081 {
2082 zlog_info ("%s ORF route refresh length error", peer->host);
2083 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2084 return;
2085 }
2086
2087 when_to_refresh = stream_getc (s);
2088 end = stream_pnt (s) + (size - 5);
2089
Paul Jakma370b64a2007-12-22 16:49:52 +00002090 while ((stream_pnt (s) + 2) < end)
paul718e3742002-12-13 20:15:29 +00002091 {
2092 orf_type = stream_getc (s);
2093 orf_len = stream_getw (s);
Paul Jakma370b64a2007-12-22 16:49:52 +00002094
2095 /* orf_len in bounds? */
2096 if ((stream_pnt (s) + orf_len) > end)
2097 break; /* XXX: Notify instead?? */
paul718e3742002-12-13 20:15:29 +00002098 if (orf_type == ORF_TYPE_PREFIX
2099 || orf_type == ORF_TYPE_PREFIX_OLD)
2100 {
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002101 uint8_t *p_pnt = stream_pnt (s);
2102 uint8_t *p_end = stream_pnt (s) + orf_len;
paul718e3742002-12-13 20:15:29 +00002103 struct orf_prefix orfp;
2104 u_char common = 0;
2105 u_int32_t seq;
2106 int psize;
2107 char name[BUFSIZ];
paul718e3742002-12-13 20:15:29 +00002108 int ret;
2109
2110 if (BGP_DEBUG (normal, NORMAL))
2111 {
ajs6b514742004-12-08 21:03:23 +00002112 zlog_debug ("%s rcvd Prefixlist ORF(%d) length %d",
paul718e3742002-12-13 20:15:29 +00002113 peer->host, orf_type, orf_len);
2114 }
2115
Paul Jakma370b64a2007-12-22 16:49:52 +00002116 /* we're going to read at least 1 byte of common ORF header,
2117 * and 7 bytes of ORF Address-filter entry from the stream
2118 */
2119 if (orf_len < 7)
2120 break;
2121
paul718e3742002-12-13 20:15:29 +00002122 /* ORF prefix-list name */
2123 sprintf (name, "%s.%d.%d", peer->host, afi, safi);
2124
2125 while (p_pnt < p_end)
2126 {
Chris Halld64379e2010-05-14 16:38:39 +04002127 /* If the ORF entry is malformed, want to read as much of it
2128 * as possible without going beyond the bounds of the entry,
2129 * to maximise debug information.
2130 */
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002131 int ok;
paul718e3742002-12-13 20:15:29 +00002132 memset (&orfp, 0, sizeof (struct orf_prefix));
2133 common = *p_pnt++;
Chris Halld64379e2010-05-14 16:38:39 +04002134 /* after ++: p_pnt <= p_end */
paul718e3742002-12-13 20:15:29 +00002135 if (common & ORF_COMMON_PART_REMOVE_ALL)
2136 {
2137 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002138 zlog_debug ("%s rcvd Remove-All pfxlist ORF request", peer->host);
David Lamparterc9c06d02015-04-13 10:21:35 +02002139 prefix_bgp_orf_remove_all (afi, name);
paul718e3742002-12-13 20:15:29 +00002140 break;
2141 }
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002142 ok = ((size_t)(p_end - p_pnt) >= sizeof(u_int32_t)) ;
Denis Ovsienkobb915f52011-12-13 21:11:39 +04002143 if (ok)
Chris Halld64379e2010-05-14 16:38:39 +04002144 {
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002145 memcpy (&seq, p_pnt, sizeof (u_int32_t));
2146 p_pnt += sizeof (u_int32_t);
2147 orfp.seq = ntohl (seq);
Chris Halld64379e2010-05-14 16:38:39 +04002148 }
2149 else
2150 p_pnt = p_end ;
2151
2152 if ((ok = (p_pnt < p_end)))
2153 orfp.ge = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */
2154 if ((ok = (p_pnt < p_end)))
2155 orfp.le = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */
2156 if ((ok = (p_pnt < p_end)))
2157 orfp.p.prefixlen = *p_pnt++ ;
2158 orfp.p.family = afi2family (afi); /* afi checked already */
2159
2160 psize = PSIZE (orfp.p.prefixlen); /* 0 if not ok */
2161 if (psize > prefix_blen(&orfp.p)) /* valid for family ? */
2162 {
2163 ok = 0 ;
2164 psize = prefix_blen(&orfp.p) ;
2165 }
2166 if (psize > (p_end - p_pnt)) /* valid for packet ? */
2167 {
2168 ok = 0 ;
2169 psize = p_end - p_pnt ;
2170 }
2171
2172 if (psize > 0)
2173 memcpy (&orfp.p.u.prefix, p_pnt, psize);
paul718e3742002-12-13 20:15:29 +00002174 p_pnt += psize;
2175
2176 if (BGP_DEBUG (normal, NORMAL))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +00002177 {
2178 char buf[INET6_BUFSIZ];
2179
2180 zlog_debug ("%s rcvd %s %s seq %u %s/%d ge %d le %d%s",
2181 peer->host,
2182 (common & ORF_COMMON_PART_REMOVE ? "Remove" : "Add"),
2183 (common & ORF_COMMON_PART_DENY ? "deny" : "permit"),
2184 orfp.seq,
2185 inet_ntop (orfp.p.family, &orfp.p.u.prefix, buf, INET6_BUFSIZ),
2186 orfp.p.prefixlen, orfp.ge, orfp.le,
2187 ok ? "" : " MALFORMED");
2188 }
2189
Chris Halld64379e2010-05-14 16:38:39 +04002190 if (ok)
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002191 ret = prefix_bgp_orf_set (name, afi, &orfp,
2192 (common & ORF_COMMON_PART_DENY ? 0 : 1 ),
2193 (common & ORF_COMMON_PART_REMOVE ? 0 : 1));
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002194
2195 if (!ok || (ok && ret != CMD_SUCCESS))
paul718e3742002-12-13 20:15:29 +00002196 {
2197 if (BGP_DEBUG (normal, NORMAL))
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002198 zlog_debug ("%s Received misformatted prefixlist ORF."
2199 " Remove All pfxlist", peer->host);
David Lamparterc9c06d02015-04-13 10:21:35 +02002200 prefix_bgp_orf_remove_all (afi, name);
paul718e3742002-12-13 20:15:29 +00002201 break;
2202 }
2203 }
2204 peer->orf_plist[afi][safi] =
David Lamparterc9c06d02015-04-13 10:21:35 +02002205 prefix_bgp_orf_lookup (afi, name);
paul718e3742002-12-13 20:15:29 +00002206 }
paul9985f832005-02-09 15:51:56 +00002207 stream_forward_getp (s, orf_len);
paul718e3742002-12-13 20:15:29 +00002208 }
2209 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002210 zlog_debug ("%s rcvd Refresh %s ORF request", peer->host,
paul718e3742002-12-13 20:15:29 +00002211 when_to_refresh == REFRESH_DEFER ? "Defer" : "Immediate");
2212 if (when_to_refresh == REFRESH_DEFER)
2213 return;
2214 }
2215
2216 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2217 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH))
2218 UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
2219
2220 /* Perform route refreshment to the peer */
2221 bgp_announce_route (peer, afi, safi);
2222}
2223
paul94f2b392005-06-28 12:44:16 +00002224static int
paul718e3742002-12-13 20:15:29 +00002225bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
2226{
2227 u_char *end;
Paul Jakma6d582722007-08-06 15:21:45 +00002228 struct capability_mp_data mpc;
2229 struct capability_header *hdr;
paul718e3742002-12-13 20:15:29 +00002230 u_char action;
paul718e3742002-12-13 20:15:29 +00002231 afi_t afi;
2232 safi_t safi;
2233
paul718e3742002-12-13 20:15:29 +00002234 end = pnt + length;
2235
2236 while (pnt < end)
Paul Jakma6d582722007-08-06 15:21:45 +00002237 {
paul718e3742002-12-13 20:15:29 +00002238 /* We need at least action, capability code and capability length. */
2239 if (pnt + 3 > end)
2240 {
2241 zlog_info ("%s Capability length error", peer->host);
2242 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2243 return -1;
2244 }
paul718e3742002-12-13 20:15:29 +00002245 action = *pnt;
Paul Jakma6d582722007-08-06 15:21:45 +00002246 hdr = (struct capability_header *)(pnt + 1);
2247
paul718e3742002-12-13 20:15:29 +00002248 /* Action value check. */
2249 if (action != CAPABILITY_ACTION_SET
2250 && action != CAPABILITY_ACTION_UNSET)
2251 {
2252 zlog_info ("%s Capability Action Value error %d",
2253 peer->host, action);
2254 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2255 return -1;
2256 }
2257
2258 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002259 zlog_debug ("%s CAPABILITY has action: %d, code: %u, length %u",
Paul Jakma6d582722007-08-06 15:21:45 +00002260 peer->host, action, hdr->code, hdr->length);
paul718e3742002-12-13 20:15:29 +00002261
2262 /* Capability length check. */
Paul Jakma6d582722007-08-06 15:21:45 +00002263 if ((pnt + hdr->length + 3) > end)
paul718e3742002-12-13 20:15:29 +00002264 {
2265 zlog_info ("%s Capability length error", peer->host);
2266 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2267 return -1;
2268 }
2269
Paul Jakma6d582722007-08-06 15:21:45 +00002270 /* Fetch structure to the byte stream. */
2271 memcpy (&mpc, pnt + 3, sizeof (struct capability_mp_data));
2272
paul718e3742002-12-13 20:15:29 +00002273 /* We know MP Capability Code. */
Paul Jakma6d582722007-08-06 15:21:45 +00002274 if (hdr->code == CAPABILITY_CODE_MP)
paul718e3742002-12-13 20:15:29 +00002275 {
Paul Jakma6d582722007-08-06 15:21:45 +00002276 afi = ntohs (mpc.afi);
2277 safi = mpc.safi;
paul718e3742002-12-13 20:15:29 +00002278
2279 /* Ignore capability when override-capability is set. */
2280 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
2281 continue;
Paul Jakma6d582722007-08-06 15:21:45 +00002282
2283 if (!bgp_afi_safi_valid_indices (afi, &safi))
2284 {
2285 if (BGP_DEBUG (normal, NORMAL))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002286 zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid "
2287 "(%u/%u)", peer->host, afi, safi);
Paul Jakma6d582722007-08-06 15:21:45 +00002288 continue;
2289 }
2290
paul718e3742002-12-13 20:15:29 +00002291 /* Address family check. */
Paul Jakma6d582722007-08-06 15:21:45 +00002292 if (BGP_DEBUG (normal, NORMAL))
2293 zlog_debug ("%s CAPABILITY has %s MP_EXT CAP for afi/safi: %u/%u",
2294 peer->host,
2295 action == CAPABILITY_ACTION_SET
2296 ? "Advertising" : "Removing",
2297 ntohs(mpc.afi) , mpc.safi);
2298
2299 if (action == CAPABILITY_ACTION_SET)
2300 {
2301 peer->afc_recv[afi][safi] = 1;
2302 if (peer->afc[afi][safi])
2303 {
2304 peer->afc_nego[afi][safi] = 1;
2305 bgp_announce_route (peer, afi, safi);
2306 }
2307 }
2308 else
2309 {
2310 peer->afc_recv[afi][safi] = 0;
2311 peer->afc_nego[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00002312
Paul Jakma6d582722007-08-06 15:21:45 +00002313 if (peer_active_nego (peer))
Chris Caputo228da422009-07-18 05:44:03 +00002314 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
Paul Jakma6d582722007-08-06 15:21:45 +00002315 else
2316 BGP_EVENT_ADD (peer, BGP_Stop);
2317 }
paul718e3742002-12-13 20:15:29 +00002318 }
paul718e3742002-12-13 20:15:29 +00002319 else
2320 {
2321 zlog_warn ("%s unrecognized capability code: %d - ignored",
Paul Jakma6d582722007-08-06 15:21:45 +00002322 peer->host, hdr->code);
paul718e3742002-12-13 20:15:29 +00002323 }
Paul Jakma6d582722007-08-06 15:21:45 +00002324 pnt += hdr->length + 3;
paul718e3742002-12-13 20:15:29 +00002325 }
2326 return 0;
2327}
2328
Paul Jakma01b7ce22009-06-18 12:34:43 +01002329/* Dynamic Capability is received.
2330 *
2331 * This is exported for unit-test purposes
2332 */
Paul Jakma6d582722007-08-06 15:21:45 +00002333int
paul718e3742002-12-13 20:15:29 +00002334bgp_capability_receive (struct peer *peer, bgp_size_t size)
2335{
2336 u_char *pnt;
paul718e3742002-12-13 20:15:29 +00002337
2338 /* Fetch pointer. */
2339 pnt = stream_pnt (peer->ibuf);
2340
2341 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002342 zlog_debug ("%s rcv CAPABILITY", peer->host);
paul718e3742002-12-13 20:15:29 +00002343
2344 /* If peer does not have the capability, send notification. */
2345 if (! CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV))
2346 {
2347 plog_err (peer->log, "%s [Error] BGP dynamic capability is not enabled",
2348 peer->host);
2349 bgp_notify_send (peer,
2350 BGP_NOTIFY_HEADER_ERR,
2351 BGP_NOTIFY_HEADER_BAD_MESTYPE);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002352 return -1;
paul718e3742002-12-13 20:15:29 +00002353 }
2354
2355 /* Status must be Established. */
2356 if (peer->status != Established)
2357 {
2358 plog_err (peer->log,
2359 "%s [Error] Dynamic capability packet received under status %s", peer->host, LOOKUP (bgp_status_msg, peer->status));
2360 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002361 return -1;
paul718e3742002-12-13 20:15:29 +00002362 }
2363
2364 /* Parse packet. */
Paul Jakma6d582722007-08-06 15:21:45 +00002365 return bgp_capability_msg_parse (peer, pnt, size);
paul718e3742002-12-13 20:15:29 +00002366}
David Lamparter6b0655a2014-06-04 06:53:35 +02002367
paul718e3742002-12-13 20:15:29 +00002368/* BGP read utility function. */
paul94f2b392005-06-28 12:44:16 +00002369static int
paul718e3742002-12-13 20:15:29 +00002370bgp_read_packet (struct peer *peer)
2371{
2372 int nbytes;
2373 int readsize;
2374
paul9985f832005-02-09 15:51:56 +00002375 readsize = peer->packet_size - stream_get_endp (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00002376
2377 /* If size is zero then return. */
2378 if (! readsize)
2379 return 0;
2380
2381 /* Read packet from fd. */
Stephen Hemminger35398582010-08-05 10:26:23 -07002382 nbytes = stream_read_try (peer->ibuf, peer->fd, readsize);
paul718e3742002-12-13 20:15:29 +00002383
2384 /* If read byte is smaller than zero then error occured. */
2385 if (nbytes < 0)
2386 {
Stephen Hemminger35398582010-08-05 10:26:23 -07002387 /* Transient error should retry */
2388 if (nbytes == -2)
paul718e3742002-12-13 20:15:29 +00002389 return -1;
2390
2391 plog_err (peer->log, "%s [Error] bgp_read_packet error: %s",
ajs6099b3b2004-11-20 02:06:59 +00002392 peer->host, safe_strerror (errno));
hasso93406d82005-02-02 14:40:33 +00002393
2394 if (peer->status == Established)
2395 {
2396 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
2397 {
2398 peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
2399 SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
2400 }
2401 else
2402 peer->last_reset = PEER_DOWN_CLOSE_SESSION;
2403 }
2404
paul718e3742002-12-13 20:15:29 +00002405 BGP_EVENT_ADD (peer, TCP_fatal_error);
2406 return -1;
2407 }
2408
2409 /* When read byte is zero : clear bgp peer and return */
2410 if (nbytes == 0)
2411 {
2412 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +00002413 plog_debug (peer->log, "%s [Event] BGP connection closed fd %d",
pauleb821182004-05-01 08:44:08 +00002414 peer->host, peer->fd);
hassoe0701b72004-05-20 09:19:34 +00002415
2416 if (peer->status == Established)
hasso93406d82005-02-02 14:40:33 +00002417 {
2418 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
2419 {
2420 peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
2421 SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
2422 }
2423 else
2424 peer->last_reset = PEER_DOWN_CLOSE_SESSION;
2425 }
hassoe0701b72004-05-20 09:19:34 +00002426
paul718e3742002-12-13 20:15:29 +00002427 BGP_EVENT_ADD (peer, TCP_connection_closed);
2428 return -1;
2429 }
2430
2431 /* We read partial packet. */
paul9985f832005-02-09 15:51:56 +00002432 if (stream_get_endp (peer->ibuf) != peer->packet_size)
paul718e3742002-12-13 20:15:29 +00002433 return -1;
2434
2435 return 0;
2436}
2437
2438/* Marker check. */
paul94f2b392005-06-28 12:44:16 +00002439static int
paul718e3742002-12-13 20:15:29 +00002440bgp_marker_all_one (struct stream *s, int length)
2441{
2442 int i;
2443
2444 for (i = 0; i < length; i++)
2445 if (s->data[i] != 0xff)
2446 return 0;
2447
2448 return 1;
2449}
2450
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002451/* Recent thread time.
2452 On same clock base as bgp_clock (MONOTONIC)
2453 but can be time of last context switch to bgp_read thread. */
2454static time_t
2455bgp_recent_clock (void)
2456{
2457 return recent_relative_time().tv_sec;
2458}
2459
paul718e3742002-12-13 20:15:29 +00002460/* Starting point of packet process function. */
2461int
2462bgp_read (struct thread *thread)
2463{
2464 int ret;
2465 u_char type = 0;
2466 struct peer *peer;
2467 bgp_size_t size;
2468 char notify_data_length[2];
2469
2470 /* Yes first of all get peer pointer. */
2471 peer = THREAD_ARG (thread);
2472 peer->t_read = NULL;
2473
2474 /* For non-blocking IO check. */
2475 if (peer->status == Connect)
2476 {
2477 bgp_connect_check (peer);
2478 goto done;
2479 }
2480 else
2481 {
pauleb821182004-05-01 08:44:08 +00002482 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +00002483 {
pauleb821182004-05-01 08:44:08 +00002484 zlog_err ("bgp_read peer's fd is negative value %d", peer->fd);
paul718e3742002-12-13 20:15:29 +00002485 return -1;
2486 }
pauleb821182004-05-01 08:44:08 +00002487 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
paul718e3742002-12-13 20:15:29 +00002488 }
2489
2490 /* Read packet header to determine type of the packet */
2491 if (peer->packet_size == 0)
2492 peer->packet_size = BGP_HEADER_SIZE;
2493
paul9985f832005-02-09 15:51:56 +00002494 if (stream_get_endp (peer->ibuf) < BGP_HEADER_SIZE)
paul718e3742002-12-13 20:15:29 +00002495 {
2496 ret = bgp_read_packet (peer);
2497
2498 /* Header read error or partial read packet. */
2499 if (ret < 0)
2500 goto done;
2501
2502 /* Get size and type. */
paul9985f832005-02-09 15:51:56 +00002503 stream_forward_getp (peer->ibuf, BGP_MARKER_SIZE);
paul718e3742002-12-13 20:15:29 +00002504 memcpy (notify_data_length, stream_pnt (peer->ibuf), 2);
2505 size = stream_getw (peer->ibuf);
2506 type = stream_getc (peer->ibuf);
2507
2508 if (BGP_DEBUG (normal, NORMAL) && type != 2 && type != 0)
ajs6b514742004-12-08 21:03:23 +00002509 zlog_debug ("%s rcv message type %d, length (excl. header) %d",
paul718e3742002-12-13 20:15:29 +00002510 peer->host, type, size - BGP_HEADER_SIZE);
2511
2512 /* Marker check */
paulf5ba3872004-07-09 12:11:31 +00002513 if (((type == BGP_MSG_OPEN) || (type == BGP_MSG_KEEPALIVE))
paul718e3742002-12-13 20:15:29 +00002514 && ! bgp_marker_all_one (peer->ibuf, BGP_MARKER_SIZE))
2515 {
2516 bgp_notify_send (peer,
2517 BGP_NOTIFY_HEADER_ERR,
2518 BGP_NOTIFY_HEADER_NOT_SYNC);
2519 goto done;
2520 }
2521
2522 /* BGP type check. */
2523 if (type != BGP_MSG_OPEN && type != BGP_MSG_UPDATE
2524 && type != BGP_MSG_NOTIFY && type != BGP_MSG_KEEPALIVE
2525 && type != BGP_MSG_ROUTE_REFRESH_NEW
2526 && type != BGP_MSG_ROUTE_REFRESH_OLD
2527 && type != BGP_MSG_CAPABILITY)
2528 {
2529 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002530 plog_debug (peer->log,
paul718e3742002-12-13 20:15:29 +00002531 "%s unknown message type 0x%02x",
2532 peer->host, type);
2533 bgp_notify_send_with_data (peer,
2534 BGP_NOTIFY_HEADER_ERR,
2535 BGP_NOTIFY_HEADER_BAD_MESTYPE,
2536 &type, 1);
2537 goto done;
2538 }
2539 /* Mimimum packet length check. */
2540 if ((size < BGP_HEADER_SIZE)
2541 || (size > BGP_MAX_PACKET_SIZE)
2542 || (type == BGP_MSG_OPEN && size < BGP_MSG_OPEN_MIN_SIZE)
2543 || (type == BGP_MSG_UPDATE && size < BGP_MSG_UPDATE_MIN_SIZE)
2544 || (type == BGP_MSG_NOTIFY && size < BGP_MSG_NOTIFY_MIN_SIZE)
2545 || (type == BGP_MSG_KEEPALIVE && size != BGP_MSG_KEEPALIVE_MIN_SIZE)
2546 || (type == BGP_MSG_ROUTE_REFRESH_NEW && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
2547 || (type == BGP_MSG_ROUTE_REFRESH_OLD && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
2548 || (type == BGP_MSG_CAPABILITY && size < BGP_MSG_CAPABILITY_MIN_SIZE))
2549 {
2550 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002551 plog_debug (peer->log,
paul718e3742002-12-13 20:15:29 +00002552 "%s bad message length - %d for %s",
2553 peer->host, size,
2554 type == 128 ? "ROUTE-REFRESH" :
2555 bgp_type_str[(int) type]);
2556 bgp_notify_send_with_data (peer,
2557 BGP_NOTIFY_HEADER_ERR,
2558 BGP_NOTIFY_HEADER_BAD_MESLEN,
hassoc9e52be2004-09-26 16:09:34 +00002559 (u_char *) notify_data_length, 2);
paul718e3742002-12-13 20:15:29 +00002560 goto done;
2561 }
2562
2563 /* Adjust size to message length. */
2564 peer->packet_size = size;
2565 }
2566
2567 ret = bgp_read_packet (peer);
2568 if (ret < 0)
2569 goto done;
2570
2571 /* Get size and type again. */
2572 size = stream_getw_from (peer->ibuf, BGP_MARKER_SIZE);
2573 type = stream_getc_from (peer->ibuf, BGP_MARKER_SIZE + 2);
2574
2575 /* BGP packet dump function. */
2576 bgp_dump_packet (peer, type, peer->ibuf);
2577
2578 size = (peer->packet_size - BGP_HEADER_SIZE);
2579
2580 /* Read rest of the packet and call each sort of packet routine */
2581 switch (type)
2582 {
2583 case BGP_MSG_OPEN:
2584 peer->open_in++;
Timo Teräsef757702015-04-29 09:43:04 +03002585 peer->rtt = sockopt_tcp_rtt(peer->fd);
paulf5ba3872004-07-09 12:11:31 +00002586 bgp_open_receive (peer, size); /* XXX return value ignored! */
paul718e3742002-12-13 20:15:29 +00002587 break;
2588 case BGP_MSG_UPDATE:
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002589 peer->readtime = bgp_recent_clock ();
paul718e3742002-12-13 20:15:29 +00002590 bgp_update_receive (peer, size);
2591 break;
2592 case BGP_MSG_NOTIFY:
2593 bgp_notify_receive (peer, size);
2594 break;
2595 case BGP_MSG_KEEPALIVE:
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002596 peer->readtime = bgp_recent_clock ();
paul718e3742002-12-13 20:15:29 +00002597 bgp_keepalive_receive (peer, size);
2598 break;
2599 case BGP_MSG_ROUTE_REFRESH_NEW:
2600 case BGP_MSG_ROUTE_REFRESH_OLD:
2601 peer->refresh_in++;
2602 bgp_route_refresh_receive (peer, size);
2603 break;
2604 case BGP_MSG_CAPABILITY:
2605 peer->dynamic_cap_in++;
2606 bgp_capability_receive (peer, size);
2607 break;
2608 }
2609
2610 /* Clear input buffer. */
2611 peer->packet_size = 0;
2612 if (peer->ibuf)
2613 stream_reset (peer->ibuf);
2614
2615 done:
2616 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2617 {
2618 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +00002619 zlog_debug ("%s [Event] Accepting BGP peer delete", peer->host);
paul718e3742002-12-13 20:15:29 +00002620 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00002621 }
2622 return 0;
2623}