blob: 14fd6e51e948910b8f0e3dff29afbdbca427612f [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
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100161 adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->update);
paul718e3742002-12-13 20:15:29 +0000162
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;
paul718e3742002-12-13 20:15:29 +0000334 bgp_size_t unfeasible_len;
335 bgp_size_t total_attr_len;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000336 size_t mp_start = 0;
337 size_t attrlen_pos = 0;
338 size_t mplen_pos = 0;
339 u_char first_time = 1;
paul718e3742002-12-13 20:15:29 +0000340
341 s = peer->work;
342 stream_reset (s);
343
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100344 while ((adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->withdraw)) != NULL)
paul718e3742002-12-13 20:15:29 +0000345 {
Paul Jakmaed3ebfa2006-10-15 23:50:16 +0000346 assert (adv->rn);
paul718e3742002-12-13 20:15:29 +0000347 adj = adv->adj;
348 rn = adv->rn;
paul718e3742002-12-13 20:15:29 +0000349
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000350 if (STREAM_REMAIN (s)
hasso4372df72004-05-20 10:20:02 +0000351 < (BGP_NLRI_LENGTH + BGP_TOTAL_ATTR_LEN + PSIZE (rn->p.prefixlen)))
paul718e3742002-12-13 20:15:29 +0000352 break;
353
354 if (stream_empty (s))
355 {
356 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000357 stream_putw (s, 0); /* unfeasible routes length */
paul718e3742002-12-13 20:15:29 +0000358 }
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000359 else
360 first_time = 0;
paul718e3742002-12-13 20:15:29 +0000361
362 if (afi == AFI_IP && safi == SAFI_UNICAST)
363 stream_put_prefix (s, &rn->p);
364 else
365 {
Paul Jakmaa3b6ea52006-05-04 07:52:12 +0000366 struct prefix_rd *prd = NULL;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000367
Paul Jakmaa3b6ea52006-05-04 07:52:12 +0000368 if (rn->prn)
369 prd = (struct prefix_rd *) &rn->prn->p;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000370
371 /* If first time, format the MP_UNREACH header */
372 if (first_time)
373 {
374 attrlen_pos = stream_get_endp (s);
375 /* total attr length = 0 for now. reevaluate later */
376 stream_putw (s, 0);
377 mp_start = stream_get_endp (s);
378 mplen_pos = bgp_packet_mpunreach_start(s, afi, safi);
379 }
380
381 bgp_packet_mpunreach_prefix(s, &rn->p, afi, safi, prd, NULL);
paul718e3742002-12-13 20:15:29 +0000382 }
383
384 if (BGP_DEBUG (update, UPDATE_OUT))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000385 {
386 char buf[INET6_BUFSIZ];
387
388 zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d -- unreachable",
389 peer->host,
390 inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ),
391 rn->p.prefixlen);
392 }
paul718e3742002-12-13 20:15:29 +0000393
394 peer->scount[afi][safi]--;
395
396 bgp_adj_out_remove (rn, adj, peer, afi, safi);
397 bgp_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +0000398 }
399
400 if (! stream_empty (s))
401 {
402 if (afi == AFI_IP && safi == SAFI_UNICAST)
403 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000404 unfeasible_len
paul9985f832005-02-09 15:51:56 +0000405 = stream_get_endp (s) - BGP_HEADER_SIZE - BGP_UNFEASIBLE_LEN;
paul718e3742002-12-13 20:15:29 +0000406 stream_putw_at (s, BGP_HEADER_SIZE, unfeasible_len);
407 stream_putw (s, 0);
408 }
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000409 else
410 {
411 /* Set the mp_unreach attr's length */
412 bgp_packet_mpunreach_end(s, mplen_pos);
413
414 /* Set total path attribute length. */
415 total_attr_len = stream_get_endp(s) - mp_start;
416 stream_putw_at (s, attrlen_pos, total_attr_len);
417 }
paul718e3742002-12-13 20:15:29 +0000418 bgp_packet_set_size (s);
paule83e2082005-05-19 02:12:25 +0000419 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +0000420 bgp_packet_add (peer, packet);
421 stream_reset (s);
422 return packet;
423 }
424
425 return NULL;
426}
427
428void
429bgp_default_update_send (struct peer *peer, struct attr *attr,
430 afi_t afi, safi_t safi, struct peer *from)
431{
432 struct stream *s;
433 struct stream *packet;
434 struct prefix p;
435 unsigned long pos;
436 bgp_size_t total_attr_len;
paul718e3742002-12-13 20:15:29 +0000437
Paul Jakma750e8142008-07-22 21:11:48 +0000438 if (DISABLE_BGP_ANNOUNCE)
439 return;
paul718e3742002-12-13 20:15:29 +0000440
441 if (afi == AFI_IP)
442 str2prefix ("0.0.0.0/0", &p);
443#ifdef HAVE_IPV6
444 else
445 str2prefix ("::/0", &p);
446#endif /* HAVE_IPV6 */
447
448 /* Logging the attribute. */
449 if (BGP_DEBUG (update, UPDATE_OUT))
450 {
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000451 char attrstr[BUFSIZ];
452 char buf[INET6_BUFSIZ];
453 attrstr[0] = '\0';
454
paul718e3742002-12-13 20:15:29 +0000455 bgp_dump_attr (peer, attr, attrstr, BUFSIZ);
ajs6b514742004-12-08 21:03:23 +0000456 zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d %s",
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000457 peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ),
paul718e3742002-12-13 20:15:29 +0000458 p.prefixlen, attrstr);
459 }
460
461 s = stream_new (BGP_MAX_PACKET_SIZE);
462
463 /* Make BGP update packet. */
464 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
465
466 /* Unfeasible Routes Length. */
467 stream_putw (s, 0);
468
469 /* Make place for total attribute length. */
paul9985f832005-02-09 15:51:56 +0000470 pos = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000471 stream_putw (s, 0);
472 total_attr_len = bgp_packet_attribute (NULL, peer, s, attr, &p, afi, safi, from, NULL, NULL);
473
474 /* Set Total Path Attribute Length. */
475 stream_putw_at (s, pos, total_attr_len);
476
477 /* NLRI set. */
478 if (p.family == AF_INET && safi == SAFI_UNICAST)
479 stream_put_prefix (s, &p);
480
481 /* Set size. */
482 bgp_packet_set_size (s);
483
paule83e2082005-05-19 02:12:25 +0000484 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +0000485 stream_free (s);
486
487 /* Dump packet if debug option is set. */
488#ifdef DEBUG
jardin2d74db52005-10-01 00:07:50 +0000489 /* bgp_packet_dump (packet); */
paul718e3742002-12-13 20:15:29 +0000490#endif /* DEBUG */
491
492 /* Add packet to the peer. */
493 bgp_packet_add (peer, packet);
494
pauleb821182004-05-01 08:44:08 +0000495 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000496}
497
498void
499bgp_default_withdraw_send (struct peer *peer, afi_t afi, safi_t safi)
500{
501 struct stream *s;
502 struct stream *packet;
503 struct prefix p;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000504 unsigned long attrlen_pos = 0;
paul718e3742002-12-13 20:15:29 +0000505 unsigned long cp;
506 bgp_size_t unfeasible_len;
507 bgp_size_t total_attr_len;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000508 size_t mp_start = 0;
509 size_t mplen_pos = 0;
paul718e3742002-12-13 20:15:29 +0000510
Paul Jakma750e8142008-07-22 21:11:48 +0000511 if (DISABLE_BGP_ANNOUNCE)
512 return;
paul718e3742002-12-13 20:15:29 +0000513
514 if (afi == AFI_IP)
515 str2prefix ("0.0.0.0/0", &p);
516#ifdef HAVE_IPV6
517 else
518 str2prefix ("::/0", &p);
519#endif /* HAVE_IPV6 */
520
521 total_attr_len = 0;
paul718e3742002-12-13 20:15:29 +0000522
523 if (BGP_DEBUG (update, UPDATE_OUT))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000524 {
525 char buf[INET6_BUFSIZ];
526
527 zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d -- unreachable",
528 peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ),
529 p.prefixlen);
530 }
paul718e3742002-12-13 20:15:29 +0000531
532 s = stream_new (BGP_MAX_PACKET_SIZE);
533
534 /* Make BGP update packet. */
535 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
536
537 /* Unfeasible Routes Length. */;
paul9985f832005-02-09 15:51:56 +0000538 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000539 stream_putw (s, 0);
540
541 /* Withdrawn Routes. */
542 if (p.family == AF_INET && safi == SAFI_UNICAST)
543 {
544 stream_put_prefix (s, &p);
545
paul9985f832005-02-09 15:51:56 +0000546 unfeasible_len = stream_get_endp (s) - cp - 2;
paul718e3742002-12-13 20:15:29 +0000547
548 /* Set unfeasible len. */
549 stream_putw_at (s, cp, unfeasible_len);
550
551 /* Set total path attribute length. */
552 stream_putw (s, 0);
553 }
554 else
555 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000556 attrlen_pos = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000557 stream_putw (s, 0);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000558 mp_start = stream_get_endp (s);
559 mplen_pos = bgp_packet_mpunreach_start(s, afi, safi);
560 bgp_packet_mpunreach_prefix(s, &p, afi, safi, NULL, NULL);
561
562 /* Set the mp_unreach attr's length */
563 bgp_packet_mpunreach_end(s, mplen_pos);
paul718e3742002-12-13 20:15:29 +0000564
565 /* Set total path attribute length. */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000566 total_attr_len = stream_get_endp(s) - mp_start;
567 stream_putw_at (s, attrlen_pos, total_attr_len);
paul718e3742002-12-13 20:15:29 +0000568 }
569
570 bgp_packet_set_size (s);
571
paule83e2082005-05-19 02:12:25 +0000572 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +0000573 stream_free (s);
574
575 /* Add packet to the peer. */
576 bgp_packet_add (peer, packet);
577
pauleb821182004-05-01 08:44:08 +0000578 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000579}
580
581/* Get next packet to be written. */
paul94f2b392005-06-28 12:44:16 +0000582static struct stream *
paul718e3742002-12-13 20:15:29 +0000583bgp_write_packet (struct peer *peer)
584{
585 afi_t afi;
586 safi_t safi;
587 struct stream *s = NULL;
588 struct bgp_advertise *adv;
589
590 s = stream_fifo_head (peer->obuf);
591 if (s)
592 return s;
593
594 for (afi = AFI_IP; afi < AFI_MAX; afi++)
595 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
596 {
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100597 adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->withdraw);
paul718e3742002-12-13 20:15:29 +0000598 if (adv)
599 {
600 s = bgp_withdraw_packet (peer, afi, safi);
601 if (s)
602 return s;
603 }
604 }
605
606 for (afi = AFI_IP; afi < AFI_MAX; afi++)
607 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
608 {
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100609 adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->update);
paul718e3742002-12-13 20:15:29 +0000610 if (adv)
611 {
612 if (adv->binfo && adv->binfo->uptime < peer->synctime)
hasso93406d82005-02-02 14:40:33 +0000613 {
614 if (CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_RCV)
615 && CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_ADV)
Vipin Kumardd49eb12014-09-30 14:36:38 -0700616 && ! (CHECK_FLAG (adv->binfo->peer->cap,
617 PEER_CAP_RESTART_BIT_RCV) &&
618 CHECK_FLAG (adv->binfo->peer->cap,
619 PEER_CAP_RESTART_BIT_ADV))
hasso93406d82005-02-02 14:40:33 +0000620 && ! CHECK_FLAG (adv->binfo->flags, BGP_INFO_STALE)
621 && safi != SAFI_MPLS_VPN)
622 {
623 if (CHECK_FLAG (adv->binfo->peer->af_sflags[afi][safi],
624 PEER_STATUS_EOR_RECEIVED))
625 s = bgp_update_packet (peer, afi, safi);
626 }
627 else
628 s = bgp_update_packet (peer, afi, safi);
629 }
paul718e3742002-12-13 20:15:29 +0000630
631 if (s)
632 return s;
633 }
hasso93406d82005-02-02 14:40:33 +0000634
635 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV))
636 {
637 if (peer->afc_nego[afi][safi] && peer->synctime
638 && ! CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND)
639 && safi != SAFI_MPLS_VPN)
640 {
641 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND);
642 return bgp_update_packet_eor (peer, afi, safi);
643 }
644 }
paul718e3742002-12-13 20:15:29 +0000645 }
646
647 return NULL;
648}
649
650/* Is there partially written packet or updates we can send right
651 now. */
paul94f2b392005-06-28 12:44:16 +0000652static int
paul718e3742002-12-13 20:15:29 +0000653bgp_write_proceed (struct peer *peer)
654{
655 afi_t afi;
656 safi_t safi;
657 struct bgp_advertise *adv;
658
659 if (stream_fifo_head (peer->obuf))
660 return 1;
661
662 for (afi = AFI_IP; afi < AFI_MAX; afi++)
663 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
664 if (FIFO_HEAD (&peer->sync[afi][safi]->withdraw))
665 return 1;
666
667 for (afi = AFI_IP; afi < AFI_MAX; afi++)
668 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100669 if ((adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->update)) != NULL)
paul718e3742002-12-13 20:15:29 +0000670 if (adv->binfo->uptime < peer->synctime)
671 return 1;
672
673 return 0;
674}
675
676/* Write packet to the peer. */
677int
678bgp_write (struct thread *thread)
679{
680 struct peer *peer;
681 u_char type;
682 struct stream *s;
683 int num;
paulfd79ac92004-10-13 05:06:08 +0000684 unsigned int count = 0;
paul718e3742002-12-13 20:15:29 +0000685
686 /* Yes first of all get peer pointer. */
687 peer = THREAD_ARG (thread);
688 peer->t_write = NULL;
689
690 /* For non-blocking IO check. */
691 if (peer->status == Connect)
692 {
693 bgp_connect_check (peer);
694 return 0;
695 }
696
Stephen Hemmingereac57022010-08-05 10:26:25 -0700697 s = bgp_write_packet (peer);
698 if (!s)
699 return 0; /* nothing to send */
700
701 sockopt_cork (peer->fd, 1);
702
703 /* Nonblocking write until TCP output buffer is full. */
704 do
paul718e3742002-12-13 20:15:29 +0000705 {
706 int writenum;
paul718e3742002-12-13 20:15:29 +0000707
708 /* Number of bytes to be sent. */
709 writenum = stream_get_endp (s) - stream_get_getp (s);
710
711 /* Call write() system call. */
pauleb821182004-05-01 08:44:08 +0000712 num = write (peer->fd, STREAM_PNT (s), writenum);
Stephen Hemminger35398582010-08-05 10:26:23 -0700713 if (num < 0)
paul718e3742002-12-13 20:15:29 +0000714 {
Stephen Hemmingereac57022010-08-05 10:26:25 -0700715 /* write failed either retry needed or error */
716 if (ERRNO_IO_RETRY(errno))
717 break;
718
719 BGP_EVENT_ADD (peer, TCP_fatal_error);
paul718e3742002-12-13 20:15:29 +0000720 return 0;
721 }
Stephen Hemminger35398582010-08-05 10:26:23 -0700722
paul718e3742002-12-13 20:15:29 +0000723 if (num != writenum)
724 {
Stephen Hemminger35398582010-08-05 10:26:23 -0700725 /* Partial write */
paul9985f832005-02-09 15:51:56 +0000726 stream_forward_getp (s, num);
Stephen Hemmingereac57022010-08-05 10:26:25 -0700727 break;
paul718e3742002-12-13 20:15:29 +0000728 }
729
730 /* Retrieve BGP packet type. */
731 stream_set_getp (s, BGP_MARKER_SIZE + 2);
732 type = stream_getc (s);
733
734 switch (type)
735 {
736 case BGP_MSG_OPEN:
737 peer->open_out++;
738 break;
739 case BGP_MSG_UPDATE:
740 peer->update_out++;
741 break;
742 case BGP_MSG_NOTIFY:
743 peer->notify_out++;
744 /* Double start timer. */
745 peer->v_start *= 2;
746
747 /* Overflow check. */
748 if (peer->v_start >= (60 * 2))
749 peer->v_start = (60 * 2);
750
Paul Jakmaca058a32006-09-14 02:58:49 +0000751 /* Flush any existing events */
Paul Jakmadcdf3992006-10-15 23:39:59 +0000752 BGP_EVENT_ADD (peer, BGP_Stop);
Stephen Hemminger3a69f742013-01-11 18:27:23 +0000753 goto done;
754
paul718e3742002-12-13 20:15:29 +0000755 case BGP_MSG_KEEPALIVE:
756 peer->keepalive_out++;
757 break;
758 case BGP_MSG_ROUTE_REFRESH_NEW:
759 case BGP_MSG_ROUTE_REFRESH_OLD:
760 peer->refresh_out++;
761 break;
762 case BGP_MSG_CAPABILITY:
763 peer->dynamic_cap_out++;
764 break;
765 }
766
767 /* OK we send packet so delete it. */
768 bgp_packet_delete (peer);
paul718e3742002-12-13 20:15:29 +0000769 }
Stephen Hemmingereac57022010-08-05 10:26:25 -0700770 while (++count < BGP_WRITE_PACKET_MAX &&
771 (s = bgp_write_packet (peer)) != NULL);
paul718e3742002-12-13 20:15:29 +0000772
773 if (bgp_write_proceed (peer))
pauleb821182004-05-01 08:44:08 +0000774 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
Stephen Hemminger3a69f742013-01-11 18:27:23 +0000775
776 done:
777 sockopt_cork (peer->fd, 0);
paul718e3742002-12-13 20:15:29 +0000778 return 0;
779}
780
781/* This is only for sending NOTIFICATION message to neighbor. */
paul94f2b392005-06-28 12:44:16 +0000782static int
paul718e3742002-12-13 20:15:29 +0000783bgp_write_notify (struct peer *peer)
784{
Stephen Hemminger35398582010-08-05 10:26:23 -0700785 int ret, val;
paul718e3742002-12-13 20:15:29 +0000786 u_char type;
787 struct stream *s;
788
789 /* There should be at least one packet. */
790 s = stream_fifo_head (peer->obuf);
791 if (!s)
792 return 0;
793 assert (stream_get_endp (s) >= BGP_HEADER_SIZE);
794
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000795 /* Stop collecting data within the socket */
796 sockopt_cork (peer->fd, 0);
797
David Lamparter8ff202e2013-07-31 14:39:41 +0200798 /* socket is in nonblocking mode, if we can't deliver the NOTIFY, well,
799 * we only care about getting a clean shutdown at this point. */
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000800 ret = write (peer->fd, STREAM_DATA (s), stream_get_endp (s));
David Lamparter8ff202e2013-07-31 14:39:41 +0200801
802 /* only connection reset/close gets counted as TCP_fatal_error, failure
803 * to write the entire NOTIFY doesn't get different FSM treatment */
paul718e3742002-12-13 20:15:29 +0000804 if (ret <= 0)
805 {
Paul Jakmadcdf3992006-10-15 23:39:59 +0000806 BGP_EVENT_ADD (peer, TCP_fatal_error);
paul718e3742002-12-13 20:15:29 +0000807 return 0;
808 }
809
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000810 /* Disable Nagle, make NOTIFY packet go out right away */
811 val = 1;
812 (void) setsockopt (peer->fd, IPPROTO_TCP, TCP_NODELAY,
813 (char *) &val, sizeof (val));
814
paul718e3742002-12-13 20:15:29 +0000815 /* Retrieve BGP packet type. */
816 stream_set_getp (s, BGP_MARKER_SIZE + 2);
817 type = stream_getc (s);
818
819 assert (type == BGP_MSG_NOTIFY);
820
821 /* Type should be notify. */
822 peer->notify_out++;
823
824 /* Double start timer. */
825 peer->v_start *= 2;
826
827 /* Overflow check. */
828 if (peer->v_start >= (60 * 2))
829 peer->v_start = (60 * 2);
830
Paul Jakmadcdf3992006-10-15 23:39:59 +0000831 BGP_EVENT_ADD (peer, BGP_Stop);
paul718e3742002-12-13 20:15:29 +0000832
833 return 0;
834}
835
836/* Make keepalive packet and send it to the peer. */
837void
838bgp_keepalive_send (struct peer *peer)
839{
840 struct stream *s;
841 int length;
842
843 s = stream_new (BGP_MAX_PACKET_SIZE);
844
845 /* Make keepalive packet. */
846 bgp_packet_set_marker (s, BGP_MSG_KEEPALIVE);
847
848 /* Set packet size. */
849 length = bgp_packet_set_size (s);
850
851 /* Dump packet if debug option is set. */
852 /* bgp_packet_dump (s); */
853
854 if (BGP_DEBUG (keepalive, KEEPALIVE))
ajs6b514742004-12-08 21:03:23 +0000855 zlog_debug ("%s sending KEEPALIVE", peer->host);
paul718e3742002-12-13 20:15:29 +0000856 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000857 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000858 peer->host, BGP_MSG_KEEPALIVE, length);
859
860 /* Add packet to the peer. */
861 bgp_packet_add (peer, s);
862
pauleb821182004-05-01 08:44:08 +0000863 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000864}
865
866/* Make open packet and send it to the peer. */
867void
868bgp_open_send (struct peer *peer)
869{
870 struct stream *s;
871 int length;
872 u_int16_t send_holdtime;
873 as_t local_as;
874
875 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
876 send_holdtime = peer->holdtime;
877 else
878 send_holdtime = peer->bgp->default_holdtime;
879
880 /* local-as Change */
881 if (peer->change_local_as)
882 local_as = peer->change_local_as;
883 else
884 local_as = peer->local_as;
885
886 s = stream_new (BGP_MAX_PACKET_SIZE);
887
888 /* Make open packet. */
889 bgp_packet_set_marker (s, BGP_MSG_OPEN);
890
891 /* Set open packet values. */
892 stream_putc (s, BGP_VERSION_4); /* BGP version */
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000893 stream_putw (s, (local_as <= BGP_AS_MAX) ? (u_int16_t) local_as
894 : BGP_AS_TRANS);
paul718e3742002-12-13 20:15:29 +0000895 stream_putw (s, send_holdtime); /* Hold Time */
896 stream_put_in_addr (s, &peer->local_id); /* BGP Identifier */
897
898 /* Set capability code. */
899 bgp_open_capability (s, peer);
900
901 /* Set BGP packet length. */
902 length = bgp_packet_set_size (s);
903
904 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +0400905 zlog_debug ("%s sending OPEN, version %d, my as %u, holdtime %d, id %s",
paul718e3742002-12-13 20:15:29 +0000906 peer->host, BGP_VERSION_4, local_as,
907 send_holdtime, inet_ntoa (peer->local_id));
908
909 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000910 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000911 peer->host, BGP_MSG_OPEN, length);
912
913 /* Dump packet if debug option is set. */
914 /* bgp_packet_dump (s); */
915
916 /* Add packet to the peer. */
917 bgp_packet_add (peer, s);
918
pauleb821182004-05-01 08:44:08 +0000919 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000920}
921
922/* Send BGP notify packet with data potion. */
923void
924bgp_notify_send_with_data (struct peer *peer, u_char code, u_char sub_code,
925 u_char *data, size_t datalen)
926{
927 struct stream *s;
928 int length;
929
930 /* Allocate new stream. */
931 s = stream_new (BGP_MAX_PACKET_SIZE);
932
933 /* Make nitify packet. */
934 bgp_packet_set_marker (s, BGP_MSG_NOTIFY);
935
936 /* Set notify packet values. */
937 stream_putc (s, code); /* BGP notify code */
938 stream_putc (s, sub_code); /* BGP notify sub_code */
939
940 /* If notify data is present. */
941 if (data)
942 stream_write (s, data, datalen);
943
944 /* Set BGP packet length. */
945 length = bgp_packet_set_size (s);
946
947 /* Add packet to the peer. */
948 stream_fifo_clean (peer->obuf);
949 bgp_packet_add (peer, s);
950
951 /* For debug */
952 {
953 struct bgp_notify bgp_notify;
954 int first = 0;
955 int i;
956 char c[4];
957
958 bgp_notify.code = code;
959 bgp_notify.subcode = sub_code;
960 bgp_notify.data = NULL;
961 bgp_notify.length = length - BGP_MSG_NOTIFY_MIN_SIZE;
962
963 if (bgp_notify.length)
964 {
965 bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
966 for (i = 0; i < bgp_notify.length; i++)
967 if (first)
968 {
969 sprintf (c, " %02x", data[i]);
970 strcat (bgp_notify.data, c);
971 }
972 else
973 {
974 first = 1;
975 sprintf (c, "%02x", data[i]);
976 strcpy (bgp_notify.data, c);
977 }
978 }
979 bgp_notify_print (peer, &bgp_notify, "sending");
980 if (bgp_notify.data)
981 XFREE (MTYPE_TMP, bgp_notify.data);
982 }
983
984 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000985 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000986 peer->host, BGP_MSG_NOTIFY, length);
987
hassoe0701b72004-05-20 09:19:34 +0000988 /* peer reset cause */
989 if (sub_code != BGP_NOTIFY_CEASE_CONFIG_CHANGE)
990 {
991 if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET)
heasley1212dc12011-09-12 13:27:52 +0400992 {
993 peer->last_reset = PEER_DOWN_USER_RESET;
994 zlog_info ("Notification sent to neighbor %s: User reset", peer->host);
995 }
hassoe0701b72004-05-20 09:19:34 +0000996 else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN)
heasley1212dc12011-09-12 13:27:52 +0400997 {
998 peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
999 zlog_info ("Notification sent to neighbor %s: shutdown", peer->host);
1000 }
hassoe0701b72004-05-20 09:19:34 +00001001 else
heasley1212dc12011-09-12 13:27:52 +04001002 {
1003 peer->last_reset = PEER_DOWN_NOTIFY_SEND;
1004 zlog_info ("Notification sent to neighbor %s: type %u/%u",
1005 peer->host, code, sub_code);
1006 }
hassoe0701b72004-05-20 09:19:34 +00001007 }
heasley1212dc12011-09-12 13:27:52 +04001008 else
1009 zlog_info ("Notification sent to neighbor %s: configuration change",
1010 peer->host);
hassoe0701b72004-05-20 09:19:34 +00001011
Denis Ovsienko7ccf5e52011-09-10 16:53:30 +04001012 /* Call immediately. */
paul718e3742002-12-13 20:15:29 +00001013 BGP_WRITE_OFF (peer->t_write);
1014
1015 bgp_write_notify (peer);
1016}
1017
1018/* Send BGP notify packet. */
1019void
1020bgp_notify_send (struct peer *peer, u_char code, u_char sub_code)
1021{
1022 bgp_notify_send_with_data (peer, code, sub_code, NULL, 0);
1023}
1024
paul718e3742002-12-13 20:15:29 +00001025/* Send route refresh message to the peer. */
1026void
1027bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
1028 u_char orf_type, u_char when_to_refresh, int remove)
1029{
1030 struct stream *s;
1031 struct stream *packet;
1032 int length;
1033 struct bgp_filter *filter;
1034 int orf_refresh = 0;
1035
Paul Jakma750e8142008-07-22 21:11:48 +00001036 if (DISABLE_BGP_ANNOUNCE)
1037 return;
paul718e3742002-12-13 20:15:29 +00001038
1039 filter = &peer->filter[afi][safi];
1040
1041 /* Adjust safi code. */
1042 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001043 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +00001044
1045 s = stream_new (BGP_MAX_PACKET_SIZE);
1046
1047 /* Make BGP update packet. */
1048 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
1049 bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_NEW);
1050 else
1051 bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_OLD);
1052
1053 /* Encode Route Refresh message. */
1054 stream_putw (s, afi);
1055 stream_putc (s, 0);
1056 stream_putc (s, safi);
1057
1058 if (orf_type == ORF_TYPE_PREFIX
1059 || orf_type == ORF_TYPE_PREFIX_OLD)
1060 if (remove || filter->plist[FILTER_IN].plist)
1061 {
1062 u_int16_t orf_len;
1063 unsigned long orfp;
1064
1065 orf_refresh = 1;
1066 stream_putc (s, when_to_refresh);
1067 stream_putc (s, orf_type);
paul9985f832005-02-09 15:51:56 +00001068 orfp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00001069 stream_putw (s, 0);
1070
1071 if (remove)
1072 {
1073 UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
1074 stream_putc (s, ORF_COMMON_PART_REMOVE_ALL);
1075 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001076 zlog_debug ("%s sending REFRESH_REQ to remove ORF(%d) (%s) for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001077 peer->host, orf_type,
1078 (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
1079 afi, safi);
1080 }
1081 else
1082 {
1083 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
1084 prefix_bgp_orf_entry (s, filter->plist[FILTER_IN].plist,
1085 ORF_COMMON_PART_ADD, ORF_COMMON_PART_PERMIT,
1086 ORF_COMMON_PART_DENY);
1087 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001088 zlog_debug ("%s sending REFRESH_REQ with pfxlist ORF(%d) (%s) for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001089 peer->host, orf_type,
1090 (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
1091 afi, safi);
1092 }
1093
1094 /* Total ORF Entry Len. */
paul9985f832005-02-09 15:51:56 +00001095 orf_len = stream_get_endp (s) - orfp - 2;
paul718e3742002-12-13 20:15:29 +00001096 stream_putw_at (s, orfp, orf_len);
1097 }
1098
1099 /* Set packet size. */
1100 length = bgp_packet_set_size (s);
1101
1102 if (BGP_DEBUG (normal, NORMAL))
1103 {
1104 if (! orf_refresh)
ajs6b514742004-12-08 21:03:23 +00001105 zlog_debug ("%s sending REFRESH_REQ for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001106 peer->host, afi, safi);
ajs6b514742004-12-08 21:03:23 +00001107 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +00001108 peer->host, CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV) ?
1109 BGP_MSG_ROUTE_REFRESH_NEW : BGP_MSG_ROUTE_REFRESH_OLD, length);
1110 }
1111
1112 /* Make real packet. */
paule83e2082005-05-19 02:12:25 +00001113 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +00001114 stream_free (s);
1115
1116 /* Add packet to the peer. */
1117 bgp_packet_add (peer, packet);
1118
pauleb821182004-05-01 08:44:08 +00001119 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +00001120}
1121
1122/* Send capability message to the peer. */
1123void
1124bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi,
1125 int capability_code, int action)
1126{
1127 struct stream *s;
1128 struct stream *packet;
1129 int length;
1130
1131 /* Adjust safi code. */
1132 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001133 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +00001134
1135 s = stream_new (BGP_MAX_PACKET_SIZE);
1136
1137 /* Make BGP update packet. */
1138 bgp_packet_set_marker (s, BGP_MSG_CAPABILITY);
1139
1140 /* Encode MP_EXT capability. */
1141 if (capability_code == CAPABILITY_CODE_MP)
1142 {
1143 stream_putc (s, action);
1144 stream_putc (s, CAPABILITY_CODE_MP);
1145 stream_putc (s, CAPABILITY_CODE_MP_LEN);
1146 stream_putw (s, afi);
1147 stream_putc (s, 0);
1148 stream_putc (s, safi);
1149
1150 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001151 zlog_debug ("%s sending CAPABILITY has %s MP_EXT CAP for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001152 peer->host, action == CAPABILITY_ACTION_SET ?
1153 "Advertising" : "Removing", afi, safi);
1154 }
1155
paul718e3742002-12-13 20:15:29 +00001156 /* Set packet size. */
1157 length = bgp_packet_set_size (s);
1158
1159 /* Make real packet. */
paule83e2082005-05-19 02:12:25 +00001160 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +00001161 stream_free (s);
1162
1163 /* Add packet to the peer. */
1164 bgp_packet_add (peer, packet);
1165
1166 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001167 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +00001168 peer->host, BGP_MSG_CAPABILITY, length);
1169
pauleb821182004-05-01 08:44:08 +00001170 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +00001171}
David Lamparter6b0655a2014-06-04 06:53:35 +02001172
paul718e3742002-12-13 20:15:29 +00001173/* RFC1771 6.8 Connection collision detection. */
paul94f2b392005-06-28 12:44:16 +00001174static int
pauleb821182004-05-01 08:44:08 +00001175bgp_collision_detect (struct peer *new, struct in_addr remote_id)
paul718e3742002-12-13 20:15:29 +00001176{
pauleb821182004-05-01 08:44:08 +00001177 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001178 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001179 struct bgp *bgp;
1180
1181 bgp = bgp_get_default ();
1182 if (! bgp)
1183 return 0;
1184
1185 /* Upon receipt of an OPEN message, the local system must examine
1186 all of its connections that are in the OpenConfirm state. A BGP
1187 speaker may also examine connections in an OpenSent state if it
1188 knows the BGP Identifier of the peer by means outside of the
1189 protocol. If among these connections there is a connection to a
1190 remote BGP speaker whose BGP Identifier equals the one in the
1191 OPEN message, then the local system performs the following
1192 collision resolution procedure: */
1193
paul1eb8ef22005-04-07 07:30:20 +00001194 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001195 {
1196 /* Under OpenConfirm status, local peer structure already hold
1197 remote router ID. */
pauleb821182004-05-01 08:44:08 +00001198
1199 if (peer != new
1200 && (peer->status == OpenConfirm || peer->status == OpenSent)
1201 && sockunion_same (&peer->su, &new->su))
1202 {
paul718e3742002-12-13 20:15:29 +00001203 /* 1. The BGP Identifier of the local system is compared to
1204 the BGP Identifier of the remote system (as specified in
1205 the OPEN message). */
1206
1207 if (ntohl (peer->local_id.s_addr) < ntohl (remote_id.s_addr))
1208 {
1209 /* 2. If the value of the local BGP Identifier is less
1210 than the remote one, the local system closes BGP
1211 connection that already exists (the one that is
1212 already in the OpenConfirm state), and accepts BGP
1213 connection initiated by the remote system. */
1214
pauleb821182004-05-01 08:44:08 +00001215 if (peer->fd >= 0)
hassoe0701b72004-05-20 09:19:34 +00001216 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
paul718e3742002-12-13 20:15:29 +00001217 return 1;
1218 }
1219 else
1220 {
1221 /* 3. Otherwise, the local system closes newly created
1222 BGP connection (the one associated with the newly
1223 received OPEN message), and continues to use the
1224 existing one (the one that is already in the
1225 OpenConfirm state). */
1226
pauleb821182004-05-01 08:44:08 +00001227 if (new->fd >= 0)
paulf5ba3872004-07-09 12:11:31 +00001228 bgp_notify_send (new, BGP_NOTIFY_CEASE,
1229 BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
paul718e3742002-12-13 20:15:29 +00001230 return -1;
1231 }
pauleb821182004-05-01 08:44:08 +00001232 }
1233 }
paul718e3742002-12-13 20:15:29 +00001234 return 0;
1235}
1236
paul94f2b392005-06-28 12:44:16 +00001237static int
paul718e3742002-12-13 20:15:29 +00001238bgp_open_receive (struct peer *peer, bgp_size_t size)
1239{
1240 int ret;
1241 u_char version;
1242 u_char optlen;
1243 u_int16_t holdtime;
1244 u_int16_t send_holdtime;
1245 as_t remote_as;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001246 as_t as4 = 0;
paul718e3742002-12-13 20:15:29 +00001247 struct peer *realpeer;
1248 struct in_addr remote_id;
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001249 int mp_capability;
paul5228ad22004-06-04 17:58:18 +00001250 u_int8_t notify_data_remote_as[2];
1251 u_int8_t notify_data_remote_id[4];
paul718e3742002-12-13 20:15:29 +00001252
1253 realpeer = NULL;
1254
1255 /* Parse open packet. */
1256 version = stream_getc (peer->ibuf);
1257 memcpy (notify_data_remote_as, stream_pnt (peer->ibuf), 2);
1258 remote_as = stream_getw (peer->ibuf);
1259 holdtime = stream_getw (peer->ibuf);
1260 memcpy (notify_data_remote_id, stream_pnt (peer->ibuf), 4);
1261 remote_id.s_addr = stream_get_ipv4 (peer->ibuf);
1262
1263 /* Receive OPEN message log */
1264 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001265 zlog_debug ("%s rcv OPEN, version %d, remote-as (in open) %u,"
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001266 " holdtime %d, id %s",
1267 peer->host, version, remote_as, holdtime,
1268 inet_ntoa (remote_id));
1269
1270 /* BEGIN to read the capability here, but dont do it yet */
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001271 mp_capability = 0;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001272 optlen = stream_getc (peer->ibuf);
1273
1274 if (optlen != 0)
1275 {
1276 /* We need the as4 capability value *right now* because
1277 * if it is there, we have not got the remote_as yet, and without
1278 * that we do not know which peer is connecting to us now.
1279 */
1280 as4 = peek_for_as4_capability (peer, optlen);
1281 }
1282
1283 /* Just in case we have a silly peer who sends AS4 capability set to 0 */
1284 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) && !as4)
1285 {
1286 zlog_err ("%s bad OPEN, got AS4 capability, but AS4 set to 0",
1287 peer->host);
1288 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1289 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1290 return -1;
1291 }
1292
1293 if (remote_as == BGP_AS_TRANS)
1294 {
1295 /* Take the AS4 from the capability. We must have received the
1296 * capability now! Otherwise we have a asn16 peer who uses
1297 * BGP_AS_TRANS, for some unknown reason.
1298 */
1299 if (as4 == BGP_AS_TRANS)
1300 {
1301 zlog_err ("%s [AS4] NEW speaker using AS_TRANS for AS4, not allowed",
1302 peer->host);
1303 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1304 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1305 return -1;
1306 }
1307
1308 if (!as4 && BGP_DEBUG (as4, AS4))
1309 zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but no AS4."
1310 " Odd, but proceeding.", peer->host);
1311 else if (as4 < BGP_AS_MAX && BGP_DEBUG (as4, AS4))
Paul Jakma0df7c912008-07-21 21:02:49 +00001312 zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but AS4 (%u) fits "
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001313 "in 2-bytes, very odd peer.", peer->host, as4);
1314 if (as4)
1315 remote_as = as4;
1316 }
1317 else
1318 {
1319 /* We may have a partner with AS4 who has an asno < BGP_AS_MAX */
1320 /* If we have got the capability, peer->as4cap must match remote_as */
1321 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)
1322 && as4 != remote_as)
1323 {
1324 /* raise error, log this, close session */
1325 zlog_err ("%s bad OPEN, got AS4 capability, but remote_as %u"
1326 " mismatch with 16bit 'myasn' %u in open",
1327 peer->host, as4, remote_as);
1328 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1329 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1330 return -1;
1331 }
1332 }
1333
paul718e3742002-12-13 20:15:29 +00001334 /* Lookup peer from Open packet. */
1335 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1336 {
1337 int as = 0;
1338
1339 realpeer = peer_lookup_with_open (&peer->su, remote_as, &remote_id, &as);
1340
1341 if (! realpeer)
1342 {
1343 /* Peer's source IP address is check in bgp_accept(), so this
1344 must be AS number mismatch or remote-id configuration
1345 mismatch. */
1346 if (as)
1347 {
1348 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001349 zlog_debug ("%s bad OPEN, wrong router identifier %s",
1350 peer->host, inet_ntoa (remote_id));
1351 bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
1352 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
1353 notify_data_remote_id, 4);
paul718e3742002-12-13 20:15:29 +00001354 }
1355 else
1356 {
1357 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001358 zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
ajs6b514742004-12-08 21:03:23 +00001359 peer->host, remote_as, peer->as);
1360 bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
1361 BGP_NOTIFY_OPEN_BAD_PEER_AS,
1362 notify_data_remote_as, 2);
paul718e3742002-12-13 20:15:29 +00001363 }
1364 return -1;
1365 }
1366 }
1367
1368 /* When collision is detected and this peer is closed. Retrun
1369 immidiately. */
1370 ret = bgp_collision_detect (peer, remote_id);
1371 if (ret < 0)
1372 return ret;
1373
pauleb821182004-05-01 08:44:08 +00001374 /* Hack part. */
1375 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1376 {
hasso93406d82005-02-02 14:40:33 +00001377 if (realpeer->status == Established
1378 && CHECK_FLAG (realpeer->sflags, PEER_STATUS_NSF_MODE))
1379 {
1380 realpeer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
1381 SET_FLAG (realpeer->sflags, PEER_STATUS_NSF_WAIT);
1382 }
1383 else if (ret == 0 && realpeer->status != Active
1384 && realpeer->status != OpenSent
Paul Jakma6e199262008-09-09 17:14:33 +01001385 && realpeer->status != OpenConfirm
1386 && realpeer->status != Connect)
pauleb821182004-05-01 08:44:08 +00001387 {
Paul Jakma2b2fc562008-09-06 13:09:35 +01001388 /* XXX: This is an awful problem..
1389 *
1390 * According to the RFC we should just let this connection (of the
1391 * accepted 'peer') continue on to Established if the other
1392 * connection (the 'realpeer' one) is in state Connect, and deal
1393 * with the more larval FSM as/when it gets far enough to receive
1394 * an Open. We don't do that though, we instead close the (more
1395 * developed) accepted connection.
1396 *
1397 * This means there's a race, which if hit, can loop:
1398 *
1399 * FSM for A FSM for B
1400 * realpeer accept-peer realpeer accept-peer
1401 *
1402 * Connect Connect
1403 * Active
1404 * OpenSent OpenSent
1405 * <arrive here,
1406 * Notify, delete>
1407 * Idle Active
1408 * OpenSent OpenSent
1409 * <arrive here,
1410 * Notify, delete>
1411 * Idle
1412 * <wait> <wait>
1413 * Connect Connect
1414 *
1415 *
1416 * If both sides are Quagga, they're almost certain to wait for
1417 * the same amount of time of course (which doesn't preclude other
1418 * implementations also waiting for same time). The race is
1419 * exacerbated by high-latency (in bgpd and/or the network).
1420 *
1421 * The reason we do this is because our FSM is tied to our peer
1422 * structure, which carries our configuration information, etc.
1423 * I.e. we can't let the accepted-peer FSM continue on as it is,
1424 * cause it's not associated with any actual peer configuration -
1425 * it's just a dummy.
1426 *
1427 * It's possible we could hack-fix this by just bgp_stop'ing the
1428 * realpeer and continueing on with the 'transfer FSM' below.
1429 * Ideally, we need to seperate FSMs from struct peer.
1430 *
1431 * Setting one side to passive avoids the race, as a workaround.
1432 */
pauleb821182004-05-01 08:44:08 +00001433 if (BGP_DEBUG (events, EVENTS))
hasso93406d82005-02-02 14:40:33 +00001434 zlog_debug ("%s peer status is %s close connection",
1435 realpeer->host, LOOKUP (bgp_status_msg,
1436 realpeer->status));
1437 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1438 BGP_NOTIFY_CEASE_CONNECT_REJECT);
1439
pauleb821182004-05-01 08:44:08 +00001440 return -1;
1441 }
1442
1443 if (BGP_DEBUG (events, EVENTS))
Paul Jakma6e199262008-09-09 17:14:33 +01001444 zlog_debug ("%s [Event] Transfer accept BGP peer to real (state %s)",
1445 peer->host,
1446 LOOKUP (bgp_status_msg, realpeer->status));
pauleb821182004-05-01 08:44:08 +00001447
1448 bgp_stop (realpeer);
1449
1450 /* Transfer file descriptor. */
1451 realpeer->fd = peer->fd;
1452 peer->fd = -1;
1453
1454 /* Transfer input buffer. */
1455 stream_free (realpeer->ibuf);
1456 realpeer->ibuf = peer->ibuf;
1457 realpeer->packet_size = peer->packet_size;
1458 peer->ibuf = NULL;
1459
1460 /* Transfer status. */
1461 realpeer->status = peer->status;
1462 bgp_stop (peer);
paul200df112005-06-01 11:17:05 +00001463
pauleb821182004-05-01 08:44:08 +00001464 /* peer pointer change. Open packet send to neighbor. */
1465 peer = realpeer;
1466 bgp_open_send (peer);
1467 if (peer->fd < 0)
1468 {
1469 zlog_err ("bgp_open_receive peer's fd is negative value %d",
1470 peer->fd);
1471 return -1;
1472 }
1473 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
1474 }
1475
paul718e3742002-12-13 20:15:29 +00001476 /* remote router-id check. */
1477 if (remote_id.s_addr == 0
Denis Ovsienko733cd9e2011-12-17 19:39:30 +04001478 || IPV4_CLASS_DE (ntohl (remote_id.s_addr))
paul718e3742002-12-13 20:15:29 +00001479 || ntohl (peer->local_id.s_addr) == ntohl (remote_id.s_addr))
1480 {
1481 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001482 zlog_debug ("%s bad OPEN, wrong router identifier %s",
paul718e3742002-12-13 20:15:29 +00001483 peer->host, inet_ntoa (remote_id));
1484 bgp_notify_send_with_data (peer,
1485 BGP_NOTIFY_OPEN_ERR,
1486 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
1487 notify_data_remote_id, 4);
1488 return -1;
1489 }
1490
1491 /* Set remote router-id */
1492 peer->remote_id = remote_id;
1493
1494 /* Peer BGP version check. */
1495 if (version != BGP_VERSION_4)
1496 {
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001497 u_int16_t maxver = htons(BGP_VERSION_4);
1498 /* XXX this reply may not be correct if version < 4 XXX */
paul718e3742002-12-13 20:15:29 +00001499 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001500 zlog_debug ("%s bad protocol version, remote requested %d, local request %d",
paul718e3742002-12-13 20:15:29 +00001501 peer->host, version, BGP_VERSION_4);
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001502 /* Data must be in network byte order here */
paul718e3742002-12-13 20:15:29 +00001503 bgp_notify_send_with_data (peer,
1504 BGP_NOTIFY_OPEN_ERR,
1505 BGP_NOTIFY_OPEN_UNSUP_VERSION,
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001506 (u_int8_t *) &maxver, 2);
paul718e3742002-12-13 20:15:29 +00001507 return -1;
1508 }
1509
1510 /* Check neighbor as number. */
1511 if (remote_as != peer->as)
1512 {
1513 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001514 zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
paul718e3742002-12-13 20:15:29 +00001515 peer->host, remote_as, peer->as);
1516 bgp_notify_send_with_data (peer,
1517 BGP_NOTIFY_OPEN_ERR,
1518 BGP_NOTIFY_OPEN_BAD_PEER_AS,
1519 notify_data_remote_as, 2);
1520 return -1;
1521 }
1522
1523 /* From the rfc: Upon receipt of an OPEN message, a BGP speaker MUST
1524 calculate the value of the Hold Timer by using the smaller of its
1525 configured Hold Time and the Hold Time received in the OPEN message.
1526 The Hold Time MUST be either zero or at least three seconds. An
1527 implementation may reject connections on the basis of the Hold Time. */
1528
1529 if (holdtime < 3 && holdtime != 0)
1530 {
1531 bgp_notify_send (peer,
1532 BGP_NOTIFY_OPEN_ERR,
1533 BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
1534 return -1;
1535 }
1536
1537 /* From the rfc: A reasonable maximum time between KEEPALIVE messages
1538 would be one third of the Hold Time interval. KEEPALIVE messages
1539 MUST NOT be sent more frequently than one per second. An
1540 implementation MAY adjust the rate at which it sends KEEPALIVE
1541 messages as a function of the Hold Time interval. */
1542
1543 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
1544 send_holdtime = peer->holdtime;
1545 else
1546 send_holdtime = peer->bgp->default_holdtime;
1547
1548 if (holdtime < send_holdtime)
1549 peer->v_holdtime = holdtime;
1550 else
1551 peer->v_holdtime = send_holdtime;
1552
1553 peer->v_keepalive = peer->v_holdtime / 3;
1554
1555 /* Open option part parse. */
paul718e3742002-12-13 20:15:29 +00001556 if (optlen != 0)
1557 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001558 if ((ret = bgp_open_option_parse (peer, optlen, &mp_capability)) < 0)
Paul Jakma58617392012-01-09 20:59:26 +00001559 {
1560 bgp_notify_send (peer,
1561 BGP_NOTIFY_OPEN_ERR,
1562 BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
1563 return ret;
1564 }
paul718e3742002-12-13 20:15:29 +00001565 }
1566 else
1567 {
1568 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001569 zlog_debug ("%s rcvd OPEN w/ OPTION parameter len: 0",
paul718e3742002-12-13 20:15:29 +00001570 peer->host);
1571 }
1572
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001573 /*
1574 * Assume that the peer supports the locally configured set of
1575 * AFI/SAFIs if the peer did not send us any Mulitiprotocol
1576 * capabilities, or if 'override-capability' is configured.
1577 */
1578 if (! mp_capability ||
1579 CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
paul718e3742002-12-13 20:15:29 +00001580 {
1581 peer->afc_nego[AFI_IP][SAFI_UNICAST] = peer->afc[AFI_IP][SAFI_UNICAST];
1582 peer->afc_nego[AFI_IP][SAFI_MULTICAST] = peer->afc[AFI_IP][SAFI_MULTICAST];
1583 peer->afc_nego[AFI_IP6][SAFI_UNICAST] = peer->afc[AFI_IP6][SAFI_UNICAST];
1584 peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = peer->afc[AFI_IP6][SAFI_MULTICAST];
1585 }
1586
1587 /* Get sockname. */
1588 bgp_getsockname (peer);
1589
1590 BGP_EVENT_ADD (peer, Receive_OPEN_message);
1591
1592 peer->packet_size = 0;
1593 if (peer->ibuf)
1594 stream_reset (peer->ibuf);
1595
1596 return 0;
1597}
1598
1599/* Parse BGP Update packet and make attribute object. */
paul94f2b392005-06-28 12:44:16 +00001600static int
paul718e3742002-12-13 20:15:29 +00001601bgp_update_receive (struct peer *peer, bgp_size_t size)
1602{
1603 int ret;
1604 u_char *end;
1605 struct stream *s;
1606 struct attr attr;
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001607 struct attr_extra extra;
paul718e3742002-12-13 20:15:29 +00001608 bgp_size_t attribute_len;
1609 bgp_size_t update_len;
1610 bgp_size_t withdraw_len;
1611 struct bgp_nlri update;
1612 struct bgp_nlri withdraw;
1613 struct bgp_nlri mp_update;
1614 struct bgp_nlri mp_withdraw;
paul718e3742002-12-13 20:15:29 +00001615
1616 /* Status must be Established. */
1617 if (peer->status != Established)
1618 {
1619 zlog_err ("%s [FSM] Update packet received under status %s",
1620 peer->host, LOOKUP (bgp_status_msg, peer->status));
1621 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
1622 return -1;
1623 }
1624
1625 /* Set initial values. */
1626 memset (&attr, 0, sizeof (struct attr));
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001627 memset (&extra, 0, sizeof (struct attr_extra));
paul718e3742002-12-13 20:15:29 +00001628 memset (&update, 0, sizeof (struct bgp_nlri));
1629 memset (&withdraw, 0, sizeof (struct bgp_nlri));
1630 memset (&mp_update, 0, sizeof (struct bgp_nlri));
1631 memset (&mp_withdraw, 0, sizeof (struct bgp_nlri));
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001632 attr.extra = &extra;
paul718e3742002-12-13 20:15:29 +00001633
1634 s = peer->ibuf;
1635 end = stream_pnt (s) + size;
1636
1637 /* RFC1771 6.3 If the Unfeasible Routes Length or Total Attribute
1638 Length is too large (i.e., if Unfeasible Routes Length + Total
1639 Attribute Length + 23 exceeds the message Length), then the Error
1640 Subcode is set to Malformed Attribute List. */
1641 if (stream_pnt (s) + 2 > end)
1642 {
1643 zlog_err ("%s [Error] Update packet error"
1644 " (packet length is short for unfeasible length)",
1645 peer->host);
1646 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1647 BGP_NOTIFY_UPDATE_MAL_ATTR);
1648 return -1;
1649 }
1650
1651 /* Unfeasible Route Length. */
1652 withdraw_len = stream_getw (s);
1653
1654 /* Unfeasible Route Length check. */
1655 if (stream_pnt (s) + withdraw_len > end)
1656 {
1657 zlog_err ("%s [Error] Update packet error"
1658 " (packet unfeasible length overflow %d)",
1659 peer->host, withdraw_len);
1660 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1661 BGP_NOTIFY_UPDATE_MAL_ATTR);
1662 return -1;
1663 }
1664
1665 /* Unfeasible Route packet format check. */
1666 if (withdraw_len > 0)
1667 {
1668 ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), withdraw_len);
1669 if (ret < 0)
1670 return -1;
1671
1672 if (BGP_DEBUG (packet, PACKET_RECV))
ajs6b514742004-12-08 21:03:23 +00001673 zlog_debug ("%s [Update:RECV] Unfeasible NLRI received", peer->host);
paul718e3742002-12-13 20:15:29 +00001674
1675 withdraw.afi = AFI_IP;
1676 withdraw.safi = SAFI_UNICAST;
1677 withdraw.nlri = stream_pnt (s);
1678 withdraw.length = withdraw_len;
paul9985f832005-02-09 15:51:56 +00001679 stream_forward_getp (s, withdraw_len);
paul718e3742002-12-13 20:15:29 +00001680 }
1681
1682 /* Attribute total length check. */
1683 if (stream_pnt (s) + 2 > end)
1684 {
1685 zlog_warn ("%s [Error] Packet Error"
1686 " (update packet is short for attribute length)",
1687 peer->host);
1688 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1689 BGP_NOTIFY_UPDATE_MAL_ATTR);
1690 return -1;
1691 }
1692
1693 /* Fetch attribute total length. */
1694 attribute_len = stream_getw (s);
1695
1696 /* Attribute length check. */
1697 if (stream_pnt (s) + attribute_len > end)
1698 {
1699 zlog_warn ("%s [Error] Packet Error"
1700 " (update packet attribute length overflow %d)",
1701 peer->host, attribute_len);
1702 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1703 BGP_NOTIFY_UPDATE_MAL_ATTR);
1704 return -1;
1705 }
Paul Jakmab881c702010-11-23 16:35:42 +00001706
1707 /* Certain attribute parsing errors should not be considered bad enough
1708 * to reset the session for, most particularly any partial/optional
1709 * attributes that have 'tunneled' over speakers that don't understand
1710 * them. Instead we withdraw only the prefix concerned.
1711 *
1712 * Complicates the flow a little though..
1713 */
1714 bgp_attr_parse_ret_t attr_parse_ret = BGP_ATTR_PARSE_PROCEED;
1715 /* This define morphs the update case into a withdraw when lower levels
1716 * have signalled an error condition where this is best.
1717 */
1718#define NLRI_ATTR_ARG (attr_parse_ret != BGP_ATTR_PARSE_WITHDRAW ? &attr : NULL)
paul718e3742002-12-13 20:15:29 +00001719
1720 /* Parse attribute when it exists. */
1721 if (attribute_len)
1722 {
Paul Jakmab881c702010-11-23 16:35:42 +00001723 attr_parse_ret = bgp_attr_parse (peer, &attr, attribute_len,
paul718e3742002-12-13 20:15:29 +00001724 &mp_update, &mp_withdraw);
Paul Jakmab881c702010-11-23 16:35:42 +00001725 if (attr_parse_ret == BGP_ATTR_PARSE_ERROR)
David Lamparterf80f8382014-06-04 01:00:51 +02001726 {
1727 bgp_attr_unintern_sub (&attr);
1728 return -1;
1729 }
paul718e3742002-12-13 20:15:29 +00001730 }
Paul Jakmab881c702010-11-23 16:35:42 +00001731
paul718e3742002-12-13 20:15:29 +00001732 /* Logging the attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001733 if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW
1734 || BGP_DEBUG (update, UPDATE_IN))
paul718e3742002-12-13 20:15:29 +00001735 {
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +00001736 char attrstr[BUFSIZ];
1737 attrstr[0] = '\0';
1738
paule01f9cb2004-07-09 17:48:53 +00001739 ret= bgp_dump_attr (peer, &attr, attrstr, BUFSIZ);
Paul Jakmab881c702010-11-23 16:35:42 +00001740 int lvl = (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
1741 ? LOG_ERR : LOG_DEBUG;
1742
1743 if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
1744 zlog (peer->log, LOG_ERR,
1745 "%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.",
1746 peer->host);
paule01f9cb2004-07-09 17:48:53 +00001747
1748 if (ret)
Paul Jakmab881c702010-11-23 16:35:42 +00001749 zlog (peer->log, lvl, "%s rcvd UPDATE w/ attr: %s",
paule01f9cb2004-07-09 17:48:53 +00001750 peer->host, attrstr);
paul718e3742002-12-13 20:15:29 +00001751 }
Paul Jakmab881c702010-11-23 16:35:42 +00001752
paul718e3742002-12-13 20:15:29 +00001753 /* Network Layer Reachability Information. */
1754 update_len = end - stream_pnt (s);
1755
1756 if (update_len)
1757 {
1758 /* Check NLRI packet format and prefix length. */
1759 ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), update_len);
1760 if (ret < 0)
Paul Jakmab881c702010-11-23 16:35:42 +00001761 {
1762 bgp_attr_unintern_sub (&attr);
Paul Jakmab881c702010-11-23 16:35:42 +00001763 return -1;
1764 }
paul718e3742002-12-13 20:15:29 +00001765
1766 /* Set NLRI portion to structure. */
1767 update.afi = AFI_IP;
1768 update.safi = SAFI_UNICAST;
1769 update.nlri = stream_pnt (s);
1770 update.length = update_len;
paul9985f832005-02-09 15:51:56 +00001771 stream_forward_getp (s, update_len);
paul718e3742002-12-13 20:15:29 +00001772 }
1773
1774 /* NLRI is processed only when the peer is configured specific
1775 Address Family and Subsequent Address Family. */
1776 if (peer->afc[AFI_IP][SAFI_UNICAST])
1777 {
1778 if (withdraw.length)
1779 bgp_nlri_parse (peer, NULL, &withdraw);
1780
1781 if (update.length)
Paul Jakmab881c702010-11-23 16:35:42 +00001782 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &update);
paule01f9cb2004-07-09 17:48:53 +00001783
hassof4184462005-02-01 20:13:16 +00001784 if (mp_update.length
1785 && mp_update.afi == AFI_IP
1786 && mp_update.safi == SAFI_UNICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001787 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
hassof4184462005-02-01 20:13:16 +00001788
1789 if (mp_withdraw.length
1790 && mp_withdraw.afi == AFI_IP
1791 && mp_withdraw.safi == SAFI_UNICAST)
1792 bgp_nlri_parse (peer, NULL, &mp_withdraw);
1793
paule01f9cb2004-07-09 17:48:53 +00001794 if (! attribute_len && ! withdraw_len)
1795 {
1796 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001797 SET_FLAG (peer->af_sflags[AFI_IP][SAFI_UNICAST],
1798 PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001799
hasso93406d82005-02-02 14:40:33 +00001800 /* NSF delete stale route */
1801 if (peer->nsf[AFI_IP][SAFI_UNICAST])
1802 bgp_clear_stale_route (peer, AFI_IP, SAFI_UNICAST);
1803
1804 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001805 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001806 peer->host);
1807 }
paul718e3742002-12-13 20:15:29 +00001808 }
1809 if (peer->afc[AFI_IP][SAFI_MULTICAST])
1810 {
1811 if (mp_update.length
1812 && mp_update.afi == AFI_IP
1813 && mp_update.safi == SAFI_MULTICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001814 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001815
1816 if (mp_withdraw.length
1817 && mp_withdraw.afi == AFI_IP
1818 && mp_withdraw.safi == SAFI_MULTICAST)
1819 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001820
hasso93406d82005-02-02 14:40:33 +00001821 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001822 && mp_withdraw.afi == AFI_IP
1823 && mp_withdraw.safi == SAFI_MULTICAST
1824 && mp_withdraw.length == 0)
1825 {
1826 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001827 SET_FLAG (peer->af_sflags[AFI_IP][SAFI_MULTICAST],
1828 PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001829
hasso93406d82005-02-02 14:40:33 +00001830 /* NSF delete stale route */
1831 if (peer->nsf[AFI_IP][SAFI_MULTICAST])
1832 bgp_clear_stale_route (peer, AFI_IP, SAFI_MULTICAST);
1833
1834 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001835 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Multicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001836 peer->host);
1837 }
paul718e3742002-12-13 20:15:29 +00001838 }
1839 if (peer->afc[AFI_IP6][SAFI_UNICAST])
1840 {
1841 if (mp_update.length
1842 && mp_update.afi == AFI_IP6
1843 && mp_update.safi == SAFI_UNICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001844 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001845
1846 if (mp_withdraw.length
1847 && mp_withdraw.afi == AFI_IP6
1848 && mp_withdraw.safi == SAFI_UNICAST)
1849 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001850
hasso93406d82005-02-02 14:40:33 +00001851 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001852 && mp_withdraw.afi == AFI_IP6
1853 && mp_withdraw.safi == SAFI_UNICAST
1854 && mp_withdraw.length == 0)
1855 {
1856 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001857 SET_FLAG (peer->af_sflags[AFI_IP6][SAFI_UNICAST], PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001858
hasso93406d82005-02-02 14:40:33 +00001859 /* NSF delete stale route */
1860 if (peer->nsf[AFI_IP6][SAFI_UNICAST])
1861 bgp_clear_stale_route (peer, AFI_IP6, SAFI_UNICAST);
1862
1863 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001864 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001865 peer->host);
1866 }
paul718e3742002-12-13 20:15:29 +00001867 }
1868 if (peer->afc[AFI_IP6][SAFI_MULTICAST])
1869 {
1870 if (mp_update.length
1871 && mp_update.afi == AFI_IP6
1872 && mp_update.safi == SAFI_MULTICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001873 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001874
1875 if (mp_withdraw.length
1876 && mp_withdraw.afi == AFI_IP6
1877 && mp_withdraw.safi == SAFI_MULTICAST)
1878 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001879
hasso93406d82005-02-02 14:40:33 +00001880 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001881 && mp_withdraw.afi == AFI_IP6
1882 && mp_withdraw.safi == SAFI_MULTICAST
1883 && mp_withdraw.length == 0)
1884 {
1885 /* End-of-RIB received */
1886
hasso93406d82005-02-02 14:40:33 +00001887 /* NSF delete stale route */
1888 if (peer->nsf[AFI_IP6][SAFI_MULTICAST])
1889 bgp_clear_stale_route (peer, AFI_IP6, SAFI_MULTICAST);
1890
paule01f9cb2004-07-09 17:48:53 +00001891 if (BGP_DEBUG (update, UPDATE_IN))
ajs6b514742004-12-08 21:03:23 +00001892 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Multicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001893 peer->host);
1894 }
paul718e3742002-12-13 20:15:29 +00001895 }
1896 if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
1897 {
1898 if (mp_update.length
1899 && mp_update.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001900 && mp_update.safi == SAFI_MPLS_LABELED_VPN)
Paul Jakmab881c702010-11-23 16:35:42 +00001901 bgp_nlri_parse_vpnv4 (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001902
1903 if (mp_withdraw.length
1904 && mp_withdraw.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001905 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00001906 bgp_nlri_parse_vpnv4 (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001907
hasso93406d82005-02-02 14:40:33 +00001908 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001909 && mp_withdraw.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001910 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN
paule01f9cb2004-07-09 17:48:53 +00001911 && mp_withdraw.length == 0)
1912 {
1913 /* End-of-RIB received */
1914
1915 if (BGP_DEBUG (update, UPDATE_IN))
ajs6b514742004-12-08 21:03:23 +00001916 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for VPNv4 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001917 peer->host);
1918 }
paul718e3742002-12-13 20:15:29 +00001919 }
1920
1921 /* Everything is done. We unintern temporary structures which
1922 interned in bgp_attr_parse(). */
Paul Jakmab881c702010-11-23 16:35:42 +00001923 bgp_attr_unintern_sub (&attr);
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001924
paul718e3742002-12-13 20:15:29 +00001925 /* If peering is stopped due to some reason, do not generate BGP
1926 event. */
1927 if (peer->status != Established)
1928 return 0;
1929
1930 /* Increment packet counter. */
1931 peer->update_in++;
Stephen Hemminger65957882010-01-15 16:22:10 +03001932 peer->update_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00001933
Jorge Boncompte [DTI2]e2c38e62012-06-20 17:45:50 +02001934 /* Rearm holdtime timer */
Jorge Boncompte [DTI2]6a4677b2012-05-07 16:53:07 +00001935 BGP_TIMER_OFF (peer->t_holdtime);
Jorge Boncompte [DTI2]e2c38e62012-06-20 17:45:50 +02001936 bgp_timer_set (peer);
paul718e3742002-12-13 20:15:29 +00001937
1938 return 0;
1939}
1940
1941/* Notify message treatment function. */
paul94f2b392005-06-28 12:44:16 +00001942static void
paul718e3742002-12-13 20:15:29 +00001943bgp_notify_receive (struct peer *peer, bgp_size_t size)
1944{
1945 struct bgp_notify bgp_notify;
1946
1947 if (peer->notify.data)
1948 {
1949 XFREE (MTYPE_TMP, peer->notify.data);
1950 peer->notify.data = NULL;
1951 peer->notify.length = 0;
1952 }
1953
1954 bgp_notify.code = stream_getc (peer->ibuf);
1955 bgp_notify.subcode = stream_getc (peer->ibuf);
1956 bgp_notify.length = size - 2;
1957 bgp_notify.data = NULL;
1958
1959 /* Preserv notify code and sub code. */
1960 peer->notify.code = bgp_notify.code;
1961 peer->notify.subcode = bgp_notify.subcode;
1962 /* For further diagnostic record returned Data. */
1963 if (bgp_notify.length)
1964 {
1965 peer->notify.length = size - 2;
1966 peer->notify.data = XMALLOC (MTYPE_TMP, size - 2);
1967 memcpy (peer->notify.data, stream_pnt (peer->ibuf), size - 2);
1968 }
1969
1970 /* For debug */
1971 {
1972 int i;
1973 int first = 0;
1974 char c[4];
1975
1976 if (bgp_notify.length)
1977 {
1978 bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
1979 for (i = 0; i < bgp_notify.length; i++)
1980 if (first)
1981 {
1982 sprintf (c, " %02x", stream_getc (peer->ibuf));
1983 strcat (bgp_notify.data, c);
1984 }
1985 else
1986 {
1987 first = 1;
1988 sprintf (c, "%02x", stream_getc (peer->ibuf));
1989 strcpy (bgp_notify.data, c);
1990 }
1991 }
1992
1993 bgp_notify_print(peer, &bgp_notify, "received");
1994 if (bgp_notify.data)
1995 XFREE (MTYPE_TMP, bgp_notify.data);
1996 }
1997
1998 /* peer count update */
1999 peer->notify_in++;
2000
hassoe0701b72004-05-20 09:19:34 +00002001 if (peer->status == Established)
2002 peer->last_reset = PEER_DOWN_NOTIFY_RECEIVED;
2003
paul718e3742002-12-13 20:15:29 +00002004 /* We have to check for Notify with Unsupported Optional Parameter.
2005 in that case we fallback to open without the capability option.
2006 But this done in bgp_stop. We just mark it here to avoid changing
2007 the fsm tables. */
2008 if (bgp_notify.code == BGP_NOTIFY_OPEN_ERR &&
2009 bgp_notify.subcode == BGP_NOTIFY_OPEN_UNSUP_PARAM )
2010 UNSET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
2011
paul718e3742002-12-13 20:15:29 +00002012 BGP_EVENT_ADD (peer, Receive_NOTIFICATION_message);
2013}
2014
2015/* Keepalive treatment function -- get keepalive send keepalive */
paul94f2b392005-06-28 12:44:16 +00002016static void
paul718e3742002-12-13 20:15:29 +00002017bgp_keepalive_receive (struct peer *peer, bgp_size_t size)
2018{
2019 if (BGP_DEBUG (keepalive, KEEPALIVE))
ajs6b514742004-12-08 21:03:23 +00002020 zlog_debug ("%s KEEPALIVE rcvd", peer->host);
paul718e3742002-12-13 20:15:29 +00002021
2022 BGP_EVENT_ADD (peer, Receive_KEEPALIVE_message);
2023}
2024
2025/* Route refresh message is received. */
paul94f2b392005-06-28 12:44:16 +00002026static void
paul718e3742002-12-13 20:15:29 +00002027bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
2028{
2029 afi_t afi;
2030 safi_t safi;
paul718e3742002-12-13 20:15:29 +00002031 struct stream *s;
2032
2033 /* If peer does not have the capability, send notification. */
2034 if (! CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_ADV))
2035 {
2036 plog_err (peer->log, "%s [Error] BGP route refresh is not enabled",
2037 peer->host);
2038 bgp_notify_send (peer,
2039 BGP_NOTIFY_HEADER_ERR,
2040 BGP_NOTIFY_HEADER_BAD_MESTYPE);
2041 return;
2042 }
2043
2044 /* Status must be Established. */
2045 if (peer->status != Established)
2046 {
2047 plog_err (peer->log,
2048 "%s [Error] Route refresh packet received under status %s",
2049 peer->host, LOOKUP (bgp_status_msg, peer->status));
2050 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
2051 return;
2052 }
2053
2054 s = peer->ibuf;
2055
2056 /* Parse packet. */
2057 afi = stream_getw (s);
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002058 /* reserved byte */
2059 stream_getc (s);
paul718e3742002-12-13 20:15:29 +00002060 safi = stream_getc (s);
2061
2062 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002063 zlog_debug ("%s rcvd REFRESH_REQ for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00002064 peer->host, afi, safi);
2065
2066 /* Check AFI and SAFI. */
2067 if ((afi != AFI_IP && afi != AFI_IP6)
2068 || (safi != SAFI_UNICAST && safi != SAFI_MULTICAST
Denis Ovsienko42e6d742011-07-14 12:36:19 +04002069 && safi != SAFI_MPLS_LABELED_VPN))
paul718e3742002-12-13 20:15:29 +00002070 {
2071 if (BGP_DEBUG (normal, NORMAL))
2072 {
ajs6b514742004-12-08 21:03:23 +00002073 zlog_debug ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored",
paul718e3742002-12-13 20:15:29 +00002074 peer->host, afi, safi);
2075 }
2076 return;
2077 }
2078
2079 /* Adjust safi code. */
Denis Ovsienko42e6d742011-07-14 12:36:19 +04002080 if (safi == SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00002081 safi = SAFI_MPLS_VPN;
2082
2083 if (size != BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE)
2084 {
2085 u_char *end;
2086 u_char when_to_refresh;
2087 u_char orf_type;
2088 u_int16_t orf_len;
2089
2090 if (size - (BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE) < 5)
2091 {
2092 zlog_info ("%s ORF route refresh length error", peer->host);
2093 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2094 return;
2095 }
2096
2097 when_to_refresh = stream_getc (s);
2098 end = stream_pnt (s) + (size - 5);
2099
Paul Jakma370b64a2007-12-22 16:49:52 +00002100 while ((stream_pnt (s) + 2) < end)
paul718e3742002-12-13 20:15:29 +00002101 {
2102 orf_type = stream_getc (s);
2103 orf_len = stream_getw (s);
Paul Jakma370b64a2007-12-22 16:49:52 +00002104
2105 /* orf_len in bounds? */
2106 if ((stream_pnt (s) + orf_len) > end)
2107 break; /* XXX: Notify instead?? */
paul718e3742002-12-13 20:15:29 +00002108 if (orf_type == ORF_TYPE_PREFIX
2109 || orf_type == ORF_TYPE_PREFIX_OLD)
2110 {
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002111 uint8_t *p_pnt = stream_pnt (s);
2112 uint8_t *p_end = stream_pnt (s) + orf_len;
paul718e3742002-12-13 20:15:29 +00002113 struct orf_prefix orfp;
2114 u_char common = 0;
2115 u_int32_t seq;
2116 int psize;
2117 char name[BUFSIZ];
paul718e3742002-12-13 20:15:29 +00002118 int ret;
2119
2120 if (BGP_DEBUG (normal, NORMAL))
2121 {
ajs6b514742004-12-08 21:03:23 +00002122 zlog_debug ("%s rcvd Prefixlist ORF(%d) length %d",
paul718e3742002-12-13 20:15:29 +00002123 peer->host, orf_type, orf_len);
2124 }
2125
Paul Jakma370b64a2007-12-22 16:49:52 +00002126 /* we're going to read at least 1 byte of common ORF header,
2127 * and 7 bytes of ORF Address-filter entry from the stream
2128 */
2129 if (orf_len < 7)
2130 break;
2131
paul718e3742002-12-13 20:15:29 +00002132 /* ORF prefix-list name */
2133 sprintf (name, "%s.%d.%d", peer->host, afi, safi);
2134
2135 while (p_pnt < p_end)
2136 {
Chris Halld64379e2010-05-14 16:38:39 +04002137 /* If the ORF entry is malformed, want to read as much of it
2138 * as possible without going beyond the bounds of the entry,
2139 * to maximise debug information.
2140 */
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002141 int ok;
paul718e3742002-12-13 20:15:29 +00002142 memset (&orfp, 0, sizeof (struct orf_prefix));
2143 common = *p_pnt++;
Chris Halld64379e2010-05-14 16:38:39 +04002144 /* after ++: p_pnt <= p_end */
paul718e3742002-12-13 20:15:29 +00002145 if (common & ORF_COMMON_PART_REMOVE_ALL)
2146 {
2147 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002148 zlog_debug ("%s rcvd Remove-All pfxlist ORF request", peer->host);
paul718e3742002-12-13 20:15:29 +00002149 prefix_bgp_orf_remove_all (name);
2150 break;
2151 }
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002152 ok = ((size_t)(p_end - p_pnt) >= sizeof(u_int32_t)) ;
Denis Ovsienkobb915f52011-12-13 21:11:39 +04002153 if (ok)
Chris Halld64379e2010-05-14 16:38:39 +04002154 {
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002155 memcpy (&seq, p_pnt, sizeof (u_int32_t));
2156 p_pnt += sizeof (u_int32_t);
2157 orfp.seq = ntohl (seq);
Chris Halld64379e2010-05-14 16:38:39 +04002158 }
2159 else
2160 p_pnt = p_end ;
2161
2162 if ((ok = (p_pnt < p_end)))
2163 orfp.ge = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */
2164 if ((ok = (p_pnt < p_end)))
2165 orfp.le = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */
2166 if ((ok = (p_pnt < p_end)))
2167 orfp.p.prefixlen = *p_pnt++ ;
2168 orfp.p.family = afi2family (afi); /* afi checked already */
2169
2170 psize = PSIZE (orfp.p.prefixlen); /* 0 if not ok */
2171 if (psize > prefix_blen(&orfp.p)) /* valid for family ? */
2172 {
2173 ok = 0 ;
2174 psize = prefix_blen(&orfp.p) ;
2175 }
2176 if (psize > (p_end - p_pnt)) /* valid for packet ? */
2177 {
2178 ok = 0 ;
2179 psize = p_end - p_pnt ;
2180 }
2181
2182 if (psize > 0)
2183 memcpy (&orfp.p.u.prefix, p_pnt, psize);
paul718e3742002-12-13 20:15:29 +00002184 p_pnt += psize;
2185
2186 if (BGP_DEBUG (normal, NORMAL))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +00002187 {
2188 char buf[INET6_BUFSIZ];
2189
2190 zlog_debug ("%s rcvd %s %s seq %u %s/%d ge %d le %d%s",
2191 peer->host,
2192 (common & ORF_COMMON_PART_REMOVE ? "Remove" : "Add"),
2193 (common & ORF_COMMON_PART_DENY ? "deny" : "permit"),
2194 orfp.seq,
2195 inet_ntop (orfp.p.family, &orfp.p.u.prefix, buf, INET6_BUFSIZ),
2196 orfp.p.prefixlen, orfp.ge, orfp.le,
2197 ok ? "" : " MALFORMED");
2198 }
2199
Chris Halld64379e2010-05-14 16:38:39 +04002200 if (ok)
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002201 ret = prefix_bgp_orf_set (name, afi, &orfp,
2202 (common & ORF_COMMON_PART_DENY ? 0 : 1 ),
2203 (common & ORF_COMMON_PART_REMOVE ? 0 : 1));
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002204
2205 if (!ok || (ok && ret != CMD_SUCCESS))
paul718e3742002-12-13 20:15:29 +00002206 {
2207 if (BGP_DEBUG (normal, NORMAL))
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002208 zlog_debug ("%s Received misformatted prefixlist ORF."
2209 " Remove All pfxlist", peer->host);
paul718e3742002-12-13 20:15:29 +00002210 prefix_bgp_orf_remove_all (name);
2211 break;
2212 }
2213 }
2214 peer->orf_plist[afi][safi] =
2215 prefix_list_lookup (AFI_ORF_PREFIX, name);
2216 }
paul9985f832005-02-09 15:51:56 +00002217 stream_forward_getp (s, orf_len);
paul718e3742002-12-13 20:15:29 +00002218 }
2219 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002220 zlog_debug ("%s rcvd Refresh %s ORF request", peer->host,
paul718e3742002-12-13 20:15:29 +00002221 when_to_refresh == REFRESH_DEFER ? "Defer" : "Immediate");
2222 if (when_to_refresh == REFRESH_DEFER)
2223 return;
2224 }
2225
2226 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2227 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH))
2228 UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
2229
2230 /* Perform route refreshment to the peer */
2231 bgp_announce_route (peer, afi, safi);
2232}
2233
paul94f2b392005-06-28 12:44:16 +00002234static int
paul718e3742002-12-13 20:15:29 +00002235bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
2236{
2237 u_char *end;
Paul Jakma6d582722007-08-06 15:21:45 +00002238 struct capability_mp_data mpc;
2239 struct capability_header *hdr;
paul718e3742002-12-13 20:15:29 +00002240 u_char action;
paul718e3742002-12-13 20:15:29 +00002241 afi_t afi;
2242 safi_t safi;
2243
paul718e3742002-12-13 20:15:29 +00002244 end = pnt + length;
2245
2246 while (pnt < end)
Paul Jakma6d582722007-08-06 15:21:45 +00002247 {
paul718e3742002-12-13 20:15:29 +00002248 /* We need at least action, capability code and capability length. */
2249 if (pnt + 3 > end)
2250 {
2251 zlog_info ("%s Capability length error", peer->host);
2252 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2253 return -1;
2254 }
paul718e3742002-12-13 20:15:29 +00002255 action = *pnt;
Paul Jakma6d582722007-08-06 15:21:45 +00002256 hdr = (struct capability_header *)(pnt + 1);
2257
paul718e3742002-12-13 20:15:29 +00002258 /* Action value check. */
2259 if (action != CAPABILITY_ACTION_SET
2260 && action != CAPABILITY_ACTION_UNSET)
2261 {
2262 zlog_info ("%s Capability Action Value error %d",
2263 peer->host, action);
2264 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2265 return -1;
2266 }
2267
2268 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002269 zlog_debug ("%s CAPABILITY has action: %d, code: %u, length %u",
Paul Jakma6d582722007-08-06 15:21:45 +00002270 peer->host, action, hdr->code, hdr->length);
paul718e3742002-12-13 20:15:29 +00002271
2272 /* Capability length check. */
Paul Jakma6d582722007-08-06 15:21:45 +00002273 if ((pnt + hdr->length + 3) > end)
paul718e3742002-12-13 20:15:29 +00002274 {
2275 zlog_info ("%s Capability length error", peer->host);
2276 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2277 return -1;
2278 }
2279
Paul Jakma6d582722007-08-06 15:21:45 +00002280 /* Fetch structure to the byte stream. */
2281 memcpy (&mpc, pnt + 3, sizeof (struct capability_mp_data));
2282
paul718e3742002-12-13 20:15:29 +00002283 /* We know MP Capability Code. */
Paul Jakma6d582722007-08-06 15:21:45 +00002284 if (hdr->code == CAPABILITY_CODE_MP)
paul718e3742002-12-13 20:15:29 +00002285 {
Paul Jakma6d582722007-08-06 15:21:45 +00002286 afi = ntohs (mpc.afi);
2287 safi = mpc.safi;
paul718e3742002-12-13 20:15:29 +00002288
2289 /* Ignore capability when override-capability is set. */
2290 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
2291 continue;
Paul Jakma6d582722007-08-06 15:21:45 +00002292
2293 if (!bgp_afi_safi_valid_indices (afi, &safi))
2294 {
2295 if (BGP_DEBUG (normal, NORMAL))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002296 zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid "
2297 "(%u/%u)", peer->host, afi, safi);
Paul Jakma6d582722007-08-06 15:21:45 +00002298 continue;
2299 }
2300
paul718e3742002-12-13 20:15:29 +00002301 /* Address family check. */
Paul Jakma6d582722007-08-06 15:21:45 +00002302 if (BGP_DEBUG (normal, NORMAL))
2303 zlog_debug ("%s CAPABILITY has %s MP_EXT CAP for afi/safi: %u/%u",
2304 peer->host,
2305 action == CAPABILITY_ACTION_SET
2306 ? "Advertising" : "Removing",
2307 ntohs(mpc.afi) , mpc.safi);
2308
2309 if (action == CAPABILITY_ACTION_SET)
2310 {
2311 peer->afc_recv[afi][safi] = 1;
2312 if (peer->afc[afi][safi])
2313 {
2314 peer->afc_nego[afi][safi] = 1;
2315 bgp_announce_route (peer, afi, safi);
2316 }
2317 }
2318 else
2319 {
2320 peer->afc_recv[afi][safi] = 0;
2321 peer->afc_nego[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00002322
Paul Jakma6d582722007-08-06 15:21:45 +00002323 if (peer_active_nego (peer))
Chris Caputo228da422009-07-18 05:44:03 +00002324 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
Paul Jakma6d582722007-08-06 15:21:45 +00002325 else
2326 BGP_EVENT_ADD (peer, BGP_Stop);
2327 }
paul718e3742002-12-13 20:15:29 +00002328 }
paul718e3742002-12-13 20:15:29 +00002329 else
2330 {
2331 zlog_warn ("%s unrecognized capability code: %d - ignored",
Paul Jakma6d582722007-08-06 15:21:45 +00002332 peer->host, hdr->code);
paul718e3742002-12-13 20:15:29 +00002333 }
Paul Jakma6d582722007-08-06 15:21:45 +00002334 pnt += hdr->length + 3;
paul718e3742002-12-13 20:15:29 +00002335 }
2336 return 0;
2337}
2338
Paul Jakma01b7ce22009-06-18 12:34:43 +01002339/* Dynamic Capability is received.
2340 *
2341 * This is exported for unit-test purposes
2342 */
Paul Jakma6d582722007-08-06 15:21:45 +00002343int
paul718e3742002-12-13 20:15:29 +00002344bgp_capability_receive (struct peer *peer, bgp_size_t size)
2345{
2346 u_char *pnt;
paul718e3742002-12-13 20:15:29 +00002347
2348 /* Fetch pointer. */
2349 pnt = stream_pnt (peer->ibuf);
2350
2351 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002352 zlog_debug ("%s rcv CAPABILITY", peer->host);
paul718e3742002-12-13 20:15:29 +00002353
2354 /* If peer does not have the capability, send notification. */
2355 if (! CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV))
2356 {
2357 plog_err (peer->log, "%s [Error] BGP dynamic capability is not enabled",
2358 peer->host);
2359 bgp_notify_send (peer,
2360 BGP_NOTIFY_HEADER_ERR,
2361 BGP_NOTIFY_HEADER_BAD_MESTYPE);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002362 return -1;
paul718e3742002-12-13 20:15:29 +00002363 }
2364
2365 /* Status must be Established. */
2366 if (peer->status != Established)
2367 {
2368 plog_err (peer->log,
2369 "%s [Error] Dynamic capability packet received under status %s", peer->host, LOOKUP (bgp_status_msg, peer->status));
2370 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002371 return -1;
paul718e3742002-12-13 20:15:29 +00002372 }
2373
2374 /* Parse packet. */
Paul Jakma6d582722007-08-06 15:21:45 +00002375 return bgp_capability_msg_parse (peer, pnt, size);
paul718e3742002-12-13 20:15:29 +00002376}
David Lamparter6b0655a2014-06-04 06:53:35 +02002377
paul718e3742002-12-13 20:15:29 +00002378/* BGP read utility function. */
paul94f2b392005-06-28 12:44:16 +00002379static int
paul718e3742002-12-13 20:15:29 +00002380bgp_read_packet (struct peer *peer)
2381{
2382 int nbytes;
2383 int readsize;
2384
paul9985f832005-02-09 15:51:56 +00002385 readsize = peer->packet_size - stream_get_endp (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00002386
2387 /* If size is zero then return. */
2388 if (! readsize)
2389 return 0;
2390
2391 /* Read packet from fd. */
Stephen Hemminger35398582010-08-05 10:26:23 -07002392 nbytes = stream_read_try (peer->ibuf, peer->fd, readsize);
paul718e3742002-12-13 20:15:29 +00002393
2394 /* If read byte is smaller than zero then error occured. */
2395 if (nbytes < 0)
2396 {
Stephen Hemminger35398582010-08-05 10:26:23 -07002397 /* Transient error should retry */
2398 if (nbytes == -2)
paul718e3742002-12-13 20:15:29 +00002399 return -1;
2400
2401 plog_err (peer->log, "%s [Error] bgp_read_packet error: %s",
ajs6099b3b2004-11-20 02:06:59 +00002402 peer->host, safe_strerror (errno));
hasso93406d82005-02-02 14:40:33 +00002403
2404 if (peer->status == Established)
2405 {
2406 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
2407 {
2408 peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
2409 SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
2410 }
2411 else
2412 peer->last_reset = PEER_DOWN_CLOSE_SESSION;
2413 }
2414
paul718e3742002-12-13 20:15:29 +00002415 BGP_EVENT_ADD (peer, TCP_fatal_error);
2416 return -1;
2417 }
2418
2419 /* When read byte is zero : clear bgp peer and return */
2420 if (nbytes == 0)
2421 {
2422 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +00002423 plog_debug (peer->log, "%s [Event] BGP connection closed fd %d",
pauleb821182004-05-01 08:44:08 +00002424 peer->host, peer->fd);
hassoe0701b72004-05-20 09:19:34 +00002425
2426 if (peer->status == Established)
hasso93406d82005-02-02 14:40:33 +00002427 {
2428 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
2429 {
2430 peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
2431 SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
2432 }
2433 else
2434 peer->last_reset = PEER_DOWN_CLOSE_SESSION;
2435 }
hassoe0701b72004-05-20 09:19:34 +00002436
paul718e3742002-12-13 20:15:29 +00002437 BGP_EVENT_ADD (peer, TCP_connection_closed);
2438 return -1;
2439 }
2440
2441 /* We read partial packet. */
paul9985f832005-02-09 15:51:56 +00002442 if (stream_get_endp (peer->ibuf) != peer->packet_size)
paul718e3742002-12-13 20:15:29 +00002443 return -1;
2444
2445 return 0;
2446}
2447
2448/* Marker check. */
paul94f2b392005-06-28 12:44:16 +00002449static int
paul718e3742002-12-13 20:15:29 +00002450bgp_marker_all_one (struct stream *s, int length)
2451{
2452 int i;
2453
2454 for (i = 0; i < length; i++)
2455 if (s->data[i] != 0xff)
2456 return 0;
2457
2458 return 1;
2459}
2460
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002461/* Recent thread time.
2462 On same clock base as bgp_clock (MONOTONIC)
2463 but can be time of last context switch to bgp_read thread. */
2464static time_t
2465bgp_recent_clock (void)
2466{
2467 return recent_relative_time().tv_sec;
2468}
2469
paul718e3742002-12-13 20:15:29 +00002470/* Starting point of packet process function. */
2471int
2472bgp_read (struct thread *thread)
2473{
2474 int ret;
2475 u_char type = 0;
2476 struct peer *peer;
2477 bgp_size_t size;
2478 char notify_data_length[2];
2479
2480 /* Yes first of all get peer pointer. */
2481 peer = THREAD_ARG (thread);
2482 peer->t_read = NULL;
2483
2484 /* For non-blocking IO check. */
2485 if (peer->status == Connect)
2486 {
2487 bgp_connect_check (peer);
2488 goto done;
2489 }
2490 else
2491 {
pauleb821182004-05-01 08:44:08 +00002492 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +00002493 {
pauleb821182004-05-01 08:44:08 +00002494 zlog_err ("bgp_read peer's fd is negative value %d", peer->fd);
paul718e3742002-12-13 20:15:29 +00002495 return -1;
2496 }
pauleb821182004-05-01 08:44:08 +00002497 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
paul718e3742002-12-13 20:15:29 +00002498 }
2499
2500 /* Read packet header to determine type of the packet */
2501 if (peer->packet_size == 0)
2502 peer->packet_size = BGP_HEADER_SIZE;
2503
paul9985f832005-02-09 15:51:56 +00002504 if (stream_get_endp (peer->ibuf) < BGP_HEADER_SIZE)
paul718e3742002-12-13 20:15:29 +00002505 {
2506 ret = bgp_read_packet (peer);
2507
2508 /* Header read error or partial read packet. */
2509 if (ret < 0)
2510 goto done;
2511
2512 /* Get size and type. */
paul9985f832005-02-09 15:51:56 +00002513 stream_forward_getp (peer->ibuf, BGP_MARKER_SIZE);
paul718e3742002-12-13 20:15:29 +00002514 memcpy (notify_data_length, stream_pnt (peer->ibuf), 2);
2515 size = stream_getw (peer->ibuf);
2516 type = stream_getc (peer->ibuf);
2517
2518 if (BGP_DEBUG (normal, NORMAL) && type != 2 && type != 0)
ajs6b514742004-12-08 21:03:23 +00002519 zlog_debug ("%s rcv message type %d, length (excl. header) %d",
paul718e3742002-12-13 20:15:29 +00002520 peer->host, type, size - BGP_HEADER_SIZE);
2521
2522 /* Marker check */
paulf5ba3872004-07-09 12:11:31 +00002523 if (((type == BGP_MSG_OPEN) || (type == BGP_MSG_KEEPALIVE))
paul718e3742002-12-13 20:15:29 +00002524 && ! bgp_marker_all_one (peer->ibuf, BGP_MARKER_SIZE))
2525 {
2526 bgp_notify_send (peer,
2527 BGP_NOTIFY_HEADER_ERR,
2528 BGP_NOTIFY_HEADER_NOT_SYNC);
2529 goto done;
2530 }
2531
2532 /* BGP type check. */
2533 if (type != BGP_MSG_OPEN && type != BGP_MSG_UPDATE
2534 && type != BGP_MSG_NOTIFY && type != BGP_MSG_KEEPALIVE
2535 && type != BGP_MSG_ROUTE_REFRESH_NEW
2536 && type != BGP_MSG_ROUTE_REFRESH_OLD
2537 && type != BGP_MSG_CAPABILITY)
2538 {
2539 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002540 plog_debug (peer->log,
paul718e3742002-12-13 20:15:29 +00002541 "%s unknown message type 0x%02x",
2542 peer->host, type);
2543 bgp_notify_send_with_data (peer,
2544 BGP_NOTIFY_HEADER_ERR,
2545 BGP_NOTIFY_HEADER_BAD_MESTYPE,
2546 &type, 1);
2547 goto done;
2548 }
2549 /* Mimimum packet length check. */
2550 if ((size < BGP_HEADER_SIZE)
2551 || (size > BGP_MAX_PACKET_SIZE)
2552 || (type == BGP_MSG_OPEN && size < BGP_MSG_OPEN_MIN_SIZE)
2553 || (type == BGP_MSG_UPDATE && size < BGP_MSG_UPDATE_MIN_SIZE)
2554 || (type == BGP_MSG_NOTIFY && size < BGP_MSG_NOTIFY_MIN_SIZE)
2555 || (type == BGP_MSG_KEEPALIVE && size != BGP_MSG_KEEPALIVE_MIN_SIZE)
2556 || (type == BGP_MSG_ROUTE_REFRESH_NEW && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
2557 || (type == BGP_MSG_ROUTE_REFRESH_OLD && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
2558 || (type == BGP_MSG_CAPABILITY && size < BGP_MSG_CAPABILITY_MIN_SIZE))
2559 {
2560 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002561 plog_debug (peer->log,
paul718e3742002-12-13 20:15:29 +00002562 "%s bad message length - %d for %s",
2563 peer->host, size,
2564 type == 128 ? "ROUTE-REFRESH" :
2565 bgp_type_str[(int) type]);
2566 bgp_notify_send_with_data (peer,
2567 BGP_NOTIFY_HEADER_ERR,
2568 BGP_NOTIFY_HEADER_BAD_MESLEN,
hassoc9e52be2004-09-26 16:09:34 +00002569 (u_char *) notify_data_length, 2);
paul718e3742002-12-13 20:15:29 +00002570 goto done;
2571 }
2572
2573 /* Adjust size to message length. */
2574 peer->packet_size = size;
2575 }
2576
2577 ret = bgp_read_packet (peer);
2578 if (ret < 0)
2579 goto done;
2580
2581 /* Get size and type again. */
2582 size = stream_getw_from (peer->ibuf, BGP_MARKER_SIZE);
2583 type = stream_getc_from (peer->ibuf, BGP_MARKER_SIZE + 2);
2584
2585 /* BGP packet dump function. */
2586 bgp_dump_packet (peer, type, peer->ibuf);
2587
2588 size = (peer->packet_size - BGP_HEADER_SIZE);
2589
2590 /* Read rest of the packet and call each sort of packet routine */
2591 switch (type)
2592 {
2593 case BGP_MSG_OPEN:
2594 peer->open_in++;
paulf5ba3872004-07-09 12:11:31 +00002595 bgp_open_receive (peer, size); /* XXX return value ignored! */
paul718e3742002-12-13 20:15:29 +00002596 break;
2597 case BGP_MSG_UPDATE:
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002598 peer->readtime = bgp_recent_clock ();
paul718e3742002-12-13 20:15:29 +00002599 bgp_update_receive (peer, size);
2600 break;
2601 case BGP_MSG_NOTIFY:
2602 bgp_notify_receive (peer, size);
2603 break;
2604 case BGP_MSG_KEEPALIVE:
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002605 peer->readtime = bgp_recent_clock ();
paul718e3742002-12-13 20:15:29 +00002606 bgp_keepalive_receive (peer, size);
2607 break;
2608 case BGP_MSG_ROUTE_REFRESH_NEW:
2609 case BGP_MSG_ROUTE_REFRESH_OLD:
2610 peer->refresh_in++;
2611 bgp_route_refresh_receive (peer, size);
2612 break;
2613 case BGP_MSG_CAPABILITY:
2614 peer->dynamic_cap_in++;
2615 bgp_capability_receive (peer, size);
2616 break;
2617 }
2618
2619 /* Clear input buffer. */
2620 peer->packet_size = 0;
2621 if (peer->ibuf)
2622 stream_reset (peer->ibuf);
2623
2624 done:
2625 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2626 {
2627 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +00002628 zlog_debug ("%s [Event] Accepting BGP peer delete", peer->host);
paul718e3742002-12-13 20:15:29 +00002629 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00002630 }
2631 return 0;
2632}