blob: 7d27972e2ad620a4b0a175731bfba2f493dfa4b7 [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;
278 struct stream *packet;
279
Paul Jakma750e8142008-07-22 21:11:48 +0000280 if (DISABLE_BGP_ANNOUNCE)
281 return NULL;
hasso93406d82005-02-02 14:40:33 +0000282
283 if (BGP_DEBUG (normal, NORMAL))
284 zlog_debug ("send End-of-RIB for %s to %s", afi_safi_print (afi, safi), peer->host);
285
286 s = stream_new (BGP_MAX_PACKET_SIZE);
287
288 /* Make BGP update packet. */
289 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
290
291 /* Unfeasible Routes Length */
292 stream_putw (s, 0);
293
294 if (afi == AFI_IP && safi == SAFI_UNICAST)
295 {
296 /* Total Path Attribute Length */
297 stream_putw (s, 0);
298 }
299 else
300 {
301 /* Total Path Attribute Length */
302 stream_putw (s, 6);
303 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
304 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
305 stream_putc (s, 3);
306 stream_putw (s, afi);
307 stream_putc (s, safi);
308 }
309
310 bgp_packet_set_size (s);
paule83e2082005-05-19 02:12:25 +0000311 packet = stream_dup (s);
hasso93406d82005-02-02 14:40:33 +0000312 bgp_packet_add (peer, packet);
313 stream_free (s);
314 return packet;
paul718e3742002-12-13 20:15:29 +0000315}
316
317/* Make BGP withdraw packet. */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000318/* For ipv4 unicast:
319 16-octet marker | 2-octet length | 1-octet type |
320 2-octet withdrawn route length | withdrawn prefixes | 2-octet attrlen (=0)
321*/
322/* For other afi/safis:
323 16-octet marker | 2-octet length | 1-octet type |
324 2-octet withdrawn route length (=0) | 2-octet attrlen |
325 mp_unreach attr type | attr len | afi | safi | withdrawn prefixes
326*/
paul94f2b392005-06-28 12:44:16 +0000327static struct stream *
paul718e3742002-12-13 20:15:29 +0000328bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi)
329{
330 struct stream *s;
331 struct stream *packet;
332 struct bgp_adj_out *adj;
333 struct bgp_advertise *adv;
334 struct bgp_node *rn;
paul718e3742002-12-13 20:15:29 +0000335 bgp_size_t unfeasible_len;
336 bgp_size_t total_attr_len;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000337 size_t mp_start = 0;
338 size_t attrlen_pos = 0;
339 size_t mplen_pos = 0;
340 u_char first_time = 1;
paul718e3742002-12-13 20:15:29 +0000341
342 s = peer->work;
343 stream_reset (s);
344
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100345 while ((adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->withdraw)) != NULL)
paul718e3742002-12-13 20:15:29 +0000346 {
Paul Jakmaed3ebfa2006-10-15 23:50:16 +0000347 assert (adv->rn);
paul718e3742002-12-13 20:15:29 +0000348 adj = adv->adj;
349 rn = adv->rn;
paul718e3742002-12-13 20:15:29 +0000350
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000351 if (STREAM_REMAIN (s)
hasso4372df72004-05-20 10:20:02 +0000352 < (BGP_NLRI_LENGTH + BGP_TOTAL_ATTR_LEN + PSIZE (rn->p.prefixlen)))
paul718e3742002-12-13 20:15:29 +0000353 break;
354
355 if (stream_empty (s))
356 {
357 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000358 stream_putw (s, 0); /* unfeasible routes length */
paul718e3742002-12-13 20:15:29 +0000359 }
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000360 else
361 first_time = 0;
paul718e3742002-12-13 20:15:29 +0000362
363 if (afi == AFI_IP && safi == SAFI_UNICAST)
364 stream_put_prefix (s, &rn->p);
365 else
366 {
Paul Jakmaa3b6ea52006-05-04 07:52:12 +0000367 struct prefix_rd *prd = NULL;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000368
Paul Jakmaa3b6ea52006-05-04 07:52:12 +0000369 if (rn->prn)
370 prd = (struct prefix_rd *) &rn->prn->p;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000371
372 /* If first time, format the MP_UNREACH header */
373 if (first_time)
374 {
375 attrlen_pos = stream_get_endp (s);
376 /* total attr length = 0 for now. reevaluate later */
377 stream_putw (s, 0);
378 mp_start = stream_get_endp (s);
379 mplen_pos = bgp_packet_mpunreach_start(s, afi, safi);
380 }
381
382 bgp_packet_mpunreach_prefix(s, &rn->p, afi, safi, prd, NULL);
paul718e3742002-12-13 20:15:29 +0000383 }
384
385 if (BGP_DEBUG (update, UPDATE_OUT))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000386 {
387 char buf[INET6_BUFSIZ];
388
389 zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d -- unreachable",
390 peer->host,
391 inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ),
392 rn->p.prefixlen);
393 }
paul718e3742002-12-13 20:15:29 +0000394
395 peer->scount[afi][safi]--;
396
397 bgp_adj_out_remove (rn, adj, peer, afi, safi);
398 bgp_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +0000399 }
400
401 if (! stream_empty (s))
402 {
403 if (afi == AFI_IP && safi == SAFI_UNICAST)
404 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000405 unfeasible_len
paul9985f832005-02-09 15:51:56 +0000406 = stream_get_endp (s) - BGP_HEADER_SIZE - BGP_UNFEASIBLE_LEN;
paul718e3742002-12-13 20:15:29 +0000407 stream_putw_at (s, BGP_HEADER_SIZE, unfeasible_len);
408 stream_putw (s, 0);
409 }
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000410 else
411 {
412 /* Set the mp_unreach attr's length */
413 bgp_packet_mpunreach_end(s, mplen_pos);
414
415 /* Set total path attribute length. */
416 total_attr_len = stream_get_endp(s) - mp_start;
417 stream_putw_at (s, attrlen_pos, total_attr_len);
418 }
paul718e3742002-12-13 20:15:29 +0000419 bgp_packet_set_size (s);
paule83e2082005-05-19 02:12:25 +0000420 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +0000421 bgp_packet_add (peer, packet);
422 stream_reset (s);
423 return packet;
424 }
425
426 return NULL;
427}
428
429void
430bgp_default_update_send (struct peer *peer, struct attr *attr,
431 afi_t afi, safi_t safi, struct peer *from)
432{
433 struct stream *s;
434 struct stream *packet;
435 struct prefix p;
436 unsigned long pos;
437 bgp_size_t total_attr_len;
paul718e3742002-12-13 20:15:29 +0000438
Paul Jakma750e8142008-07-22 21:11:48 +0000439 if (DISABLE_BGP_ANNOUNCE)
440 return;
paul718e3742002-12-13 20:15:29 +0000441
442 if (afi == AFI_IP)
443 str2prefix ("0.0.0.0/0", &p);
444#ifdef HAVE_IPV6
445 else
446 str2prefix ("::/0", &p);
447#endif /* HAVE_IPV6 */
448
449 /* Logging the attribute. */
450 if (BGP_DEBUG (update, UPDATE_OUT))
451 {
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000452 char attrstr[BUFSIZ];
453 char buf[INET6_BUFSIZ];
454 attrstr[0] = '\0';
455
paul718e3742002-12-13 20:15:29 +0000456 bgp_dump_attr (peer, attr, attrstr, BUFSIZ);
ajs6b514742004-12-08 21:03:23 +0000457 zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d %s",
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000458 peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ),
paul718e3742002-12-13 20:15:29 +0000459 p.prefixlen, attrstr);
460 }
461
462 s = stream_new (BGP_MAX_PACKET_SIZE);
463
464 /* Make BGP update packet. */
465 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
466
467 /* Unfeasible Routes Length. */
468 stream_putw (s, 0);
469
470 /* Make place for total attribute length. */
paul9985f832005-02-09 15:51:56 +0000471 pos = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000472 stream_putw (s, 0);
473 total_attr_len = bgp_packet_attribute (NULL, peer, s, attr, &p, afi, safi, from, NULL, NULL);
474
475 /* Set Total Path Attribute Length. */
476 stream_putw_at (s, pos, total_attr_len);
477
478 /* NLRI set. */
479 if (p.family == AF_INET && safi == SAFI_UNICAST)
480 stream_put_prefix (s, &p);
481
482 /* Set size. */
483 bgp_packet_set_size (s);
484
paule83e2082005-05-19 02:12:25 +0000485 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +0000486 stream_free (s);
487
488 /* Dump packet if debug option is set. */
489#ifdef DEBUG
jardin2d74db52005-10-01 00:07:50 +0000490 /* bgp_packet_dump (packet); */
paul718e3742002-12-13 20:15:29 +0000491#endif /* DEBUG */
492
493 /* Add packet to the peer. */
494 bgp_packet_add (peer, packet);
495
pauleb821182004-05-01 08:44:08 +0000496 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000497}
498
499void
500bgp_default_withdraw_send (struct peer *peer, afi_t afi, safi_t safi)
501{
502 struct stream *s;
503 struct stream *packet;
504 struct prefix p;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000505 unsigned long attrlen_pos = 0;
paul718e3742002-12-13 20:15:29 +0000506 unsigned long cp;
507 bgp_size_t unfeasible_len;
508 bgp_size_t total_attr_len;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000509 size_t mp_start = 0;
510 size_t mplen_pos = 0;
paul718e3742002-12-13 20:15:29 +0000511
Paul Jakma750e8142008-07-22 21:11:48 +0000512 if (DISABLE_BGP_ANNOUNCE)
513 return;
paul718e3742002-12-13 20:15:29 +0000514
515 if (afi == AFI_IP)
516 str2prefix ("0.0.0.0/0", &p);
517#ifdef HAVE_IPV6
518 else
519 str2prefix ("::/0", &p);
520#endif /* HAVE_IPV6 */
521
522 total_attr_len = 0;
paul718e3742002-12-13 20:15:29 +0000523
524 if (BGP_DEBUG (update, UPDATE_OUT))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000525 {
526 char buf[INET6_BUFSIZ];
527
528 zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d -- unreachable",
529 peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ),
530 p.prefixlen);
531 }
paul718e3742002-12-13 20:15:29 +0000532
533 s = stream_new (BGP_MAX_PACKET_SIZE);
534
535 /* Make BGP update packet. */
536 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
537
538 /* Unfeasible Routes Length. */;
paul9985f832005-02-09 15:51:56 +0000539 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000540 stream_putw (s, 0);
541
542 /* Withdrawn Routes. */
543 if (p.family == AF_INET && safi == SAFI_UNICAST)
544 {
545 stream_put_prefix (s, &p);
546
paul9985f832005-02-09 15:51:56 +0000547 unfeasible_len = stream_get_endp (s) - cp - 2;
paul718e3742002-12-13 20:15:29 +0000548
549 /* Set unfeasible len. */
550 stream_putw_at (s, cp, unfeasible_len);
551
552 /* Set total path attribute length. */
553 stream_putw (s, 0);
554 }
555 else
556 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000557 attrlen_pos = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000558 stream_putw (s, 0);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000559 mp_start = stream_get_endp (s);
560 mplen_pos = bgp_packet_mpunreach_start(s, afi, safi);
561 bgp_packet_mpunreach_prefix(s, &p, afi, safi, NULL, NULL);
562
563 /* Set the mp_unreach attr's length */
564 bgp_packet_mpunreach_end(s, mplen_pos);
paul718e3742002-12-13 20:15:29 +0000565
566 /* Set total path attribute length. */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000567 total_attr_len = stream_get_endp(s) - mp_start;
568 stream_putw_at (s, attrlen_pos, total_attr_len);
paul718e3742002-12-13 20:15:29 +0000569 }
570
571 bgp_packet_set_size (s);
572
paule83e2082005-05-19 02:12:25 +0000573 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +0000574 stream_free (s);
575
576 /* Add packet to the peer. */
577 bgp_packet_add (peer, packet);
578
pauleb821182004-05-01 08:44:08 +0000579 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000580}
581
582/* Get next packet to be written. */
paul94f2b392005-06-28 12:44:16 +0000583static struct stream *
paul718e3742002-12-13 20:15:29 +0000584bgp_write_packet (struct peer *peer)
585{
586 afi_t afi;
587 safi_t safi;
588 struct stream *s = NULL;
589 struct bgp_advertise *adv;
590
591 s = stream_fifo_head (peer->obuf);
592 if (s)
593 return s;
594
595 for (afi = AFI_IP; afi < AFI_MAX; afi++)
596 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
597 {
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100598 adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->withdraw);
paul718e3742002-12-13 20:15:29 +0000599 if (adv)
600 {
601 s = bgp_withdraw_packet (peer, afi, safi);
602 if (s)
603 return s;
604 }
605 }
606
607 for (afi = AFI_IP; afi < AFI_MAX; afi++)
608 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
609 {
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100610 adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->update);
paul718e3742002-12-13 20:15:29 +0000611 if (adv)
612 {
613 if (adv->binfo && adv->binfo->uptime < peer->synctime)
hasso93406d82005-02-02 14:40:33 +0000614 {
615 if (CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_RCV)
616 && CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_ADV)
Vipin Kumardd49eb12014-09-30 14:36:38 -0700617 && ! (CHECK_FLAG (adv->binfo->peer->cap,
618 PEER_CAP_RESTART_BIT_RCV) &&
619 CHECK_FLAG (adv->binfo->peer->cap,
620 PEER_CAP_RESTART_BIT_ADV))
hasso93406d82005-02-02 14:40:33 +0000621 && ! CHECK_FLAG (adv->binfo->flags, BGP_INFO_STALE)
622 && safi != SAFI_MPLS_VPN)
623 {
624 if (CHECK_FLAG (adv->binfo->peer->af_sflags[afi][safi],
625 PEER_STATUS_EOR_RECEIVED))
626 s = bgp_update_packet (peer, afi, safi);
627 }
628 else
629 s = bgp_update_packet (peer, afi, safi);
630 }
paul718e3742002-12-13 20:15:29 +0000631
632 if (s)
633 return s;
634 }
hasso93406d82005-02-02 14:40:33 +0000635
636 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV))
637 {
638 if (peer->afc_nego[afi][safi] && peer->synctime
639 && ! CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND)
640 && safi != SAFI_MPLS_VPN)
641 {
642 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND);
643 return bgp_update_packet_eor (peer, afi, safi);
644 }
645 }
paul718e3742002-12-13 20:15:29 +0000646 }
647
648 return NULL;
649}
650
651/* Is there partially written packet or updates we can send right
652 now. */
paul94f2b392005-06-28 12:44:16 +0000653static int
paul718e3742002-12-13 20:15:29 +0000654bgp_write_proceed (struct peer *peer)
655{
656 afi_t afi;
657 safi_t safi;
658 struct bgp_advertise *adv;
659
660 if (stream_fifo_head (peer->obuf))
661 return 1;
662
663 for (afi = AFI_IP; afi < AFI_MAX; afi++)
664 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
665 if (FIFO_HEAD (&peer->sync[afi][safi]->withdraw))
666 return 1;
667
668 for (afi = AFI_IP; afi < AFI_MAX; afi++)
669 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100670 if ((adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->update)) != NULL)
paul718e3742002-12-13 20:15:29 +0000671 if (adv->binfo->uptime < peer->synctime)
672 return 1;
673
674 return 0;
675}
676
677/* Write packet to the peer. */
678int
679bgp_write (struct thread *thread)
680{
681 struct peer *peer;
682 u_char type;
683 struct stream *s;
684 int num;
paulfd79ac92004-10-13 05:06:08 +0000685 unsigned int count = 0;
paul718e3742002-12-13 20:15:29 +0000686
687 /* Yes first of all get peer pointer. */
688 peer = THREAD_ARG (thread);
689 peer->t_write = NULL;
690
691 /* For non-blocking IO check. */
692 if (peer->status == Connect)
693 {
694 bgp_connect_check (peer);
695 return 0;
696 }
697
Stephen Hemmingereac57022010-08-05 10:26:25 -0700698 s = bgp_write_packet (peer);
699 if (!s)
700 return 0; /* nothing to send */
701
702 sockopt_cork (peer->fd, 1);
703
704 /* Nonblocking write until TCP output buffer is full. */
705 do
paul718e3742002-12-13 20:15:29 +0000706 {
707 int writenum;
paul718e3742002-12-13 20:15:29 +0000708
709 /* Number of bytes to be sent. */
710 writenum = stream_get_endp (s) - stream_get_getp (s);
711
712 /* Call write() system call. */
pauleb821182004-05-01 08:44:08 +0000713 num = write (peer->fd, STREAM_PNT (s), writenum);
Stephen Hemminger35398582010-08-05 10:26:23 -0700714 if (num < 0)
paul718e3742002-12-13 20:15:29 +0000715 {
Stephen Hemmingereac57022010-08-05 10:26:25 -0700716 /* write failed either retry needed or error */
717 if (ERRNO_IO_RETRY(errno))
718 break;
719
720 BGP_EVENT_ADD (peer, TCP_fatal_error);
paul718e3742002-12-13 20:15:29 +0000721 return 0;
722 }
Stephen Hemminger35398582010-08-05 10:26:23 -0700723
paul718e3742002-12-13 20:15:29 +0000724 if (num != writenum)
725 {
Stephen Hemminger35398582010-08-05 10:26:23 -0700726 /* Partial write */
paul9985f832005-02-09 15:51:56 +0000727 stream_forward_getp (s, num);
Stephen Hemmingereac57022010-08-05 10:26:25 -0700728 break;
paul718e3742002-12-13 20:15:29 +0000729 }
730
731 /* Retrieve BGP packet type. */
732 stream_set_getp (s, BGP_MARKER_SIZE + 2);
733 type = stream_getc (s);
734
735 switch (type)
736 {
737 case BGP_MSG_OPEN:
738 peer->open_out++;
739 break;
740 case BGP_MSG_UPDATE:
741 peer->update_out++;
742 break;
743 case BGP_MSG_NOTIFY:
744 peer->notify_out++;
745 /* Double start timer. */
746 peer->v_start *= 2;
747
748 /* Overflow check. */
749 if (peer->v_start >= (60 * 2))
750 peer->v_start = (60 * 2);
751
Paul Jakmaca058a32006-09-14 02:58:49 +0000752 /* Flush any existing events */
Paul Jakmadcdf3992006-10-15 23:39:59 +0000753 BGP_EVENT_ADD (peer, BGP_Stop);
Stephen Hemminger3a69f742013-01-11 18:27:23 +0000754 goto done;
755
paul718e3742002-12-13 20:15:29 +0000756 case BGP_MSG_KEEPALIVE:
757 peer->keepalive_out++;
758 break;
759 case BGP_MSG_ROUTE_REFRESH_NEW:
760 case BGP_MSG_ROUTE_REFRESH_OLD:
761 peer->refresh_out++;
762 break;
763 case BGP_MSG_CAPABILITY:
764 peer->dynamic_cap_out++;
765 break;
766 }
767
768 /* OK we send packet so delete it. */
769 bgp_packet_delete (peer);
paul718e3742002-12-13 20:15:29 +0000770 }
Stephen Hemmingereac57022010-08-05 10:26:25 -0700771 while (++count < BGP_WRITE_PACKET_MAX &&
772 (s = bgp_write_packet (peer)) != NULL);
paul718e3742002-12-13 20:15:29 +0000773
774 if (bgp_write_proceed (peer))
pauleb821182004-05-01 08:44:08 +0000775 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
Stephen Hemminger3a69f742013-01-11 18:27:23 +0000776
777 done:
778 sockopt_cork (peer->fd, 0);
paul718e3742002-12-13 20:15:29 +0000779 return 0;
780}
781
782/* This is only for sending NOTIFICATION message to neighbor. */
paul94f2b392005-06-28 12:44:16 +0000783static int
paul718e3742002-12-13 20:15:29 +0000784bgp_write_notify (struct peer *peer)
785{
Stephen Hemminger35398582010-08-05 10:26:23 -0700786 int ret, val;
paul718e3742002-12-13 20:15:29 +0000787 u_char type;
788 struct stream *s;
789
790 /* There should be at least one packet. */
791 s = stream_fifo_head (peer->obuf);
792 if (!s)
793 return 0;
794 assert (stream_get_endp (s) >= BGP_HEADER_SIZE);
795
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000796 /* Stop collecting data within the socket */
797 sockopt_cork (peer->fd, 0);
798
David Lamparter8ff202e2013-07-31 14:39:41 +0200799 /* socket is in nonblocking mode, if we can't deliver the NOTIFY, well,
800 * we only care about getting a clean shutdown at this point. */
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000801 ret = write (peer->fd, STREAM_DATA (s), stream_get_endp (s));
David Lamparter8ff202e2013-07-31 14:39:41 +0200802
803 /* only connection reset/close gets counted as TCP_fatal_error, failure
804 * to write the entire NOTIFY doesn't get different FSM treatment */
paul718e3742002-12-13 20:15:29 +0000805 if (ret <= 0)
806 {
Paul Jakmadcdf3992006-10-15 23:39:59 +0000807 BGP_EVENT_ADD (peer, TCP_fatal_error);
paul718e3742002-12-13 20:15:29 +0000808 return 0;
809 }
810
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000811 /* Disable Nagle, make NOTIFY packet go out right away */
812 val = 1;
813 (void) setsockopt (peer->fd, IPPROTO_TCP, TCP_NODELAY,
814 (char *) &val, sizeof (val));
815
paul718e3742002-12-13 20:15:29 +0000816 /* Retrieve BGP packet type. */
817 stream_set_getp (s, BGP_MARKER_SIZE + 2);
818 type = stream_getc (s);
819
820 assert (type == BGP_MSG_NOTIFY);
821
822 /* Type should be notify. */
823 peer->notify_out++;
824
825 /* Double start timer. */
826 peer->v_start *= 2;
827
828 /* Overflow check. */
829 if (peer->v_start >= (60 * 2))
830 peer->v_start = (60 * 2);
831
Paul Jakmadcdf3992006-10-15 23:39:59 +0000832 BGP_EVENT_ADD (peer, BGP_Stop);
paul718e3742002-12-13 20:15:29 +0000833
834 return 0;
835}
836
837/* Make keepalive packet and send it to the peer. */
838void
839bgp_keepalive_send (struct peer *peer)
840{
841 struct stream *s;
842 int length;
843
844 s = stream_new (BGP_MAX_PACKET_SIZE);
845
846 /* Make keepalive packet. */
847 bgp_packet_set_marker (s, BGP_MSG_KEEPALIVE);
848
849 /* Set packet size. */
850 length = bgp_packet_set_size (s);
851
852 /* Dump packet if debug option is set. */
853 /* bgp_packet_dump (s); */
854
855 if (BGP_DEBUG (keepalive, KEEPALIVE))
ajs6b514742004-12-08 21:03:23 +0000856 zlog_debug ("%s sending KEEPALIVE", peer->host);
paul718e3742002-12-13 20:15:29 +0000857 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000858 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000859 peer->host, BGP_MSG_KEEPALIVE, length);
860
861 /* Add packet to the peer. */
862 bgp_packet_add (peer, s);
863
pauleb821182004-05-01 08:44:08 +0000864 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000865}
866
867/* Make open packet and send it to the peer. */
868void
869bgp_open_send (struct peer *peer)
870{
871 struct stream *s;
872 int length;
873 u_int16_t send_holdtime;
874 as_t local_as;
875
876 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
877 send_holdtime = peer->holdtime;
878 else
879 send_holdtime = peer->bgp->default_holdtime;
880
881 /* local-as Change */
882 if (peer->change_local_as)
883 local_as = peer->change_local_as;
884 else
885 local_as = peer->local_as;
886
887 s = stream_new (BGP_MAX_PACKET_SIZE);
888
889 /* Make open packet. */
890 bgp_packet_set_marker (s, BGP_MSG_OPEN);
891
892 /* Set open packet values. */
893 stream_putc (s, BGP_VERSION_4); /* BGP version */
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000894 stream_putw (s, (local_as <= BGP_AS_MAX) ? (u_int16_t) local_as
895 : BGP_AS_TRANS);
paul718e3742002-12-13 20:15:29 +0000896 stream_putw (s, send_holdtime); /* Hold Time */
897 stream_put_in_addr (s, &peer->local_id); /* BGP Identifier */
898
899 /* Set capability code. */
900 bgp_open_capability (s, peer);
901
902 /* Set BGP packet length. */
903 length = bgp_packet_set_size (s);
904
905 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +0400906 zlog_debug ("%s sending OPEN, version %d, my as %u, holdtime %d, id %s",
paul718e3742002-12-13 20:15:29 +0000907 peer->host, BGP_VERSION_4, local_as,
908 send_holdtime, inet_ntoa (peer->local_id));
909
910 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000911 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000912 peer->host, BGP_MSG_OPEN, length);
913
914 /* Dump packet if debug option is set. */
915 /* bgp_packet_dump (s); */
916
917 /* Add packet to the peer. */
918 bgp_packet_add (peer, s);
919
pauleb821182004-05-01 08:44:08 +0000920 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000921}
922
923/* Send BGP notify packet with data potion. */
924void
925bgp_notify_send_with_data (struct peer *peer, u_char code, u_char sub_code,
926 u_char *data, size_t datalen)
927{
928 struct stream *s;
929 int length;
930
931 /* Allocate new stream. */
932 s = stream_new (BGP_MAX_PACKET_SIZE);
933
934 /* Make nitify packet. */
935 bgp_packet_set_marker (s, BGP_MSG_NOTIFY);
936
937 /* Set notify packet values. */
938 stream_putc (s, code); /* BGP notify code */
939 stream_putc (s, sub_code); /* BGP notify sub_code */
940
941 /* If notify data is present. */
942 if (data)
943 stream_write (s, data, datalen);
944
945 /* Set BGP packet length. */
946 length = bgp_packet_set_size (s);
947
948 /* Add packet to the peer. */
949 stream_fifo_clean (peer->obuf);
950 bgp_packet_add (peer, s);
951
952 /* For debug */
953 {
954 struct bgp_notify bgp_notify;
955 int first = 0;
956 int i;
957 char c[4];
958
959 bgp_notify.code = code;
960 bgp_notify.subcode = sub_code;
961 bgp_notify.data = NULL;
962 bgp_notify.length = length - BGP_MSG_NOTIFY_MIN_SIZE;
963
964 if (bgp_notify.length)
965 {
966 bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
967 for (i = 0; i < bgp_notify.length; i++)
968 if (first)
969 {
970 sprintf (c, " %02x", data[i]);
971 strcat (bgp_notify.data, c);
972 }
973 else
974 {
975 first = 1;
976 sprintf (c, "%02x", data[i]);
977 strcpy (bgp_notify.data, c);
978 }
979 }
980 bgp_notify_print (peer, &bgp_notify, "sending");
981 if (bgp_notify.data)
982 XFREE (MTYPE_TMP, bgp_notify.data);
983 }
984
985 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000986 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000987 peer->host, BGP_MSG_NOTIFY, length);
988
hassoe0701b72004-05-20 09:19:34 +0000989 /* peer reset cause */
990 if (sub_code != BGP_NOTIFY_CEASE_CONFIG_CHANGE)
991 {
992 if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET)
heasley1212dc12011-09-12 13:27:52 +0400993 {
994 peer->last_reset = PEER_DOWN_USER_RESET;
995 zlog_info ("Notification sent to neighbor %s: User reset", peer->host);
996 }
hassoe0701b72004-05-20 09:19:34 +0000997 else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN)
heasley1212dc12011-09-12 13:27:52 +0400998 {
999 peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
1000 zlog_info ("Notification sent to neighbor %s: shutdown", peer->host);
1001 }
hassoe0701b72004-05-20 09:19:34 +00001002 else
heasley1212dc12011-09-12 13:27:52 +04001003 {
1004 peer->last_reset = PEER_DOWN_NOTIFY_SEND;
1005 zlog_info ("Notification sent to neighbor %s: type %u/%u",
1006 peer->host, code, sub_code);
1007 }
hassoe0701b72004-05-20 09:19:34 +00001008 }
heasley1212dc12011-09-12 13:27:52 +04001009 else
1010 zlog_info ("Notification sent to neighbor %s: configuration change",
1011 peer->host);
hassoe0701b72004-05-20 09:19:34 +00001012
Denis Ovsienko7ccf5e52011-09-10 16:53:30 +04001013 /* Call immediately. */
paul718e3742002-12-13 20:15:29 +00001014 BGP_WRITE_OFF (peer->t_write);
1015
1016 bgp_write_notify (peer);
1017}
1018
1019/* Send BGP notify packet. */
1020void
1021bgp_notify_send (struct peer *peer, u_char code, u_char sub_code)
1022{
1023 bgp_notify_send_with_data (peer, code, sub_code, NULL, 0);
1024}
1025
paul718e3742002-12-13 20:15:29 +00001026/* Send route refresh message to the peer. */
1027void
1028bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
1029 u_char orf_type, u_char when_to_refresh, int remove)
1030{
1031 struct stream *s;
1032 struct stream *packet;
1033 int length;
1034 struct bgp_filter *filter;
1035 int orf_refresh = 0;
1036
Paul Jakma750e8142008-07-22 21:11:48 +00001037 if (DISABLE_BGP_ANNOUNCE)
1038 return;
paul718e3742002-12-13 20:15:29 +00001039
1040 filter = &peer->filter[afi][safi];
1041
1042 /* Adjust safi code. */
1043 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001044 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +00001045
1046 s = stream_new (BGP_MAX_PACKET_SIZE);
1047
1048 /* Make BGP update packet. */
1049 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
1050 bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_NEW);
1051 else
1052 bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_OLD);
1053
1054 /* Encode Route Refresh message. */
1055 stream_putw (s, afi);
1056 stream_putc (s, 0);
1057 stream_putc (s, safi);
1058
1059 if (orf_type == ORF_TYPE_PREFIX
1060 || orf_type == ORF_TYPE_PREFIX_OLD)
1061 if (remove || filter->plist[FILTER_IN].plist)
1062 {
1063 u_int16_t orf_len;
1064 unsigned long orfp;
1065
1066 orf_refresh = 1;
1067 stream_putc (s, when_to_refresh);
1068 stream_putc (s, orf_type);
paul9985f832005-02-09 15:51:56 +00001069 orfp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00001070 stream_putw (s, 0);
1071
1072 if (remove)
1073 {
1074 UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
1075 stream_putc (s, ORF_COMMON_PART_REMOVE_ALL);
1076 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001077 zlog_debug ("%s sending REFRESH_REQ to remove 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 else
1083 {
1084 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
1085 prefix_bgp_orf_entry (s, filter->plist[FILTER_IN].plist,
1086 ORF_COMMON_PART_ADD, ORF_COMMON_PART_PERMIT,
1087 ORF_COMMON_PART_DENY);
1088 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001089 zlog_debug ("%s sending REFRESH_REQ with pfxlist ORF(%d) (%s) for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001090 peer->host, orf_type,
1091 (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
1092 afi, safi);
1093 }
1094
1095 /* Total ORF Entry Len. */
paul9985f832005-02-09 15:51:56 +00001096 orf_len = stream_get_endp (s) - orfp - 2;
paul718e3742002-12-13 20:15:29 +00001097 stream_putw_at (s, orfp, orf_len);
1098 }
1099
1100 /* Set packet size. */
1101 length = bgp_packet_set_size (s);
1102
1103 if (BGP_DEBUG (normal, NORMAL))
1104 {
1105 if (! orf_refresh)
ajs6b514742004-12-08 21:03:23 +00001106 zlog_debug ("%s sending REFRESH_REQ for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001107 peer->host, afi, safi);
ajs6b514742004-12-08 21:03:23 +00001108 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +00001109 peer->host, CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV) ?
1110 BGP_MSG_ROUTE_REFRESH_NEW : BGP_MSG_ROUTE_REFRESH_OLD, length);
1111 }
1112
1113 /* Make real packet. */
paule83e2082005-05-19 02:12:25 +00001114 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +00001115 stream_free (s);
1116
1117 /* Add packet to the peer. */
1118 bgp_packet_add (peer, packet);
1119
pauleb821182004-05-01 08:44:08 +00001120 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +00001121}
1122
1123/* Send capability message to the peer. */
1124void
1125bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi,
1126 int capability_code, int action)
1127{
1128 struct stream *s;
1129 struct stream *packet;
1130 int length;
1131
1132 /* Adjust safi code. */
1133 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001134 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +00001135
1136 s = stream_new (BGP_MAX_PACKET_SIZE);
1137
1138 /* Make BGP update packet. */
1139 bgp_packet_set_marker (s, BGP_MSG_CAPABILITY);
1140
1141 /* Encode MP_EXT capability. */
1142 if (capability_code == CAPABILITY_CODE_MP)
1143 {
1144 stream_putc (s, action);
1145 stream_putc (s, CAPABILITY_CODE_MP);
1146 stream_putc (s, CAPABILITY_CODE_MP_LEN);
1147 stream_putw (s, afi);
1148 stream_putc (s, 0);
1149 stream_putc (s, safi);
1150
1151 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001152 zlog_debug ("%s sending CAPABILITY has %s MP_EXT CAP for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001153 peer->host, action == CAPABILITY_ACTION_SET ?
1154 "Advertising" : "Removing", afi, safi);
1155 }
1156
paul718e3742002-12-13 20:15:29 +00001157 /* Set packet size. */
1158 length = bgp_packet_set_size (s);
1159
1160 /* Make real packet. */
paule83e2082005-05-19 02:12:25 +00001161 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +00001162 stream_free (s);
1163
1164 /* Add packet to the peer. */
1165 bgp_packet_add (peer, packet);
1166
1167 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001168 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +00001169 peer->host, BGP_MSG_CAPABILITY, length);
1170
pauleb821182004-05-01 08:44:08 +00001171 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +00001172}
David Lamparter6b0655a2014-06-04 06:53:35 +02001173
paul718e3742002-12-13 20:15:29 +00001174/* RFC1771 6.8 Connection collision detection. */
paul94f2b392005-06-28 12:44:16 +00001175static int
pauleb821182004-05-01 08:44:08 +00001176bgp_collision_detect (struct peer *new, struct in_addr remote_id)
paul718e3742002-12-13 20:15:29 +00001177{
pauleb821182004-05-01 08:44:08 +00001178 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001179 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001180 struct bgp *bgp;
1181
1182 bgp = bgp_get_default ();
1183 if (! bgp)
1184 return 0;
1185
1186 /* Upon receipt of an OPEN message, the local system must examine
1187 all of its connections that are in the OpenConfirm state. A BGP
1188 speaker may also examine connections in an OpenSent state if it
1189 knows the BGP Identifier of the peer by means outside of the
1190 protocol. If among these connections there is a connection to a
1191 remote BGP speaker whose BGP Identifier equals the one in the
1192 OPEN message, then the local system performs the following
1193 collision resolution procedure: */
1194
paul1eb8ef22005-04-07 07:30:20 +00001195 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001196 {
1197 /* Under OpenConfirm status, local peer structure already hold
1198 remote router ID. */
pauleb821182004-05-01 08:44:08 +00001199
1200 if (peer != new
1201 && (peer->status == OpenConfirm || peer->status == OpenSent)
1202 && sockunion_same (&peer->su, &new->su))
1203 {
paul718e3742002-12-13 20:15:29 +00001204 /* 1. The BGP Identifier of the local system is compared to
1205 the BGP Identifier of the remote system (as specified in
1206 the OPEN message). */
1207
1208 if (ntohl (peer->local_id.s_addr) < ntohl (remote_id.s_addr))
1209 {
1210 /* 2. If the value of the local BGP Identifier is less
1211 than the remote one, the local system closes BGP
1212 connection that already exists (the one that is
1213 already in the OpenConfirm state), and accepts BGP
1214 connection initiated by the remote system. */
1215
pauleb821182004-05-01 08:44:08 +00001216 if (peer->fd >= 0)
hassoe0701b72004-05-20 09:19:34 +00001217 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
paul718e3742002-12-13 20:15:29 +00001218 return 1;
1219 }
1220 else
1221 {
1222 /* 3. Otherwise, the local system closes newly created
1223 BGP connection (the one associated with the newly
1224 received OPEN message), and continues to use the
1225 existing one (the one that is already in the
1226 OpenConfirm state). */
1227
pauleb821182004-05-01 08:44:08 +00001228 if (new->fd >= 0)
paulf5ba3872004-07-09 12:11:31 +00001229 bgp_notify_send (new, BGP_NOTIFY_CEASE,
1230 BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
paul718e3742002-12-13 20:15:29 +00001231 return -1;
1232 }
pauleb821182004-05-01 08:44:08 +00001233 }
1234 }
paul718e3742002-12-13 20:15:29 +00001235 return 0;
1236}
1237
paul94f2b392005-06-28 12:44:16 +00001238static int
paul718e3742002-12-13 20:15:29 +00001239bgp_open_receive (struct peer *peer, bgp_size_t size)
1240{
1241 int ret;
1242 u_char version;
1243 u_char optlen;
1244 u_int16_t holdtime;
1245 u_int16_t send_holdtime;
1246 as_t remote_as;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001247 as_t as4 = 0;
paul718e3742002-12-13 20:15:29 +00001248 struct peer *realpeer;
1249 struct in_addr remote_id;
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001250 int mp_capability;
paul5228ad22004-06-04 17:58:18 +00001251 u_int8_t notify_data_remote_as[2];
1252 u_int8_t notify_data_remote_id[4];
paul718e3742002-12-13 20:15:29 +00001253
1254 realpeer = NULL;
1255
1256 /* Parse open packet. */
1257 version = stream_getc (peer->ibuf);
1258 memcpy (notify_data_remote_as, stream_pnt (peer->ibuf), 2);
1259 remote_as = stream_getw (peer->ibuf);
1260 holdtime = stream_getw (peer->ibuf);
1261 memcpy (notify_data_remote_id, stream_pnt (peer->ibuf), 4);
1262 remote_id.s_addr = stream_get_ipv4 (peer->ibuf);
1263
1264 /* Receive OPEN message log */
1265 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001266 zlog_debug ("%s rcv OPEN, version %d, remote-as (in open) %u,"
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001267 " holdtime %d, id %s",
1268 peer->host, version, remote_as, holdtime,
1269 inet_ntoa (remote_id));
1270
1271 /* BEGIN to read the capability here, but dont do it yet */
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001272 mp_capability = 0;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001273 optlen = stream_getc (peer->ibuf);
1274
1275 if (optlen != 0)
1276 {
1277 /* We need the as4 capability value *right now* because
1278 * if it is there, we have not got the remote_as yet, and without
1279 * that we do not know which peer is connecting to us now.
1280 */
1281 as4 = peek_for_as4_capability (peer, optlen);
1282 }
1283
1284 /* Just in case we have a silly peer who sends AS4 capability set to 0 */
1285 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) && !as4)
1286 {
1287 zlog_err ("%s bad OPEN, got AS4 capability, but AS4 set to 0",
1288 peer->host);
1289 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1290 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1291 return -1;
1292 }
1293
1294 if (remote_as == BGP_AS_TRANS)
1295 {
1296 /* Take the AS4 from the capability. We must have received the
1297 * capability now! Otherwise we have a asn16 peer who uses
1298 * BGP_AS_TRANS, for some unknown reason.
1299 */
1300 if (as4 == BGP_AS_TRANS)
1301 {
1302 zlog_err ("%s [AS4] NEW speaker using AS_TRANS for AS4, not allowed",
1303 peer->host);
1304 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1305 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1306 return -1;
1307 }
1308
1309 if (!as4 && BGP_DEBUG (as4, AS4))
1310 zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but no AS4."
1311 " Odd, but proceeding.", peer->host);
1312 else if (as4 < BGP_AS_MAX && BGP_DEBUG (as4, AS4))
Paul Jakma0df7c912008-07-21 21:02:49 +00001313 zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but AS4 (%u) fits "
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001314 "in 2-bytes, very odd peer.", peer->host, as4);
1315 if (as4)
1316 remote_as = as4;
1317 }
1318 else
1319 {
1320 /* We may have a partner with AS4 who has an asno < BGP_AS_MAX */
1321 /* If we have got the capability, peer->as4cap must match remote_as */
1322 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)
1323 && as4 != remote_as)
1324 {
1325 /* raise error, log this, close session */
1326 zlog_err ("%s bad OPEN, got AS4 capability, but remote_as %u"
1327 " mismatch with 16bit 'myasn' %u in open",
1328 peer->host, as4, remote_as);
1329 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1330 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1331 return -1;
1332 }
1333 }
1334
paul718e3742002-12-13 20:15:29 +00001335 /* Lookup peer from Open packet. */
1336 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1337 {
1338 int as = 0;
1339
1340 realpeer = peer_lookup_with_open (&peer->su, remote_as, &remote_id, &as);
1341
1342 if (! realpeer)
1343 {
1344 /* Peer's source IP address is check in bgp_accept(), so this
1345 must be AS number mismatch or remote-id configuration
1346 mismatch. */
1347 if (as)
1348 {
1349 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001350 zlog_debug ("%s bad OPEN, wrong router identifier %s",
1351 peer->host, inet_ntoa (remote_id));
1352 bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
1353 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
1354 notify_data_remote_id, 4);
paul718e3742002-12-13 20:15:29 +00001355 }
1356 else
1357 {
1358 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001359 zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
ajs6b514742004-12-08 21:03:23 +00001360 peer->host, remote_as, peer->as);
1361 bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
1362 BGP_NOTIFY_OPEN_BAD_PEER_AS,
1363 notify_data_remote_as, 2);
paul718e3742002-12-13 20:15:29 +00001364 }
1365 return -1;
1366 }
1367 }
1368
1369 /* When collision is detected and this peer is closed. Retrun
1370 immidiately. */
1371 ret = bgp_collision_detect (peer, remote_id);
1372 if (ret < 0)
1373 return ret;
1374
pauleb821182004-05-01 08:44:08 +00001375 /* Hack part. */
1376 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1377 {
hasso93406d82005-02-02 14:40:33 +00001378 if (realpeer->status == Established
1379 && CHECK_FLAG (realpeer->sflags, PEER_STATUS_NSF_MODE))
1380 {
1381 realpeer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
1382 SET_FLAG (realpeer->sflags, PEER_STATUS_NSF_WAIT);
1383 }
1384 else if (ret == 0 && realpeer->status != Active
1385 && realpeer->status != OpenSent
Paul Jakma6e199262008-09-09 17:14:33 +01001386 && realpeer->status != OpenConfirm
1387 && realpeer->status != Connect)
pauleb821182004-05-01 08:44:08 +00001388 {
Paul Jakma2b2fc562008-09-06 13:09:35 +01001389 /* XXX: This is an awful problem..
1390 *
1391 * According to the RFC we should just let this connection (of the
1392 * accepted 'peer') continue on to Established if the other
1393 * connection (the 'realpeer' one) is in state Connect, and deal
1394 * with the more larval FSM as/when it gets far enough to receive
1395 * an Open. We don't do that though, we instead close the (more
1396 * developed) accepted connection.
1397 *
1398 * This means there's a race, which if hit, can loop:
1399 *
1400 * FSM for A FSM for B
1401 * realpeer accept-peer realpeer accept-peer
1402 *
1403 * Connect Connect
1404 * Active
1405 * OpenSent OpenSent
1406 * <arrive here,
1407 * Notify, delete>
1408 * Idle Active
1409 * OpenSent OpenSent
1410 * <arrive here,
1411 * Notify, delete>
1412 * Idle
1413 * <wait> <wait>
1414 * Connect Connect
1415 *
1416 *
1417 * If both sides are Quagga, they're almost certain to wait for
1418 * the same amount of time of course (which doesn't preclude other
1419 * implementations also waiting for same time). The race is
1420 * exacerbated by high-latency (in bgpd and/or the network).
1421 *
1422 * The reason we do this is because our FSM is tied to our peer
1423 * structure, which carries our configuration information, etc.
1424 * I.e. we can't let the accepted-peer FSM continue on as it is,
1425 * cause it's not associated with any actual peer configuration -
1426 * it's just a dummy.
1427 *
1428 * It's possible we could hack-fix this by just bgp_stop'ing the
1429 * realpeer and continueing on with the 'transfer FSM' below.
1430 * Ideally, we need to seperate FSMs from struct peer.
1431 *
1432 * Setting one side to passive avoids the race, as a workaround.
1433 */
pauleb821182004-05-01 08:44:08 +00001434 if (BGP_DEBUG (events, EVENTS))
hasso93406d82005-02-02 14:40:33 +00001435 zlog_debug ("%s peer status is %s close connection",
1436 realpeer->host, LOOKUP (bgp_status_msg,
1437 realpeer->status));
1438 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1439 BGP_NOTIFY_CEASE_CONNECT_REJECT);
1440
pauleb821182004-05-01 08:44:08 +00001441 return -1;
1442 }
1443
1444 if (BGP_DEBUG (events, EVENTS))
Paul Jakma6e199262008-09-09 17:14:33 +01001445 zlog_debug ("%s [Event] Transfer accept BGP peer to real (state %s)",
1446 peer->host,
1447 LOOKUP (bgp_status_msg, realpeer->status));
pauleb821182004-05-01 08:44:08 +00001448
1449 bgp_stop (realpeer);
1450
1451 /* Transfer file descriptor. */
1452 realpeer->fd = peer->fd;
1453 peer->fd = -1;
1454
1455 /* Transfer input buffer. */
1456 stream_free (realpeer->ibuf);
1457 realpeer->ibuf = peer->ibuf;
1458 realpeer->packet_size = peer->packet_size;
1459 peer->ibuf = NULL;
1460
1461 /* Transfer status. */
1462 realpeer->status = peer->status;
1463 bgp_stop (peer);
paul200df112005-06-01 11:17:05 +00001464
pauleb821182004-05-01 08:44:08 +00001465 /* peer pointer change. Open packet send to neighbor. */
1466 peer = realpeer;
1467 bgp_open_send (peer);
1468 if (peer->fd < 0)
1469 {
1470 zlog_err ("bgp_open_receive peer's fd is negative value %d",
1471 peer->fd);
1472 return -1;
1473 }
1474 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
1475 }
1476
paul718e3742002-12-13 20:15:29 +00001477 /* remote router-id check. */
1478 if (remote_id.s_addr == 0
Denis Ovsienko733cd9e2011-12-17 19:39:30 +04001479 || IPV4_CLASS_DE (ntohl (remote_id.s_addr))
paul718e3742002-12-13 20:15:29 +00001480 || ntohl (peer->local_id.s_addr) == ntohl (remote_id.s_addr))
1481 {
1482 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001483 zlog_debug ("%s bad OPEN, wrong router identifier %s",
paul718e3742002-12-13 20:15:29 +00001484 peer->host, inet_ntoa (remote_id));
1485 bgp_notify_send_with_data (peer,
1486 BGP_NOTIFY_OPEN_ERR,
1487 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
1488 notify_data_remote_id, 4);
1489 return -1;
1490 }
1491
1492 /* Set remote router-id */
1493 peer->remote_id = remote_id;
1494
1495 /* Peer BGP version check. */
1496 if (version != BGP_VERSION_4)
1497 {
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001498 u_int16_t maxver = htons(BGP_VERSION_4);
1499 /* XXX this reply may not be correct if version < 4 XXX */
paul718e3742002-12-13 20:15:29 +00001500 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001501 zlog_debug ("%s bad protocol version, remote requested %d, local request %d",
paul718e3742002-12-13 20:15:29 +00001502 peer->host, version, BGP_VERSION_4);
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001503 /* Data must be in network byte order here */
paul718e3742002-12-13 20:15:29 +00001504 bgp_notify_send_with_data (peer,
1505 BGP_NOTIFY_OPEN_ERR,
1506 BGP_NOTIFY_OPEN_UNSUP_VERSION,
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001507 (u_int8_t *) &maxver, 2);
paul718e3742002-12-13 20:15:29 +00001508 return -1;
1509 }
1510
1511 /* Check neighbor as number. */
1512 if (remote_as != peer->as)
1513 {
1514 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001515 zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
paul718e3742002-12-13 20:15:29 +00001516 peer->host, remote_as, peer->as);
1517 bgp_notify_send_with_data (peer,
1518 BGP_NOTIFY_OPEN_ERR,
1519 BGP_NOTIFY_OPEN_BAD_PEER_AS,
1520 notify_data_remote_as, 2);
1521 return -1;
1522 }
1523
1524 /* From the rfc: Upon receipt of an OPEN message, a BGP speaker MUST
1525 calculate the value of the Hold Timer by using the smaller of its
1526 configured Hold Time and the Hold Time received in the OPEN message.
1527 The Hold Time MUST be either zero or at least three seconds. An
1528 implementation may reject connections on the basis of the Hold Time. */
1529
1530 if (holdtime < 3 && holdtime != 0)
1531 {
1532 bgp_notify_send (peer,
1533 BGP_NOTIFY_OPEN_ERR,
1534 BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
1535 return -1;
1536 }
1537
1538 /* From the rfc: A reasonable maximum time between KEEPALIVE messages
1539 would be one third of the Hold Time interval. KEEPALIVE messages
1540 MUST NOT be sent more frequently than one per second. An
1541 implementation MAY adjust the rate at which it sends KEEPALIVE
1542 messages as a function of the Hold Time interval. */
1543
1544 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
1545 send_holdtime = peer->holdtime;
1546 else
1547 send_holdtime = peer->bgp->default_holdtime;
1548
1549 if (holdtime < send_holdtime)
1550 peer->v_holdtime = holdtime;
1551 else
1552 peer->v_holdtime = send_holdtime;
1553
1554 peer->v_keepalive = peer->v_holdtime / 3;
1555
1556 /* Open option part parse. */
paul718e3742002-12-13 20:15:29 +00001557 if (optlen != 0)
1558 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001559 if ((ret = bgp_open_option_parse (peer, optlen, &mp_capability)) < 0)
Paul Jakma58617392012-01-09 20:59:26 +00001560 {
1561 bgp_notify_send (peer,
1562 BGP_NOTIFY_OPEN_ERR,
1563 BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
1564 return ret;
1565 }
paul718e3742002-12-13 20:15:29 +00001566 }
1567 else
1568 {
1569 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001570 zlog_debug ("%s rcvd OPEN w/ OPTION parameter len: 0",
paul718e3742002-12-13 20:15:29 +00001571 peer->host);
1572 }
1573
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001574 /*
1575 * Assume that the peer supports the locally configured set of
1576 * AFI/SAFIs if the peer did not send us any Mulitiprotocol
1577 * capabilities, or if 'override-capability' is configured.
1578 */
1579 if (! mp_capability ||
1580 CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
paul718e3742002-12-13 20:15:29 +00001581 {
1582 peer->afc_nego[AFI_IP][SAFI_UNICAST] = peer->afc[AFI_IP][SAFI_UNICAST];
1583 peer->afc_nego[AFI_IP][SAFI_MULTICAST] = peer->afc[AFI_IP][SAFI_MULTICAST];
1584 peer->afc_nego[AFI_IP6][SAFI_UNICAST] = peer->afc[AFI_IP6][SAFI_UNICAST];
1585 peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = peer->afc[AFI_IP6][SAFI_MULTICAST];
1586 }
1587
1588 /* Get sockname. */
1589 bgp_getsockname (peer);
1590
1591 BGP_EVENT_ADD (peer, Receive_OPEN_message);
1592
1593 peer->packet_size = 0;
1594 if (peer->ibuf)
1595 stream_reset (peer->ibuf);
1596
1597 return 0;
1598}
1599
1600/* Parse BGP Update packet and make attribute object. */
paul94f2b392005-06-28 12:44:16 +00001601static int
paul718e3742002-12-13 20:15:29 +00001602bgp_update_receive (struct peer *peer, bgp_size_t size)
1603{
1604 int ret;
1605 u_char *end;
1606 struct stream *s;
1607 struct attr attr;
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001608 struct attr_extra extra;
paul718e3742002-12-13 20:15:29 +00001609 bgp_size_t attribute_len;
1610 bgp_size_t update_len;
1611 bgp_size_t withdraw_len;
1612 struct bgp_nlri update;
1613 struct bgp_nlri withdraw;
1614 struct bgp_nlri mp_update;
1615 struct bgp_nlri mp_withdraw;
paul718e3742002-12-13 20:15:29 +00001616
1617 /* Status must be Established. */
1618 if (peer->status != Established)
1619 {
1620 zlog_err ("%s [FSM] Update packet received under status %s",
1621 peer->host, LOOKUP (bgp_status_msg, peer->status));
1622 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
1623 return -1;
1624 }
1625
1626 /* Set initial values. */
1627 memset (&attr, 0, sizeof (struct attr));
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001628 memset (&extra, 0, sizeof (struct attr_extra));
paul718e3742002-12-13 20:15:29 +00001629 memset (&update, 0, sizeof (struct bgp_nlri));
1630 memset (&withdraw, 0, sizeof (struct bgp_nlri));
1631 memset (&mp_update, 0, sizeof (struct bgp_nlri));
1632 memset (&mp_withdraw, 0, sizeof (struct bgp_nlri));
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001633 attr.extra = &extra;
paul718e3742002-12-13 20:15:29 +00001634
1635 s = peer->ibuf;
1636 end = stream_pnt (s) + size;
1637
1638 /* RFC1771 6.3 If the Unfeasible Routes Length or Total Attribute
1639 Length is too large (i.e., if Unfeasible Routes Length + Total
1640 Attribute Length + 23 exceeds the message Length), then the Error
1641 Subcode is set to Malformed Attribute List. */
1642 if (stream_pnt (s) + 2 > end)
1643 {
1644 zlog_err ("%s [Error] Update packet error"
1645 " (packet length is short for unfeasible length)",
1646 peer->host);
1647 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1648 BGP_NOTIFY_UPDATE_MAL_ATTR);
1649 return -1;
1650 }
1651
1652 /* Unfeasible Route Length. */
1653 withdraw_len = stream_getw (s);
1654
1655 /* Unfeasible Route Length check. */
1656 if (stream_pnt (s) + withdraw_len > end)
1657 {
1658 zlog_err ("%s [Error] Update packet error"
1659 " (packet unfeasible length overflow %d)",
1660 peer->host, withdraw_len);
1661 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1662 BGP_NOTIFY_UPDATE_MAL_ATTR);
1663 return -1;
1664 }
1665
1666 /* Unfeasible Route packet format check. */
1667 if (withdraw_len > 0)
1668 {
1669 ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), withdraw_len);
1670 if (ret < 0)
1671 return -1;
1672
1673 if (BGP_DEBUG (packet, PACKET_RECV))
ajs6b514742004-12-08 21:03:23 +00001674 zlog_debug ("%s [Update:RECV] Unfeasible NLRI received", peer->host);
paul718e3742002-12-13 20:15:29 +00001675
1676 withdraw.afi = AFI_IP;
1677 withdraw.safi = SAFI_UNICAST;
1678 withdraw.nlri = stream_pnt (s);
1679 withdraw.length = withdraw_len;
paul9985f832005-02-09 15:51:56 +00001680 stream_forward_getp (s, withdraw_len);
paul718e3742002-12-13 20:15:29 +00001681 }
1682
1683 /* Attribute total length check. */
1684 if (stream_pnt (s) + 2 > end)
1685 {
1686 zlog_warn ("%s [Error] Packet Error"
1687 " (update packet is short for attribute length)",
1688 peer->host);
1689 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1690 BGP_NOTIFY_UPDATE_MAL_ATTR);
1691 return -1;
1692 }
1693
1694 /* Fetch attribute total length. */
1695 attribute_len = stream_getw (s);
1696
1697 /* Attribute length check. */
1698 if (stream_pnt (s) + attribute_len > end)
1699 {
1700 zlog_warn ("%s [Error] Packet Error"
1701 " (update packet attribute length overflow %d)",
1702 peer->host, attribute_len);
1703 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1704 BGP_NOTIFY_UPDATE_MAL_ATTR);
1705 return -1;
1706 }
Paul Jakmab881c702010-11-23 16:35:42 +00001707
1708 /* Certain attribute parsing errors should not be considered bad enough
1709 * to reset the session for, most particularly any partial/optional
1710 * attributes that have 'tunneled' over speakers that don't understand
1711 * them. Instead we withdraw only the prefix concerned.
1712 *
1713 * Complicates the flow a little though..
1714 */
1715 bgp_attr_parse_ret_t attr_parse_ret = BGP_ATTR_PARSE_PROCEED;
1716 /* This define morphs the update case into a withdraw when lower levels
1717 * have signalled an error condition where this is best.
1718 */
1719#define NLRI_ATTR_ARG (attr_parse_ret != BGP_ATTR_PARSE_WITHDRAW ? &attr : NULL)
paul718e3742002-12-13 20:15:29 +00001720
1721 /* Parse attribute when it exists. */
1722 if (attribute_len)
1723 {
Paul Jakmab881c702010-11-23 16:35:42 +00001724 attr_parse_ret = bgp_attr_parse (peer, &attr, attribute_len,
paul718e3742002-12-13 20:15:29 +00001725 &mp_update, &mp_withdraw);
Paul Jakmab881c702010-11-23 16:35:42 +00001726 if (attr_parse_ret == BGP_ATTR_PARSE_ERROR)
David Lamparterf80f8382014-06-04 01:00:51 +02001727 {
1728 bgp_attr_unintern_sub (&attr);
1729 return -1;
1730 }
paul718e3742002-12-13 20:15:29 +00001731 }
Paul Jakmab881c702010-11-23 16:35:42 +00001732
paul718e3742002-12-13 20:15:29 +00001733 /* Logging the attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001734 if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW
1735 || BGP_DEBUG (update, UPDATE_IN))
paul718e3742002-12-13 20:15:29 +00001736 {
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +00001737 char attrstr[BUFSIZ];
1738 attrstr[0] = '\0';
1739
paule01f9cb2004-07-09 17:48:53 +00001740 ret= bgp_dump_attr (peer, &attr, attrstr, BUFSIZ);
Paul Jakmab881c702010-11-23 16:35:42 +00001741 int lvl = (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
1742 ? LOG_ERR : LOG_DEBUG;
1743
1744 if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
1745 zlog (peer->log, LOG_ERR,
1746 "%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.",
1747 peer->host);
paule01f9cb2004-07-09 17:48:53 +00001748
1749 if (ret)
Paul Jakmab881c702010-11-23 16:35:42 +00001750 zlog (peer->log, lvl, "%s rcvd UPDATE w/ attr: %s",
paule01f9cb2004-07-09 17:48:53 +00001751 peer->host, attrstr);
paul718e3742002-12-13 20:15:29 +00001752 }
Paul Jakmab881c702010-11-23 16:35:42 +00001753
paul718e3742002-12-13 20:15:29 +00001754 /* Network Layer Reachability Information. */
1755 update_len = end - stream_pnt (s);
1756
1757 if (update_len)
1758 {
1759 /* Check NLRI packet format and prefix length. */
1760 ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), update_len);
1761 if (ret < 0)
Paul Jakmab881c702010-11-23 16:35:42 +00001762 {
1763 bgp_attr_unintern_sub (&attr);
Paul Jakmab881c702010-11-23 16:35:42 +00001764 return -1;
1765 }
paul718e3742002-12-13 20:15:29 +00001766
1767 /* Set NLRI portion to structure. */
1768 update.afi = AFI_IP;
1769 update.safi = SAFI_UNICAST;
1770 update.nlri = stream_pnt (s);
1771 update.length = update_len;
paul9985f832005-02-09 15:51:56 +00001772 stream_forward_getp (s, update_len);
paul718e3742002-12-13 20:15:29 +00001773 }
1774
1775 /* NLRI is processed only when the peer is configured specific
1776 Address Family and Subsequent Address Family. */
1777 if (peer->afc[AFI_IP][SAFI_UNICAST])
1778 {
1779 if (withdraw.length)
1780 bgp_nlri_parse (peer, NULL, &withdraw);
1781
1782 if (update.length)
Paul Jakmab881c702010-11-23 16:35:42 +00001783 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &update);
paule01f9cb2004-07-09 17:48:53 +00001784
hassof4184462005-02-01 20:13:16 +00001785 if (mp_update.length
1786 && mp_update.afi == AFI_IP
1787 && mp_update.safi == SAFI_UNICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001788 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
hassof4184462005-02-01 20:13:16 +00001789
1790 if (mp_withdraw.length
1791 && mp_withdraw.afi == AFI_IP
1792 && mp_withdraw.safi == SAFI_UNICAST)
1793 bgp_nlri_parse (peer, NULL, &mp_withdraw);
1794
paule01f9cb2004-07-09 17:48:53 +00001795 if (! attribute_len && ! withdraw_len)
1796 {
1797 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001798 SET_FLAG (peer->af_sflags[AFI_IP][SAFI_UNICAST],
1799 PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001800
hasso93406d82005-02-02 14:40:33 +00001801 /* NSF delete stale route */
1802 if (peer->nsf[AFI_IP][SAFI_UNICAST])
1803 bgp_clear_stale_route (peer, AFI_IP, SAFI_UNICAST);
1804
1805 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001806 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001807 peer->host);
1808 }
paul718e3742002-12-13 20:15:29 +00001809 }
1810 if (peer->afc[AFI_IP][SAFI_MULTICAST])
1811 {
1812 if (mp_update.length
1813 && mp_update.afi == AFI_IP
1814 && mp_update.safi == SAFI_MULTICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001815 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001816
1817 if (mp_withdraw.length
1818 && mp_withdraw.afi == AFI_IP
1819 && mp_withdraw.safi == SAFI_MULTICAST)
1820 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001821
hasso93406d82005-02-02 14:40:33 +00001822 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001823 && mp_withdraw.afi == AFI_IP
1824 && mp_withdraw.safi == SAFI_MULTICAST
1825 && mp_withdraw.length == 0)
1826 {
1827 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001828 SET_FLAG (peer->af_sflags[AFI_IP][SAFI_MULTICAST],
1829 PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001830
hasso93406d82005-02-02 14:40:33 +00001831 /* NSF delete stale route */
1832 if (peer->nsf[AFI_IP][SAFI_MULTICAST])
1833 bgp_clear_stale_route (peer, AFI_IP, SAFI_MULTICAST);
1834
1835 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001836 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Multicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001837 peer->host);
1838 }
paul718e3742002-12-13 20:15:29 +00001839 }
1840 if (peer->afc[AFI_IP6][SAFI_UNICAST])
1841 {
1842 if (mp_update.length
1843 && mp_update.afi == AFI_IP6
1844 && mp_update.safi == SAFI_UNICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001845 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001846
1847 if (mp_withdraw.length
1848 && mp_withdraw.afi == AFI_IP6
1849 && mp_withdraw.safi == SAFI_UNICAST)
1850 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001851
hasso93406d82005-02-02 14:40:33 +00001852 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001853 && mp_withdraw.afi == AFI_IP6
1854 && mp_withdraw.safi == SAFI_UNICAST
1855 && mp_withdraw.length == 0)
1856 {
1857 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001858 SET_FLAG (peer->af_sflags[AFI_IP6][SAFI_UNICAST], PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001859
hasso93406d82005-02-02 14:40:33 +00001860 /* NSF delete stale route */
1861 if (peer->nsf[AFI_IP6][SAFI_UNICAST])
1862 bgp_clear_stale_route (peer, AFI_IP6, SAFI_UNICAST);
1863
1864 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001865 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001866 peer->host);
1867 }
paul718e3742002-12-13 20:15:29 +00001868 }
1869 if (peer->afc[AFI_IP6][SAFI_MULTICAST])
1870 {
1871 if (mp_update.length
1872 && mp_update.afi == AFI_IP6
1873 && mp_update.safi == SAFI_MULTICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001874 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001875
1876 if (mp_withdraw.length
1877 && mp_withdraw.afi == AFI_IP6
1878 && mp_withdraw.safi == SAFI_MULTICAST)
1879 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001880
hasso93406d82005-02-02 14:40:33 +00001881 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001882 && mp_withdraw.afi == AFI_IP6
1883 && mp_withdraw.safi == SAFI_MULTICAST
1884 && mp_withdraw.length == 0)
1885 {
1886 /* End-of-RIB received */
1887
hasso93406d82005-02-02 14:40:33 +00001888 /* NSF delete stale route */
1889 if (peer->nsf[AFI_IP6][SAFI_MULTICAST])
1890 bgp_clear_stale_route (peer, AFI_IP6, SAFI_MULTICAST);
1891
paule01f9cb2004-07-09 17:48:53 +00001892 if (BGP_DEBUG (update, UPDATE_IN))
ajs6b514742004-12-08 21:03:23 +00001893 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Multicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001894 peer->host);
1895 }
paul718e3742002-12-13 20:15:29 +00001896 }
1897 if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
1898 {
1899 if (mp_update.length
1900 && mp_update.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001901 && mp_update.safi == SAFI_MPLS_LABELED_VPN)
Paul Jakmab881c702010-11-23 16:35:42 +00001902 bgp_nlri_parse_vpnv4 (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001903
1904 if (mp_withdraw.length
1905 && mp_withdraw.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001906 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00001907 bgp_nlri_parse_vpnv4 (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001908
hasso93406d82005-02-02 14:40:33 +00001909 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001910 && mp_withdraw.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001911 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN
paule01f9cb2004-07-09 17:48:53 +00001912 && mp_withdraw.length == 0)
1913 {
1914 /* End-of-RIB received */
1915
1916 if (BGP_DEBUG (update, UPDATE_IN))
ajs6b514742004-12-08 21:03:23 +00001917 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for VPNv4 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001918 peer->host);
1919 }
paul718e3742002-12-13 20:15:29 +00001920 }
1921
1922 /* Everything is done. We unintern temporary structures which
1923 interned in bgp_attr_parse(). */
Paul Jakmab881c702010-11-23 16:35:42 +00001924 bgp_attr_unintern_sub (&attr);
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001925
paul718e3742002-12-13 20:15:29 +00001926 /* If peering is stopped due to some reason, do not generate BGP
1927 event. */
1928 if (peer->status != Established)
1929 return 0;
1930
1931 /* Increment packet counter. */
1932 peer->update_in++;
Stephen Hemminger65957882010-01-15 16:22:10 +03001933 peer->update_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00001934
Jorge Boncompte [DTI2]e2c38e62012-06-20 17:45:50 +02001935 /* Rearm holdtime timer */
Jorge Boncompte [DTI2]6a4677b2012-05-07 16:53:07 +00001936 BGP_TIMER_OFF (peer->t_holdtime);
Jorge Boncompte [DTI2]e2c38e62012-06-20 17:45:50 +02001937 bgp_timer_set (peer);
paul718e3742002-12-13 20:15:29 +00001938
1939 return 0;
1940}
1941
1942/* Notify message treatment function. */
paul94f2b392005-06-28 12:44:16 +00001943static void
paul718e3742002-12-13 20:15:29 +00001944bgp_notify_receive (struct peer *peer, bgp_size_t size)
1945{
1946 struct bgp_notify bgp_notify;
1947
1948 if (peer->notify.data)
1949 {
1950 XFREE (MTYPE_TMP, peer->notify.data);
1951 peer->notify.data = NULL;
1952 peer->notify.length = 0;
1953 }
1954
1955 bgp_notify.code = stream_getc (peer->ibuf);
1956 bgp_notify.subcode = stream_getc (peer->ibuf);
1957 bgp_notify.length = size - 2;
1958 bgp_notify.data = NULL;
1959
1960 /* Preserv notify code and sub code. */
1961 peer->notify.code = bgp_notify.code;
1962 peer->notify.subcode = bgp_notify.subcode;
1963 /* For further diagnostic record returned Data. */
1964 if (bgp_notify.length)
1965 {
1966 peer->notify.length = size - 2;
1967 peer->notify.data = XMALLOC (MTYPE_TMP, size - 2);
1968 memcpy (peer->notify.data, stream_pnt (peer->ibuf), size - 2);
1969 }
1970
1971 /* For debug */
1972 {
1973 int i;
1974 int first = 0;
1975 char c[4];
1976
1977 if (bgp_notify.length)
1978 {
1979 bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
1980 for (i = 0; i < bgp_notify.length; i++)
1981 if (first)
1982 {
1983 sprintf (c, " %02x", stream_getc (peer->ibuf));
1984 strcat (bgp_notify.data, c);
1985 }
1986 else
1987 {
1988 first = 1;
1989 sprintf (c, "%02x", stream_getc (peer->ibuf));
1990 strcpy (bgp_notify.data, c);
1991 }
1992 }
1993
1994 bgp_notify_print(peer, &bgp_notify, "received");
1995 if (bgp_notify.data)
1996 XFREE (MTYPE_TMP, bgp_notify.data);
1997 }
1998
1999 /* peer count update */
2000 peer->notify_in++;
2001
hassoe0701b72004-05-20 09:19:34 +00002002 if (peer->status == Established)
2003 peer->last_reset = PEER_DOWN_NOTIFY_RECEIVED;
2004
paul718e3742002-12-13 20:15:29 +00002005 /* We have to check for Notify with Unsupported Optional Parameter.
2006 in that case we fallback to open without the capability option.
2007 But this done in bgp_stop. We just mark it here to avoid changing
2008 the fsm tables. */
2009 if (bgp_notify.code == BGP_NOTIFY_OPEN_ERR &&
2010 bgp_notify.subcode == BGP_NOTIFY_OPEN_UNSUP_PARAM )
2011 UNSET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
2012
paul718e3742002-12-13 20:15:29 +00002013 BGP_EVENT_ADD (peer, Receive_NOTIFICATION_message);
2014}
2015
2016/* Keepalive treatment function -- get keepalive send keepalive */
paul94f2b392005-06-28 12:44:16 +00002017static void
paul718e3742002-12-13 20:15:29 +00002018bgp_keepalive_receive (struct peer *peer, bgp_size_t size)
2019{
2020 if (BGP_DEBUG (keepalive, KEEPALIVE))
ajs6b514742004-12-08 21:03:23 +00002021 zlog_debug ("%s KEEPALIVE rcvd", peer->host);
paul718e3742002-12-13 20:15:29 +00002022
2023 BGP_EVENT_ADD (peer, Receive_KEEPALIVE_message);
2024}
2025
2026/* Route refresh message is received. */
paul94f2b392005-06-28 12:44:16 +00002027static void
paul718e3742002-12-13 20:15:29 +00002028bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
2029{
2030 afi_t afi;
2031 safi_t safi;
paul718e3742002-12-13 20:15:29 +00002032 struct stream *s;
2033
2034 /* If peer does not have the capability, send notification. */
2035 if (! CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_ADV))
2036 {
2037 plog_err (peer->log, "%s [Error] BGP route refresh is not enabled",
2038 peer->host);
2039 bgp_notify_send (peer,
2040 BGP_NOTIFY_HEADER_ERR,
2041 BGP_NOTIFY_HEADER_BAD_MESTYPE);
2042 return;
2043 }
2044
2045 /* Status must be Established. */
2046 if (peer->status != Established)
2047 {
2048 plog_err (peer->log,
2049 "%s [Error] Route refresh packet received under status %s",
2050 peer->host, LOOKUP (bgp_status_msg, peer->status));
2051 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
2052 return;
2053 }
2054
2055 s = peer->ibuf;
2056
2057 /* Parse packet. */
2058 afi = stream_getw (s);
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002059 /* reserved byte */
2060 stream_getc (s);
paul718e3742002-12-13 20:15:29 +00002061 safi = stream_getc (s);
2062
2063 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002064 zlog_debug ("%s rcvd REFRESH_REQ for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00002065 peer->host, afi, safi);
2066
2067 /* Check AFI and SAFI. */
2068 if ((afi != AFI_IP && afi != AFI_IP6)
2069 || (safi != SAFI_UNICAST && safi != SAFI_MULTICAST
Denis Ovsienko42e6d742011-07-14 12:36:19 +04002070 && safi != SAFI_MPLS_LABELED_VPN))
paul718e3742002-12-13 20:15:29 +00002071 {
2072 if (BGP_DEBUG (normal, NORMAL))
2073 {
ajs6b514742004-12-08 21:03:23 +00002074 zlog_debug ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored",
paul718e3742002-12-13 20:15:29 +00002075 peer->host, afi, safi);
2076 }
2077 return;
2078 }
2079
2080 /* Adjust safi code. */
Denis Ovsienko42e6d742011-07-14 12:36:19 +04002081 if (safi == SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00002082 safi = SAFI_MPLS_VPN;
2083
2084 if (size != BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE)
2085 {
2086 u_char *end;
2087 u_char when_to_refresh;
2088 u_char orf_type;
2089 u_int16_t orf_len;
2090
2091 if (size - (BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE) < 5)
2092 {
2093 zlog_info ("%s ORF route refresh length error", peer->host);
2094 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2095 return;
2096 }
2097
2098 when_to_refresh = stream_getc (s);
2099 end = stream_pnt (s) + (size - 5);
2100
Paul Jakma370b64a2007-12-22 16:49:52 +00002101 while ((stream_pnt (s) + 2) < end)
paul718e3742002-12-13 20:15:29 +00002102 {
2103 orf_type = stream_getc (s);
2104 orf_len = stream_getw (s);
Paul Jakma370b64a2007-12-22 16:49:52 +00002105
2106 /* orf_len in bounds? */
2107 if ((stream_pnt (s) + orf_len) > end)
2108 break; /* XXX: Notify instead?? */
paul718e3742002-12-13 20:15:29 +00002109 if (orf_type == ORF_TYPE_PREFIX
2110 || orf_type == ORF_TYPE_PREFIX_OLD)
2111 {
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002112 uint8_t *p_pnt = stream_pnt (s);
2113 uint8_t *p_end = stream_pnt (s) + orf_len;
paul718e3742002-12-13 20:15:29 +00002114 struct orf_prefix orfp;
2115 u_char common = 0;
2116 u_int32_t seq;
2117 int psize;
2118 char name[BUFSIZ];
paul718e3742002-12-13 20:15:29 +00002119 int ret;
2120
2121 if (BGP_DEBUG (normal, NORMAL))
2122 {
ajs6b514742004-12-08 21:03:23 +00002123 zlog_debug ("%s rcvd Prefixlist ORF(%d) length %d",
paul718e3742002-12-13 20:15:29 +00002124 peer->host, orf_type, orf_len);
2125 }
2126
Paul Jakma370b64a2007-12-22 16:49:52 +00002127 /* we're going to read at least 1 byte of common ORF header,
2128 * and 7 bytes of ORF Address-filter entry from the stream
2129 */
2130 if (orf_len < 7)
2131 break;
2132
paul718e3742002-12-13 20:15:29 +00002133 /* ORF prefix-list name */
2134 sprintf (name, "%s.%d.%d", peer->host, afi, safi);
2135
2136 while (p_pnt < p_end)
2137 {
Chris Halld64379e2010-05-14 16:38:39 +04002138 /* If the ORF entry is malformed, want to read as much of it
2139 * as possible without going beyond the bounds of the entry,
2140 * to maximise debug information.
2141 */
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002142 int ok;
paul718e3742002-12-13 20:15:29 +00002143 memset (&orfp, 0, sizeof (struct orf_prefix));
2144 common = *p_pnt++;
Chris Halld64379e2010-05-14 16:38:39 +04002145 /* after ++: p_pnt <= p_end */
paul718e3742002-12-13 20:15:29 +00002146 if (common & ORF_COMMON_PART_REMOVE_ALL)
2147 {
2148 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002149 zlog_debug ("%s rcvd Remove-All pfxlist ORF request", peer->host);
David Lamparterc9c06d02015-04-13 10:21:35 +02002150 prefix_bgp_orf_remove_all (afi, name);
paul718e3742002-12-13 20:15:29 +00002151 break;
2152 }
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002153 ok = ((size_t)(p_end - p_pnt) >= sizeof(u_int32_t)) ;
Denis Ovsienkobb915f52011-12-13 21:11:39 +04002154 if (ok)
Chris Halld64379e2010-05-14 16:38:39 +04002155 {
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002156 memcpy (&seq, p_pnt, sizeof (u_int32_t));
2157 p_pnt += sizeof (u_int32_t);
2158 orfp.seq = ntohl (seq);
Chris Halld64379e2010-05-14 16:38:39 +04002159 }
2160 else
2161 p_pnt = p_end ;
2162
2163 if ((ok = (p_pnt < p_end)))
2164 orfp.ge = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */
2165 if ((ok = (p_pnt < p_end)))
2166 orfp.le = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */
2167 if ((ok = (p_pnt < p_end)))
2168 orfp.p.prefixlen = *p_pnt++ ;
2169 orfp.p.family = afi2family (afi); /* afi checked already */
2170
2171 psize = PSIZE (orfp.p.prefixlen); /* 0 if not ok */
2172 if (psize > prefix_blen(&orfp.p)) /* valid for family ? */
2173 {
2174 ok = 0 ;
2175 psize = prefix_blen(&orfp.p) ;
2176 }
2177 if (psize > (p_end - p_pnt)) /* valid for packet ? */
2178 {
2179 ok = 0 ;
2180 psize = p_end - p_pnt ;
2181 }
2182
2183 if (psize > 0)
2184 memcpy (&orfp.p.u.prefix, p_pnt, psize);
paul718e3742002-12-13 20:15:29 +00002185 p_pnt += psize;
2186
2187 if (BGP_DEBUG (normal, NORMAL))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +00002188 {
2189 char buf[INET6_BUFSIZ];
2190
2191 zlog_debug ("%s rcvd %s %s seq %u %s/%d ge %d le %d%s",
2192 peer->host,
2193 (common & ORF_COMMON_PART_REMOVE ? "Remove" : "Add"),
2194 (common & ORF_COMMON_PART_DENY ? "deny" : "permit"),
2195 orfp.seq,
2196 inet_ntop (orfp.p.family, &orfp.p.u.prefix, buf, INET6_BUFSIZ),
2197 orfp.p.prefixlen, orfp.ge, orfp.le,
2198 ok ? "" : " MALFORMED");
2199 }
2200
Chris Halld64379e2010-05-14 16:38:39 +04002201 if (ok)
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002202 ret = prefix_bgp_orf_set (name, afi, &orfp,
2203 (common & ORF_COMMON_PART_DENY ? 0 : 1 ),
2204 (common & ORF_COMMON_PART_REMOVE ? 0 : 1));
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002205
2206 if (!ok || (ok && ret != CMD_SUCCESS))
paul718e3742002-12-13 20:15:29 +00002207 {
2208 if (BGP_DEBUG (normal, NORMAL))
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002209 zlog_debug ("%s Received misformatted prefixlist ORF."
2210 " Remove All pfxlist", peer->host);
David Lamparterc9c06d02015-04-13 10:21:35 +02002211 prefix_bgp_orf_remove_all (afi, name);
paul718e3742002-12-13 20:15:29 +00002212 break;
2213 }
2214 }
2215 peer->orf_plist[afi][safi] =
David Lamparterc9c06d02015-04-13 10:21:35 +02002216 prefix_bgp_orf_lookup (afi, name);
paul718e3742002-12-13 20:15:29 +00002217 }
paul9985f832005-02-09 15:51:56 +00002218 stream_forward_getp (s, orf_len);
paul718e3742002-12-13 20:15:29 +00002219 }
2220 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002221 zlog_debug ("%s rcvd Refresh %s ORF request", peer->host,
paul718e3742002-12-13 20:15:29 +00002222 when_to_refresh == REFRESH_DEFER ? "Defer" : "Immediate");
2223 if (when_to_refresh == REFRESH_DEFER)
2224 return;
2225 }
2226
2227 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2228 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH))
2229 UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
2230
2231 /* Perform route refreshment to the peer */
2232 bgp_announce_route (peer, afi, safi);
2233}
2234
paul94f2b392005-06-28 12:44:16 +00002235static int
paul718e3742002-12-13 20:15:29 +00002236bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
2237{
2238 u_char *end;
Paul Jakma6d582722007-08-06 15:21:45 +00002239 struct capability_mp_data mpc;
2240 struct capability_header *hdr;
paul718e3742002-12-13 20:15:29 +00002241 u_char action;
paul718e3742002-12-13 20:15:29 +00002242 afi_t afi;
2243 safi_t safi;
2244
paul718e3742002-12-13 20:15:29 +00002245 end = pnt + length;
2246
2247 while (pnt < end)
Paul Jakma6d582722007-08-06 15:21:45 +00002248 {
paul718e3742002-12-13 20:15:29 +00002249 /* We need at least action, capability code and capability length. */
2250 if (pnt + 3 > end)
2251 {
2252 zlog_info ("%s Capability length error", peer->host);
2253 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2254 return -1;
2255 }
paul718e3742002-12-13 20:15:29 +00002256 action = *pnt;
Paul Jakma6d582722007-08-06 15:21:45 +00002257 hdr = (struct capability_header *)(pnt + 1);
2258
paul718e3742002-12-13 20:15:29 +00002259 /* Action value check. */
2260 if (action != CAPABILITY_ACTION_SET
2261 && action != CAPABILITY_ACTION_UNSET)
2262 {
2263 zlog_info ("%s Capability Action Value error %d",
2264 peer->host, action);
2265 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2266 return -1;
2267 }
2268
2269 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002270 zlog_debug ("%s CAPABILITY has action: %d, code: %u, length %u",
Paul Jakma6d582722007-08-06 15:21:45 +00002271 peer->host, action, hdr->code, hdr->length);
paul718e3742002-12-13 20:15:29 +00002272
2273 /* Capability length check. */
Paul Jakma6d582722007-08-06 15:21:45 +00002274 if ((pnt + hdr->length + 3) > end)
paul718e3742002-12-13 20:15:29 +00002275 {
2276 zlog_info ("%s Capability length error", peer->host);
2277 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2278 return -1;
2279 }
2280
Paul Jakma6d582722007-08-06 15:21:45 +00002281 /* Fetch structure to the byte stream. */
2282 memcpy (&mpc, pnt + 3, sizeof (struct capability_mp_data));
2283
paul718e3742002-12-13 20:15:29 +00002284 /* We know MP Capability Code. */
Paul Jakma6d582722007-08-06 15:21:45 +00002285 if (hdr->code == CAPABILITY_CODE_MP)
paul718e3742002-12-13 20:15:29 +00002286 {
Paul Jakma6d582722007-08-06 15:21:45 +00002287 afi = ntohs (mpc.afi);
2288 safi = mpc.safi;
paul718e3742002-12-13 20:15:29 +00002289
2290 /* Ignore capability when override-capability is set. */
2291 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
2292 continue;
Paul Jakma6d582722007-08-06 15:21:45 +00002293
2294 if (!bgp_afi_safi_valid_indices (afi, &safi))
2295 {
2296 if (BGP_DEBUG (normal, NORMAL))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002297 zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid "
2298 "(%u/%u)", peer->host, afi, safi);
Paul Jakma6d582722007-08-06 15:21:45 +00002299 continue;
2300 }
2301
paul718e3742002-12-13 20:15:29 +00002302 /* Address family check. */
Paul Jakma6d582722007-08-06 15:21:45 +00002303 if (BGP_DEBUG (normal, NORMAL))
2304 zlog_debug ("%s CAPABILITY has %s MP_EXT CAP for afi/safi: %u/%u",
2305 peer->host,
2306 action == CAPABILITY_ACTION_SET
2307 ? "Advertising" : "Removing",
2308 ntohs(mpc.afi) , mpc.safi);
2309
2310 if (action == CAPABILITY_ACTION_SET)
2311 {
2312 peer->afc_recv[afi][safi] = 1;
2313 if (peer->afc[afi][safi])
2314 {
2315 peer->afc_nego[afi][safi] = 1;
2316 bgp_announce_route (peer, afi, safi);
2317 }
2318 }
2319 else
2320 {
2321 peer->afc_recv[afi][safi] = 0;
2322 peer->afc_nego[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00002323
Paul Jakma6d582722007-08-06 15:21:45 +00002324 if (peer_active_nego (peer))
Chris Caputo228da422009-07-18 05:44:03 +00002325 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
Paul Jakma6d582722007-08-06 15:21:45 +00002326 else
2327 BGP_EVENT_ADD (peer, BGP_Stop);
2328 }
paul718e3742002-12-13 20:15:29 +00002329 }
paul718e3742002-12-13 20:15:29 +00002330 else
2331 {
2332 zlog_warn ("%s unrecognized capability code: %d - ignored",
Paul Jakma6d582722007-08-06 15:21:45 +00002333 peer->host, hdr->code);
paul718e3742002-12-13 20:15:29 +00002334 }
Paul Jakma6d582722007-08-06 15:21:45 +00002335 pnt += hdr->length + 3;
paul718e3742002-12-13 20:15:29 +00002336 }
2337 return 0;
2338}
2339
Paul Jakma01b7ce22009-06-18 12:34:43 +01002340/* Dynamic Capability is received.
2341 *
2342 * This is exported for unit-test purposes
2343 */
Paul Jakma6d582722007-08-06 15:21:45 +00002344int
paul718e3742002-12-13 20:15:29 +00002345bgp_capability_receive (struct peer *peer, bgp_size_t size)
2346{
2347 u_char *pnt;
paul718e3742002-12-13 20:15:29 +00002348
2349 /* Fetch pointer. */
2350 pnt = stream_pnt (peer->ibuf);
2351
2352 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002353 zlog_debug ("%s rcv CAPABILITY", peer->host);
paul718e3742002-12-13 20:15:29 +00002354
2355 /* If peer does not have the capability, send notification. */
2356 if (! CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV))
2357 {
2358 plog_err (peer->log, "%s [Error] BGP dynamic capability is not enabled",
2359 peer->host);
2360 bgp_notify_send (peer,
2361 BGP_NOTIFY_HEADER_ERR,
2362 BGP_NOTIFY_HEADER_BAD_MESTYPE);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002363 return -1;
paul718e3742002-12-13 20:15:29 +00002364 }
2365
2366 /* Status must be Established. */
2367 if (peer->status != Established)
2368 {
2369 plog_err (peer->log,
2370 "%s [Error] Dynamic capability packet received under status %s", peer->host, LOOKUP (bgp_status_msg, peer->status));
2371 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002372 return -1;
paul718e3742002-12-13 20:15:29 +00002373 }
2374
2375 /* Parse packet. */
Paul Jakma6d582722007-08-06 15:21:45 +00002376 return bgp_capability_msg_parse (peer, pnt, size);
paul718e3742002-12-13 20:15:29 +00002377}
David Lamparter6b0655a2014-06-04 06:53:35 +02002378
paul718e3742002-12-13 20:15:29 +00002379/* BGP read utility function. */
paul94f2b392005-06-28 12:44:16 +00002380static int
paul718e3742002-12-13 20:15:29 +00002381bgp_read_packet (struct peer *peer)
2382{
2383 int nbytes;
2384 int readsize;
2385
paul9985f832005-02-09 15:51:56 +00002386 readsize = peer->packet_size - stream_get_endp (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00002387
2388 /* If size is zero then return. */
2389 if (! readsize)
2390 return 0;
2391
2392 /* Read packet from fd. */
Stephen Hemminger35398582010-08-05 10:26:23 -07002393 nbytes = stream_read_try (peer->ibuf, peer->fd, readsize);
paul718e3742002-12-13 20:15:29 +00002394
2395 /* If read byte is smaller than zero then error occured. */
2396 if (nbytes < 0)
2397 {
Stephen Hemminger35398582010-08-05 10:26:23 -07002398 /* Transient error should retry */
2399 if (nbytes == -2)
paul718e3742002-12-13 20:15:29 +00002400 return -1;
2401
2402 plog_err (peer->log, "%s [Error] bgp_read_packet error: %s",
ajs6099b3b2004-11-20 02:06:59 +00002403 peer->host, safe_strerror (errno));
hasso93406d82005-02-02 14:40:33 +00002404
2405 if (peer->status == Established)
2406 {
2407 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
2408 {
2409 peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
2410 SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
2411 }
2412 else
2413 peer->last_reset = PEER_DOWN_CLOSE_SESSION;
2414 }
2415
paul718e3742002-12-13 20:15:29 +00002416 BGP_EVENT_ADD (peer, TCP_fatal_error);
2417 return -1;
2418 }
2419
2420 /* When read byte is zero : clear bgp peer and return */
2421 if (nbytes == 0)
2422 {
2423 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +00002424 plog_debug (peer->log, "%s [Event] BGP connection closed fd %d",
pauleb821182004-05-01 08:44:08 +00002425 peer->host, peer->fd);
hassoe0701b72004-05-20 09:19:34 +00002426
2427 if (peer->status == Established)
hasso93406d82005-02-02 14:40:33 +00002428 {
2429 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
2430 {
2431 peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
2432 SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
2433 }
2434 else
2435 peer->last_reset = PEER_DOWN_CLOSE_SESSION;
2436 }
hassoe0701b72004-05-20 09:19:34 +00002437
paul718e3742002-12-13 20:15:29 +00002438 BGP_EVENT_ADD (peer, TCP_connection_closed);
2439 return -1;
2440 }
2441
2442 /* We read partial packet. */
paul9985f832005-02-09 15:51:56 +00002443 if (stream_get_endp (peer->ibuf) != peer->packet_size)
paul718e3742002-12-13 20:15:29 +00002444 return -1;
2445
2446 return 0;
2447}
2448
2449/* Marker check. */
paul94f2b392005-06-28 12:44:16 +00002450static int
paul718e3742002-12-13 20:15:29 +00002451bgp_marker_all_one (struct stream *s, int length)
2452{
2453 int i;
2454
2455 for (i = 0; i < length; i++)
2456 if (s->data[i] != 0xff)
2457 return 0;
2458
2459 return 1;
2460}
2461
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002462/* Recent thread time.
2463 On same clock base as bgp_clock (MONOTONIC)
2464 but can be time of last context switch to bgp_read thread. */
2465static time_t
2466bgp_recent_clock (void)
2467{
2468 return recent_relative_time().tv_sec;
2469}
2470
paul718e3742002-12-13 20:15:29 +00002471/* Starting point of packet process function. */
2472int
2473bgp_read (struct thread *thread)
2474{
2475 int ret;
2476 u_char type = 0;
2477 struct peer *peer;
2478 bgp_size_t size;
2479 char notify_data_length[2];
2480
2481 /* Yes first of all get peer pointer. */
2482 peer = THREAD_ARG (thread);
2483 peer->t_read = NULL;
2484
2485 /* For non-blocking IO check. */
2486 if (peer->status == Connect)
2487 {
2488 bgp_connect_check (peer);
2489 goto done;
2490 }
2491 else
2492 {
pauleb821182004-05-01 08:44:08 +00002493 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +00002494 {
pauleb821182004-05-01 08:44:08 +00002495 zlog_err ("bgp_read peer's fd is negative value %d", peer->fd);
paul718e3742002-12-13 20:15:29 +00002496 return -1;
2497 }
pauleb821182004-05-01 08:44:08 +00002498 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
paul718e3742002-12-13 20:15:29 +00002499 }
2500
2501 /* Read packet header to determine type of the packet */
2502 if (peer->packet_size == 0)
2503 peer->packet_size = BGP_HEADER_SIZE;
2504
paul9985f832005-02-09 15:51:56 +00002505 if (stream_get_endp (peer->ibuf) < BGP_HEADER_SIZE)
paul718e3742002-12-13 20:15:29 +00002506 {
2507 ret = bgp_read_packet (peer);
2508
2509 /* Header read error or partial read packet. */
2510 if (ret < 0)
2511 goto done;
2512
2513 /* Get size and type. */
paul9985f832005-02-09 15:51:56 +00002514 stream_forward_getp (peer->ibuf, BGP_MARKER_SIZE);
paul718e3742002-12-13 20:15:29 +00002515 memcpy (notify_data_length, stream_pnt (peer->ibuf), 2);
2516 size = stream_getw (peer->ibuf);
2517 type = stream_getc (peer->ibuf);
2518
2519 if (BGP_DEBUG (normal, NORMAL) && type != 2 && type != 0)
ajs6b514742004-12-08 21:03:23 +00002520 zlog_debug ("%s rcv message type %d, length (excl. header) %d",
paul718e3742002-12-13 20:15:29 +00002521 peer->host, type, size - BGP_HEADER_SIZE);
2522
2523 /* Marker check */
paulf5ba3872004-07-09 12:11:31 +00002524 if (((type == BGP_MSG_OPEN) || (type == BGP_MSG_KEEPALIVE))
paul718e3742002-12-13 20:15:29 +00002525 && ! bgp_marker_all_one (peer->ibuf, BGP_MARKER_SIZE))
2526 {
2527 bgp_notify_send (peer,
2528 BGP_NOTIFY_HEADER_ERR,
2529 BGP_NOTIFY_HEADER_NOT_SYNC);
2530 goto done;
2531 }
2532
2533 /* BGP type check. */
2534 if (type != BGP_MSG_OPEN && type != BGP_MSG_UPDATE
2535 && type != BGP_MSG_NOTIFY && type != BGP_MSG_KEEPALIVE
2536 && type != BGP_MSG_ROUTE_REFRESH_NEW
2537 && type != BGP_MSG_ROUTE_REFRESH_OLD
2538 && type != BGP_MSG_CAPABILITY)
2539 {
2540 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002541 plog_debug (peer->log,
paul718e3742002-12-13 20:15:29 +00002542 "%s unknown message type 0x%02x",
2543 peer->host, type);
2544 bgp_notify_send_with_data (peer,
2545 BGP_NOTIFY_HEADER_ERR,
2546 BGP_NOTIFY_HEADER_BAD_MESTYPE,
2547 &type, 1);
2548 goto done;
2549 }
2550 /* Mimimum packet length check. */
2551 if ((size < BGP_HEADER_SIZE)
2552 || (size > BGP_MAX_PACKET_SIZE)
2553 || (type == BGP_MSG_OPEN && size < BGP_MSG_OPEN_MIN_SIZE)
2554 || (type == BGP_MSG_UPDATE && size < BGP_MSG_UPDATE_MIN_SIZE)
2555 || (type == BGP_MSG_NOTIFY && size < BGP_MSG_NOTIFY_MIN_SIZE)
2556 || (type == BGP_MSG_KEEPALIVE && size != BGP_MSG_KEEPALIVE_MIN_SIZE)
2557 || (type == BGP_MSG_ROUTE_REFRESH_NEW && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
2558 || (type == BGP_MSG_ROUTE_REFRESH_OLD && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
2559 || (type == BGP_MSG_CAPABILITY && size < BGP_MSG_CAPABILITY_MIN_SIZE))
2560 {
2561 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002562 plog_debug (peer->log,
paul718e3742002-12-13 20:15:29 +00002563 "%s bad message length - %d for %s",
2564 peer->host, size,
2565 type == 128 ? "ROUTE-REFRESH" :
2566 bgp_type_str[(int) type]);
2567 bgp_notify_send_with_data (peer,
2568 BGP_NOTIFY_HEADER_ERR,
2569 BGP_NOTIFY_HEADER_BAD_MESLEN,
hassoc9e52be2004-09-26 16:09:34 +00002570 (u_char *) notify_data_length, 2);
paul718e3742002-12-13 20:15:29 +00002571 goto done;
2572 }
2573
2574 /* Adjust size to message length. */
2575 peer->packet_size = size;
2576 }
2577
2578 ret = bgp_read_packet (peer);
2579 if (ret < 0)
2580 goto done;
2581
2582 /* Get size and type again. */
2583 size = stream_getw_from (peer->ibuf, BGP_MARKER_SIZE);
2584 type = stream_getc_from (peer->ibuf, BGP_MARKER_SIZE + 2);
2585
2586 /* BGP packet dump function. */
2587 bgp_dump_packet (peer, type, peer->ibuf);
2588
2589 size = (peer->packet_size - BGP_HEADER_SIZE);
2590
2591 /* Read rest of the packet and call each sort of packet routine */
2592 switch (type)
2593 {
2594 case BGP_MSG_OPEN:
2595 peer->open_in++;
Timo Teräsef757702015-04-29 09:43:04 +03002596 peer->rtt = sockopt_tcp_rtt(peer->fd);
paulf5ba3872004-07-09 12:11:31 +00002597 bgp_open_receive (peer, size); /* XXX return value ignored! */
paul718e3742002-12-13 20:15:29 +00002598 break;
2599 case BGP_MSG_UPDATE:
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002600 peer->readtime = bgp_recent_clock ();
paul718e3742002-12-13 20:15:29 +00002601 bgp_update_receive (peer, size);
2602 break;
2603 case BGP_MSG_NOTIFY:
2604 bgp_notify_receive (peer, size);
2605 break;
2606 case BGP_MSG_KEEPALIVE:
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002607 peer->readtime = bgp_recent_clock ();
paul718e3742002-12-13 20:15:29 +00002608 bgp_keepalive_receive (peer, size);
2609 break;
2610 case BGP_MSG_ROUTE_REFRESH_NEW:
2611 case BGP_MSG_ROUTE_REFRESH_OLD:
2612 peer->refresh_in++;
2613 bgp_route_refresh_receive (peer, size);
2614 break;
2615 case BGP_MSG_CAPABILITY:
2616 peer->dynamic_cap_in++;
2617 bgp_capability_receive (peer, size);
2618 break;
2619 }
2620
2621 /* Clear input buffer. */
2622 peer->packet_size = 0;
2623 if (peer->ibuf)
2624 stream_reset (peer->ibuf);
2625
2626 done:
2627 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2628 {
2629 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +00002630 zlog_debug ("%s [Event] Accepting BGP peer delete", peer->host);
paul718e3742002-12-13 20:15:29 +00002631 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00002632 }
2633 return 0;
2634}