blob: 65c6cac16ac77afc9152d50a35e9f9582125f37c [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 () */
31#include "linklist.h"
32#include "plist.h"
33
34#include "bgpd/bgpd.h"
35#include "bgpd/bgp_table.h"
36#include "bgpd/bgp_dump.h"
37#include "bgpd/bgp_attr.h"
38#include "bgpd/bgp_debug.h"
39#include "bgpd/bgp_fsm.h"
40#include "bgpd/bgp_route.h"
41#include "bgpd/bgp_packet.h"
42#include "bgpd/bgp_open.h"
43#include "bgpd/bgp_aspath.h"
44#include "bgpd/bgp_community.h"
45#include "bgpd/bgp_ecommunity.h"
46#include "bgpd/bgp_network.h"
47#include "bgpd/bgp_mplsvpn.h"
48#include "bgpd/bgp_advertise.h"
hasso93406d82005-02-02 14:40:33 +000049#include "bgpd/bgp_vty.h"
paul718e3742002-12-13 20:15:29 +000050
51int stream_put_prefix (struct stream *, struct prefix *);
David Lamparter6b0655a2014-06-04 06:53:35 +020052
paul718e3742002-12-13 20:15:29 +000053/* Set up BGP packet marker and packet type. */
54static int
55bgp_packet_set_marker (struct stream *s, u_char type)
56{
57 int i;
58
59 /* Fill in marker. */
60 for (i = 0; i < BGP_MARKER_SIZE; i++)
61 stream_putc (s, 0xff);
62
63 /* Dummy total length. This field is should be filled in later on. */
64 stream_putw (s, 0);
65
66 /* BGP packet type. */
67 stream_putc (s, type);
68
69 /* Return current stream size. */
paul9985f832005-02-09 15:51:56 +000070 return stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +000071}
72
73/* Set BGP packet header size entry. If size is zero then use current
74 stream size. */
75static int
76bgp_packet_set_size (struct stream *s)
77{
78 int cp;
79
80 /* Preserve current pointer. */
paul9985f832005-02-09 15:51:56 +000081 cp = stream_get_endp (s);
82 stream_putw_at (s, BGP_MARKER_SIZE, cp);
paul718e3742002-12-13 20:15:29 +000083
84 return cp;
85}
86
87/* Add new packet to the peer. */
paul94f2b392005-06-28 12:44:16 +000088static void
paul718e3742002-12-13 20:15:29 +000089bgp_packet_add (struct peer *peer, struct stream *s)
90{
91 /* Add packet to the end of list. */
92 stream_fifo_push (peer->obuf, s);
93}
94
95/* Free first packet. */
paul94f2b392005-06-28 12:44:16 +000096static void
paul718e3742002-12-13 20:15:29 +000097bgp_packet_delete (struct peer *peer)
98{
99 stream_free (stream_fifo_pop (peer->obuf));
100}
101
paul718e3742002-12-13 20:15:29 +0000102/* Check file descriptor whether connect is established. */
103static void
104bgp_connect_check (struct peer *peer)
105{
106 int status;
paul5228ad22004-06-04 17:58:18 +0000107 socklen_t slen;
paul718e3742002-12-13 20:15:29 +0000108 int ret;
109
110 /* Anyway I have to reset read and write thread. */
111 BGP_READ_OFF (peer->t_read);
112 BGP_WRITE_OFF (peer->t_write);
113
114 /* Check file descriptor. */
115 slen = sizeof (status);
pauleb821182004-05-01 08:44:08 +0000116 ret = getsockopt(peer->fd, SOL_SOCKET, SO_ERROR, (void *) &status, &slen);
paul718e3742002-12-13 20:15:29 +0000117
118 /* If getsockopt is fail, this is fatal error. */
119 if (ret < 0)
120 {
121 zlog (peer->log, LOG_INFO, "can't get sockopt for nonblocking connect");
122 BGP_EVENT_ADD (peer, TCP_fatal_error);
123 return;
124 }
125
126 /* When status is 0 then TCP connection is established. */
127 if (status == 0)
128 {
129 BGP_EVENT_ADD (peer, TCP_connection_open);
130 }
131 else
132 {
133 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +0000134 plog_debug (peer->log, "%s [Event] Connect failed (%s)",
ajs6099b3b2004-11-20 02:06:59 +0000135 peer->host, safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000136 BGP_EVENT_ADD (peer, TCP_connection_open_failed);
137 }
138}
139
140/* Make BGP update packet. */
paul94f2b392005-06-28 12:44:16 +0000141static struct stream *
paul718e3742002-12-13 20:15:29 +0000142bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
143{
144 struct stream *s;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000145 struct stream *snlri;
paul718e3742002-12-13 20:15:29 +0000146 struct bgp_adj_out *adj;
147 struct bgp_advertise *adv;
148 struct stream *packet;
149 struct bgp_node *rn = NULL;
150 struct bgp_info *binfo = NULL;
151 bgp_size_t total_attr_len = 0;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000152 unsigned long attrlen_pos = 0;
153 size_t mpattrlen_pos = 0;
154 size_t mpattr_pos = 0;
paul718e3742002-12-13 20:15:29 +0000155
156 s = peer->work;
157 stream_reset (s);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000158 snlri = peer->scratch;
159 stream_reset (snlri);
paul718e3742002-12-13 20:15:29 +0000160
161 adv = FIFO_HEAD (&peer->sync[afi][safi]->update);
162
163 while (adv)
164 {
Paul Jakmaed3ebfa2006-10-15 23:50:16 +0000165 assert (adv->rn);
166 rn = adv->rn;
paul718e3742002-12-13 20:15:29 +0000167 adj = adv->adj;
168 if (adv->binfo)
169 binfo = adv->binfo;
paul718e3742002-12-13 20:15:29 +0000170
171 /* When remaining space can't include NLRI and it's length. */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000172 if (STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) <=
173 (BGP_NLRI_LENGTH + PSIZE (rn->p.prefixlen)))
paul718e3742002-12-13 20:15:29 +0000174 break;
175
176 /* If packet is empty, set attribute. */
177 if (stream_empty (s))
178 {
Paul Jakmaed3ebfa2006-10-15 23:50:16 +0000179 struct peer *from = NULL;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000180
Greg Troxeld3ddb222010-09-17 10:47:49 -0400181 if (binfo)
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000182 from = binfo->peer;
183
184 /* 1: Write the BGP message header - 16 bytes marker, 2 bytes length,
185 * one byte message type.
186 */
paul718e3742002-12-13 20:15:29 +0000187 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000188
189 /* 2: withdrawn routes length */
paul718e3742002-12-13 20:15:29 +0000190 stream_putw (s, 0);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000191
192 /* 3: total attributes length - attrlen_pos stores the position */
193 attrlen_pos = stream_get_endp (s);
194 stream_putw (s, 0);
195
196 /* 4: if there is MP_REACH_NLRI attribute, that should be the first
197 * attribute, according to draft-ietf-idr-error-handling. Save the
198 * position.
199 */
200 mpattr_pos = stream_get_endp(s);
201
202 /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */
203 total_attr_len = bgp_packet_attribute (NULL, peer, s,
paul5228ad22004-06-04 17:58:18 +0000204 adv->baa->attr,
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000205 NULL, afi, safi,
206 from, NULL, NULL);
paul718e3742002-12-13 20:15:29 +0000207 }
208
209 if (afi == AFI_IP && safi == SAFI_UNICAST)
210 stream_put_prefix (s, &rn->p);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000211 else
212 {
213 /* Encode the prefix in MP_REACH_NLRI attribute */
214 struct prefix_rd *prd = NULL;
215 u_char *tag = NULL;
216
217 if (rn->prn)
218 prd = (struct prefix_rd *) &rn->prn->p;
219 if (binfo && binfo->extra)
220 tag = binfo->extra->tag;
221
222 if (stream_empty(snlri))
223 mpattrlen_pos = bgp_packet_mpattr_start(snlri, afi, safi,
224 adv->baa->attr);
225 bgp_packet_mpattr_prefix(snlri, afi, safi, &rn->p, prd, tag);
226 }
paul718e3742002-12-13 20:15:29 +0000227 if (BGP_DEBUG (update, UPDATE_OUT))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000228 {
229 char buf[INET6_BUFSIZ];
230
231 zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d",
232 peer->host,
233 inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ),
234 rn->p.prefixlen);
235 }
paul718e3742002-12-13 20:15:29 +0000236
237 /* Synchnorize attribute. */
238 if (adj->attr)
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000239 bgp_attr_unintern (&adj->attr);
paul718e3742002-12-13 20:15:29 +0000240 else
241 peer->scount[afi][safi]++;
242
243 adj->attr = bgp_attr_intern (adv->baa->attr);
244
245 adv = bgp_advertise_clean (peer, adj, afi, safi);
paul718e3742002-12-13 20:15:29 +0000246 }
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000247
paul718e3742002-12-13 20:15:29 +0000248 if (! stream_empty (s))
249 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000250 if (!stream_empty(snlri))
251 {
252 bgp_packet_mpattr_end(snlri, mpattrlen_pos);
253 total_attr_len += stream_get_endp(snlri);
254 }
255
256 /* set the total attribute length correctly */
257 stream_putw_at (s, attrlen_pos, total_attr_len);
258
259 if (!stream_empty(snlri))
260 packet = stream_dupcat(s, snlri, mpattr_pos);
261 else
262 packet = stream_dup (s);
263 bgp_packet_set_size (packet);
paul718e3742002-12-13 20:15:29 +0000264 bgp_packet_add (peer, packet);
pauleb821182004-05-01 08:44:08 +0000265 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000266 stream_reset (s);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000267 stream_reset (snlri);
paul718e3742002-12-13 20:15:29 +0000268 return packet;
269 }
270 return NULL;
hasso93406d82005-02-02 14:40:33 +0000271}
paul718e3742002-12-13 20:15:29 +0000272
paul94f2b392005-06-28 12:44:16 +0000273static struct stream *
hasso93406d82005-02-02 14:40:33 +0000274bgp_update_packet_eor (struct peer *peer, afi_t afi, safi_t safi)
275{
276 struct stream *s;
277 struct stream *packet;
278
Paul Jakma750e8142008-07-22 21:11:48 +0000279 if (DISABLE_BGP_ANNOUNCE)
280 return NULL;
hasso93406d82005-02-02 14:40:33 +0000281
282 if (BGP_DEBUG (normal, NORMAL))
283 zlog_debug ("send End-of-RIB for %s to %s", afi_safi_print (afi, safi), peer->host);
284
285 s = stream_new (BGP_MAX_PACKET_SIZE);
286
287 /* Make BGP update packet. */
288 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
289
290 /* Unfeasible Routes Length */
291 stream_putw (s, 0);
292
293 if (afi == AFI_IP && safi == SAFI_UNICAST)
294 {
295 /* Total Path Attribute Length */
296 stream_putw (s, 0);
297 }
298 else
299 {
300 /* Total Path Attribute Length */
301 stream_putw (s, 6);
302 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
303 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
304 stream_putc (s, 3);
305 stream_putw (s, afi);
306 stream_putc (s, safi);
307 }
308
309 bgp_packet_set_size (s);
paule83e2082005-05-19 02:12:25 +0000310 packet = stream_dup (s);
hasso93406d82005-02-02 14:40:33 +0000311 bgp_packet_add (peer, packet);
312 stream_free (s);
313 return packet;
paul718e3742002-12-13 20:15:29 +0000314}
315
316/* Make BGP withdraw packet. */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000317/* For ipv4 unicast:
318 16-octet marker | 2-octet length | 1-octet type |
319 2-octet withdrawn route length | withdrawn prefixes | 2-octet attrlen (=0)
320*/
321/* For other afi/safis:
322 16-octet marker | 2-octet length | 1-octet type |
323 2-octet withdrawn route length (=0) | 2-octet attrlen |
324 mp_unreach attr type | attr len | afi | safi | withdrawn prefixes
325*/
paul94f2b392005-06-28 12:44:16 +0000326static struct stream *
paul718e3742002-12-13 20:15:29 +0000327bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi)
328{
329 struct stream *s;
330 struct stream *packet;
331 struct bgp_adj_out *adj;
332 struct bgp_advertise *adv;
333 struct bgp_node *rn;
334 unsigned long pos;
335 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
345 while ((adv = FIFO_HEAD (&peer->sync[afi][safi]->withdraw)) != NULL)
346 {
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 {
598 adv = FIFO_HEAD (&peer->sync[afi][safi]->withdraw);
599 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 {
610 adv = FIFO_HEAD (&peer->sync[afi][safi]->update);
611 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)
617 && ! CHECK_FLAG (adv->binfo->flags, BGP_INFO_STALE)
618 && safi != SAFI_MPLS_VPN)
619 {
620 if (CHECK_FLAG (adv->binfo->peer->af_sflags[afi][safi],
621 PEER_STATUS_EOR_RECEIVED))
622 s = bgp_update_packet (peer, afi, safi);
623 }
624 else
625 s = bgp_update_packet (peer, afi, safi);
626 }
paul718e3742002-12-13 20:15:29 +0000627
628 if (s)
629 return s;
630 }
hasso93406d82005-02-02 14:40:33 +0000631
632 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV))
633 {
634 if (peer->afc_nego[afi][safi] && peer->synctime
635 && ! CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND)
636 && safi != SAFI_MPLS_VPN)
637 {
638 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND);
639 return bgp_update_packet_eor (peer, afi, safi);
640 }
641 }
paul718e3742002-12-13 20:15:29 +0000642 }
643
644 return NULL;
645}
646
647/* Is there partially written packet or updates we can send right
648 now. */
paul94f2b392005-06-28 12:44:16 +0000649static int
paul718e3742002-12-13 20:15:29 +0000650bgp_write_proceed (struct peer *peer)
651{
652 afi_t afi;
653 safi_t safi;
654 struct bgp_advertise *adv;
655
656 if (stream_fifo_head (peer->obuf))
657 return 1;
658
659 for (afi = AFI_IP; afi < AFI_MAX; afi++)
660 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
661 if (FIFO_HEAD (&peer->sync[afi][safi]->withdraw))
662 return 1;
663
664 for (afi = AFI_IP; afi < AFI_MAX; afi++)
665 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
666 if ((adv = FIFO_HEAD (&peer->sync[afi][safi]->update)) != NULL)
667 if (adv->binfo->uptime < peer->synctime)
668 return 1;
669
670 return 0;
671}
672
673/* Write packet to the peer. */
674int
675bgp_write (struct thread *thread)
676{
677 struct peer *peer;
678 u_char type;
679 struct stream *s;
680 int num;
paulfd79ac92004-10-13 05:06:08 +0000681 unsigned int count = 0;
paul718e3742002-12-13 20:15:29 +0000682
683 /* Yes first of all get peer pointer. */
684 peer = THREAD_ARG (thread);
685 peer->t_write = NULL;
686
687 /* For non-blocking IO check. */
688 if (peer->status == Connect)
689 {
690 bgp_connect_check (peer);
691 return 0;
692 }
693
Stephen Hemmingereac57022010-08-05 10:26:25 -0700694 s = bgp_write_packet (peer);
695 if (!s)
696 return 0; /* nothing to send */
697
698 sockopt_cork (peer->fd, 1);
699
700 /* Nonblocking write until TCP output buffer is full. */
701 do
paul718e3742002-12-13 20:15:29 +0000702 {
703 int writenum;
paul718e3742002-12-13 20:15:29 +0000704
705 /* Number of bytes to be sent. */
706 writenum = stream_get_endp (s) - stream_get_getp (s);
707
708 /* Call write() system call. */
pauleb821182004-05-01 08:44:08 +0000709 num = write (peer->fd, STREAM_PNT (s), writenum);
Stephen Hemminger35398582010-08-05 10:26:23 -0700710 if (num < 0)
paul718e3742002-12-13 20:15:29 +0000711 {
Stephen Hemmingereac57022010-08-05 10:26:25 -0700712 /* write failed either retry needed or error */
713 if (ERRNO_IO_RETRY(errno))
714 break;
715
716 BGP_EVENT_ADD (peer, TCP_fatal_error);
paul718e3742002-12-13 20:15:29 +0000717 return 0;
718 }
Stephen Hemminger35398582010-08-05 10:26:23 -0700719
paul718e3742002-12-13 20:15:29 +0000720 if (num != writenum)
721 {
Stephen Hemminger35398582010-08-05 10:26:23 -0700722 /* Partial write */
paul9985f832005-02-09 15:51:56 +0000723 stream_forward_getp (s, num);
Stephen Hemmingereac57022010-08-05 10:26:25 -0700724 break;
paul718e3742002-12-13 20:15:29 +0000725 }
726
727 /* Retrieve BGP packet type. */
728 stream_set_getp (s, BGP_MARKER_SIZE + 2);
729 type = stream_getc (s);
730
731 switch (type)
732 {
733 case BGP_MSG_OPEN:
734 peer->open_out++;
735 break;
736 case BGP_MSG_UPDATE:
737 peer->update_out++;
738 break;
739 case BGP_MSG_NOTIFY:
740 peer->notify_out++;
741 /* Double start timer. */
742 peer->v_start *= 2;
743
744 /* Overflow check. */
745 if (peer->v_start >= (60 * 2))
746 peer->v_start = (60 * 2);
747
Paul Jakmaca058a32006-09-14 02:58:49 +0000748 /* Flush any existing events */
Paul Jakmadcdf3992006-10-15 23:39:59 +0000749 BGP_EVENT_ADD (peer, BGP_Stop);
Stephen Hemminger3a69f742013-01-11 18:27:23 +0000750 goto done;
751
paul718e3742002-12-13 20:15:29 +0000752 case BGP_MSG_KEEPALIVE:
753 peer->keepalive_out++;
754 break;
755 case BGP_MSG_ROUTE_REFRESH_NEW:
756 case BGP_MSG_ROUTE_REFRESH_OLD:
757 peer->refresh_out++;
758 break;
759 case BGP_MSG_CAPABILITY:
760 peer->dynamic_cap_out++;
761 break;
762 }
763
764 /* OK we send packet so delete it. */
765 bgp_packet_delete (peer);
paul718e3742002-12-13 20:15:29 +0000766 }
Stephen Hemmingereac57022010-08-05 10:26:25 -0700767 while (++count < BGP_WRITE_PACKET_MAX &&
768 (s = bgp_write_packet (peer)) != NULL);
paul718e3742002-12-13 20:15:29 +0000769
770 if (bgp_write_proceed (peer))
pauleb821182004-05-01 08:44:08 +0000771 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
Stephen Hemminger3a69f742013-01-11 18:27:23 +0000772
773 done:
774 sockopt_cork (peer->fd, 0);
paul718e3742002-12-13 20:15:29 +0000775 return 0;
776}
777
778/* This is only for sending NOTIFICATION message to neighbor. */
paul94f2b392005-06-28 12:44:16 +0000779static int
paul718e3742002-12-13 20:15:29 +0000780bgp_write_notify (struct peer *peer)
781{
Stephen Hemminger35398582010-08-05 10:26:23 -0700782 int ret, val;
paul718e3742002-12-13 20:15:29 +0000783 u_char type;
784 struct stream *s;
785
786 /* There should be at least one packet. */
787 s = stream_fifo_head (peer->obuf);
788 if (!s)
789 return 0;
790 assert (stream_get_endp (s) >= BGP_HEADER_SIZE);
791
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000792 /* Stop collecting data within the socket */
793 sockopt_cork (peer->fd, 0);
794
David Lamparter8ff202e2013-07-31 14:39:41 +0200795 /* socket is in nonblocking mode, if we can't deliver the NOTIFY, well,
796 * we only care about getting a clean shutdown at this point. */
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000797 ret = write (peer->fd, STREAM_DATA (s), stream_get_endp (s));
David Lamparter8ff202e2013-07-31 14:39:41 +0200798
799 /* only connection reset/close gets counted as TCP_fatal_error, failure
800 * to write the entire NOTIFY doesn't get different FSM treatment */
paul718e3742002-12-13 20:15:29 +0000801 if (ret <= 0)
802 {
Paul Jakmadcdf3992006-10-15 23:39:59 +0000803 BGP_EVENT_ADD (peer, TCP_fatal_error);
paul718e3742002-12-13 20:15:29 +0000804 return 0;
805 }
806
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000807 /* Disable Nagle, make NOTIFY packet go out right away */
808 val = 1;
809 (void) setsockopt (peer->fd, IPPROTO_TCP, TCP_NODELAY,
810 (char *) &val, sizeof (val));
811
paul718e3742002-12-13 20:15:29 +0000812 /* Retrieve BGP packet type. */
813 stream_set_getp (s, BGP_MARKER_SIZE + 2);
814 type = stream_getc (s);
815
816 assert (type == BGP_MSG_NOTIFY);
817
818 /* Type should be notify. */
819 peer->notify_out++;
820
821 /* Double start timer. */
822 peer->v_start *= 2;
823
824 /* Overflow check. */
825 if (peer->v_start >= (60 * 2))
826 peer->v_start = (60 * 2);
827
Paul Jakmadcdf3992006-10-15 23:39:59 +0000828 BGP_EVENT_ADD (peer, BGP_Stop);
paul718e3742002-12-13 20:15:29 +0000829
830 return 0;
831}
832
833/* Make keepalive packet and send it to the peer. */
834void
835bgp_keepalive_send (struct peer *peer)
836{
837 struct stream *s;
838 int length;
839
840 s = stream_new (BGP_MAX_PACKET_SIZE);
841
842 /* Make keepalive packet. */
843 bgp_packet_set_marker (s, BGP_MSG_KEEPALIVE);
844
845 /* Set packet size. */
846 length = bgp_packet_set_size (s);
847
848 /* Dump packet if debug option is set. */
849 /* bgp_packet_dump (s); */
850
851 if (BGP_DEBUG (keepalive, KEEPALIVE))
ajs6b514742004-12-08 21:03:23 +0000852 zlog_debug ("%s sending KEEPALIVE", peer->host);
paul718e3742002-12-13 20:15:29 +0000853 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000854 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000855 peer->host, BGP_MSG_KEEPALIVE, length);
856
857 /* Add packet to the peer. */
858 bgp_packet_add (peer, s);
859
pauleb821182004-05-01 08:44:08 +0000860 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000861}
862
863/* Make open packet and send it to the peer. */
864void
865bgp_open_send (struct peer *peer)
866{
867 struct stream *s;
868 int length;
869 u_int16_t send_holdtime;
870 as_t local_as;
871
872 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
873 send_holdtime = peer->holdtime;
874 else
875 send_holdtime = peer->bgp->default_holdtime;
876
877 /* local-as Change */
878 if (peer->change_local_as)
879 local_as = peer->change_local_as;
880 else
881 local_as = peer->local_as;
882
883 s = stream_new (BGP_MAX_PACKET_SIZE);
884
885 /* Make open packet. */
886 bgp_packet_set_marker (s, BGP_MSG_OPEN);
887
888 /* Set open packet values. */
889 stream_putc (s, BGP_VERSION_4); /* BGP version */
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000890 stream_putw (s, (local_as <= BGP_AS_MAX) ? (u_int16_t) local_as
891 : BGP_AS_TRANS);
paul718e3742002-12-13 20:15:29 +0000892 stream_putw (s, send_holdtime); /* Hold Time */
893 stream_put_in_addr (s, &peer->local_id); /* BGP Identifier */
894
895 /* Set capability code. */
896 bgp_open_capability (s, peer);
897
898 /* Set BGP packet length. */
899 length = bgp_packet_set_size (s);
900
901 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +0400902 zlog_debug ("%s sending OPEN, version %d, my as %u, holdtime %d, id %s",
paul718e3742002-12-13 20:15:29 +0000903 peer->host, BGP_VERSION_4, local_as,
904 send_holdtime, inet_ntoa (peer->local_id));
905
906 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000907 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000908 peer->host, BGP_MSG_OPEN, length);
909
910 /* Dump packet if debug option is set. */
911 /* bgp_packet_dump (s); */
912
913 /* Add packet to the peer. */
914 bgp_packet_add (peer, s);
915
pauleb821182004-05-01 08:44:08 +0000916 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000917}
918
919/* Send BGP notify packet with data potion. */
920void
921bgp_notify_send_with_data (struct peer *peer, u_char code, u_char sub_code,
922 u_char *data, size_t datalen)
923{
924 struct stream *s;
925 int length;
926
927 /* Allocate new stream. */
928 s = stream_new (BGP_MAX_PACKET_SIZE);
929
930 /* Make nitify packet. */
931 bgp_packet_set_marker (s, BGP_MSG_NOTIFY);
932
933 /* Set notify packet values. */
934 stream_putc (s, code); /* BGP notify code */
935 stream_putc (s, sub_code); /* BGP notify sub_code */
936
937 /* If notify data is present. */
938 if (data)
939 stream_write (s, data, datalen);
940
941 /* Set BGP packet length. */
942 length = bgp_packet_set_size (s);
943
944 /* Add packet to the peer. */
945 stream_fifo_clean (peer->obuf);
946 bgp_packet_add (peer, s);
947
948 /* For debug */
949 {
950 struct bgp_notify bgp_notify;
951 int first = 0;
952 int i;
953 char c[4];
954
955 bgp_notify.code = code;
956 bgp_notify.subcode = sub_code;
957 bgp_notify.data = NULL;
958 bgp_notify.length = length - BGP_MSG_NOTIFY_MIN_SIZE;
959
960 if (bgp_notify.length)
961 {
962 bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
963 for (i = 0; i < bgp_notify.length; i++)
964 if (first)
965 {
966 sprintf (c, " %02x", data[i]);
967 strcat (bgp_notify.data, c);
968 }
969 else
970 {
971 first = 1;
972 sprintf (c, "%02x", data[i]);
973 strcpy (bgp_notify.data, c);
974 }
975 }
976 bgp_notify_print (peer, &bgp_notify, "sending");
977 if (bgp_notify.data)
978 XFREE (MTYPE_TMP, bgp_notify.data);
979 }
980
981 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000982 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000983 peer->host, BGP_MSG_NOTIFY, length);
984
hassoe0701b72004-05-20 09:19:34 +0000985 /* peer reset cause */
986 if (sub_code != BGP_NOTIFY_CEASE_CONFIG_CHANGE)
987 {
988 if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET)
heasley1212dc12011-09-12 13:27:52 +0400989 {
990 peer->last_reset = PEER_DOWN_USER_RESET;
991 zlog_info ("Notification sent to neighbor %s: User reset", peer->host);
992 }
hassoe0701b72004-05-20 09:19:34 +0000993 else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN)
heasley1212dc12011-09-12 13:27:52 +0400994 {
995 peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
996 zlog_info ("Notification sent to neighbor %s: shutdown", peer->host);
997 }
hassoe0701b72004-05-20 09:19:34 +0000998 else
heasley1212dc12011-09-12 13:27:52 +0400999 {
1000 peer->last_reset = PEER_DOWN_NOTIFY_SEND;
1001 zlog_info ("Notification sent to neighbor %s: type %u/%u",
1002 peer->host, code, sub_code);
1003 }
hassoe0701b72004-05-20 09:19:34 +00001004 }
heasley1212dc12011-09-12 13:27:52 +04001005 else
1006 zlog_info ("Notification sent to neighbor %s: configuration change",
1007 peer->host);
hassoe0701b72004-05-20 09:19:34 +00001008
Denis Ovsienko7ccf5e52011-09-10 16:53:30 +04001009 /* Call immediately. */
paul718e3742002-12-13 20:15:29 +00001010 BGP_WRITE_OFF (peer->t_write);
1011
1012 bgp_write_notify (peer);
1013}
1014
1015/* Send BGP notify packet. */
1016void
1017bgp_notify_send (struct peer *peer, u_char code, u_char sub_code)
1018{
1019 bgp_notify_send_with_data (peer, code, sub_code, NULL, 0);
1020}
1021
paul718e3742002-12-13 20:15:29 +00001022/* Send route refresh message to the peer. */
1023void
1024bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
1025 u_char orf_type, u_char when_to_refresh, int remove)
1026{
1027 struct stream *s;
1028 struct stream *packet;
1029 int length;
1030 struct bgp_filter *filter;
1031 int orf_refresh = 0;
1032
Paul Jakma750e8142008-07-22 21:11:48 +00001033 if (DISABLE_BGP_ANNOUNCE)
1034 return;
paul718e3742002-12-13 20:15:29 +00001035
1036 filter = &peer->filter[afi][safi];
1037
1038 /* Adjust safi code. */
1039 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001040 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +00001041
1042 s = stream_new (BGP_MAX_PACKET_SIZE);
1043
1044 /* Make BGP update packet. */
1045 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
1046 bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_NEW);
1047 else
1048 bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_OLD);
1049
1050 /* Encode Route Refresh message. */
1051 stream_putw (s, afi);
1052 stream_putc (s, 0);
1053 stream_putc (s, safi);
1054
1055 if (orf_type == ORF_TYPE_PREFIX
1056 || orf_type == ORF_TYPE_PREFIX_OLD)
1057 if (remove || filter->plist[FILTER_IN].plist)
1058 {
1059 u_int16_t orf_len;
1060 unsigned long orfp;
1061
1062 orf_refresh = 1;
1063 stream_putc (s, when_to_refresh);
1064 stream_putc (s, orf_type);
paul9985f832005-02-09 15:51:56 +00001065 orfp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00001066 stream_putw (s, 0);
1067
1068 if (remove)
1069 {
1070 UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
1071 stream_putc (s, ORF_COMMON_PART_REMOVE_ALL);
1072 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001073 zlog_debug ("%s sending REFRESH_REQ to remove ORF(%d) (%s) for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001074 peer->host, orf_type,
1075 (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
1076 afi, safi);
1077 }
1078 else
1079 {
1080 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
1081 prefix_bgp_orf_entry (s, filter->plist[FILTER_IN].plist,
1082 ORF_COMMON_PART_ADD, ORF_COMMON_PART_PERMIT,
1083 ORF_COMMON_PART_DENY);
1084 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001085 zlog_debug ("%s sending REFRESH_REQ with pfxlist ORF(%d) (%s) for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001086 peer->host, orf_type,
1087 (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
1088 afi, safi);
1089 }
1090
1091 /* Total ORF Entry Len. */
paul9985f832005-02-09 15:51:56 +00001092 orf_len = stream_get_endp (s) - orfp - 2;
paul718e3742002-12-13 20:15:29 +00001093 stream_putw_at (s, orfp, orf_len);
1094 }
1095
1096 /* Set packet size. */
1097 length = bgp_packet_set_size (s);
1098
1099 if (BGP_DEBUG (normal, NORMAL))
1100 {
1101 if (! orf_refresh)
ajs6b514742004-12-08 21:03:23 +00001102 zlog_debug ("%s sending REFRESH_REQ for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001103 peer->host, afi, safi);
ajs6b514742004-12-08 21:03:23 +00001104 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +00001105 peer->host, CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV) ?
1106 BGP_MSG_ROUTE_REFRESH_NEW : BGP_MSG_ROUTE_REFRESH_OLD, length);
1107 }
1108
1109 /* Make real packet. */
paule83e2082005-05-19 02:12:25 +00001110 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +00001111 stream_free (s);
1112
1113 /* Add packet to the peer. */
1114 bgp_packet_add (peer, packet);
1115
pauleb821182004-05-01 08:44:08 +00001116 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +00001117}
1118
1119/* Send capability message to the peer. */
1120void
1121bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi,
1122 int capability_code, int action)
1123{
1124 struct stream *s;
1125 struct stream *packet;
1126 int length;
1127
1128 /* Adjust safi code. */
1129 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001130 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +00001131
1132 s = stream_new (BGP_MAX_PACKET_SIZE);
1133
1134 /* Make BGP update packet. */
1135 bgp_packet_set_marker (s, BGP_MSG_CAPABILITY);
1136
1137 /* Encode MP_EXT capability. */
1138 if (capability_code == CAPABILITY_CODE_MP)
1139 {
1140 stream_putc (s, action);
1141 stream_putc (s, CAPABILITY_CODE_MP);
1142 stream_putc (s, CAPABILITY_CODE_MP_LEN);
1143 stream_putw (s, afi);
1144 stream_putc (s, 0);
1145 stream_putc (s, safi);
1146
1147 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001148 zlog_debug ("%s sending CAPABILITY has %s MP_EXT CAP for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001149 peer->host, action == CAPABILITY_ACTION_SET ?
1150 "Advertising" : "Removing", afi, safi);
1151 }
1152
paul718e3742002-12-13 20:15:29 +00001153 /* Set packet size. */
1154 length = bgp_packet_set_size (s);
1155
1156 /* Make real packet. */
paule83e2082005-05-19 02:12:25 +00001157 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +00001158 stream_free (s);
1159
1160 /* Add packet to the peer. */
1161 bgp_packet_add (peer, packet);
1162
1163 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001164 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +00001165 peer->host, BGP_MSG_CAPABILITY, length);
1166
pauleb821182004-05-01 08:44:08 +00001167 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +00001168}
David Lamparter6b0655a2014-06-04 06:53:35 +02001169
paul718e3742002-12-13 20:15:29 +00001170/* RFC1771 6.8 Connection collision detection. */
paul94f2b392005-06-28 12:44:16 +00001171static int
pauleb821182004-05-01 08:44:08 +00001172bgp_collision_detect (struct peer *new, struct in_addr remote_id)
paul718e3742002-12-13 20:15:29 +00001173{
pauleb821182004-05-01 08:44:08 +00001174 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001175 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001176 struct bgp *bgp;
1177
1178 bgp = bgp_get_default ();
1179 if (! bgp)
1180 return 0;
1181
1182 /* Upon receipt of an OPEN message, the local system must examine
1183 all of its connections that are in the OpenConfirm state. A BGP
1184 speaker may also examine connections in an OpenSent state if it
1185 knows the BGP Identifier of the peer by means outside of the
1186 protocol. If among these connections there is a connection to a
1187 remote BGP speaker whose BGP Identifier equals the one in the
1188 OPEN message, then the local system performs the following
1189 collision resolution procedure: */
1190
paul1eb8ef22005-04-07 07:30:20 +00001191 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001192 {
1193 /* Under OpenConfirm status, local peer structure already hold
1194 remote router ID. */
pauleb821182004-05-01 08:44:08 +00001195
1196 if (peer != new
1197 && (peer->status == OpenConfirm || peer->status == OpenSent)
1198 && sockunion_same (&peer->su, &new->su))
1199 {
paul718e3742002-12-13 20:15:29 +00001200 /* 1. The BGP Identifier of the local system is compared to
1201 the BGP Identifier of the remote system (as specified in
1202 the OPEN message). */
1203
1204 if (ntohl (peer->local_id.s_addr) < ntohl (remote_id.s_addr))
1205 {
1206 /* 2. If the value of the local BGP Identifier is less
1207 than the remote one, the local system closes BGP
1208 connection that already exists (the one that is
1209 already in the OpenConfirm state), and accepts BGP
1210 connection initiated by the remote system. */
1211
pauleb821182004-05-01 08:44:08 +00001212 if (peer->fd >= 0)
hassoe0701b72004-05-20 09:19:34 +00001213 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
paul718e3742002-12-13 20:15:29 +00001214 return 1;
1215 }
1216 else
1217 {
1218 /* 3. Otherwise, the local system closes newly created
1219 BGP connection (the one associated with the newly
1220 received OPEN message), and continues to use the
1221 existing one (the one that is already in the
1222 OpenConfirm state). */
1223
pauleb821182004-05-01 08:44:08 +00001224 if (new->fd >= 0)
paulf5ba3872004-07-09 12:11:31 +00001225 bgp_notify_send (new, BGP_NOTIFY_CEASE,
1226 BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
paul718e3742002-12-13 20:15:29 +00001227 return -1;
1228 }
pauleb821182004-05-01 08:44:08 +00001229 }
1230 }
paul718e3742002-12-13 20:15:29 +00001231 return 0;
1232}
1233
paul94f2b392005-06-28 12:44:16 +00001234static int
paul718e3742002-12-13 20:15:29 +00001235bgp_open_receive (struct peer *peer, bgp_size_t size)
1236{
1237 int ret;
1238 u_char version;
1239 u_char optlen;
1240 u_int16_t holdtime;
1241 u_int16_t send_holdtime;
1242 as_t remote_as;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001243 as_t as4 = 0;
paul718e3742002-12-13 20:15:29 +00001244 struct peer *realpeer;
1245 struct in_addr remote_id;
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001246 int mp_capability;
paul5228ad22004-06-04 17:58:18 +00001247 u_int8_t notify_data_remote_as[2];
1248 u_int8_t notify_data_remote_id[4];
paul718e3742002-12-13 20:15:29 +00001249
1250 realpeer = NULL;
1251
1252 /* Parse open packet. */
1253 version = stream_getc (peer->ibuf);
1254 memcpy (notify_data_remote_as, stream_pnt (peer->ibuf), 2);
1255 remote_as = stream_getw (peer->ibuf);
1256 holdtime = stream_getw (peer->ibuf);
1257 memcpy (notify_data_remote_id, stream_pnt (peer->ibuf), 4);
1258 remote_id.s_addr = stream_get_ipv4 (peer->ibuf);
1259
1260 /* Receive OPEN message log */
1261 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001262 zlog_debug ("%s rcv OPEN, version %d, remote-as (in open) %u,"
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001263 " holdtime %d, id %s",
1264 peer->host, version, remote_as, holdtime,
1265 inet_ntoa (remote_id));
1266
1267 /* BEGIN to read the capability here, but dont do it yet */
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001268 mp_capability = 0;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001269 optlen = stream_getc (peer->ibuf);
1270
1271 if (optlen != 0)
1272 {
1273 /* We need the as4 capability value *right now* because
1274 * if it is there, we have not got the remote_as yet, and without
1275 * that we do not know which peer is connecting to us now.
1276 */
1277 as4 = peek_for_as4_capability (peer, optlen);
1278 }
1279
1280 /* Just in case we have a silly peer who sends AS4 capability set to 0 */
1281 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) && !as4)
1282 {
1283 zlog_err ("%s bad OPEN, got AS4 capability, but AS4 set to 0",
1284 peer->host);
1285 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1286 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1287 return -1;
1288 }
1289
1290 if (remote_as == BGP_AS_TRANS)
1291 {
1292 /* Take the AS4 from the capability. We must have received the
1293 * capability now! Otherwise we have a asn16 peer who uses
1294 * BGP_AS_TRANS, for some unknown reason.
1295 */
1296 if (as4 == BGP_AS_TRANS)
1297 {
1298 zlog_err ("%s [AS4] NEW speaker using AS_TRANS for AS4, not allowed",
1299 peer->host);
1300 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1301 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1302 return -1;
1303 }
1304
1305 if (!as4 && BGP_DEBUG (as4, AS4))
1306 zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but no AS4."
1307 " Odd, but proceeding.", peer->host);
1308 else if (as4 < BGP_AS_MAX && BGP_DEBUG (as4, AS4))
Paul Jakma0df7c912008-07-21 21:02:49 +00001309 zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but AS4 (%u) fits "
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001310 "in 2-bytes, very odd peer.", peer->host, as4);
1311 if (as4)
1312 remote_as = as4;
1313 }
1314 else
1315 {
1316 /* We may have a partner with AS4 who has an asno < BGP_AS_MAX */
1317 /* If we have got the capability, peer->as4cap must match remote_as */
1318 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)
1319 && as4 != remote_as)
1320 {
1321 /* raise error, log this, close session */
1322 zlog_err ("%s bad OPEN, got AS4 capability, but remote_as %u"
1323 " mismatch with 16bit 'myasn' %u in open",
1324 peer->host, as4, remote_as);
1325 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1326 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1327 return -1;
1328 }
1329 }
1330
paul718e3742002-12-13 20:15:29 +00001331 /* Lookup peer from Open packet. */
1332 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1333 {
1334 int as = 0;
1335
1336 realpeer = peer_lookup_with_open (&peer->su, remote_as, &remote_id, &as);
1337
1338 if (! realpeer)
1339 {
1340 /* Peer's source IP address is check in bgp_accept(), so this
1341 must be AS number mismatch or remote-id configuration
1342 mismatch. */
1343 if (as)
1344 {
1345 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001346 zlog_debug ("%s bad OPEN, wrong router identifier %s",
1347 peer->host, inet_ntoa (remote_id));
1348 bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
1349 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
1350 notify_data_remote_id, 4);
paul718e3742002-12-13 20:15:29 +00001351 }
1352 else
1353 {
1354 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001355 zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
ajs6b514742004-12-08 21:03:23 +00001356 peer->host, remote_as, peer->as);
1357 bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
1358 BGP_NOTIFY_OPEN_BAD_PEER_AS,
1359 notify_data_remote_as, 2);
paul718e3742002-12-13 20:15:29 +00001360 }
1361 return -1;
1362 }
1363 }
1364
1365 /* When collision is detected and this peer is closed. Retrun
1366 immidiately. */
1367 ret = bgp_collision_detect (peer, remote_id);
1368 if (ret < 0)
1369 return ret;
1370
pauleb821182004-05-01 08:44:08 +00001371 /* Hack part. */
1372 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1373 {
hasso93406d82005-02-02 14:40:33 +00001374 if (realpeer->status == Established
1375 && CHECK_FLAG (realpeer->sflags, PEER_STATUS_NSF_MODE))
1376 {
1377 realpeer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
1378 SET_FLAG (realpeer->sflags, PEER_STATUS_NSF_WAIT);
1379 }
1380 else if (ret == 0 && realpeer->status != Active
1381 && realpeer->status != OpenSent
Paul Jakma6e199262008-09-09 17:14:33 +01001382 && realpeer->status != OpenConfirm
1383 && realpeer->status != Connect)
pauleb821182004-05-01 08:44:08 +00001384 {
Paul Jakma2b2fc562008-09-06 13:09:35 +01001385 /* XXX: This is an awful problem..
1386 *
1387 * According to the RFC we should just let this connection (of the
1388 * accepted 'peer') continue on to Established if the other
1389 * connection (the 'realpeer' one) is in state Connect, and deal
1390 * with the more larval FSM as/when it gets far enough to receive
1391 * an Open. We don't do that though, we instead close the (more
1392 * developed) accepted connection.
1393 *
1394 * This means there's a race, which if hit, can loop:
1395 *
1396 * FSM for A FSM for B
1397 * realpeer accept-peer realpeer accept-peer
1398 *
1399 * Connect Connect
1400 * Active
1401 * OpenSent OpenSent
1402 * <arrive here,
1403 * Notify, delete>
1404 * Idle Active
1405 * OpenSent OpenSent
1406 * <arrive here,
1407 * Notify, delete>
1408 * Idle
1409 * <wait> <wait>
1410 * Connect Connect
1411 *
1412 *
1413 * If both sides are Quagga, they're almost certain to wait for
1414 * the same amount of time of course (which doesn't preclude other
1415 * implementations also waiting for same time). The race is
1416 * exacerbated by high-latency (in bgpd and/or the network).
1417 *
1418 * The reason we do this is because our FSM is tied to our peer
1419 * structure, which carries our configuration information, etc.
1420 * I.e. we can't let the accepted-peer FSM continue on as it is,
1421 * cause it's not associated with any actual peer configuration -
1422 * it's just a dummy.
1423 *
1424 * It's possible we could hack-fix this by just bgp_stop'ing the
1425 * realpeer and continueing on with the 'transfer FSM' below.
1426 * Ideally, we need to seperate FSMs from struct peer.
1427 *
1428 * Setting one side to passive avoids the race, as a workaround.
1429 */
pauleb821182004-05-01 08:44:08 +00001430 if (BGP_DEBUG (events, EVENTS))
hasso93406d82005-02-02 14:40:33 +00001431 zlog_debug ("%s peer status is %s close connection",
1432 realpeer->host, LOOKUP (bgp_status_msg,
1433 realpeer->status));
1434 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1435 BGP_NOTIFY_CEASE_CONNECT_REJECT);
1436
pauleb821182004-05-01 08:44:08 +00001437 return -1;
1438 }
1439
1440 if (BGP_DEBUG (events, EVENTS))
Paul Jakma6e199262008-09-09 17:14:33 +01001441 zlog_debug ("%s [Event] Transfer accept BGP peer to real (state %s)",
1442 peer->host,
1443 LOOKUP (bgp_status_msg, realpeer->status));
pauleb821182004-05-01 08:44:08 +00001444
1445 bgp_stop (realpeer);
1446
1447 /* Transfer file descriptor. */
1448 realpeer->fd = peer->fd;
1449 peer->fd = -1;
1450
1451 /* Transfer input buffer. */
1452 stream_free (realpeer->ibuf);
1453 realpeer->ibuf = peer->ibuf;
1454 realpeer->packet_size = peer->packet_size;
1455 peer->ibuf = NULL;
1456
1457 /* Transfer status. */
1458 realpeer->status = peer->status;
1459 bgp_stop (peer);
paul200df112005-06-01 11:17:05 +00001460
pauleb821182004-05-01 08:44:08 +00001461 /* peer pointer change. Open packet send to neighbor. */
1462 peer = realpeer;
1463 bgp_open_send (peer);
1464 if (peer->fd < 0)
1465 {
1466 zlog_err ("bgp_open_receive peer's fd is negative value %d",
1467 peer->fd);
1468 return -1;
1469 }
1470 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
1471 }
1472
paul718e3742002-12-13 20:15:29 +00001473 /* remote router-id check. */
1474 if (remote_id.s_addr == 0
Denis Ovsienko733cd9e2011-12-17 19:39:30 +04001475 || IPV4_CLASS_DE (ntohl (remote_id.s_addr))
paul718e3742002-12-13 20:15:29 +00001476 || ntohl (peer->local_id.s_addr) == ntohl (remote_id.s_addr))
1477 {
1478 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001479 zlog_debug ("%s bad OPEN, wrong router identifier %s",
paul718e3742002-12-13 20:15:29 +00001480 peer->host, inet_ntoa (remote_id));
1481 bgp_notify_send_with_data (peer,
1482 BGP_NOTIFY_OPEN_ERR,
1483 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
1484 notify_data_remote_id, 4);
1485 return -1;
1486 }
1487
1488 /* Set remote router-id */
1489 peer->remote_id = remote_id;
1490
1491 /* Peer BGP version check. */
1492 if (version != BGP_VERSION_4)
1493 {
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001494 u_int16_t maxver = htons(BGP_VERSION_4);
1495 /* XXX this reply may not be correct if version < 4 XXX */
paul718e3742002-12-13 20:15:29 +00001496 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001497 zlog_debug ("%s bad protocol version, remote requested %d, local request %d",
paul718e3742002-12-13 20:15:29 +00001498 peer->host, version, BGP_VERSION_4);
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001499 /* Data must be in network byte order here */
paul718e3742002-12-13 20:15:29 +00001500 bgp_notify_send_with_data (peer,
1501 BGP_NOTIFY_OPEN_ERR,
1502 BGP_NOTIFY_OPEN_UNSUP_VERSION,
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001503 (u_int8_t *) &maxver, 2);
paul718e3742002-12-13 20:15:29 +00001504 return -1;
1505 }
1506
1507 /* Check neighbor as number. */
1508 if (remote_as != peer->as)
1509 {
1510 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001511 zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
paul718e3742002-12-13 20:15:29 +00001512 peer->host, remote_as, peer->as);
1513 bgp_notify_send_with_data (peer,
1514 BGP_NOTIFY_OPEN_ERR,
1515 BGP_NOTIFY_OPEN_BAD_PEER_AS,
1516 notify_data_remote_as, 2);
1517 return -1;
1518 }
1519
1520 /* From the rfc: Upon receipt of an OPEN message, a BGP speaker MUST
1521 calculate the value of the Hold Timer by using the smaller of its
1522 configured Hold Time and the Hold Time received in the OPEN message.
1523 The Hold Time MUST be either zero or at least three seconds. An
1524 implementation may reject connections on the basis of the Hold Time. */
1525
1526 if (holdtime < 3 && holdtime != 0)
1527 {
1528 bgp_notify_send (peer,
1529 BGP_NOTIFY_OPEN_ERR,
1530 BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
1531 return -1;
1532 }
1533
1534 /* From the rfc: A reasonable maximum time between KEEPALIVE messages
1535 would be one third of the Hold Time interval. KEEPALIVE messages
1536 MUST NOT be sent more frequently than one per second. An
1537 implementation MAY adjust the rate at which it sends KEEPALIVE
1538 messages as a function of the Hold Time interval. */
1539
1540 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
1541 send_holdtime = peer->holdtime;
1542 else
1543 send_holdtime = peer->bgp->default_holdtime;
1544
1545 if (holdtime < send_holdtime)
1546 peer->v_holdtime = holdtime;
1547 else
1548 peer->v_holdtime = send_holdtime;
1549
1550 peer->v_keepalive = peer->v_holdtime / 3;
1551
1552 /* Open option part parse. */
paul718e3742002-12-13 20:15:29 +00001553 if (optlen != 0)
1554 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001555 if ((ret = bgp_open_option_parse (peer, optlen, &mp_capability)) < 0)
Paul Jakma58617392012-01-09 20:59:26 +00001556 {
1557 bgp_notify_send (peer,
1558 BGP_NOTIFY_OPEN_ERR,
1559 BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
1560 return ret;
1561 }
paul718e3742002-12-13 20:15:29 +00001562 }
1563 else
1564 {
1565 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001566 zlog_debug ("%s rcvd OPEN w/ OPTION parameter len: 0",
paul718e3742002-12-13 20:15:29 +00001567 peer->host);
1568 }
1569
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001570 /*
1571 * Assume that the peer supports the locally configured set of
1572 * AFI/SAFIs if the peer did not send us any Mulitiprotocol
1573 * capabilities, or if 'override-capability' is configured.
1574 */
1575 if (! mp_capability ||
1576 CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
paul718e3742002-12-13 20:15:29 +00001577 {
1578 peer->afc_nego[AFI_IP][SAFI_UNICAST] = peer->afc[AFI_IP][SAFI_UNICAST];
1579 peer->afc_nego[AFI_IP][SAFI_MULTICAST] = peer->afc[AFI_IP][SAFI_MULTICAST];
1580 peer->afc_nego[AFI_IP6][SAFI_UNICAST] = peer->afc[AFI_IP6][SAFI_UNICAST];
1581 peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = peer->afc[AFI_IP6][SAFI_MULTICAST];
1582 }
1583
1584 /* Get sockname. */
1585 bgp_getsockname (peer);
1586
1587 BGP_EVENT_ADD (peer, Receive_OPEN_message);
1588
1589 peer->packet_size = 0;
1590 if (peer->ibuf)
1591 stream_reset (peer->ibuf);
1592
1593 return 0;
1594}
1595
1596/* Parse BGP Update packet and make attribute object. */
paul94f2b392005-06-28 12:44:16 +00001597static int
paul718e3742002-12-13 20:15:29 +00001598bgp_update_receive (struct peer *peer, bgp_size_t size)
1599{
1600 int ret;
1601 u_char *end;
1602 struct stream *s;
1603 struct attr attr;
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001604 struct attr_extra extra;
paul718e3742002-12-13 20:15:29 +00001605 bgp_size_t attribute_len;
1606 bgp_size_t update_len;
1607 bgp_size_t withdraw_len;
1608 struct bgp_nlri update;
1609 struct bgp_nlri withdraw;
1610 struct bgp_nlri mp_update;
1611 struct bgp_nlri mp_withdraw;
paul718e3742002-12-13 20:15:29 +00001612
1613 /* Status must be Established. */
1614 if (peer->status != Established)
1615 {
1616 zlog_err ("%s [FSM] Update packet received under status %s",
1617 peer->host, LOOKUP (bgp_status_msg, peer->status));
1618 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
1619 return -1;
1620 }
1621
1622 /* Set initial values. */
1623 memset (&attr, 0, sizeof (struct attr));
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001624 memset (&extra, 0, sizeof (struct attr_extra));
paul718e3742002-12-13 20:15:29 +00001625 memset (&update, 0, sizeof (struct bgp_nlri));
1626 memset (&withdraw, 0, sizeof (struct bgp_nlri));
1627 memset (&mp_update, 0, sizeof (struct bgp_nlri));
1628 memset (&mp_withdraw, 0, sizeof (struct bgp_nlri));
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001629 attr.extra = &extra;
paul718e3742002-12-13 20:15:29 +00001630
1631 s = peer->ibuf;
1632 end = stream_pnt (s) + size;
1633
1634 /* RFC1771 6.3 If the Unfeasible Routes Length or Total Attribute
1635 Length is too large (i.e., if Unfeasible Routes Length + Total
1636 Attribute Length + 23 exceeds the message Length), then the Error
1637 Subcode is set to Malformed Attribute List. */
1638 if (stream_pnt (s) + 2 > end)
1639 {
1640 zlog_err ("%s [Error] Update packet error"
1641 " (packet length is short for unfeasible length)",
1642 peer->host);
1643 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1644 BGP_NOTIFY_UPDATE_MAL_ATTR);
1645 return -1;
1646 }
1647
1648 /* Unfeasible Route Length. */
1649 withdraw_len = stream_getw (s);
1650
1651 /* Unfeasible Route Length check. */
1652 if (stream_pnt (s) + withdraw_len > end)
1653 {
1654 zlog_err ("%s [Error] Update packet error"
1655 " (packet unfeasible length overflow %d)",
1656 peer->host, withdraw_len);
1657 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1658 BGP_NOTIFY_UPDATE_MAL_ATTR);
1659 return -1;
1660 }
1661
1662 /* Unfeasible Route packet format check. */
1663 if (withdraw_len > 0)
1664 {
1665 ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), withdraw_len);
1666 if (ret < 0)
1667 return -1;
1668
1669 if (BGP_DEBUG (packet, PACKET_RECV))
ajs6b514742004-12-08 21:03:23 +00001670 zlog_debug ("%s [Update:RECV] Unfeasible NLRI received", peer->host);
paul718e3742002-12-13 20:15:29 +00001671
1672 withdraw.afi = AFI_IP;
1673 withdraw.safi = SAFI_UNICAST;
1674 withdraw.nlri = stream_pnt (s);
1675 withdraw.length = withdraw_len;
paul9985f832005-02-09 15:51:56 +00001676 stream_forward_getp (s, withdraw_len);
paul718e3742002-12-13 20:15:29 +00001677 }
1678
1679 /* Attribute total length check. */
1680 if (stream_pnt (s) + 2 > end)
1681 {
1682 zlog_warn ("%s [Error] Packet Error"
1683 " (update packet is short for attribute length)",
1684 peer->host);
1685 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1686 BGP_NOTIFY_UPDATE_MAL_ATTR);
1687 return -1;
1688 }
1689
1690 /* Fetch attribute total length. */
1691 attribute_len = stream_getw (s);
1692
1693 /* Attribute length check. */
1694 if (stream_pnt (s) + attribute_len > end)
1695 {
1696 zlog_warn ("%s [Error] Packet Error"
1697 " (update packet attribute length overflow %d)",
1698 peer->host, attribute_len);
1699 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1700 BGP_NOTIFY_UPDATE_MAL_ATTR);
1701 return -1;
1702 }
Paul Jakmab881c702010-11-23 16:35:42 +00001703
1704 /* Certain attribute parsing errors should not be considered bad enough
1705 * to reset the session for, most particularly any partial/optional
1706 * attributes that have 'tunneled' over speakers that don't understand
1707 * them. Instead we withdraw only the prefix concerned.
1708 *
1709 * Complicates the flow a little though..
1710 */
1711 bgp_attr_parse_ret_t attr_parse_ret = BGP_ATTR_PARSE_PROCEED;
1712 /* This define morphs the update case into a withdraw when lower levels
1713 * have signalled an error condition where this is best.
1714 */
1715#define NLRI_ATTR_ARG (attr_parse_ret != BGP_ATTR_PARSE_WITHDRAW ? &attr : NULL)
paul718e3742002-12-13 20:15:29 +00001716
1717 /* Parse attribute when it exists. */
1718 if (attribute_len)
1719 {
Paul Jakmab881c702010-11-23 16:35:42 +00001720 attr_parse_ret = bgp_attr_parse (peer, &attr, attribute_len,
paul718e3742002-12-13 20:15:29 +00001721 &mp_update, &mp_withdraw);
Paul Jakmab881c702010-11-23 16:35:42 +00001722 if (attr_parse_ret == BGP_ATTR_PARSE_ERROR)
David Lamparterf80f8382014-06-04 01:00:51 +02001723 {
1724 bgp_attr_unintern_sub (&attr);
1725 return -1;
1726 }
paul718e3742002-12-13 20:15:29 +00001727 }
Paul Jakmab881c702010-11-23 16:35:42 +00001728
paul718e3742002-12-13 20:15:29 +00001729 /* Logging the attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001730 if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW
1731 || BGP_DEBUG (update, UPDATE_IN))
paul718e3742002-12-13 20:15:29 +00001732 {
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +00001733 char attrstr[BUFSIZ];
1734 attrstr[0] = '\0';
1735
paule01f9cb2004-07-09 17:48:53 +00001736 ret= bgp_dump_attr (peer, &attr, attrstr, BUFSIZ);
Paul Jakmab881c702010-11-23 16:35:42 +00001737 int lvl = (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
1738 ? LOG_ERR : LOG_DEBUG;
1739
1740 if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
1741 zlog (peer->log, LOG_ERR,
1742 "%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.",
1743 peer->host);
paule01f9cb2004-07-09 17:48:53 +00001744
1745 if (ret)
Paul Jakmab881c702010-11-23 16:35:42 +00001746 zlog (peer->log, lvl, "%s rcvd UPDATE w/ attr: %s",
paule01f9cb2004-07-09 17:48:53 +00001747 peer->host, attrstr);
paul718e3742002-12-13 20:15:29 +00001748 }
Paul Jakmab881c702010-11-23 16:35:42 +00001749
paul718e3742002-12-13 20:15:29 +00001750 /* Network Layer Reachability Information. */
1751 update_len = end - stream_pnt (s);
1752
1753 if (update_len)
1754 {
1755 /* Check NLRI packet format and prefix length. */
1756 ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), update_len);
1757 if (ret < 0)
Paul Jakmab881c702010-11-23 16:35:42 +00001758 {
1759 bgp_attr_unintern_sub (&attr);
Paul Jakmab881c702010-11-23 16:35:42 +00001760 return -1;
1761 }
paul718e3742002-12-13 20:15:29 +00001762
1763 /* Set NLRI portion to structure. */
1764 update.afi = AFI_IP;
1765 update.safi = SAFI_UNICAST;
1766 update.nlri = stream_pnt (s);
1767 update.length = update_len;
paul9985f832005-02-09 15:51:56 +00001768 stream_forward_getp (s, update_len);
paul718e3742002-12-13 20:15:29 +00001769 }
1770
1771 /* NLRI is processed only when the peer is configured specific
1772 Address Family and Subsequent Address Family. */
1773 if (peer->afc[AFI_IP][SAFI_UNICAST])
1774 {
1775 if (withdraw.length)
1776 bgp_nlri_parse (peer, NULL, &withdraw);
1777
1778 if (update.length)
1779 {
1780 /* We check well-known attribute only for IPv4 unicast
1781 update. */
1782 ret = bgp_attr_check (peer, &attr);
1783 if (ret < 0)
Paul Jakmab881c702010-11-23 16:35:42 +00001784 {
1785 bgp_attr_unintern_sub (&attr);
Paul Jakmab881c702010-11-23 16:35:42 +00001786 return -1;
1787 }
paul718e3742002-12-13 20:15:29 +00001788
Paul Jakmab881c702010-11-23 16:35:42 +00001789 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &update);
paul718e3742002-12-13 20:15:29 +00001790 }
paule01f9cb2004-07-09 17:48:53 +00001791
hassof4184462005-02-01 20:13:16 +00001792 if (mp_update.length
1793 && mp_update.afi == AFI_IP
1794 && mp_update.safi == SAFI_UNICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001795 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
hassof4184462005-02-01 20:13:16 +00001796
1797 if (mp_withdraw.length
1798 && mp_withdraw.afi == AFI_IP
1799 && mp_withdraw.safi == SAFI_UNICAST)
1800 bgp_nlri_parse (peer, NULL, &mp_withdraw);
1801
paule01f9cb2004-07-09 17:48:53 +00001802 if (! attribute_len && ! withdraw_len)
1803 {
1804 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001805 SET_FLAG (peer->af_sflags[AFI_IP][SAFI_UNICAST],
1806 PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001807
hasso93406d82005-02-02 14:40:33 +00001808 /* NSF delete stale route */
1809 if (peer->nsf[AFI_IP][SAFI_UNICAST])
1810 bgp_clear_stale_route (peer, AFI_IP, SAFI_UNICAST);
1811
1812 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001813 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001814 peer->host);
1815 }
paul718e3742002-12-13 20:15:29 +00001816 }
1817 if (peer->afc[AFI_IP][SAFI_MULTICAST])
1818 {
1819 if (mp_update.length
1820 && mp_update.afi == AFI_IP
1821 && mp_update.safi == SAFI_MULTICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001822 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001823
1824 if (mp_withdraw.length
1825 && mp_withdraw.afi == AFI_IP
1826 && mp_withdraw.safi == SAFI_MULTICAST)
1827 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001828
hasso93406d82005-02-02 14:40:33 +00001829 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001830 && mp_withdraw.afi == AFI_IP
1831 && mp_withdraw.safi == SAFI_MULTICAST
1832 && mp_withdraw.length == 0)
1833 {
1834 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001835 SET_FLAG (peer->af_sflags[AFI_IP][SAFI_MULTICAST],
1836 PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001837
hasso93406d82005-02-02 14:40:33 +00001838 /* NSF delete stale route */
1839 if (peer->nsf[AFI_IP][SAFI_MULTICAST])
1840 bgp_clear_stale_route (peer, AFI_IP, SAFI_MULTICAST);
1841
1842 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001843 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Multicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001844 peer->host);
1845 }
paul718e3742002-12-13 20:15:29 +00001846 }
1847 if (peer->afc[AFI_IP6][SAFI_UNICAST])
1848 {
1849 if (mp_update.length
1850 && mp_update.afi == AFI_IP6
1851 && mp_update.safi == SAFI_UNICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001852 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001853
1854 if (mp_withdraw.length
1855 && mp_withdraw.afi == AFI_IP6
1856 && mp_withdraw.safi == SAFI_UNICAST)
1857 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001858
hasso93406d82005-02-02 14:40:33 +00001859 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001860 && mp_withdraw.afi == AFI_IP6
1861 && mp_withdraw.safi == SAFI_UNICAST
1862 && mp_withdraw.length == 0)
1863 {
1864 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001865 SET_FLAG (peer->af_sflags[AFI_IP6][SAFI_UNICAST], PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001866
hasso93406d82005-02-02 14:40:33 +00001867 /* NSF delete stale route */
1868 if (peer->nsf[AFI_IP6][SAFI_UNICAST])
1869 bgp_clear_stale_route (peer, AFI_IP6, SAFI_UNICAST);
1870
1871 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001872 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001873 peer->host);
1874 }
paul718e3742002-12-13 20:15:29 +00001875 }
1876 if (peer->afc[AFI_IP6][SAFI_MULTICAST])
1877 {
1878 if (mp_update.length
1879 && mp_update.afi == AFI_IP6
1880 && mp_update.safi == SAFI_MULTICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001881 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001882
1883 if (mp_withdraw.length
1884 && mp_withdraw.afi == AFI_IP6
1885 && mp_withdraw.safi == SAFI_MULTICAST)
1886 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001887
hasso93406d82005-02-02 14:40:33 +00001888 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001889 && mp_withdraw.afi == AFI_IP6
1890 && mp_withdraw.safi == SAFI_MULTICAST
1891 && mp_withdraw.length == 0)
1892 {
1893 /* End-of-RIB received */
1894
hasso93406d82005-02-02 14:40:33 +00001895 /* NSF delete stale route */
1896 if (peer->nsf[AFI_IP6][SAFI_MULTICAST])
1897 bgp_clear_stale_route (peer, AFI_IP6, SAFI_MULTICAST);
1898
paule01f9cb2004-07-09 17:48:53 +00001899 if (BGP_DEBUG (update, UPDATE_IN))
ajs6b514742004-12-08 21:03:23 +00001900 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Multicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001901 peer->host);
1902 }
paul718e3742002-12-13 20:15:29 +00001903 }
1904 if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
1905 {
1906 if (mp_update.length
1907 && mp_update.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001908 && mp_update.safi == SAFI_MPLS_LABELED_VPN)
Paul Jakmab881c702010-11-23 16:35:42 +00001909 bgp_nlri_parse_vpnv4 (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001910
1911 if (mp_withdraw.length
1912 && mp_withdraw.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001913 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00001914 bgp_nlri_parse_vpnv4 (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001915
hasso93406d82005-02-02 14:40:33 +00001916 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001917 && mp_withdraw.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001918 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN
paule01f9cb2004-07-09 17:48:53 +00001919 && mp_withdraw.length == 0)
1920 {
1921 /* End-of-RIB received */
1922
1923 if (BGP_DEBUG (update, UPDATE_IN))
ajs6b514742004-12-08 21:03:23 +00001924 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for VPNv4 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001925 peer->host);
1926 }
paul718e3742002-12-13 20:15:29 +00001927 }
1928
1929 /* Everything is done. We unintern temporary structures which
1930 interned in bgp_attr_parse(). */
Paul Jakmab881c702010-11-23 16:35:42 +00001931 bgp_attr_unintern_sub (&attr);
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001932
paul718e3742002-12-13 20:15:29 +00001933 /* If peering is stopped due to some reason, do not generate BGP
1934 event. */
1935 if (peer->status != Established)
1936 return 0;
1937
1938 /* Increment packet counter. */
1939 peer->update_in++;
Stephen Hemminger65957882010-01-15 16:22:10 +03001940 peer->update_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00001941
Jorge Boncompte [DTI2]e2c38e62012-06-20 17:45:50 +02001942 /* Rearm holdtime timer */
Jorge Boncompte [DTI2]6a4677b2012-05-07 16:53:07 +00001943 BGP_TIMER_OFF (peer->t_holdtime);
Jorge Boncompte [DTI2]e2c38e62012-06-20 17:45:50 +02001944 bgp_timer_set (peer);
paul718e3742002-12-13 20:15:29 +00001945
1946 return 0;
1947}
1948
1949/* Notify message treatment function. */
paul94f2b392005-06-28 12:44:16 +00001950static void
paul718e3742002-12-13 20:15:29 +00001951bgp_notify_receive (struct peer *peer, bgp_size_t size)
1952{
1953 struct bgp_notify bgp_notify;
1954
1955 if (peer->notify.data)
1956 {
1957 XFREE (MTYPE_TMP, peer->notify.data);
1958 peer->notify.data = NULL;
1959 peer->notify.length = 0;
1960 }
1961
1962 bgp_notify.code = stream_getc (peer->ibuf);
1963 bgp_notify.subcode = stream_getc (peer->ibuf);
1964 bgp_notify.length = size - 2;
1965 bgp_notify.data = NULL;
1966
1967 /* Preserv notify code and sub code. */
1968 peer->notify.code = bgp_notify.code;
1969 peer->notify.subcode = bgp_notify.subcode;
1970 /* For further diagnostic record returned Data. */
1971 if (bgp_notify.length)
1972 {
1973 peer->notify.length = size - 2;
1974 peer->notify.data = XMALLOC (MTYPE_TMP, size - 2);
1975 memcpy (peer->notify.data, stream_pnt (peer->ibuf), size - 2);
1976 }
1977
1978 /* For debug */
1979 {
1980 int i;
1981 int first = 0;
1982 char c[4];
1983
1984 if (bgp_notify.length)
1985 {
1986 bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
1987 for (i = 0; i < bgp_notify.length; i++)
1988 if (first)
1989 {
1990 sprintf (c, " %02x", stream_getc (peer->ibuf));
1991 strcat (bgp_notify.data, c);
1992 }
1993 else
1994 {
1995 first = 1;
1996 sprintf (c, "%02x", stream_getc (peer->ibuf));
1997 strcpy (bgp_notify.data, c);
1998 }
1999 }
2000
2001 bgp_notify_print(peer, &bgp_notify, "received");
2002 if (bgp_notify.data)
2003 XFREE (MTYPE_TMP, bgp_notify.data);
2004 }
2005
2006 /* peer count update */
2007 peer->notify_in++;
2008
hassoe0701b72004-05-20 09:19:34 +00002009 if (peer->status == Established)
2010 peer->last_reset = PEER_DOWN_NOTIFY_RECEIVED;
2011
paul718e3742002-12-13 20:15:29 +00002012 /* We have to check for Notify with Unsupported Optional Parameter.
2013 in that case we fallback to open without the capability option.
2014 But this done in bgp_stop. We just mark it here to avoid changing
2015 the fsm tables. */
2016 if (bgp_notify.code == BGP_NOTIFY_OPEN_ERR &&
2017 bgp_notify.subcode == BGP_NOTIFY_OPEN_UNSUP_PARAM )
2018 UNSET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
2019
paul718e3742002-12-13 20:15:29 +00002020 BGP_EVENT_ADD (peer, Receive_NOTIFICATION_message);
2021}
2022
2023/* Keepalive treatment function -- get keepalive send keepalive */
paul94f2b392005-06-28 12:44:16 +00002024static void
paul718e3742002-12-13 20:15:29 +00002025bgp_keepalive_receive (struct peer *peer, bgp_size_t size)
2026{
2027 if (BGP_DEBUG (keepalive, KEEPALIVE))
ajs6b514742004-12-08 21:03:23 +00002028 zlog_debug ("%s KEEPALIVE rcvd", peer->host);
paul718e3742002-12-13 20:15:29 +00002029
2030 BGP_EVENT_ADD (peer, Receive_KEEPALIVE_message);
2031}
2032
2033/* Route refresh message is received. */
paul94f2b392005-06-28 12:44:16 +00002034static void
paul718e3742002-12-13 20:15:29 +00002035bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
2036{
2037 afi_t afi;
2038 safi_t safi;
2039 u_char reserved;
2040 struct stream *s;
2041
2042 /* If peer does not have the capability, send notification. */
2043 if (! CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_ADV))
2044 {
2045 plog_err (peer->log, "%s [Error] BGP route refresh is not enabled",
2046 peer->host);
2047 bgp_notify_send (peer,
2048 BGP_NOTIFY_HEADER_ERR,
2049 BGP_NOTIFY_HEADER_BAD_MESTYPE);
2050 return;
2051 }
2052
2053 /* Status must be Established. */
2054 if (peer->status != Established)
2055 {
2056 plog_err (peer->log,
2057 "%s [Error] Route refresh packet received under status %s",
2058 peer->host, LOOKUP (bgp_status_msg, peer->status));
2059 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
2060 return;
2061 }
2062
2063 s = peer->ibuf;
2064
2065 /* Parse packet. */
2066 afi = stream_getw (s);
2067 reserved = stream_getc (s);
2068 safi = stream_getc (s);
2069
2070 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002071 zlog_debug ("%s rcvd REFRESH_REQ for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00002072 peer->host, afi, safi);
2073
2074 /* Check AFI and SAFI. */
2075 if ((afi != AFI_IP && afi != AFI_IP6)
2076 || (safi != SAFI_UNICAST && safi != SAFI_MULTICAST
Denis Ovsienko42e6d742011-07-14 12:36:19 +04002077 && safi != SAFI_MPLS_LABELED_VPN))
paul718e3742002-12-13 20:15:29 +00002078 {
2079 if (BGP_DEBUG (normal, NORMAL))
2080 {
ajs6b514742004-12-08 21:03:23 +00002081 zlog_debug ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored",
paul718e3742002-12-13 20:15:29 +00002082 peer->host, afi, safi);
2083 }
2084 return;
2085 }
2086
2087 /* Adjust safi code. */
Denis Ovsienko42e6d742011-07-14 12:36:19 +04002088 if (safi == SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00002089 safi = SAFI_MPLS_VPN;
2090
2091 if (size != BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE)
2092 {
2093 u_char *end;
2094 u_char when_to_refresh;
2095 u_char orf_type;
2096 u_int16_t orf_len;
2097
2098 if (size - (BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE) < 5)
2099 {
2100 zlog_info ("%s ORF route refresh length error", peer->host);
2101 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2102 return;
2103 }
2104
2105 when_to_refresh = stream_getc (s);
2106 end = stream_pnt (s) + (size - 5);
2107
Paul Jakma370b64a2007-12-22 16:49:52 +00002108 while ((stream_pnt (s) + 2) < end)
paul718e3742002-12-13 20:15:29 +00002109 {
2110 orf_type = stream_getc (s);
2111 orf_len = stream_getw (s);
Paul Jakma370b64a2007-12-22 16:49:52 +00002112
2113 /* orf_len in bounds? */
2114 if ((stream_pnt (s) + orf_len) > end)
2115 break; /* XXX: Notify instead?? */
paul718e3742002-12-13 20:15:29 +00002116 if (orf_type == ORF_TYPE_PREFIX
2117 || orf_type == ORF_TYPE_PREFIX_OLD)
2118 {
2119 u_char *p_pnt = stream_pnt (s);
2120 u_char *p_end = stream_pnt (s) + orf_len;
2121 struct orf_prefix orfp;
2122 u_char common = 0;
2123 u_int32_t seq;
2124 int psize;
2125 char name[BUFSIZ];
paul718e3742002-12-13 20:15:29 +00002126 int ret;
2127
2128 if (BGP_DEBUG (normal, NORMAL))
2129 {
ajs6b514742004-12-08 21:03:23 +00002130 zlog_debug ("%s rcvd Prefixlist ORF(%d) length %d",
paul718e3742002-12-13 20:15:29 +00002131 peer->host, orf_type, orf_len);
2132 }
2133
Paul Jakma370b64a2007-12-22 16:49:52 +00002134 /* we're going to read at least 1 byte of common ORF header,
2135 * and 7 bytes of ORF Address-filter entry from the stream
2136 */
2137 if (orf_len < 7)
2138 break;
2139
paul718e3742002-12-13 20:15:29 +00002140 /* ORF prefix-list name */
2141 sprintf (name, "%s.%d.%d", peer->host, afi, safi);
2142
2143 while (p_pnt < p_end)
2144 {
Chris Halld64379e2010-05-14 16:38:39 +04002145 /* If the ORF entry is malformed, want to read as much of it
2146 * as possible without going beyond the bounds of the entry,
2147 * to maximise debug information.
2148 */
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002149 int ok;
paul718e3742002-12-13 20:15:29 +00002150 memset (&orfp, 0, sizeof (struct orf_prefix));
2151 common = *p_pnt++;
Chris Halld64379e2010-05-14 16:38:39 +04002152 /* after ++: p_pnt <= p_end */
paul718e3742002-12-13 20:15:29 +00002153 if (common & ORF_COMMON_PART_REMOVE_ALL)
2154 {
2155 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002156 zlog_debug ("%s rcvd Remove-All pfxlist ORF request", peer->host);
paul718e3742002-12-13 20:15:29 +00002157 prefix_bgp_orf_remove_all (name);
2158 break;
2159 }
Chris Halld64379e2010-05-14 16:38:39 +04002160 ok = ((p_end - p_pnt) >= sizeof(u_int32_t)) ;
Denis Ovsienkobb915f52011-12-13 21:11:39 +04002161 if (ok)
Chris Halld64379e2010-05-14 16:38:39 +04002162 {
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002163 memcpy (&seq, p_pnt, sizeof (u_int32_t));
2164 p_pnt += sizeof (u_int32_t);
2165 orfp.seq = ntohl (seq);
Chris Halld64379e2010-05-14 16:38:39 +04002166 }
2167 else
2168 p_pnt = p_end ;
2169
2170 if ((ok = (p_pnt < p_end)))
2171 orfp.ge = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */
2172 if ((ok = (p_pnt < p_end)))
2173 orfp.le = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */
2174 if ((ok = (p_pnt < p_end)))
2175 orfp.p.prefixlen = *p_pnt++ ;
2176 orfp.p.family = afi2family (afi); /* afi checked already */
2177
2178 psize = PSIZE (orfp.p.prefixlen); /* 0 if not ok */
2179 if (psize > prefix_blen(&orfp.p)) /* valid for family ? */
2180 {
2181 ok = 0 ;
2182 psize = prefix_blen(&orfp.p) ;
2183 }
2184 if (psize > (p_end - p_pnt)) /* valid for packet ? */
2185 {
2186 ok = 0 ;
2187 psize = p_end - p_pnt ;
2188 }
2189
2190 if (psize > 0)
2191 memcpy (&orfp.p.u.prefix, p_pnt, psize);
paul718e3742002-12-13 20:15:29 +00002192 p_pnt += psize;
2193
2194 if (BGP_DEBUG (normal, NORMAL))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +00002195 {
2196 char buf[INET6_BUFSIZ];
2197
2198 zlog_debug ("%s rcvd %s %s seq %u %s/%d ge %d le %d%s",
2199 peer->host,
2200 (common & ORF_COMMON_PART_REMOVE ? "Remove" : "Add"),
2201 (common & ORF_COMMON_PART_DENY ? "deny" : "permit"),
2202 orfp.seq,
2203 inet_ntop (orfp.p.family, &orfp.p.u.prefix, buf, INET6_BUFSIZ),
2204 orfp.p.prefixlen, orfp.ge, orfp.le,
2205 ok ? "" : " MALFORMED");
2206 }
2207
Chris Halld64379e2010-05-14 16:38:39 +04002208 if (ok)
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002209 ret = prefix_bgp_orf_set (name, afi, &orfp,
2210 (common & ORF_COMMON_PART_DENY ? 0 : 1 ),
2211 (common & ORF_COMMON_PART_REMOVE ? 0 : 1));
paul718e3742002-12-13 20:15:29 +00002212
Chris Halld64379e2010-05-14 16:38:39 +04002213 if (!ok || (ret != CMD_SUCCESS))
paul718e3742002-12-13 20:15:29 +00002214 {
2215 if (BGP_DEBUG (normal, NORMAL))
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002216 zlog_debug ("%s Received misformatted prefixlist ORF."
2217 " Remove All pfxlist", peer->host);
paul718e3742002-12-13 20:15:29 +00002218 prefix_bgp_orf_remove_all (name);
2219 break;
2220 }
2221 }
2222 peer->orf_plist[afi][safi] =
2223 prefix_list_lookup (AFI_ORF_PREFIX, name);
2224 }
paul9985f832005-02-09 15:51:56 +00002225 stream_forward_getp (s, orf_len);
paul718e3742002-12-13 20:15:29 +00002226 }
2227 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002228 zlog_debug ("%s rcvd Refresh %s ORF request", peer->host,
paul718e3742002-12-13 20:15:29 +00002229 when_to_refresh == REFRESH_DEFER ? "Defer" : "Immediate");
2230 if (when_to_refresh == REFRESH_DEFER)
2231 return;
2232 }
2233
2234 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2235 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH))
2236 UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
2237
2238 /* Perform route refreshment to the peer */
2239 bgp_announce_route (peer, afi, safi);
2240}
2241
paul94f2b392005-06-28 12:44:16 +00002242static int
paul718e3742002-12-13 20:15:29 +00002243bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
2244{
2245 u_char *end;
Paul Jakma6d582722007-08-06 15:21:45 +00002246 struct capability_mp_data mpc;
2247 struct capability_header *hdr;
paul718e3742002-12-13 20:15:29 +00002248 u_char action;
2249 struct bgp *bgp;
2250 afi_t afi;
2251 safi_t safi;
2252
2253 bgp = peer->bgp;
2254 end = pnt + length;
2255
2256 while (pnt < end)
Paul Jakma6d582722007-08-06 15:21:45 +00002257 {
paul718e3742002-12-13 20:15:29 +00002258 /* We need at least action, capability code and capability length. */
2259 if (pnt + 3 > end)
2260 {
2261 zlog_info ("%s Capability length error", peer->host);
2262 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2263 return -1;
2264 }
paul718e3742002-12-13 20:15:29 +00002265 action = *pnt;
Paul Jakma6d582722007-08-06 15:21:45 +00002266 hdr = (struct capability_header *)(pnt + 1);
2267
paul718e3742002-12-13 20:15:29 +00002268 /* Action value check. */
2269 if (action != CAPABILITY_ACTION_SET
2270 && action != CAPABILITY_ACTION_UNSET)
2271 {
2272 zlog_info ("%s Capability Action Value error %d",
2273 peer->host, action);
2274 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2275 return -1;
2276 }
2277
2278 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002279 zlog_debug ("%s CAPABILITY has action: %d, code: %u, length %u",
Paul Jakma6d582722007-08-06 15:21:45 +00002280 peer->host, action, hdr->code, hdr->length);
paul718e3742002-12-13 20:15:29 +00002281
2282 /* Capability length check. */
Paul Jakma6d582722007-08-06 15:21:45 +00002283 if ((pnt + hdr->length + 3) > end)
paul718e3742002-12-13 20:15:29 +00002284 {
2285 zlog_info ("%s Capability length error", peer->host);
2286 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2287 return -1;
2288 }
2289
Paul Jakma6d582722007-08-06 15:21:45 +00002290 /* Fetch structure to the byte stream. */
2291 memcpy (&mpc, pnt + 3, sizeof (struct capability_mp_data));
2292
paul718e3742002-12-13 20:15:29 +00002293 /* We know MP Capability Code. */
Paul Jakma6d582722007-08-06 15:21:45 +00002294 if (hdr->code == CAPABILITY_CODE_MP)
paul718e3742002-12-13 20:15:29 +00002295 {
Paul Jakma6d582722007-08-06 15:21:45 +00002296 afi = ntohs (mpc.afi);
2297 safi = mpc.safi;
paul718e3742002-12-13 20:15:29 +00002298
2299 /* Ignore capability when override-capability is set. */
2300 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
2301 continue;
Paul Jakma6d582722007-08-06 15:21:45 +00002302
2303 if (!bgp_afi_safi_valid_indices (afi, &safi))
2304 {
2305 if (BGP_DEBUG (normal, NORMAL))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002306 zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid "
2307 "(%u/%u)", peer->host, afi, safi);
Paul Jakma6d582722007-08-06 15:21:45 +00002308 continue;
2309 }
2310
paul718e3742002-12-13 20:15:29 +00002311 /* Address family check. */
Paul Jakma6d582722007-08-06 15:21:45 +00002312 if (BGP_DEBUG (normal, NORMAL))
2313 zlog_debug ("%s CAPABILITY has %s MP_EXT CAP for afi/safi: %u/%u",
2314 peer->host,
2315 action == CAPABILITY_ACTION_SET
2316 ? "Advertising" : "Removing",
2317 ntohs(mpc.afi) , mpc.safi);
2318
2319 if (action == CAPABILITY_ACTION_SET)
2320 {
2321 peer->afc_recv[afi][safi] = 1;
2322 if (peer->afc[afi][safi])
2323 {
2324 peer->afc_nego[afi][safi] = 1;
2325 bgp_announce_route (peer, afi, safi);
2326 }
2327 }
2328 else
2329 {
2330 peer->afc_recv[afi][safi] = 0;
2331 peer->afc_nego[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00002332
Paul Jakma6d582722007-08-06 15:21:45 +00002333 if (peer_active_nego (peer))
Chris Caputo228da422009-07-18 05:44:03 +00002334 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
Paul Jakma6d582722007-08-06 15:21:45 +00002335 else
2336 BGP_EVENT_ADD (peer, BGP_Stop);
2337 }
paul718e3742002-12-13 20:15:29 +00002338 }
paul718e3742002-12-13 20:15:29 +00002339 else
2340 {
2341 zlog_warn ("%s unrecognized capability code: %d - ignored",
Paul Jakma6d582722007-08-06 15:21:45 +00002342 peer->host, hdr->code);
paul718e3742002-12-13 20:15:29 +00002343 }
Paul Jakma6d582722007-08-06 15:21:45 +00002344 pnt += hdr->length + 3;
paul718e3742002-12-13 20:15:29 +00002345 }
2346 return 0;
2347}
2348
Paul Jakma01b7ce22009-06-18 12:34:43 +01002349/* Dynamic Capability is received.
2350 *
2351 * This is exported for unit-test purposes
2352 */
Paul Jakma6d582722007-08-06 15:21:45 +00002353int
paul718e3742002-12-13 20:15:29 +00002354bgp_capability_receive (struct peer *peer, bgp_size_t size)
2355{
2356 u_char *pnt;
paul718e3742002-12-13 20:15:29 +00002357
2358 /* Fetch pointer. */
2359 pnt = stream_pnt (peer->ibuf);
2360
2361 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002362 zlog_debug ("%s rcv CAPABILITY", peer->host);
paul718e3742002-12-13 20:15:29 +00002363
2364 /* If peer does not have the capability, send notification. */
2365 if (! CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV))
2366 {
2367 plog_err (peer->log, "%s [Error] BGP dynamic capability is not enabled",
2368 peer->host);
2369 bgp_notify_send (peer,
2370 BGP_NOTIFY_HEADER_ERR,
2371 BGP_NOTIFY_HEADER_BAD_MESTYPE);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002372 return -1;
paul718e3742002-12-13 20:15:29 +00002373 }
2374
2375 /* Status must be Established. */
2376 if (peer->status != Established)
2377 {
2378 plog_err (peer->log,
2379 "%s [Error] Dynamic capability packet received under status %s", peer->host, LOOKUP (bgp_status_msg, peer->status));
2380 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002381 return -1;
paul718e3742002-12-13 20:15:29 +00002382 }
2383
2384 /* Parse packet. */
Paul Jakma6d582722007-08-06 15:21:45 +00002385 return bgp_capability_msg_parse (peer, pnt, size);
paul718e3742002-12-13 20:15:29 +00002386}
David Lamparter6b0655a2014-06-04 06:53:35 +02002387
paul718e3742002-12-13 20:15:29 +00002388/* BGP read utility function. */
paul94f2b392005-06-28 12:44:16 +00002389static int
paul718e3742002-12-13 20:15:29 +00002390bgp_read_packet (struct peer *peer)
2391{
2392 int nbytes;
2393 int readsize;
2394
paul9985f832005-02-09 15:51:56 +00002395 readsize = peer->packet_size - stream_get_endp (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00002396
2397 /* If size is zero then return. */
2398 if (! readsize)
2399 return 0;
2400
2401 /* Read packet from fd. */
Stephen Hemminger35398582010-08-05 10:26:23 -07002402 nbytes = stream_read_try (peer->ibuf, peer->fd, readsize);
paul718e3742002-12-13 20:15:29 +00002403
2404 /* If read byte is smaller than zero then error occured. */
2405 if (nbytes < 0)
2406 {
Stephen Hemminger35398582010-08-05 10:26:23 -07002407 /* Transient error should retry */
2408 if (nbytes == -2)
paul718e3742002-12-13 20:15:29 +00002409 return -1;
2410
2411 plog_err (peer->log, "%s [Error] bgp_read_packet error: %s",
ajs6099b3b2004-11-20 02:06:59 +00002412 peer->host, safe_strerror (errno));
hasso93406d82005-02-02 14:40:33 +00002413
2414 if (peer->status == Established)
2415 {
2416 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
2417 {
2418 peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
2419 SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
2420 }
2421 else
2422 peer->last_reset = PEER_DOWN_CLOSE_SESSION;
2423 }
2424
paul718e3742002-12-13 20:15:29 +00002425 BGP_EVENT_ADD (peer, TCP_fatal_error);
2426 return -1;
2427 }
2428
2429 /* When read byte is zero : clear bgp peer and return */
2430 if (nbytes == 0)
2431 {
2432 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +00002433 plog_debug (peer->log, "%s [Event] BGP connection closed fd %d",
pauleb821182004-05-01 08:44:08 +00002434 peer->host, peer->fd);
hassoe0701b72004-05-20 09:19:34 +00002435
2436 if (peer->status == Established)
hasso93406d82005-02-02 14:40:33 +00002437 {
2438 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
2439 {
2440 peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
2441 SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
2442 }
2443 else
2444 peer->last_reset = PEER_DOWN_CLOSE_SESSION;
2445 }
hassoe0701b72004-05-20 09:19:34 +00002446
paul718e3742002-12-13 20:15:29 +00002447 BGP_EVENT_ADD (peer, TCP_connection_closed);
2448 return -1;
2449 }
2450
2451 /* We read partial packet. */
paul9985f832005-02-09 15:51:56 +00002452 if (stream_get_endp (peer->ibuf) != peer->packet_size)
paul718e3742002-12-13 20:15:29 +00002453 return -1;
2454
2455 return 0;
2456}
2457
2458/* Marker check. */
paul94f2b392005-06-28 12:44:16 +00002459static int
paul718e3742002-12-13 20:15:29 +00002460bgp_marker_all_one (struct stream *s, int length)
2461{
2462 int i;
2463
2464 for (i = 0; i < length; i++)
2465 if (s->data[i] != 0xff)
2466 return 0;
2467
2468 return 1;
2469}
2470
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002471/* Recent thread time.
2472 On same clock base as bgp_clock (MONOTONIC)
2473 but can be time of last context switch to bgp_read thread. */
2474static time_t
2475bgp_recent_clock (void)
2476{
2477 return recent_relative_time().tv_sec;
2478}
2479
paul718e3742002-12-13 20:15:29 +00002480/* Starting point of packet process function. */
2481int
2482bgp_read (struct thread *thread)
2483{
2484 int ret;
2485 u_char type = 0;
2486 struct peer *peer;
2487 bgp_size_t size;
2488 char notify_data_length[2];
2489
2490 /* Yes first of all get peer pointer. */
2491 peer = THREAD_ARG (thread);
2492 peer->t_read = NULL;
2493
2494 /* For non-blocking IO check. */
2495 if (peer->status == Connect)
2496 {
2497 bgp_connect_check (peer);
2498 goto done;
2499 }
2500 else
2501 {
pauleb821182004-05-01 08:44:08 +00002502 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +00002503 {
pauleb821182004-05-01 08:44:08 +00002504 zlog_err ("bgp_read peer's fd is negative value %d", peer->fd);
paul718e3742002-12-13 20:15:29 +00002505 return -1;
2506 }
pauleb821182004-05-01 08:44:08 +00002507 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
paul718e3742002-12-13 20:15:29 +00002508 }
2509
2510 /* Read packet header to determine type of the packet */
2511 if (peer->packet_size == 0)
2512 peer->packet_size = BGP_HEADER_SIZE;
2513
paul9985f832005-02-09 15:51:56 +00002514 if (stream_get_endp (peer->ibuf) < BGP_HEADER_SIZE)
paul718e3742002-12-13 20:15:29 +00002515 {
2516 ret = bgp_read_packet (peer);
2517
2518 /* Header read error or partial read packet. */
2519 if (ret < 0)
2520 goto done;
2521
2522 /* Get size and type. */
paul9985f832005-02-09 15:51:56 +00002523 stream_forward_getp (peer->ibuf, BGP_MARKER_SIZE);
paul718e3742002-12-13 20:15:29 +00002524 memcpy (notify_data_length, stream_pnt (peer->ibuf), 2);
2525 size = stream_getw (peer->ibuf);
2526 type = stream_getc (peer->ibuf);
2527
2528 if (BGP_DEBUG (normal, NORMAL) && type != 2 && type != 0)
ajs6b514742004-12-08 21:03:23 +00002529 zlog_debug ("%s rcv message type %d, length (excl. header) %d",
paul718e3742002-12-13 20:15:29 +00002530 peer->host, type, size - BGP_HEADER_SIZE);
2531
2532 /* Marker check */
paulf5ba3872004-07-09 12:11:31 +00002533 if (((type == BGP_MSG_OPEN) || (type == BGP_MSG_KEEPALIVE))
paul718e3742002-12-13 20:15:29 +00002534 && ! bgp_marker_all_one (peer->ibuf, BGP_MARKER_SIZE))
2535 {
2536 bgp_notify_send (peer,
2537 BGP_NOTIFY_HEADER_ERR,
2538 BGP_NOTIFY_HEADER_NOT_SYNC);
2539 goto done;
2540 }
2541
2542 /* BGP type check. */
2543 if (type != BGP_MSG_OPEN && type != BGP_MSG_UPDATE
2544 && type != BGP_MSG_NOTIFY && type != BGP_MSG_KEEPALIVE
2545 && type != BGP_MSG_ROUTE_REFRESH_NEW
2546 && type != BGP_MSG_ROUTE_REFRESH_OLD
2547 && type != BGP_MSG_CAPABILITY)
2548 {
2549 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002550 plog_debug (peer->log,
paul718e3742002-12-13 20:15:29 +00002551 "%s unknown message type 0x%02x",
2552 peer->host, type);
2553 bgp_notify_send_with_data (peer,
2554 BGP_NOTIFY_HEADER_ERR,
2555 BGP_NOTIFY_HEADER_BAD_MESTYPE,
2556 &type, 1);
2557 goto done;
2558 }
2559 /* Mimimum packet length check. */
2560 if ((size < BGP_HEADER_SIZE)
2561 || (size > BGP_MAX_PACKET_SIZE)
2562 || (type == BGP_MSG_OPEN && size < BGP_MSG_OPEN_MIN_SIZE)
2563 || (type == BGP_MSG_UPDATE && size < BGP_MSG_UPDATE_MIN_SIZE)
2564 || (type == BGP_MSG_NOTIFY && size < BGP_MSG_NOTIFY_MIN_SIZE)
2565 || (type == BGP_MSG_KEEPALIVE && size != BGP_MSG_KEEPALIVE_MIN_SIZE)
2566 || (type == BGP_MSG_ROUTE_REFRESH_NEW && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
2567 || (type == BGP_MSG_ROUTE_REFRESH_OLD && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
2568 || (type == BGP_MSG_CAPABILITY && size < BGP_MSG_CAPABILITY_MIN_SIZE))
2569 {
2570 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002571 plog_debug (peer->log,
paul718e3742002-12-13 20:15:29 +00002572 "%s bad message length - %d for %s",
2573 peer->host, size,
2574 type == 128 ? "ROUTE-REFRESH" :
2575 bgp_type_str[(int) type]);
2576 bgp_notify_send_with_data (peer,
2577 BGP_NOTIFY_HEADER_ERR,
2578 BGP_NOTIFY_HEADER_BAD_MESLEN,
hassoc9e52be2004-09-26 16:09:34 +00002579 (u_char *) notify_data_length, 2);
paul718e3742002-12-13 20:15:29 +00002580 goto done;
2581 }
2582
2583 /* Adjust size to message length. */
2584 peer->packet_size = size;
2585 }
2586
2587 ret = bgp_read_packet (peer);
2588 if (ret < 0)
2589 goto done;
2590
2591 /* Get size and type again. */
2592 size = stream_getw_from (peer->ibuf, BGP_MARKER_SIZE);
2593 type = stream_getc_from (peer->ibuf, BGP_MARKER_SIZE + 2);
2594
2595 /* BGP packet dump function. */
2596 bgp_dump_packet (peer, type, peer->ibuf);
2597
2598 size = (peer->packet_size - BGP_HEADER_SIZE);
2599
2600 /* Read rest of the packet and call each sort of packet routine */
2601 switch (type)
2602 {
2603 case BGP_MSG_OPEN:
2604 peer->open_in++;
paulf5ba3872004-07-09 12:11:31 +00002605 bgp_open_receive (peer, size); /* XXX return value ignored! */
paul718e3742002-12-13 20:15:29 +00002606 break;
2607 case BGP_MSG_UPDATE:
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002608 peer->readtime = bgp_recent_clock ();
paul718e3742002-12-13 20:15:29 +00002609 bgp_update_receive (peer, size);
2610 break;
2611 case BGP_MSG_NOTIFY:
2612 bgp_notify_receive (peer, size);
2613 break;
2614 case BGP_MSG_KEEPALIVE:
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002615 peer->readtime = bgp_recent_clock ();
paul718e3742002-12-13 20:15:29 +00002616 bgp_keepalive_receive (peer, size);
2617 break;
2618 case BGP_MSG_ROUTE_REFRESH_NEW:
2619 case BGP_MSG_ROUTE_REFRESH_OLD:
2620 peer->refresh_in++;
2621 bgp_route_refresh_receive (peer, size);
2622 break;
2623 case BGP_MSG_CAPABILITY:
2624 peer->dynamic_cap_in++;
2625 bgp_capability_receive (peer, size);
2626 break;
2627 }
2628
2629 /* Clear input buffer. */
2630 peer->packet_size = 0;
2631 if (peer->ibuf)
2632 stream_reset (peer->ibuf);
2633
2634 done:
2635 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2636 {
2637 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +00002638 zlog_debug ("%s [Event] Accepting BGP peer delete", peer->host);
paul718e3742002-12-13 20:15:29 +00002639 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00002640 }
2641 return 0;
2642}