blob: e1ae494d371c70cc5d89af52403b548b61181437 [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");
970 if (bgp_notify.data)
971 XFREE (MTYPE_TMP, bgp_notify.data);
972 }
973
974 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000975 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000976 peer->host, BGP_MSG_NOTIFY, length);
977
hassoe0701b72004-05-20 09:19:34 +0000978 /* peer reset cause */
979 if (sub_code != BGP_NOTIFY_CEASE_CONFIG_CHANGE)
980 {
981 if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET)
heasley1212dc12011-09-12 13:27:52 +0400982 {
983 peer->last_reset = PEER_DOWN_USER_RESET;
984 zlog_info ("Notification sent to neighbor %s: User reset", peer->host);
985 }
hassoe0701b72004-05-20 09:19:34 +0000986 else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN)
heasley1212dc12011-09-12 13:27:52 +0400987 {
988 peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
989 zlog_info ("Notification sent to neighbor %s: shutdown", peer->host);
990 }
hassoe0701b72004-05-20 09:19:34 +0000991 else
heasley1212dc12011-09-12 13:27:52 +0400992 {
993 peer->last_reset = PEER_DOWN_NOTIFY_SEND;
994 zlog_info ("Notification sent to neighbor %s: type %u/%u",
995 peer->host, code, sub_code);
996 }
hassoe0701b72004-05-20 09:19:34 +0000997 }
heasley1212dc12011-09-12 13:27:52 +0400998 else
999 zlog_info ("Notification sent to neighbor %s: configuration change",
1000 peer->host);
hassoe0701b72004-05-20 09:19:34 +00001001
Denis Ovsienko7ccf5e52011-09-10 16:53:30 +04001002 /* Call immediately. */
paul718e3742002-12-13 20:15:29 +00001003 BGP_WRITE_OFF (peer->t_write);
1004
1005 bgp_write_notify (peer);
1006}
1007
1008/* Send BGP notify packet. */
1009void
1010bgp_notify_send (struct peer *peer, u_char code, u_char sub_code)
1011{
1012 bgp_notify_send_with_data (peer, code, sub_code, NULL, 0);
1013}
1014
paul718e3742002-12-13 20:15:29 +00001015/* Send route refresh message to the peer. */
1016void
1017bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
1018 u_char orf_type, u_char when_to_refresh, int remove)
1019{
1020 struct stream *s;
paul718e3742002-12-13 20:15:29 +00001021 int length;
1022 struct bgp_filter *filter;
1023 int orf_refresh = 0;
1024
Paul Jakma750e8142008-07-22 21:11:48 +00001025 if (DISABLE_BGP_ANNOUNCE)
1026 return;
paul718e3742002-12-13 20:15:29 +00001027
1028 filter = &peer->filter[afi][safi];
1029
1030 /* Adjust safi code. */
1031 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001032 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +00001033
1034 s = stream_new (BGP_MAX_PACKET_SIZE);
1035
1036 /* Make BGP update packet. */
1037 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
1038 bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_NEW);
1039 else
1040 bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_OLD);
1041
1042 /* Encode Route Refresh message. */
1043 stream_putw (s, afi);
1044 stream_putc (s, 0);
1045 stream_putc (s, safi);
1046
1047 if (orf_type == ORF_TYPE_PREFIX
1048 || orf_type == ORF_TYPE_PREFIX_OLD)
1049 if (remove || filter->plist[FILTER_IN].plist)
1050 {
1051 u_int16_t orf_len;
1052 unsigned long orfp;
1053
1054 orf_refresh = 1;
1055 stream_putc (s, when_to_refresh);
1056 stream_putc (s, orf_type);
paul9985f832005-02-09 15:51:56 +00001057 orfp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00001058 stream_putw (s, 0);
1059
1060 if (remove)
1061 {
1062 UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
1063 stream_putc (s, ORF_COMMON_PART_REMOVE_ALL);
1064 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001065 zlog_debug ("%s sending REFRESH_REQ to remove ORF(%d) (%s) for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001066 peer->host, orf_type,
1067 (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
1068 afi, safi);
1069 }
1070 else
1071 {
1072 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
1073 prefix_bgp_orf_entry (s, filter->plist[FILTER_IN].plist,
1074 ORF_COMMON_PART_ADD, ORF_COMMON_PART_PERMIT,
1075 ORF_COMMON_PART_DENY);
1076 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001077 zlog_debug ("%s sending REFRESH_REQ with pfxlist ORF(%d) (%s) for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001078 peer->host, orf_type,
1079 (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
1080 afi, safi);
1081 }
1082
1083 /* Total ORF Entry Len. */
paul9985f832005-02-09 15:51:56 +00001084 orf_len = stream_get_endp (s) - orfp - 2;
paul718e3742002-12-13 20:15:29 +00001085 stream_putw_at (s, orfp, orf_len);
1086 }
1087
1088 /* Set packet size. */
1089 length = bgp_packet_set_size (s);
1090
1091 if (BGP_DEBUG (normal, NORMAL))
1092 {
1093 if (! orf_refresh)
ajs6b514742004-12-08 21:03:23 +00001094 zlog_debug ("%s sending REFRESH_REQ for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001095 peer->host, afi, safi);
ajs6b514742004-12-08 21:03:23 +00001096 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +00001097 peer->host, CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV) ?
1098 BGP_MSG_ROUTE_REFRESH_NEW : BGP_MSG_ROUTE_REFRESH_OLD, length);
1099 }
1100
paul718e3742002-12-13 20:15:29 +00001101 /* Add packet to the peer. */
Donald Sharpa752c3b2015-08-18 08:48:53 -04001102 bgp_packet_add (peer, s);
paul718e3742002-12-13 20:15:29 +00001103
pauleb821182004-05-01 08:44:08 +00001104 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +00001105}
1106
1107/* Send capability message to the peer. */
1108void
1109bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi,
1110 int capability_code, int action)
1111{
1112 struct stream *s;
paul718e3742002-12-13 20:15:29 +00001113 int length;
1114
1115 /* Adjust safi code. */
1116 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001117 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +00001118
1119 s = stream_new (BGP_MAX_PACKET_SIZE);
1120
1121 /* Make BGP update packet. */
1122 bgp_packet_set_marker (s, BGP_MSG_CAPABILITY);
1123
1124 /* Encode MP_EXT capability. */
1125 if (capability_code == CAPABILITY_CODE_MP)
1126 {
1127 stream_putc (s, action);
1128 stream_putc (s, CAPABILITY_CODE_MP);
1129 stream_putc (s, CAPABILITY_CODE_MP_LEN);
1130 stream_putw (s, afi);
1131 stream_putc (s, 0);
1132 stream_putc (s, safi);
1133
1134 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001135 zlog_debug ("%s sending CAPABILITY has %s MP_EXT CAP for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001136 peer->host, action == CAPABILITY_ACTION_SET ?
1137 "Advertising" : "Removing", afi, safi);
1138 }
1139
paul718e3742002-12-13 20:15:29 +00001140 /* Set packet size. */
1141 length = bgp_packet_set_size (s);
1142
paul718e3742002-12-13 20:15:29 +00001143
1144 /* Add packet to the peer. */
Donald Sharpa752c3b2015-08-18 08:48:53 -04001145 bgp_packet_add (peer, s);
paul718e3742002-12-13 20:15:29 +00001146
1147 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001148 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +00001149 peer->host, BGP_MSG_CAPABILITY, length);
1150
pauleb821182004-05-01 08:44:08 +00001151 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +00001152}
David Lamparter6b0655a2014-06-04 06:53:35 +02001153
paul718e3742002-12-13 20:15:29 +00001154/* RFC1771 6.8 Connection collision detection. */
paul94f2b392005-06-28 12:44:16 +00001155static int
pauleb821182004-05-01 08:44:08 +00001156bgp_collision_detect (struct peer *new, struct in_addr remote_id)
paul718e3742002-12-13 20:15:29 +00001157{
pauleb821182004-05-01 08:44:08 +00001158 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001159 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001160 struct bgp *bgp;
1161
1162 bgp = bgp_get_default ();
1163 if (! bgp)
1164 return 0;
1165
1166 /* Upon receipt of an OPEN message, the local system must examine
1167 all of its connections that are in the OpenConfirm state. A BGP
1168 speaker may also examine connections in an OpenSent state if it
1169 knows the BGP Identifier of the peer by means outside of the
1170 protocol. If among these connections there is a connection to a
1171 remote BGP speaker whose BGP Identifier equals the one in the
1172 OPEN message, then the local system performs the following
1173 collision resolution procedure: */
1174
paul1eb8ef22005-04-07 07:30:20 +00001175 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001176 {
1177 /* Under OpenConfirm status, local peer structure already hold
1178 remote router ID. */
pauleb821182004-05-01 08:44:08 +00001179
1180 if (peer != new
1181 && (peer->status == OpenConfirm || peer->status == OpenSent)
1182 && sockunion_same (&peer->su, &new->su))
1183 {
paul718e3742002-12-13 20:15:29 +00001184 /* 1. The BGP Identifier of the local system is compared to
1185 the BGP Identifier of the remote system (as specified in
1186 the OPEN message). */
1187
1188 if (ntohl (peer->local_id.s_addr) < ntohl (remote_id.s_addr))
1189 {
1190 /* 2. If the value of the local BGP Identifier is less
1191 than the remote one, the local system closes BGP
1192 connection that already exists (the one that is
1193 already in the OpenConfirm state), and accepts BGP
1194 connection initiated by the remote system. */
1195
pauleb821182004-05-01 08:44:08 +00001196 if (peer->fd >= 0)
hassoe0701b72004-05-20 09:19:34 +00001197 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
paul718e3742002-12-13 20:15:29 +00001198 return 1;
1199 }
1200 else
1201 {
1202 /* 3. Otherwise, the local system closes newly created
1203 BGP connection (the one associated with the newly
1204 received OPEN message), and continues to use the
1205 existing one (the one that is already in the
1206 OpenConfirm state). */
1207
pauleb821182004-05-01 08:44:08 +00001208 if (new->fd >= 0)
paulf5ba3872004-07-09 12:11:31 +00001209 bgp_notify_send (new, BGP_NOTIFY_CEASE,
1210 BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
paul718e3742002-12-13 20:15:29 +00001211 return -1;
1212 }
pauleb821182004-05-01 08:44:08 +00001213 }
1214 }
paul718e3742002-12-13 20:15:29 +00001215 return 0;
1216}
1217
paul94f2b392005-06-28 12:44:16 +00001218static int
paul718e3742002-12-13 20:15:29 +00001219bgp_open_receive (struct peer *peer, bgp_size_t size)
1220{
1221 int ret;
1222 u_char version;
1223 u_char optlen;
1224 u_int16_t holdtime;
1225 u_int16_t send_holdtime;
1226 as_t remote_as;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001227 as_t as4 = 0;
paul718e3742002-12-13 20:15:29 +00001228 struct peer *realpeer;
1229 struct in_addr remote_id;
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001230 int mp_capability;
paul5228ad22004-06-04 17:58:18 +00001231 u_int8_t notify_data_remote_as[2];
1232 u_int8_t notify_data_remote_id[4];
paul718e3742002-12-13 20:15:29 +00001233
1234 realpeer = NULL;
1235
1236 /* Parse open packet. */
1237 version = stream_getc (peer->ibuf);
1238 memcpy (notify_data_remote_as, stream_pnt (peer->ibuf), 2);
1239 remote_as = stream_getw (peer->ibuf);
1240 holdtime = stream_getw (peer->ibuf);
1241 memcpy (notify_data_remote_id, stream_pnt (peer->ibuf), 4);
1242 remote_id.s_addr = stream_get_ipv4 (peer->ibuf);
1243
1244 /* Receive OPEN message log */
1245 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001246 zlog_debug ("%s rcv OPEN, version %d, remote-as (in open) %u,"
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001247 " holdtime %d, id %s",
1248 peer->host, version, remote_as, holdtime,
1249 inet_ntoa (remote_id));
1250
1251 /* BEGIN to read the capability here, but dont do it yet */
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001252 mp_capability = 0;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001253 optlen = stream_getc (peer->ibuf);
1254
1255 if (optlen != 0)
1256 {
1257 /* We need the as4 capability value *right now* because
1258 * if it is there, we have not got the remote_as yet, and without
1259 * that we do not know which peer is connecting to us now.
1260 */
1261 as4 = peek_for_as4_capability (peer, optlen);
1262 }
1263
1264 /* Just in case we have a silly peer who sends AS4 capability set to 0 */
1265 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) && !as4)
1266 {
1267 zlog_err ("%s bad OPEN, got AS4 capability, but AS4 set to 0",
1268 peer->host);
1269 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1270 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1271 return -1;
1272 }
1273
1274 if (remote_as == BGP_AS_TRANS)
1275 {
1276 /* Take the AS4 from the capability. We must have received the
1277 * capability now! Otherwise we have a asn16 peer who uses
1278 * BGP_AS_TRANS, for some unknown reason.
1279 */
1280 if (as4 == BGP_AS_TRANS)
1281 {
1282 zlog_err ("%s [AS4] NEW speaker using AS_TRANS for AS4, not allowed",
1283 peer->host);
1284 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1285 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1286 return -1;
1287 }
1288
1289 if (!as4 && BGP_DEBUG (as4, AS4))
1290 zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but no AS4."
1291 " Odd, but proceeding.", peer->host);
1292 else if (as4 < BGP_AS_MAX && BGP_DEBUG (as4, AS4))
Paul Jakma0df7c912008-07-21 21:02:49 +00001293 zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but AS4 (%u) fits "
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001294 "in 2-bytes, very odd peer.", peer->host, as4);
1295 if (as4)
1296 remote_as = as4;
1297 }
1298 else
1299 {
1300 /* We may have a partner with AS4 who has an asno < BGP_AS_MAX */
1301 /* If we have got the capability, peer->as4cap must match remote_as */
1302 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)
1303 && as4 != remote_as)
1304 {
1305 /* raise error, log this, close session */
1306 zlog_err ("%s bad OPEN, got AS4 capability, but remote_as %u"
1307 " mismatch with 16bit 'myasn' %u in open",
1308 peer->host, as4, remote_as);
1309 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1310 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1311 return -1;
1312 }
1313 }
1314
paul718e3742002-12-13 20:15:29 +00001315 /* Lookup peer from Open packet. */
1316 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1317 {
1318 int as = 0;
1319
1320 realpeer = peer_lookup_with_open (&peer->su, remote_as, &remote_id, &as);
1321
1322 if (! realpeer)
1323 {
1324 /* Peer's source IP address is check in bgp_accept(), so this
1325 must be AS number mismatch or remote-id configuration
1326 mismatch. */
1327 if (as)
1328 {
1329 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001330 zlog_debug ("%s bad OPEN, wrong router identifier %s",
1331 peer->host, inet_ntoa (remote_id));
1332 bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
1333 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
1334 notify_data_remote_id, 4);
paul718e3742002-12-13 20:15:29 +00001335 }
1336 else
1337 {
1338 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001339 zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
ajs6b514742004-12-08 21:03:23 +00001340 peer->host, remote_as, peer->as);
1341 bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
1342 BGP_NOTIFY_OPEN_BAD_PEER_AS,
1343 notify_data_remote_as, 2);
paul718e3742002-12-13 20:15:29 +00001344 }
1345 return -1;
1346 }
1347 }
1348
1349 /* When collision is detected and this peer is closed. Retrun
1350 immidiately. */
1351 ret = bgp_collision_detect (peer, remote_id);
1352 if (ret < 0)
1353 return ret;
1354
pauleb821182004-05-01 08:44:08 +00001355 /* Hack part. */
1356 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1357 {
hasso93406d82005-02-02 14:40:33 +00001358 if (realpeer->status == Established
1359 && CHECK_FLAG (realpeer->sflags, PEER_STATUS_NSF_MODE))
1360 {
1361 realpeer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
1362 SET_FLAG (realpeer->sflags, PEER_STATUS_NSF_WAIT);
1363 }
1364 else if (ret == 0 && realpeer->status != Active
1365 && realpeer->status != OpenSent
Paul Jakma6e199262008-09-09 17:14:33 +01001366 && realpeer->status != OpenConfirm
1367 && realpeer->status != Connect)
pauleb821182004-05-01 08:44:08 +00001368 {
Paul Jakma2b2fc562008-09-06 13:09:35 +01001369 /* XXX: This is an awful problem..
1370 *
1371 * According to the RFC we should just let this connection (of the
1372 * accepted 'peer') continue on to Established if the other
1373 * connection (the 'realpeer' one) is in state Connect, and deal
1374 * with the more larval FSM as/when it gets far enough to receive
1375 * an Open. We don't do that though, we instead close the (more
1376 * developed) accepted connection.
1377 *
1378 * This means there's a race, which if hit, can loop:
1379 *
1380 * FSM for A FSM for B
1381 * realpeer accept-peer realpeer accept-peer
1382 *
1383 * Connect Connect
1384 * Active
1385 * OpenSent OpenSent
1386 * <arrive here,
1387 * Notify, delete>
1388 * Idle Active
1389 * OpenSent OpenSent
1390 * <arrive here,
1391 * Notify, delete>
1392 * Idle
1393 * <wait> <wait>
1394 * Connect Connect
1395 *
1396 *
1397 * If both sides are Quagga, they're almost certain to wait for
1398 * the same amount of time of course (which doesn't preclude other
1399 * implementations also waiting for same time). The race is
1400 * exacerbated by high-latency (in bgpd and/or the network).
1401 *
1402 * The reason we do this is because our FSM is tied to our peer
1403 * structure, which carries our configuration information, etc.
1404 * I.e. we can't let the accepted-peer FSM continue on as it is,
1405 * cause it's not associated with any actual peer configuration -
1406 * it's just a dummy.
1407 *
1408 * It's possible we could hack-fix this by just bgp_stop'ing the
1409 * realpeer and continueing on with the 'transfer FSM' below.
1410 * Ideally, we need to seperate FSMs from struct peer.
1411 *
1412 * Setting one side to passive avoids the race, as a workaround.
1413 */
pauleb821182004-05-01 08:44:08 +00001414 if (BGP_DEBUG (events, EVENTS))
hasso93406d82005-02-02 14:40:33 +00001415 zlog_debug ("%s peer status is %s close connection",
1416 realpeer->host, LOOKUP (bgp_status_msg,
1417 realpeer->status));
1418 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1419 BGP_NOTIFY_CEASE_CONNECT_REJECT);
1420
pauleb821182004-05-01 08:44:08 +00001421 return -1;
1422 }
1423
1424 if (BGP_DEBUG (events, EVENTS))
Paul Jakma6e199262008-09-09 17:14:33 +01001425 zlog_debug ("%s [Event] Transfer accept BGP peer to real (state %s)",
1426 peer->host,
1427 LOOKUP (bgp_status_msg, realpeer->status));
pauleb821182004-05-01 08:44:08 +00001428
1429 bgp_stop (realpeer);
1430
1431 /* Transfer file descriptor. */
1432 realpeer->fd = peer->fd;
1433 peer->fd = -1;
1434
1435 /* Transfer input buffer. */
1436 stream_free (realpeer->ibuf);
1437 realpeer->ibuf = peer->ibuf;
1438 realpeer->packet_size = peer->packet_size;
1439 peer->ibuf = NULL;
1440
1441 /* Transfer status. */
1442 realpeer->status = peer->status;
1443 bgp_stop (peer);
paul200df112005-06-01 11:17:05 +00001444
pauleb821182004-05-01 08:44:08 +00001445 /* peer pointer change. Open packet send to neighbor. */
1446 peer = realpeer;
1447 bgp_open_send (peer);
1448 if (peer->fd < 0)
1449 {
1450 zlog_err ("bgp_open_receive peer's fd is negative value %d",
1451 peer->fd);
1452 return -1;
1453 }
1454 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
1455 }
1456
paul718e3742002-12-13 20:15:29 +00001457 /* remote router-id check. */
1458 if (remote_id.s_addr == 0
Denis Ovsienko733cd9e2011-12-17 19:39:30 +04001459 || IPV4_CLASS_DE (ntohl (remote_id.s_addr))
paul718e3742002-12-13 20:15:29 +00001460 || ntohl (peer->local_id.s_addr) == ntohl (remote_id.s_addr))
1461 {
1462 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001463 zlog_debug ("%s bad OPEN, wrong router identifier %s",
paul718e3742002-12-13 20:15:29 +00001464 peer->host, inet_ntoa (remote_id));
1465 bgp_notify_send_with_data (peer,
1466 BGP_NOTIFY_OPEN_ERR,
1467 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
1468 notify_data_remote_id, 4);
1469 return -1;
1470 }
1471
1472 /* Set remote router-id */
1473 peer->remote_id = remote_id;
1474
1475 /* Peer BGP version check. */
1476 if (version != BGP_VERSION_4)
1477 {
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001478 u_int16_t maxver = htons(BGP_VERSION_4);
1479 /* XXX this reply may not be correct if version < 4 XXX */
paul718e3742002-12-13 20:15:29 +00001480 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001481 zlog_debug ("%s bad protocol version, remote requested %d, local request %d",
paul718e3742002-12-13 20:15:29 +00001482 peer->host, version, BGP_VERSION_4);
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001483 /* Data must be in network byte order here */
paul718e3742002-12-13 20:15:29 +00001484 bgp_notify_send_with_data (peer,
1485 BGP_NOTIFY_OPEN_ERR,
1486 BGP_NOTIFY_OPEN_UNSUP_VERSION,
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001487 (u_int8_t *) &maxver, 2);
paul718e3742002-12-13 20:15:29 +00001488 return -1;
1489 }
1490
1491 /* Check neighbor as number. */
1492 if (remote_as != peer->as)
1493 {
1494 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001495 zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
paul718e3742002-12-13 20:15:29 +00001496 peer->host, remote_as, peer->as);
1497 bgp_notify_send_with_data (peer,
1498 BGP_NOTIFY_OPEN_ERR,
1499 BGP_NOTIFY_OPEN_BAD_PEER_AS,
1500 notify_data_remote_as, 2);
1501 return -1;
1502 }
1503
1504 /* From the rfc: Upon receipt of an OPEN message, a BGP speaker MUST
1505 calculate the value of the Hold Timer by using the smaller of its
1506 configured Hold Time and the Hold Time received in the OPEN message.
1507 The Hold Time MUST be either zero or at least three seconds. An
1508 implementation may reject connections on the basis of the Hold Time. */
1509
1510 if (holdtime < 3 && holdtime != 0)
1511 {
1512 bgp_notify_send (peer,
1513 BGP_NOTIFY_OPEN_ERR,
1514 BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
1515 return -1;
1516 }
1517
1518 /* From the rfc: A reasonable maximum time between KEEPALIVE messages
1519 would be one third of the Hold Time interval. KEEPALIVE messages
1520 MUST NOT be sent more frequently than one per second. An
1521 implementation MAY adjust the rate at which it sends KEEPALIVE
1522 messages as a function of the Hold Time interval. */
1523
1524 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
1525 send_holdtime = peer->holdtime;
1526 else
1527 send_holdtime = peer->bgp->default_holdtime;
1528
1529 if (holdtime < send_holdtime)
1530 peer->v_holdtime = holdtime;
1531 else
1532 peer->v_holdtime = send_holdtime;
1533
1534 peer->v_keepalive = peer->v_holdtime / 3;
1535
1536 /* Open option part parse. */
paul718e3742002-12-13 20:15:29 +00001537 if (optlen != 0)
1538 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001539 if ((ret = bgp_open_option_parse (peer, optlen, &mp_capability)) < 0)
Paul Jakma58617392012-01-09 20:59:26 +00001540 {
1541 bgp_notify_send (peer,
1542 BGP_NOTIFY_OPEN_ERR,
1543 BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
1544 return ret;
1545 }
paul718e3742002-12-13 20:15:29 +00001546 }
1547 else
1548 {
1549 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001550 zlog_debug ("%s rcvd OPEN w/ OPTION parameter len: 0",
paul718e3742002-12-13 20:15:29 +00001551 peer->host);
1552 }
1553
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001554 /*
1555 * Assume that the peer supports the locally configured set of
1556 * AFI/SAFIs if the peer did not send us any Mulitiprotocol
1557 * capabilities, or if 'override-capability' is configured.
1558 */
1559 if (! mp_capability ||
1560 CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
paul718e3742002-12-13 20:15:29 +00001561 {
1562 peer->afc_nego[AFI_IP][SAFI_UNICAST] = peer->afc[AFI_IP][SAFI_UNICAST];
1563 peer->afc_nego[AFI_IP][SAFI_MULTICAST] = peer->afc[AFI_IP][SAFI_MULTICAST];
1564 peer->afc_nego[AFI_IP6][SAFI_UNICAST] = peer->afc[AFI_IP6][SAFI_UNICAST];
1565 peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = peer->afc[AFI_IP6][SAFI_MULTICAST];
1566 }
1567
1568 /* Get sockname. */
1569 bgp_getsockname (peer);
1570
1571 BGP_EVENT_ADD (peer, Receive_OPEN_message);
1572
1573 peer->packet_size = 0;
1574 if (peer->ibuf)
1575 stream_reset (peer->ibuf);
1576
1577 return 0;
1578}
1579
1580/* Parse BGP Update packet and make attribute object. */
paul94f2b392005-06-28 12:44:16 +00001581static int
paul718e3742002-12-13 20:15:29 +00001582bgp_update_receive (struct peer *peer, bgp_size_t size)
1583{
1584 int ret;
1585 u_char *end;
1586 struct stream *s;
1587 struct attr attr;
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001588 struct attr_extra extra;
paul718e3742002-12-13 20:15:29 +00001589 bgp_size_t attribute_len;
1590 bgp_size_t update_len;
1591 bgp_size_t withdraw_len;
1592 struct bgp_nlri update;
1593 struct bgp_nlri withdraw;
1594 struct bgp_nlri mp_update;
1595 struct bgp_nlri mp_withdraw;
paul718e3742002-12-13 20:15:29 +00001596
1597 /* Status must be Established. */
1598 if (peer->status != Established)
1599 {
1600 zlog_err ("%s [FSM] Update packet received under status %s",
1601 peer->host, LOOKUP (bgp_status_msg, peer->status));
1602 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
1603 return -1;
1604 }
1605
1606 /* Set initial values. */
1607 memset (&attr, 0, sizeof (struct attr));
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001608 memset (&extra, 0, sizeof (struct attr_extra));
paul718e3742002-12-13 20:15:29 +00001609 memset (&update, 0, sizeof (struct bgp_nlri));
1610 memset (&withdraw, 0, sizeof (struct bgp_nlri));
1611 memset (&mp_update, 0, sizeof (struct bgp_nlri));
1612 memset (&mp_withdraw, 0, sizeof (struct bgp_nlri));
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001613 attr.extra = &extra;
paul718e3742002-12-13 20:15:29 +00001614
1615 s = peer->ibuf;
1616 end = stream_pnt (s) + size;
1617
1618 /* RFC1771 6.3 If the Unfeasible Routes Length or Total Attribute
1619 Length is too large (i.e., if Unfeasible Routes Length + Total
1620 Attribute Length + 23 exceeds the message Length), then the Error
1621 Subcode is set to Malformed Attribute List. */
1622 if (stream_pnt (s) + 2 > end)
1623 {
1624 zlog_err ("%s [Error] Update packet error"
1625 " (packet length is short for unfeasible length)",
1626 peer->host);
1627 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1628 BGP_NOTIFY_UPDATE_MAL_ATTR);
1629 return -1;
1630 }
1631
1632 /* Unfeasible Route Length. */
1633 withdraw_len = stream_getw (s);
1634
1635 /* Unfeasible Route Length check. */
1636 if (stream_pnt (s) + withdraw_len > end)
1637 {
1638 zlog_err ("%s [Error] Update packet error"
1639 " (packet unfeasible length overflow %d)",
1640 peer->host, withdraw_len);
1641 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1642 BGP_NOTIFY_UPDATE_MAL_ATTR);
1643 return -1;
1644 }
1645
1646 /* Unfeasible Route packet format check. */
1647 if (withdraw_len > 0)
1648 {
1649 ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), withdraw_len);
1650 if (ret < 0)
1651 return -1;
1652
1653 if (BGP_DEBUG (packet, PACKET_RECV))
ajs6b514742004-12-08 21:03:23 +00001654 zlog_debug ("%s [Update:RECV] Unfeasible NLRI received", peer->host);
paul718e3742002-12-13 20:15:29 +00001655
1656 withdraw.afi = AFI_IP;
1657 withdraw.safi = SAFI_UNICAST;
1658 withdraw.nlri = stream_pnt (s);
1659 withdraw.length = withdraw_len;
paul9985f832005-02-09 15:51:56 +00001660 stream_forward_getp (s, withdraw_len);
paul718e3742002-12-13 20:15:29 +00001661 }
1662
1663 /* Attribute total length check. */
1664 if (stream_pnt (s) + 2 > end)
1665 {
1666 zlog_warn ("%s [Error] Packet Error"
1667 " (update packet is short for attribute length)",
1668 peer->host);
1669 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1670 BGP_NOTIFY_UPDATE_MAL_ATTR);
1671 return -1;
1672 }
1673
1674 /* Fetch attribute total length. */
1675 attribute_len = stream_getw (s);
1676
1677 /* Attribute length check. */
1678 if (stream_pnt (s) + attribute_len > end)
1679 {
1680 zlog_warn ("%s [Error] Packet Error"
1681 " (update packet attribute length overflow %d)",
1682 peer->host, attribute_len);
1683 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1684 BGP_NOTIFY_UPDATE_MAL_ATTR);
1685 return -1;
1686 }
Paul Jakmab881c702010-11-23 16:35:42 +00001687
1688 /* Certain attribute parsing errors should not be considered bad enough
1689 * to reset the session for, most particularly any partial/optional
1690 * attributes that have 'tunneled' over speakers that don't understand
1691 * them. Instead we withdraw only the prefix concerned.
1692 *
1693 * Complicates the flow a little though..
1694 */
1695 bgp_attr_parse_ret_t attr_parse_ret = BGP_ATTR_PARSE_PROCEED;
1696 /* This define morphs the update case into a withdraw when lower levels
1697 * have signalled an error condition where this is best.
1698 */
1699#define NLRI_ATTR_ARG (attr_parse_ret != BGP_ATTR_PARSE_WITHDRAW ? &attr : NULL)
paul718e3742002-12-13 20:15:29 +00001700
1701 /* Parse attribute when it exists. */
1702 if (attribute_len)
1703 {
Paul Jakmab881c702010-11-23 16:35:42 +00001704 attr_parse_ret = bgp_attr_parse (peer, &attr, attribute_len,
paul718e3742002-12-13 20:15:29 +00001705 &mp_update, &mp_withdraw);
Paul Jakmab881c702010-11-23 16:35:42 +00001706 if (attr_parse_ret == BGP_ATTR_PARSE_ERROR)
David Lamparterf80f8382014-06-04 01:00:51 +02001707 {
1708 bgp_attr_unintern_sub (&attr);
1709 return -1;
1710 }
paul718e3742002-12-13 20:15:29 +00001711 }
Paul Jakmab881c702010-11-23 16:35:42 +00001712
paul718e3742002-12-13 20:15:29 +00001713 /* Logging the attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001714 if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW
1715 || BGP_DEBUG (update, UPDATE_IN))
paul718e3742002-12-13 20:15:29 +00001716 {
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +00001717 char attrstr[BUFSIZ];
1718 attrstr[0] = '\0';
1719
paule01f9cb2004-07-09 17:48:53 +00001720 ret= bgp_dump_attr (peer, &attr, attrstr, BUFSIZ);
Paul Jakmab881c702010-11-23 16:35:42 +00001721 int lvl = (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
1722 ? LOG_ERR : LOG_DEBUG;
1723
1724 if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
1725 zlog (peer->log, LOG_ERR,
1726 "%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.",
1727 peer->host);
paule01f9cb2004-07-09 17:48:53 +00001728
1729 if (ret)
Paul Jakmab881c702010-11-23 16:35:42 +00001730 zlog (peer->log, lvl, "%s rcvd UPDATE w/ attr: %s",
paule01f9cb2004-07-09 17:48:53 +00001731 peer->host, attrstr);
paul718e3742002-12-13 20:15:29 +00001732 }
Paul Jakmab881c702010-11-23 16:35:42 +00001733
paul718e3742002-12-13 20:15:29 +00001734 /* Network Layer Reachability Information. */
1735 update_len = end - stream_pnt (s);
1736
1737 if (update_len)
1738 {
1739 /* Check NLRI packet format and prefix length. */
1740 ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), update_len);
1741 if (ret < 0)
Paul Jakmab881c702010-11-23 16:35:42 +00001742 {
1743 bgp_attr_unintern_sub (&attr);
Paul Jakmab881c702010-11-23 16:35:42 +00001744 return -1;
1745 }
paul718e3742002-12-13 20:15:29 +00001746
1747 /* Set NLRI portion to structure. */
1748 update.afi = AFI_IP;
1749 update.safi = SAFI_UNICAST;
1750 update.nlri = stream_pnt (s);
1751 update.length = update_len;
paul9985f832005-02-09 15:51:56 +00001752 stream_forward_getp (s, update_len);
paul718e3742002-12-13 20:15:29 +00001753 }
1754
1755 /* NLRI is processed only when the peer is configured specific
1756 Address Family and Subsequent Address Family. */
1757 if (peer->afc[AFI_IP][SAFI_UNICAST])
1758 {
1759 if (withdraw.length)
1760 bgp_nlri_parse (peer, NULL, &withdraw);
1761
1762 if (update.length)
Paul Jakmab881c702010-11-23 16:35:42 +00001763 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &update);
paule01f9cb2004-07-09 17:48:53 +00001764
hassof4184462005-02-01 20:13:16 +00001765 if (mp_update.length
1766 && mp_update.afi == AFI_IP
1767 && mp_update.safi == SAFI_UNICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001768 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
hassof4184462005-02-01 20:13:16 +00001769
1770 if (mp_withdraw.length
1771 && mp_withdraw.afi == AFI_IP
1772 && mp_withdraw.safi == SAFI_UNICAST)
1773 bgp_nlri_parse (peer, NULL, &mp_withdraw);
1774
paule01f9cb2004-07-09 17:48:53 +00001775 if (! attribute_len && ! withdraw_len)
1776 {
1777 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001778 SET_FLAG (peer->af_sflags[AFI_IP][SAFI_UNICAST],
1779 PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001780
hasso93406d82005-02-02 14:40:33 +00001781 /* NSF delete stale route */
1782 if (peer->nsf[AFI_IP][SAFI_UNICAST])
1783 bgp_clear_stale_route (peer, AFI_IP, SAFI_UNICAST);
1784
1785 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001786 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001787 peer->host);
1788 }
paul718e3742002-12-13 20:15:29 +00001789 }
1790 if (peer->afc[AFI_IP][SAFI_MULTICAST])
1791 {
1792 if (mp_update.length
1793 && mp_update.afi == AFI_IP
1794 && mp_update.safi == SAFI_MULTICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001795 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001796
1797 if (mp_withdraw.length
1798 && mp_withdraw.afi == AFI_IP
1799 && mp_withdraw.safi == SAFI_MULTICAST)
1800 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001801
hasso93406d82005-02-02 14:40:33 +00001802 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001803 && mp_withdraw.afi == AFI_IP
1804 && mp_withdraw.safi == SAFI_MULTICAST
1805 && mp_withdraw.length == 0)
1806 {
1807 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001808 SET_FLAG (peer->af_sflags[AFI_IP][SAFI_MULTICAST],
1809 PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001810
hasso93406d82005-02-02 14:40:33 +00001811 /* NSF delete stale route */
1812 if (peer->nsf[AFI_IP][SAFI_MULTICAST])
1813 bgp_clear_stale_route (peer, AFI_IP, SAFI_MULTICAST);
1814
1815 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001816 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Multicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001817 peer->host);
1818 }
paul718e3742002-12-13 20:15:29 +00001819 }
1820 if (peer->afc[AFI_IP6][SAFI_UNICAST])
1821 {
1822 if (mp_update.length
1823 && mp_update.afi == AFI_IP6
1824 && mp_update.safi == SAFI_UNICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001825 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001826
1827 if (mp_withdraw.length
1828 && mp_withdraw.afi == AFI_IP6
1829 && mp_withdraw.safi == SAFI_UNICAST)
1830 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001831
hasso93406d82005-02-02 14:40:33 +00001832 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001833 && mp_withdraw.afi == AFI_IP6
1834 && mp_withdraw.safi == SAFI_UNICAST
1835 && mp_withdraw.length == 0)
1836 {
1837 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001838 SET_FLAG (peer->af_sflags[AFI_IP6][SAFI_UNICAST], PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001839
hasso93406d82005-02-02 14:40:33 +00001840 /* NSF delete stale route */
1841 if (peer->nsf[AFI_IP6][SAFI_UNICAST])
1842 bgp_clear_stale_route (peer, AFI_IP6, SAFI_UNICAST);
1843
1844 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001845 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001846 peer->host);
1847 }
paul718e3742002-12-13 20:15:29 +00001848 }
1849 if (peer->afc[AFI_IP6][SAFI_MULTICAST])
1850 {
1851 if (mp_update.length
1852 && mp_update.afi == AFI_IP6
1853 && mp_update.safi == SAFI_MULTICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001854 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001855
1856 if (mp_withdraw.length
1857 && mp_withdraw.afi == AFI_IP6
1858 && mp_withdraw.safi == SAFI_MULTICAST)
1859 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001860
hasso93406d82005-02-02 14:40:33 +00001861 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001862 && mp_withdraw.afi == AFI_IP6
1863 && mp_withdraw.safi == SAFI_MULTICAST
1864 && mp_withdraw.length == 0)
1865 {
1866 /* End-of-RIB received */
1867
hasso93406d82005-02-02 14:40:33 +00001868 /* NSF delete stale route */
1869 if (peer->nsf[AFI_IP6][SAFI_MULTICAST])
1870 bgp_clear_stale_route (peer, AFI_IP6, SAFI_MULTICAST);
1871
paule01f9cb2004-07-09 17:48:53 +00001872 if (BGP_DEBUG (update, UPDATE_IN))
ajs6b514742004-12-08 21:03:23 +00001873 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Multicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001874 peer->host);
1875 }
paul718e3742002-12-13 20:15:29 +00001876 }
1877 if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
1878 {
1879 if (mp_update.length
1880 && mp_update.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001881 && mp_update.safi == SAFI_MPLS_LABELED_VPN)
Paul Jakmab881c702010-11-23 16:35:42 +00001882 bgp_nlri_parse_vpnv4 (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001883
1884 if (mp_withdraw.length
1885 && mp_withdraw.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001886 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00001887 bgp_nlri_parse_vpnv4 (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001888
hasso93406d82005-02-02 14:40:33 +00001889 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001890 && mp_withdraw.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001891 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN
paule01f9cb2004-07-09 17:48:53 +00001892 && mp_withdraw.length == 0)
1893 {
1894 /* End-of-RIB received */
1895
1896 if (BGP_DEBUG (update, UPDATE_IN))
ajs6b514742004-12-08 21:03:23 +00001897 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for VPNv4 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001898 peer->host);
1899 }
paul718e3742002-12-13 20:15:29 +00001900 }
1901
1902 /* Everything is done. We unintern temporary structures which
1903 interned in bgp_attr_parse(). */
Paul Jakmab881c702010-11-23 16:35:42 +00001904 bgp_attr_unintern_sub (&attr);
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001905
paul718e3742002-12-13 20:15:29 +00001906 /* If peering is stopped due to some reason, do not generate BGP
1907 event. */
1908 if (peer->status != Established)
1909 return 0;
1910
1911 /* Increment packet counter. */
1912 peer->update_in++;
Stephen Hemminger65957882010-01-15 16:22:10 +03001913 peer->update_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00001914
Jorge Boncompte [DTI2]e2c38e62012-06-20 17:45:50 +02001915 /* Rearm holdtime timer */
Jorge Boncompte [DTI2]6a4677b2012-05-07 16:53:07 +00001916 BGP_TIMER_OFF (peer->t_holdtime);
Jorge Boncompte [DTI2]e2c38e62012-06-20 17:45:50 +02001917 bgp_timer_set (peer);
paul718e3742002-12-13 20:15:29 +00001918
1919 return 0;
1920}
1921
1922/* Notify message treatment function. */
paul94f2b392005-06-28 12:44:16 +00001923static void
paul718e3742002-12-13 20:15:29 +00001924bgp_notify_receive (struct peer *peer, bgp_size_t size)
1925{
1926 struct bgp_notify bgp_notify;
1927
1928 if (peer->notify.data)
1929 {
1930 XFREE (MTYPE_TMP, peer->notify.data);
1931 peer->notify.data = NULL;
1932 peer->notify.length = 0;
1933 }
1934
1935 bgp_notify.code = stream_getc (peer->ibuf);
1936 bgp_notify.subcode = stream_getc (peer->ibuf);
1937 bgp_notify.length = size - 2;
1938 bgp_notify.data = NULL;
1939
1940 /* Preserv notify code and sub code. */
1941 peer->notify.code = bgp_notify.code;
1942 peer->notify.subcode = bgp_notify.subcode;
1943 /* For further diagnostic record returned Data. */
1944 if (bgp_notify.length)
1945 {
1946 peer->notify.length = size - 2;
1947 peer->notify.data = XMALLOC (MTYPE_TMP, size - 2);
1948 memcpy (peer->notify.data, stream_pnt (peer->ibuf), size - 2);
1949 }
1950
1951 /* For debug */
1952 {
1953 int i;
1954 int first = 0;
1955 char c[4];
1956
1957 if (bgp_notify.length)
1958 {
1959 bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
1960 for (i = 0; i < bgp_notify.length; i++)
1961 if (first)
1962 {
1963 sprintf (c, " %02x", stream_getc (peer->ibuf));
1964 strcat (bgp_notify.data, c);
1965 }
1966 else
1967 {
1968 first = 1;
1969 sprintf (c, "%02x", stream_getc (peer->ibuf));
1970 strcpy (bgp_notify.data, c);
1971 }
1972 }
1973
1974 bgp_notify_print(peer, &bgp_notify, "received");
1975 if (bgp_notify.data)
1976 XFREE (MTYPE_TMP, bgp_notify.data);
1977 }
1978
1979 /* peer count update */
1980 peer->notify_in++;
1981
hassoe0701b72004-05-20 09:19:34 +00001982 if (peer->status == Established)
1983 peer->last_reset = PEER_DOWN_NOTIFY_RECEIVED;
1984
paul718e3742002-12-13 20:15:29 +00001985 /* We have to check for Notify with Unsupported Optional Parameter.
1986 in that case we fallback to open without the capability option.
1987 But this done in bgp_stop. We just mark it here to avoid changing
1988 the fsm tables. */
1989 if (bgp_notify.code == BGP_NOTIFY_OPEN_ERR &&
1990 bgp_notify.subcode == BGP_NOTIFY_OPEN_UNSUP_PARAM )
1991 UNSET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
1992
paul718e3742002-12-13 20:15:29 +00001993 BGP_EVENT_ADD (peer, Receive_NOTIFICATION_message);
1994}
1995
1996/* Keepalive treatment function -- get keepalive send keepalive */
paul94f2b392005-06-28 12:44:16 +00001997static void
paul718e3742002-12-13 20:15:29 +00001998bgp_keepalive_receive (struct peer *peer, bgp_size_t size)
1999{
2000 if (BGP_DEBUG (keepalive, KEEPALIVE))
ajs6b514742004-12-08 21:03:23 +00002001 zlog_debug ("%s KEEPALIVE rcvd", peer->host);
paul718e3742002-12-13 20:15:29 +00002002
2003 BGP_EVENT_ADD (peer, Receive_KEEPALIVE_message);
2004}
2005
2006/* Route refresh message is received. */
paul94f2b392005-06-28 12:44:16 +00002007static void
paul718e3742002-12-13 20:15:29 +00002008bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
2009{
2010 afi_t afi;
2011 safi_t safi;
paul718e3742002-12-13 20:15:29 +00002012 struct stream *s;
2013
2014 /* If peer does not have the capability, send notification. */
2015 if (! CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_ADV))
2016 {
2017 plog_err (peer->log, "%s [Error] BGP route refresh is not enabled",
2018 peer->host);
2019 bgp_notify_send (peer,
2020 BGP_NOTIFY_HEADER_ERR,
2021 BGP_NOTIFY_HEADER_BAD_MESTYPE);
2022 return;
2023 }
2024
2025 /* Status must be Established. */
2026 if (peer->status != Established)
2027 {
2028 plog_err (peer->log,
2029 "%s [Error] Route refresh packet received under status %s",
2030 peer->host, LOOKUP (bgp_status_msg, peer->status));
2031 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
2032 return;
2033 }
2034
2035 s = peer->ibuf;
2036
2037 /* Parse packet. */
2038 afi = stream_getw (s);
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002039 /* reserved byte */
2040 stream_getc (s);
paul718e3742002-12-13 20:15:29 +00002041 safi = stream_getc (s);
2042
2043 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002044 zlog_debug ("%s rcvd REFRESH_REQ for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00002045 peer->host, afi, safi);
2046
2047 /* Check AFI and SAFI. */
2048 if ((afi != AFI_IP && afi != AFI_IP6)
2049 || (safi != SAFI_UNICAST && safi != SAFI_MULTICAST
Denis Ovsienko42e6d742011-07-14 12:36:19 +04002050 && safi != SAFI_MPLS_LABELED_VPN))
paul718e3742002-12-13 20:15:29 +00002051 {
2052 if (BGP_DEBUG (normal, NORMAL))
2053 {
ajs6b514742004-12-08 21:03:23 +00002054 zlog_debug ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored",
paul718e3742002-12-13 20:15:29 +00002055 peer->host, afi, safi);
2056 }
2057 return;
2058 }
2059
2060 /* Adjust safi code. */
Denis Ovsienko42e6d742011-07-14 12:36:19 +04002061 if (safi == SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00002062 safi = SAFI_MPLS_VPN;
2063
2064 if (size != BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE)
2065 {
2066 u_char *end;
2067 u_char when_to_refresh;
2068 u_char orf_type;
2069 u_int16_t orf_len;
2070
2071 if (size - (BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE) < 5)
2072 {
2073 zlog_info ("%s ORF route refresh length error", peer->host);
2074 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2075 return;
2076 }
2077
2078 when_to_refresh = stream_getc (s);
2079 end = stream_pnt (s) + (size - 5);
2080
Paul Jakma370b64a2007-12-22 16:49:52 +00002081 while ((stream_pnt (s) + 2) < end)
paul718e3742002-12-13 20:15:29 +00002082 {
2083 orf_type = stream_getc (s);
2084 orf_len = stream_getw (s);
Paul Jakma370b64a2007-12-22 16:49:52 +00002085
2086 /* orf_len in bounds? */
2087 if ((stream_pnt (s) + orf_len) > end)
2088 break; /* XXX: Notify instead?? */
paul718e3742002-12-13 20:15:29 +00002089 if (orf_type == ORF_TYPE_PREFIX
2090 || orf_type == ORF_TYPE_PREFIX_OLD)
2091 {
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002092 uint8_t *p_pnt = stream_pnt (s);
2093 uint8_t *p_end = stream_pnt (s) + orf_len;
paul718e3742002-12-13 20:15:29 +00002094 struct orf_prefix orfp;
2095 u_char common = 0;
2096 u_int32_t seq;
2097 int psize;
2098 char name[BUFSIZ];
paul718e3742002-12-13 20:15:29 +00002099 int ret;
2100
2101 if (BGP_DEBUG (normal, NORMAL))
2102 {
ajs6b514742004-12-08 21:03:23 +00002103 zlog_debug ("%s rcvd Prefixlist ORF(%d) length %d",
paul718e3742002-12-13 20:15:29 +00002104 peer->host, orf_type, orf_len);
2105 }
2106
Paul Jakma370b64a2007-12-22 16:49:52 +00002107 /* we're going to read at least 1 byte of common ORF header,
2108 * and 7 bytes of ORF Address-filter entry from the stream
2109 */
2110 if (orf_len < 7)
2111 break;
2112
paul718e3742002-12-13 20:15:29 +00002113 /* ORF prefix-list name */
2114 sprintf (name, "%s.%d.%d", peer->host, afi, safi);
2115
2116 while (p_pnt < p_end)
2117 {
Chris Halld64379e2010-05-14 16:38:39 +04002118 /* If the ORF entry is malformed, want to read as much of it
2119 * as possible without going beyond the bounds of the entry,
2120 * to maximise debug information.
2121 */
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002122 int ok;
paul718e3742002-12-13 20:15:29 +00002123 memset (&orfp, 0, sizeof (struct orf_prefix));
2124 common = *p_pnt++;
Chris Halld64379e2010-05-14 16:38:39 +04002125 /* after ++: p_pnt <= p_end */
paul718e3742002-12-13 20:15:29 +00002126 if (common & ORF_COMMON_PART_REMOVE_ALL)
2127 {
2128 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002129 zlog_debug ("%s rcvd Remove-All pfxlist ORF request", peer->host);
David Lamparterc9c06d02015-04-13 10:21:35 +02002130 prefix_bgp_orf_remove_all (afi, name);
paul718e3742002-12-13 20:15:29 +00002131 break;
2132 }
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002133 ok = ((size_t)(p_end - p_pnt) >= sizeof(u_int32_t)) ;
Denis Ovsienkobb915f52011-12-13 21:11:39 +04002134 if (ok)
Chris Halld64379e2010-05-14 16:38:39 +04002135 {
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002136 memcpy (&seq, p_pnt, sizeof (u_int32_t));
2137 p_pnt += sizeof (u_int32_t);
2138 orfp.seq = ntohl (seq);
Chris Halld64379e2010-05-14 16:38:39 +04002139 }
2140 else
2141 p_pnt = p_end ;
2142
2143 if ((ok = (p_pnt < p_end)))
2144 orfp.ge = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */
2145 if ((ok = (p_pnt < p_end)))
2146 orfp.le = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */
2147 if ((ok = (p_pnt < p_end)))
2148 orfp.p.prefixlen = *p_pnt++ ;
2149 orfp.p.family = afi2family (afi); /* afi checked already */
2150
2151 psize = PSIZE (orfp.p.prefixlen); /* 0 if not ok */
2152 if (psize > prefix_blen(&orfp.p)) /* valid for family ? */
2153 {
2154 ok = 0 ;
2155 psize = prefix_blen(&orfp.p) ;
2156 }
2157 if (psize > (p_end - p_pnt)) /* valid for packet ? */
2158 {
2159 ok = 0 ;
2160 psize = p_end - p_pnt ;
2161 }
2162
2163 if (psize > 0)
2164 memcpy (&orfp.p.u.prefix, p_pnt, psize);
paul718e3742002-12-13 20:15:29 +00002165 p_pnt += psize;
2166
2167 if (BGP_DEBUG (normal, NORMAL))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +00002168 {
2169 char buf[INET6_BUFSIZ];
2170
2171 zlog_debug ("%s rcvd %s %s seq %u %s/%d ge %d le %d%s",
2172 peer->host,
2173 (common & ORF_COMMON_PART_REMOVE ? "Remove" : "Add"),
2174 (common & ORF_COMMON_PART_DENY ? "deny" : "permit"),
2175 orfp.seq,
2176 inet_ntop (orfp.p.family, &orfp.p.u.prefix, buf, INET6_BUFSIZ),
2177 orfp.p.prefixlen, orfp.ge, orfp.le,
2178 ok ? "" : " MALFORMED");
2179 }
2180
Chris Halld64379e2010-05-14 16:38:39 +04002181 if (ok)
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002182 ret = prefix_bgp_orf_set (name, afi, &orfp,
2183 (common & ORF_COMMON_PART_DENY ? 0 : 1 ),
2184 (common & ORF_COMMON_PART_REMOVE ? 0 : 1));
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002185
2186 if (!ok || (ok && ret != CMD_SUCCESS))
paul718e3742002-12-13 20:15:29 +00002187 {
2188 if (BGP_DEBUG (normal, NORMAL))
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002189 zlog_debug ("%s Received misformatted prefixlist ORF."
2190 " Remove All pfxlist", peer->host);
David Lamparterc9c06d02015-04-13 10:21:35 +02002191 prefix_bgp_orf_remove_all (afi, name);
paul718e3742002-12-13 20:15:29 +00002192 break;
2193 }
2194 }
2195 peer->orf_plist[afi][safi] =
David Lamparterc9c06d02015-04-13 10:21:35 +02002196 prefix_bgp_orf_lookup (afi, name);
paul718e3742002-12-13 20:15:29 +00002197 }
paul9985f832005-02-09 15:51:56 +00002198 stream_forward_getp (s, orf_len);
paul718e3742002-12-13 20:15:29 +00002199 }
2200 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002201 zlog_debug ("%s rcvd Refresh %s ORF request", peer->host,
paul718e3742002-12-13 20:15:29 +00002202 when_to_refresh == REFRESH_DEFER ? "Defer" : "Immediate");
2203 if (when_to_refresh == REFRESH_DEFER)
2204 return;
2205 }
2206
2207 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2208 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH))
2209 UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
2210
2211 /* Perform route refreshment to the peer */
2212 bgp_announce_route (peer, afi, safi);
2213}
2214
paul94f2b392005-06-28 12:44:16 +00002215static int
paul718e3742002-12-13 20:15:29 +00002216bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
2217{
2218 u_char *end;
Paul Jakma6d582722007-08-06 15:21:45 +00002219 struct capability_mp_data mpc;
2220 struct capability_header *hdr;
paul718e3742002-12-13 20:15:29 +00002221 u_char action;
paul718e3742002-12-13 20:15:29 +00002222 afi_t afi;
2223 safi_t safi;
2224
paul718e3742002-12-13 20:15:29 +00002225 end = pnt + length;
2226
2227 while (pnt < end)
Paul Jakma6d582722007-08-06 15:21:45 +00002228 {
paul718e3742002-12-13 20:15:29 +00002229 /* We need at least action, capability code and capability length. */
2230 if (pnt + 3 > end)
2231 {
2232 zlog_info ("%s Capability length error", peer->host);
2233 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2234 return -1;
2235 }
paul718e3742002-12-13 20:15:29 +00002236 action = *pnt;
Paul Jakma6d582722007-08-06 15:21:45 +00002237 hdr = (struct capability_header *)(pnt + 1);
2238
paul718e3742002-12-13 20:15:29 +00002239 /* Action value check. */
2240 if (action != CAPABILITY_ACTION_SET
2241 && action != CAPABILITY_ACTION_UNSET)
2242 {
2243 zlog_info ("%s Capability Action Value error %d",
2244 peer->host, action);
2245 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2246 return -1;
2247 }
2248
2249 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002250 zlog_debug ("%s CAPABILITY has action: %d, code: %u, length %u",
Paul Jakma6d582722007-08-06 15:21:45 +00002251 peer->host, action, hdr->code, hdr->length);
paul718e3742002-12-13 20:15:29 +00002252
2253 /* Capability length check. */
Paul Jakma6d582722007-08-06 15:21:45 +00002254 if ((pnt + hdr->length + 3) > end)
paul718e3742002-12-13 20:15:29 +00002255 {
2256 zlog_info ("%s Capability length error", peer->host);
2257 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2258 return -1;
2259 }
2260
Paul Jakma6d582722007-08-06 15:21:45 +00002261 /* Fetch structure to the byte stream. */
2262 memcpy (&mpc, pnt + 3, sizeof (struct capability_mp_data));
2263
paul718e3742002-12-13 20:15:29 +00002264 /* We know MP Capability Code. */
Paul Jakma6d582722007-08-06 15:21:45 +00002265 if (hdr->code == CAPABILITY_CODE_MP)
paul718e3742002-12-13 20:15:29 +00002266 {
Paul Jakma6d582722007-08-06 15:21:45 +00002267 afi = ntohs (mpc.afi);
2268 safi = mpc.safi;
paul718e3742002-12-13 20:15:29 +00002269
2270 /* Ignore capability when override-capability is set. */
2271 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
2272 continue;
Paul Jakma6d582722007-08-06 15:21:45 +00002273
2274 if (!bgp_afi_safi_valid_indices (afi, &safi))
2275 {
2276 if (BGP_DEBUG (normal, NORMAL))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002277 zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid "
2278 "(%u/%u)", peer->host, afi, safi);
Paul Jakma6d582722007-08-06 15:21:45 +00002279 continue;
2280 }
2281
paul718e3742002-12-13 20:15:29 +00002282 /* Address family check. */
Paul Jakma6d582722007-08-06 15:21:45 +00002283 if (BGP_DEBUG (normal, NORMAL))
2284 zlog_debug ("%s CAPABILITY has %s MP_EXT CAP for afi/safi: %u/%u",
2285 peer->host,
2286 action == CAPABILITY_ACTION_SET
2287 ? "Advertising" : "Removing",
2288 ntohs(mpc.afi) , mpc.safi);
2289
2290 if (action == CAPABILITY_ACTION_SET)
2291 {
2292 peer->afc_recv[afi][safi] = 1;
2293 if (peer->afc[afi][safi])
2294 {
2295 peer->afc_nego[afi][safi] = 1;
2296 bgp_announce_route (peer, afi, safi);
2297 }
2298 }
2299 else
2300 {
2301 peer->afc_recv[afi][safi] = 0;
2302 peer->afc_nego[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00002303
Paul Jakma6d582722007-08-06 15:21:45 +00002304 if (peer_active_nego (peer))
Chris Caputo228da422009-07-18 05:44:03 +00002305 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
Paul Jakma6d582722007-08-06 15:21:45 +00002306 else
2307 BGP_EVENT_ADD (peer, BGP_Stop);
2308 }
paul718e3742002-12-13 20:15:29 +00002309 }
paul718e3742002-12-13 20:15:29 +00002310 else
2311 {
2312 zlog_warn ("%s unrecognized capability code: %d - ignored",
Paul Jakma6d582722007-08-06 15:21:45 +00002313 peer->host, hdr->code);
paul718e3742002-12-13 20:15:29 +00002314 }
Paul Jakma6d582722007-08-06 15:21:45 +00002315 pnt += hdr->length + 3;
paul718e3742002-12-13 20:15:29 +00002316 }
2317 return 0;
2318}
2319
Paul Jakma01b7ce22009-06-18 12:34:43 +01002320/* Dynamic Capability is received.
2321 *
2322 * This is exported for unit-test purposes
2323 */
Paul Jakma6d582722007-08-06 15:21:45 +00002324int
paul718e3742002-12-13 20:15:29 +00002325bgp_capability_receive (struct peer *peer, bgp_size_t size)
2326{
2327 u_char *pnt;
paul718e3742002-12-13 20:15:29 +00002328
2329 /* Fetch pointer. */
2330 pnt = stream_pnt (peer->ibuf);
2331
2332 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002333 zlog_debug ("%s rcv CAPABILITY", peer->host);
paul718e3742002-12-13 20:15:29 +00002334
2335 /* If peer does not have the capability, send notification. */
2336 if (! CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV))
2337 {
2338 plog_err (peer->log, "%s [Error] BGP dynamic capability is not enabled",
2339 peer->host);
2340 bgp_notify_send (peer,
2341 BGP_NOTIFY_HEADER_ERR,
2342 BGP_NOTIFY_HEADER_BAD_MESTYPE);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002343 return -1;
paul718e3742002-12-13 20:15:29 +00002344 }
2345
2346 /* Status must be Established. */
2347 if (peer->status != Established)
2348 {
2349 plog_err (peer->log,
2350 "%s [Error] Dynamic capability packet received under status %s", peer->host, LOOKUP (bgp_status_msg, peer->status));
2351 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002352 return -1;
paul718e3742002-12-13 20:15:29 +00002353 }
2354
2355 /* Parse packet. */
Paul Jakma6d582722007-08-06 15:21:45 +00002356 return bgp_capability_msg_parse (peer, pnt, size);
paul718e3742002-12-13 20:15:29 +00002357}
David Lamparter6b0655a2014-06-04 06:53:35 +02002358
paul718e3742002-12-13 20:15:29 +00002359/* BGP read utility function. */
paul94f2b392005-06-28 12:44:16 +00002360static int
paul718e3742002-12-13 20:15:29 +00002361bgp_read_packet (struct peer *peer)
2362{
2363 int nbytes;
2364 int readsize;
2365
paul9985f832005-02-09 15:51:56 +00002366 readsize = peer->packet_size - stream_get_endp (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00002367
2368 /* If size is zero then return. */
2369 if (! readsize)
2370 return 0;
2371
2372 /* Read packet from fd. */
Stephen Hemminger35398582010-08-05 10:26:23 -07002373 nbytes = stream_read_try (peer->ibuf, peer->fd, readsize);
paul718e3742002-12-13 20:15:29 +00002374
2375 /* If read byte is smaller than zero then error occured. */
2376 if (nbytes < 0)
2377 {
Stephen Hemminger35398582010-08-05 10:26:23 -07002378 /* Transient error should retry */
2379 if (nbytes == -2)
paul718e3742002-12-13 20:15:29 +00002380 return -1;
2381
2382 plog_err (peer->log, "%s [Error] bgp_read_packet error: %s",
ajs6099b3b2004-11-20 02:06:59 +00002383 peer->host, safe_strerror (errno));
hasso93406d82005-02-02 14:40:33 +00002384
2385 if (peer->status == Established)
2386 {
2387 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
2388 {
2389 peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
2390 SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
2391 }
2392 else
2393 peer->last_reset = PEER_DOWN_CLOSE_SESSION;
2394 }
2395
paul718e3742002-12-13 20:15:29 +00002396 BGP_EVENT_ADD (peer, TCP_fatal_error);
2397 return -1;
2398 }
2399
2400 /* When read byte is zero : clear bgp peer and return */
2401 if (nbytes == 0)
2402 {
2403 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +00002404 plog_debug (peer->log, "%s [Event] BGP connection closed fd %d",
pauleb821182004-05-01 08:44:08 +00002405 peer->host, peer->fd);
hassoe0701b72004-05-20 09:19:34 +00002406
2407 if (peer->status == Established)
hasso93406d82005-02-02 14:40:33 +00002408 {
2409 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
2410 {
2411 peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
2412 SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
2413 }
2414 else
2415 peer->last_reset = PEER_DOWN_CLOSE_SESSION;
2416 }
hassoe0701b72004-05-20 09:19:34 +00002417
paul718e3742002-12-13 20:15:29 +00002418 BGP_EVENT_ADD (peer, TCP_connection_closed);
2419 return -1;
2420 }
2421
2422 /* We read partial packet. */
paul9985f832005-02-09 15:51:56 +00002423 if (stream_get_endp (peer->ibuf) != peer->packet_size)
paul718e3742002-12-13 20:15:29 +00002424 return -1;
2425
2426 return 0;
2427}
2428
2429/* Marker check. */
paul94f2b392005-06-28 12:44:16 +00002430static int
paul718e3742002-12-13 20:15:29 +00002431bgp_marker_all_one (struct stream *s, int length)
2432{
2433 int i;
2434
2435 for (i = 0; i < length; i++)
2436 if (s->data[i] != 0xff)
2437 return 0;
2438
2439 return 1;
2440}
2441
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002442/* Recent thread time.
2443 On same clock base as bgp_clock (MONOTONIC)
2444 but can be time of last context switch to bgp_read thread. */
2445static time_t
2446bgp_recent_clock (void)
2447{
2448 return recent_relative_time().tv_sec;
2449}
2450
paul718e3742002-12-13 20:15:29 +00002451/* Starting point of packet process function. */
2452int
2453bgp_read (struct thread *thread)
2454{
2455 int ret;
2456 u_char type = 0;
2457 struct peer *peer;
2458 bgp_size_t size;
2459 char notify_data_length[2];
2460
2461 /* Yes first of all get peer pointer. */
2462 peer = THREAD_ARG (thread);
2463 peer->t_read = NULL;
2464
2465 /* For non-blocking IO check. */
2466 if (peer->status == Connect)
2467 {
2468 bgp_connect_check (peer);
2469 goto done;
2470 }
2471 else
2472 {
pauleb821182004-05-01 08:44:08 +00002473 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +00002474 {
pauleb821182004-05-01 08:44:08 +00002475 zlog_err ("bgp_read peer's fd is negative value %d", peer->fd);
paul718e3742002-12-13 20:15:29 +00002476 return -1;
2477 }
pauleb821182004-05-01 08:44:08 +00002478 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
paul718e3742002-12-13 20:15:29 +00002479 }
2480
2481 /* Read packet header to determine type of the packet */
2482 if (peer->packet_size == 0)
2483 peer->packet_size = BGP_HEADER_SIZE;
2484
paul9985f832005-02-09 15:51:56 +00002485 if (stream_get_endp (peer->ibuf) < BGP_HEADER_SIZE)
paul718e3742002-12-13 20:15:29 +00002486 {
2487 ret = bgp_read_packet (peer);
2488
2489 /* Header read error or partial read packet. */
2490 if (ret < 0)
2491 goto done;
2492
2493 /* Get size and type. */
paul9985f832005-02-09 15:51:56 +00002494 stream_forward_getp (peer->ibuf, BGP_MARKER_SIZE);
paul718e3742002-12-13 20:15:29 +00002495 memcpy (notify_data_length, stream_pnt (peer->ibuf), 2);
2496 size = stream_getw (peer->ibuf);
2497 type = stream_getc (peer->ibuf);
2498
2499 if (BGP_DEBUG (normal, NORMAL) && type != 2 && type != 0)
ajs6b514742004-12-08 21:03:23 +00002500 zlog_debug ("%s rcv message type %d, length (excl. header) %d",
paul718e3742002-12-13 20:15:29 +00002501 peer->host, type, size - BGP_HEADER_SIZE);
2502
2503 /* Marker check */
paulf5ba3872004-07-09 12:11:31 +00002504 if (((type == BGP_MSG_OPEN) || (type == BGP_MSG_KEEPALIVE))
paul718e3742002-12-13 20:15:29 +00002505 && ! bgp_marker_all_one (peer->ibuf, BGP_MARKER_SIZE))
2506 {
2507 bgp_notify_send (peer,
2508 BGP_NOTIFY_HEADER_ERR,
2509 BGP_NOTIFY_HEADER_NOT_SYNC);
2510 goto done;
2511 }
2512
2513 /* BGP type check. */
2514 if (type != BGP_MSG_OPEN && type != BGP_MSG_UPDATE
2515 && type != BGP_MSG_NOTIFY && type != BGP_MSG_KEEPALIVE
2516 && type != BGP_MSG_ROUTE_REFRESH_NEW
2517 && type != BGP_MSG_ROUTE_REFRESH_OLD
2518 && type != BGP_MSG_CAPABILITY)
2519 {
2520 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002521 plog_debug (peer->log,
paul718e3742002-12-13 20:15:29 +00002522 "%s unknown message type 0x%02x",
2523 peer->host, type);
2524 bgp_notify_send_with_data (peer,
2525 BGP_NOTIFY_HEADER_ERR,
2526 BGP_NOTIFY_HEADER_BAD_MESTYPE,
2527 &type, 1);
2528 goto done;
2529 }
2530 /* Mimimum packet length check. */
2531 if ((size < BGP_HEADER_SIZE)
2532 || (size > BGP_MAX_PACKET_SIZE)
2533 || (type == BGP_MSG_OPEN && size < BGP_MSG_OPEN_MIN_SIZE)
2534 || (type == BGP_MSG_UPDATE && size < BGP_MSG_UPDATE_MIN_SIZE)
2535 || (type == BGP_MSG_NOTIFY && size < BGP_MSG_NOTIFY_MIN_SIZE)
2536 || (type == BGP_MSG_KEEPALIVE && size != BGP_MSG_KEEPALIVE_MIN_SIZE)
2537 || (type == BGP_MSG_ROUTE_REFRESH_NEW && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
2538 || (type == BGP_MSG_ROUTE_REFRESH_OLD && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
2539 || (type == BGP_MSG_CAPABILITY && size < BGP_MSG_CAPABILITY_MIN_SIZE))
2540 {
2541 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002542 plog_debug (peer->log,
paul718e3742002-12-13 20:15:29 +00002543 "%s bad message length - %d for %s",
2544 peer->host, size,
2545 type == 128 ? "ROUTE-REFRESH" :
2546 bgp_type_str[(int) type]);
2547 bgp_notify_send_with_data (peer,
2548 BGP_NOTIFY_HEADER_ERR,
2549 BGP_NOTIFY_HEADER_BAD_MESLEN,
hassoc9e52be2004-09-26 16:09:34 +00002550 (u_char *) notify_data_length, 2);
paul718e3742002-12-13 20:15:29 +00002551 goto done;
2552 }
2553
2554 /* Adjust size to message length. */
2555 peer->packet_size = size;
2556 }
2557
2558 ret = bgp_read_packet (peer);
2559 if (ret < 0)
2560 goto done;
2561
2562 /* Get size and type again. */
2563 size = stream_getw_from (peer->ibuf, BGP_MARKER_SIZE);
2564 type = stream_getc_from (peer->ibuf, BGP_MARKER_SIZE + 2);
2565
2566 /* BGP packet dump function. */
2567 bgp_dump_packet (peer, type, peer->ibuf);
2568
2569 size = (peer->packet_size - BGP_HEADER_SIZE);
2570
2571 /* Read rest of the packet and call each sort of packet routine */
2572 switch (type)
2573 {
2574 case BGP_MSG_OPEN:
2575 peer->open_in++;
Timo Teräsef757702015-04-29 09:43:04 +03002576 peer->rtt = sockopt_tcp_rtt(peer->fd);
paulf5ba3872004-07-09 12:11:31 +00002577 bgp_open_receive (peer, size); /* XXX return value ignored! */
paul718e3742002-12-13 20:15:29 +00002578 break;
2579 case BGP_MSG_UPDATE:
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002580 peer->readtime = bgp_recent_clock ();
paul718e3742002-12-13 20:15:29 +00002581 bgp_update_receive (peer, size);
2582 break;
2583 case BGP_MSG_NOTIFY:
2584 bgp_notify_receive (peer, size);
2585 break;
2586 case BGP_MSG_KEEPALIVE:
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002587 peer->readtime = bgp_recent_clock ();
paul718e3742002-12-13 20:15:29 +00002588 bgp_keepalive_receive (peer, size);
2589 break;
2590 case BGP_MSG_ROUTE_REFRESH_NEW:
2591 case BGP_MSG_ROUTE_REFRESH_OLD:
2592 peer->refresh_in++;
2593 bgp_route_refresh_receive (peer, size);
2594 break;
2595 case BGP_MSG_CAPABILITY:
2596 peer->dynamic_cap_in++;
2597 bgp_capability_receive (peer, size);
2598 break;
2599 }
2600
2601 /* Clear input buffer. */
2602 peer->packet_size = 0;
2603 if (peer->ibuf)
2604 stream_reset (peer->ibuf);
2605
2606 done:
2607 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2608 {
2609 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +00002610 zlog_debug ("%s [Event] Accepting BGP peer delete", peer->host);
paul718e3742002-12-13 20:15:29 +00002611 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00002612 }
2613 return 0;
2614}