blob: 35a22c1e335d0d956ca44db4ec26fa5da01e585f [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)
616 && ! CHECK_FLAG (adv->binfo->flags, BGP_INFO_STALE)
617 && safi != SAFI_MPLS_VPN)
618 {
619 if (CHECK_FLAG (adv->binfo->peer->af_sflags[afi][safi],
620 PEER_STATUS_EOR_RECEIVED))
621 s = bgp_update_packet (peer, afi, safi);
622 }
623 else
624 s = bgp_update_packet (peer, afi, safi);
625 }
paul718e3742002-12-13 20:15:29 +0000626
627 if (s)
628 return s;
629 }
hasso93406d82005-02-02 14:40:33 +0000630
631 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV))
632 {
633 if (peer->afc_nego[afi][safi] && peer->synctime
634 && ! CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND)
635 && safi != SAFI_MPLS_VPN)
636 {
637 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND);
638 return bgp_update_packet_eor (peer, afi, safi);
639 }
640 }
paul718e3742002-12-13 20:15:29 +0000641 }
642
643 return NULL;
644}
645
646/* Is there partially written packet or updates we can send right
647 now. */
paul94f2b392005-06-28 12:44:16 +0000648static int
paul718e3742002-12-13 20:15:29 +0000649bgp_write_proceed (struct peer *peer)
650{
651 afi_t afi;
652 safi_t safi;
653 struct bgp_advertise *adv;
654
655 if (stream_fifo_head (peer->obuf))
656 return 1;
657
658 for (afi = AFI_IP; afi < AFI_MAX; afi++)
659 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
660 if (FIFO_HEAD (&peer->sync[afi][safi]->withdraw))
661 return 1;
662
663 for (afi = AFI_IP; afi < AFI_MAX; afi++)
664 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
Paul Jakma7aa9dce2014-09-19 14:42:23 +0100665 if ((adv = BGP_ADV_FIFO_HEAD (&peer->sync[afi][safi]->update)) != NULL)
paul718e3742002-12-13 20:15:29 +0000666 if (adv->binfo->uptime < peer->synctime)
667 return 1;
668
669 return 0;
670}
671
672/* Write packet to the peer. */
673int
674bgp_write (struct thread *thread)
675{
676 struct peer *peer;
677 u_char type;
678 struct stream *s;
679 int num;
paulfd79ac92004-10-13 05:06:08 +0000680 unsigned int count = 0;
paul718e3742002-12-13 20:15:29 +0000681
682 /* Yes first of all get peer pointer. */
683 peer = THREAD_ARG (thread);
684 peer->t_write = NULL;
685
686 /* For non-blocking IO check. */
687 if (peer->status == Connect)
688 {
689 bgp_connect_check (peer);
690 return 0;
691 }
692
Stephen Hemmingereac57022010-08-05 10:26:25 -0700693 s = bgp_write_packet (peer);
694 if (!s)
695 return 0; /* nothing to send */
696
697 sockopt_cork (peer->fd, 1);
698
699 /* Nonblocking write until TCP output buffer is full. */
700 do
paul718e3742002-12-13 20:15:29 +0000701 {
702 int writenum;
paul718e3742002-12-13 20:15:29 +0000703
704 /* Number of bytes to be sent. */
705 writenum = stream_get_endp (s) - stream_get_getp (s);
706
707 /* Call write() system call. */
pauleb821182004-05-01 08:44:08 +0000708 num = write (peer->fd, STREAM_PNT (s), writenum);
Stephen Hemminger35398582010-08-05 10:26:23 -0700709 if (num < 0)
paul718e3742002-12-13 20:15:29 +0000710 {
Stephen Hemmingereac57022010-08-05 10:26:25 -0700711 /* write failed either retry needed or error */
712 if (ERRNO_IO_RETRY(errno))
713 break;
714
715 BGP_EVENT_ADD (peer, TCP_fatal_error);
paul718e3742002-12-13 20:15:29 +0000716 return 0;
717 }
Stephen Hemminger35398582010-08-05 10:26:23 -0700718
paul718e3742002-12-13 20:15:29 +0000719 if (num != writenum)
720 {
Stephen Hemminger35398582010-08-05 10:26:23 -0700721 /* Partial write */
paul9985f832005-02-09 15:51:56 +0000722 stream_forward_getp (s, num);
Stephen Hemmingereac57022010-08-05 10:26:25 -0700723 break;
paul718e3742002-12-13 20:15:29 +0000724 }
725
726 /* Retrieve BGP packet type. */
727 stream_set_getp (s, BGP_MARKER_SIZE + 2);
728 type = stream_getc (s);
729
730 switch (type)
731 {
732 case BGP_MSG_OPEN:
733 peer->open_out++;
734 break;
735 case BGP_MSG_UPDATE:
736 peer->update_out++;
737 break;
738 case BGP_MSG_NOTIFY:
739 peer->notify_out++;
740 /* Double start timer. */
741 peer->v_start *= 2;
742
743 /* Overflow check. */
744 if (peer->v_start >= (60 * 2))
745 peer->v_start = (60 * 2);
746
Paul Jakmaca058a32006-09-14 02:58:49 +0000747 /* Flush any existing events */
Paul Jakmadcdf3992006-10-15 23:39:59 +0000748 BGP_EVENT_ADD (peer, BGP_Stop);
Stephen Hemminger3a69f742013-01-11 18:27:23 +0000749 goto done;
750
paul718e3742002-12-13 20:15:29 +0000751 case BGP_MSG_KEEPALIVE:
752 peer->keepalive_out++;
753 break;
754 case BGP_MSG_ROUTE_REFRESH_NEW:
755 case BGP_MSG_ROUTE_REFRESH_OLD:
756 peer->refresh_out++;
757 break;
758 case BGP_MSG_CAPABILITY:
759 peer->dynamic_cap_out++;
760 break;
761 }
762
763 /* OK we send packet so delete it. */
764 bgp_packet_delete (peer);
paul718e3742002-12-13 20:15:29 +0000765 }
Stephen Hemmingereac57022010-08-05 10:26:25 -0700766 while (++count < BGP_WRITE_PACKET_MAX &&
767 (s = bgp_write_packet (peer)) != NULL);
paul718e3742002-12-13 20:15:29 +0000768
769 if (bgp_write_proceed (peer))
pauleb821182004-05-01 08:44:08 +0000770 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
Stephen Hemminger3a69f742013-01-11 18:27:23 +0000771
772 done:
773 sockopt_cork (peer->fd, 0);
paul718e3742002-12-13 20:15:29 +0000774 return 0;
775}
776
777/* This is only for sending NOTIFICATION message to neighbor. */
paul94f2b392005-06-28 12:44:16 +0000778static int
paul718e3742002-12-13 20:15:29 +0000779bgp_write_notify (struct peer *peer)
780{
Stephen Hemminger35398582010-08-05 10:26:23 -0700781 int ret, val;
paul718e3742002-12-13 20:15:29 +0000782 u_char type;
783 struct stream *s;
784
785 /* There should be at least one packet. */
786 s = stream_fifo_head (peer->obuf);
787 if (!s)
788 return 0;
789 assert (stream_get_endp (s) >= BGP_HEADER_SIZE);
790
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000791 /* Stop collecting data within the socket */
792 sockopt_cork (peer->fd, 0);
793
David Lamparter8ff202e2013-07-31 14:39:41 +0200794 /* socket is in nonblocking mode, if we can't deliver the NOTIFY, well,
795 * we only care about getting a clean shutdown at this point. */
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000796 ret = write (peer->fd, STREAM_DATA (s), stream_get_endp (s));
David Lamparter8ff202e2013-07-31 14:39:41 +0200797
798 /* only connection reset/close gets counted as TCP_fatal_error, failure
799 * to write the entire NOTIFY doesn't get different FSM treatment */
paul718e3742002-12-13 20:15:29 +0000800 if (ret <= 0)
801 {
Paul Jakmadcdf3992006-10-15 23:39:59 +0000802 BGP_EVENT_ADD (peer, TCP_fatal_error);
paul718e3742002-12-13 20:15:29 +0000803 return 0;
804 }
805
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000806 /* Disable Nagle, make NOTIFY packet go out right away */
807 val = 1;
808 (void) setsockopt (peer->fd, IPPROTO_TCP, TCP_NODELAY,
809 (char *) &val, sizeof (val));
810
paul718e3742002-12-13 20:15:29 +0000811 /* Retrieve BGP packet type. */
812 stream_set_getp (s, BGP_MARKER_SIZE + 2);
813 type = stream_getc (s);
814
815 assert (type == BGP_MSG_NOTIFY);
816
817 /* Type should be notify. */
818 peer->notify_out++;
819
820 /* Double start timer. */
821 peer->v_start *= 2;
822
823 /* Overflow check. */
824 if (peer->v_start >= (60 * 2))
825 peer->v_start = (60 * 2);
826
Paul Jakmadcdf3992006-10-15 23:39:59 +0000827 BGP_EVENT_ADD (peer, BGP_Stop);
paul718e3742002-12-13 20:15:29 +0000828
829 return 0;
830}
831
832/* Make keepalive packet and send it to the peer. */
833void
834bgp_keepalive_send (struct peer *peer)
835{
836 struct stream *s;
837 int length;
838
839 s = stream_new (BGP_MAX_PACKET_SIZE);
840
841 /* Make keepalive packet. */
842 bgp_packet_set_marker (s, BGP_MSG_KEEPALIVE);
843
844 /* Set packet size. */
845 length = bgp_packet_set_size (s);
846
847 /* Dump packet if debug option is set. */
848 /* bgp_packet_dump (s); */
849
850 if (BGP_DEBUG (keepalive, KEEPALIVE))
ajs6b514742004-12-08 21:03:23 +0000851 zlog_debug ("%s sending KEEPALIVE", peer->host);
paul718e3742002-12-13 20:15:29 +0000852 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000853 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000854 peer->host, BGP_MSG_KEEPALIVE, length);
855
856 /* Add packet to the peer. */
857 bgp_packet_add (peer, s);
858
pauleb821182004-05-01 08:44:08 +0000859 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000860}
861
862/* Make open packet and send it to the peer. */
863void
864bgp_open_send (struct peer *peer)
865{
866 struct stream *s;
867 int length;
868 u_int16_t send_holdtime;
869 as_t local_as;
870
871 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
872 send_holdtime = peer->holdtime;
873 else
874 send_holdtime = peer->bgp->default_holdtime;
875
876 /* local-as Change */
877 if (peer->change_local_as)
878 local_as = peer->change_local_as;
879 else
880 local_as = peer->local_as;
881
882 s = stream_new (BGP_MAX_PACKET_SIZE);
883
884 /* Make open packet. */
885 bgp_packet_set_marker (s, BGP_MSG_OPEN);
886
887 /* Set open packet values. */
888 stream_putc (s, BGP_VERSION_4); /* BGP version */
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000889 stream_putw (s, (local_as <= BGP_AS_MAX) ? (u_int16_t) local_as
890 : BGP_AS_TRANS);
paul718e3742002-12-13 20:15:29 +0000891 stream_putw (s, send_holdtime); /* Hold Time */
892 stream_put_in_addr (s, &peer->local_id); /* BGP Identifier */
893
894 /* Set capability code. */
895 bgp_open_capability (s, peer);
896
897 /* Set BGP packet length. */
898 length = bgp_packet_set_size (s);
899
900 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +0400901 zlog_debug ("%s sending OPEN, version %d, my as %u, holdtime %d, id %s",
paul718e3742002-12-13 20:15:29 +0000902 peer->host, BGP_VERSION_4, local_as,
903 send_holdtime, inet_ntoa (peer->local_id));
904
905 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000906 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000907 peer->host, BGP_MSG_OPEN, length);
908
909 /* Dump packet if debug option is set. */
910 /* bgp_packet_dump (s); */
911
912 /* Add packet to the peer. */
913 bgp_packet_add (peer, s);
914
pauleb821182004-05-01 08:44:08 +0000915 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000916}
917
918/* Send BGP notify packet with data potion. */
919void
920bgp_notify_send_with_data (struct peer *peer, u_char code, u_char sub_code,
921 u_char *data, size_t datalen)
922{
923 struct stream *s;
924 int length;
925
926 /* Allocate new stream. */
927 s = stream_new (BGP_MAX_PACKET_SIZE);
928
929 /* Make nitify packet. */
930 bgp_packet_set_marker (s, BGP_MSG_NOTIFY);
931
932 /* Set notify packet values. */
933 stream_putc (s, code); /* BGP notify code */
934 stream_putc (s, sub_code); /* BGP notify sub_code */
935
936 /* If notify data is present. */
937 if (data)
938 stream_write (s, data, datalen);
939
940 /* Set BGP packet length. */
941 length = bgp_packet_set_size (s);
942
943 /* Add packet to the peer. */
944 stream_fifo_clean (peer->obuf);
945 bgp_packet_add (peer, s);
946
947 /* For debug */
948 {
949 struct bgp_notify bgp_notify;
950 int first = 0;
951 int i;
952 char c[4];
953
954 bgp_notify.code = code;
955 bgp_notify.subcode = sub_code;
956 bgp_notify.data = NULL;
957 bgp_notify.length = length - BGP_MSG_NOTIFY_MIN_SIZE;
958
959 if (bgp_notify.length)
960 {
961 bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
962 for (i = 0; i < bgp_notify.length; i++)
963 if (first)
964 {
965 sprintf (c, " %02x", data[i]);
966 strcat (bgp_notify.data, c);
967 }
968 else
969 {
970 first = 1;
971 sprintf (c, "%02x", data[i]);
972 strcpy (bgp_notify.data, c);
973 }
974 }
975 bgp_notify_print (peer, &bgp_notify, "sending");
976 if (bgp_notify.data)
977 XFREE (MTYPE_TMP, bgp_notify.data);
978 }
979
980 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000981 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000982 peer->host, BGP_MSG_NOTIFY, length);
983
hassoe0701b72004-05-20 09:19:34 +0000984 /* peer reset cause */
985 if (sub_code != BGP_NOTIFY_CEASE_CONFIG_CHANGE)
986 {
987 if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET)
heasley1212dc12011-09-12 13:27:52 +0400988 {
989 peer->last_reset = PEER_DOWN_USER_RESET;
990 zlog_info ("Notification sent to neighbor %s: User reset", peer->host);
991 }
hassoe0701b72004-05-20 09:19:34 +0000992 else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN)
heasley1212dc12011-09-12 13:27:52 +0400993 {
994 peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
995 zlog_info ("Notification sent to neighbor %s: shutdown", peer->host);
996 }
hassoe0701b72004-05-20 09:19:34 +0000997 else
heasley1212dc12011-09-12 13:27:52 +0400998 {
999 peer->last_reset = PEER_DOWN_NOTIFY_SEND;
1000 zlog_info ("Notification sent to neighbor %s: type %u/%u",
1001 peer->host, code, sub_code);
1002 }
hassoe0701b72004-05-20 09:19:34 +00001003 }
heasley1212dc12011-09-12 13:27:52 +04001004 else
1005 zlog_info ("Notification sent to neighbor %s: configuration change",
1006 peer->host);
hassoe0701b72004-05-20 09:19:34 +00001007
Denis Ovsienko7ccf5e52011-09-10 16:53:30 +04001008 /* Call immediately. */
paul718e3742002-12-13 20:15:29 +00001009 BGP_WRITE_OFF (peer->t_write);
1010
1011 bgp_write_notify (peer);
1012}
1013
1014/* Send BGP notify packet. */
1015void
1016bgp_notify_send (struct peer *peer, u_char code, u_char sub_code)
1017{
1018 bgp_notify_send_with_data (peer, code, sub_code, NULL, 0);
1019}
1020
paul718e3742002-12-13 20:15:29 +00001021/* Send route refresh message to the peer. */
1022void
1023bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
1024 u_char orf_type, u_char when_to_refresh, int remove)
1025{
1026 struct stream *s;
1027 struct stream *packet;
1028 int length;
1029 struct bgp_filter *filter;
1030 int orf_refresh = 0;
1031
Paul Jakma750e8142008-07-22 21:11:48 +00001032 if (DISABLE_BGP_ANNOUNCE)
1033 return;
paul718e3742002-12-13 20:15:29 +00001034
1035 filter = &peer->filter[afi][safi];
1036
1037 /* Adjust safi code. */
1038 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001039 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +00001040
1041 s = stream_new (BGP_MAX_PACKET_SIZE);
1042
1043 /* Make BGP update packet. */
1044 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
1045 bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_NEW);
1046 else
1047 bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_OLD);
1048
1049 /* Encode Route Refresh message. */
1050 stream_putw (s, afi);
1051 stream_putc (s, 0);
1052 stream_putc (s, safi);
1053
1054 if (orf_type == ORF_TYPE_PREFIX
1055 || orf_type == ORF_TYPE_PREFIX_OLD)
1056 if (remove || filter->plist[FILTER_IN].plist)
1057 {
1058 u_int16_t orf_len;
1059 unsigned long orfp;
1060
1061 orf_refresh = 1;
1062 stream_putc (s, when_to_refresh);
1063 stream_putc (s, orf_type);
paul9985f832005-02-09 15:51:56 +00001064 orfp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00001065 stream_putw (s, 0);
1066
1067 if (remove)
1068 {
1069 UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
1070 stream_putc (s, ORF_COMMON_PART_REMOVE_ALL);
1071 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001072 zlog_debug ("%s sending REFRESH_REQ to remove ORF(%d) (%s) for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001073 peer->host, orf_type,
1074 (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
1075 afi, safi);
1076 }
1077 else
1078 {
1079 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
1080 prefix_bgp_orf_entry (s, filter->plist[FILTER_IN].plist,
1081 ORF_COMMON_PART_ADD, ORF_COMMON_PART_PERMIT,
1082 ORF_COMMON_PART_DENY);
1083 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001084 zlog_debug ("%s sending REFRESH_REQ with pfxlist ORF(%d) (%s) for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001085 peer->host, orf_type,
1086 (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
1087 afi, safi);
1088 }
1089
1090 /* Total ORF Entry Len. */
paul9985f832005-02-09 15:51:56 +00001091 orf_len = stream_get_endp (s) - orfp - 2;
paul718e3742002-12-13 20:15:29 +00001092 stream_putw_at (s, orfp, orf_len);
1093 }
1094
1095 /* Set packet size. */
1096 length = bgp_packet_set_size (s);
1097
1098 if (BGP_DEBUG (normal, NORMAL))
1099 {
1100 if (! orf_refresh)
ajs6b514742004-12-08 21:03:23 +00001101 zlog_debug ("%s sending REFRESH_REQ for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001102 peer->host, afi, safi);
ajs6b514742004-12-08 21:03:23 +00001103 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +00001104 peer->host, CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV) ?
1105 BGP_MSG_ROUTE_REFRESH_NEW : BGP_MSG_ROUTE_REFRESH_OLD, length);
1106 }
1107
1108 /* Make real packet. */
paule83e2082005-05-19 02:12:25 +00001109 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +00001110 stream_free (s);
1111
1112 /* Add packet to the peer. */
1113 bgp_packet_add (peer, packet);
1114
pauleb821182004-05-01 08:44:08 +00001115 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +00001116}
1117
1118/* Send capability message to the peer. */
1119void
1120bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi,
1121 int capability_code, int action)
1122{
1123 struct stream *s;
1124 struct stream *packet;
1125 int length;
1126
1127 /* Adjust safi code. */
1128 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001129 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +00001130
1131 s = stream_new (BGP_MAX_PACKET_SIZE);
1132
1133 /* Make BGP update packet. */
1134 bgp_packet_set_marker (s, BGP_MSG_CAPABILITY);
1135
1136 /* Encode MP_EXT capability. */
1137 if (capability_code == CAPABILITY_CODE_MP)
1138 {
1139 stream_putc (s, action);
1140 stream_putc (s, CAPABILITY_CODE_MP);
1141 stream_putc (s, CAPABILITY_CODE_MP_LEN);
1142 stream_putw (s, afi);
1143 stream_putc (s, 0);
1144 stream_putc (s, safi);
1145
1146 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001147 zlog_debug ("%s sending CAPABILITY has %s MP_EXT CAP for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001148 peer->host, action == CAPABILITY_ACTION_SET ?
1149 "Advertising" : "Removing", afi, safi);
1150 }
1151
paul718e3742002-12-13 20:15:29 +00001152 /* Set packet size. */
1153 length = bgp_packet_set_size (s);
1154
1155 /* Make real packet. */
paule83e2082005-05-19 02:12:25 +00001156 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +00001157 stream_free (s);
1158
1159 /* Add packet to the peer. */
1160 bgp_packet_add (peer, packet);
1161
1162 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001163 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +00001164 peer->host, BGP_MSG_CAPABILITY, length);
1165
pauleb821182004-05-01 08:44:08 +00001166 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +00001167}
David Lamparter6b0655a2014-06-04 06:53:35 +02001168
paul718e3742002-12-13 20:15:29 +00001169/* RFC1771 6.8 Connection collision detection. */
paul94f2b392005-06-28 12:44:16 +00001170static int
pauleb821182004-05-01 08:44:08 +00001171bgp_collision_detect (struct peer *new, struct in_addr remote_id)
paul718e3742002-12-13 20:15:29 +00001172{
pauleb821182004-05-01 08:44:08 +00001173 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001174 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001175 struct bgp *bgp;
1176
1177 bgp = bgp_get_default ();
1178 if (! bgp)
1179 return 0;
1180
1181 /* Upon receipt of an OPEN message, the local system must examine
1182 all of its connections that are in the OpenConfirm state. A BGP
1183 speaker may also examine connections in an OpenSent state if it
1184 knows the BGP Identifier of the peer by means outside of the
1185 protocol. If among these connections there is a connection to a
1186 remote BGP speaker whose BGP Identifier equals the one in the
1187 OPEN message, then the local system performs the following
1188 collision resolution procedure: */
1189
paul1eb8ef22005-04-07 07:30:20 +00001190 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001191 {
1192 /* Under OpenConfirm status, local peer structure already hold
1193 remote router ID. */
pauleb821182004-05-01 08:44:08 +00001194
1195 if (peer != new
1196 && (peer->status == OpenConfirm || peer->status == OpenSent)
1197 && sockunion_same (&peer->su, &new->su))
1198 {
paul718e3742002-12-13 20:15:29 +00001199 /* 1. The BGP Identifier of the local system is compared to
1200 the BGP Identifier of the remote system (as specified in
1201 the OPEN message). */
1202
1203 if (ntohl (peer->local_id.s_addr) < ntohl (remote_id.s_addr))
1204 {
1205 /* 2. If the value of the local BGP Identifier is less
1206 than the remote one, the local system closes BGP
1207 connection that already exists (the one that is
1208 already in the OpenConfirm state), and accepts BGP
1209 connection initiated by the remote system. */
1210
pauleb821182004-05-01 08:44:08 +00001211 if (peer->fd >= 0)
hassoe0701b72004-05-20 09:19:34 +00001212 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
paul718e3742002-12-13 20:15:29 +00001213 return 1;
1214 }
1215 else
1216 {
1217 /* 3. Otherwise, the local system closes newly created
1218 BGP connection (the one associated with the newly
1219 received OPEN message), and continues to use the
1220 existing one (the one that is already in the
1221 OpenConfirm state). */
1222
pauleb821182004-05-01 08:44:08 +00001223 if (new->fd >= 0)
paulf5ba3872004-07-09 12:11:31 +00001224 bgp_notify_send (new, BGP_NOTIFY_CEASE,
1225 BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
paul718e3742002-12-13 20:15:29 +00001226 return -1;
1227 }
pauleb821182004-05-01 08:44:08 +00001228 }
1229 }
paul718e3742002-12-13 20:15:29 +00001230 return 0;
1231}
1232
paul94f2b392005-06-28 12:44:16 +00001233static int
paul718e3742002-12-13 20:15:29 +00001234bgp_open_receive (struct peer *peer, bgp_size_t size)
1235{
1236 int ret;
1237 u_char version;
1238 u_char optlen;
1239 u_int16_t holdtime;
1240 u_int16_t send_holdtime;
1241 as_t remote_as;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001242 as_t as4 = 0;
paul718e3742002-12-13 20:15:29 +00001243 struct peer *realpeer;
1244 struct in_addr remote_id;
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001245 int mp_capability;
paul5228ad22004-06-04 17:58:18 +00001246 u_int8_t notify_data_remote_as[2];
1247 u_int8_t notify_data_remote_id[4];
paul718e3742002-12-13 20:15:29 +00001248
1249 realpeer = NULL;
1250
1251 /* Parse open packet. */
1252 version = stream_getc (peer->ibuf);
1253 memcpy (notify_data_remote_as, stream_pnt (peer->ibuf), 2);
1254 remote_as = stream_getw (peer->ibuf);
1255 holdtime = stream_getw (peer->ibuf);
1256 memcpy (notify_data_remote_id, stream_pnt (peer->ibuf), 4);
1257 remote_id.s_addr = stream_get_ipv4 (peer->ibuf);
1258
1259 /* Receive OPEN message log */
1260 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001261 zlog_debug ("%s rcv OPEN, version %d, remote-as (in open) %u,"
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001262 " holdtime %d, id %s",
1263 peer->host, version, remote_as, holdtime,
1264 inet_ntoa (remote_id));
1265
1266 /* BEGIN to read the capability here, but dont do it yet */
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001267 mp_capability = 0;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001268 optlen = stream_getc (peer->ibuf);
1269
1270 if (optlen != 0)
1271 {
1272 /* We need the as4 capability value *right now* because
1273 * if it is there, we have not got the remote_as yet, and without
1274 * that we do not know which peer is connecting to us now.
1275 */
1276 as4 = peek_for_as4_capability (peer, optlen);
1277 }
1278
1279 /* Just in case we have a silly peer who sends AS4 capability set to 0 */
1280 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) && !as4)
1281 {
1282 zlog_err ("%s bad OPEN, got AS4 capability, but AS4 set to 0",
1283 peer->host);
1284 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1285 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1286 return -1;
1287 }
1288
1289 if (remote_as == BGP_AS_TRANS)
1290 {
1291 /* Take the AS4 from the capability. We must have received the
1292 * capability now! Otherwise we have a asn16 peer who uses
1293 * BGP_AS_TRANS, for some unknown reason.
1294 */
1295 if (as4 == BGP_AS_TRANS)
1296 {
1297 zlog_err ("%s [AS4] NEW speaker using AS_TRANS for AS4, not allowed",
1298 peer->host);
1299 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1300 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1301 return -1;
1302 }
1303
1304 if (!as4 && BGP_DEBUG (as4, AS4))
1305 zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but no AS4."
1306 " Odd, but proceeding.", peer->host);
1307 else if (as4 < BGP_AS_MAX && BGP_DEBUG (as4, AS4))
Paul Jakma0df7c912008-07-21 21:02:49 +00001308 zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but AS4 (%u) fits "
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001309 "in 2-bytes, very odd peer.", peer->host, as4);
1310 if (as4)
1311 remote_as = as4;
1312 }
1313 else
1314 {
1315 /* We may have a partner with AS4 who has an asno < BGP_AS_MAX */
1316 /* If we have got the capability, peer->as4cap must match remote_as */
1317 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)
1318 && as4 != remote_as)
1319 {
1320 /* raise error, log this, close session */
1321 zlog_err ("%s bad OPEN, got AS4 capability, but remote_as %u"
1322 " mismatch with 16bit 'myasn' %u in open",
1323 peer->host, as4, remote_as);
1324 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1325 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1326 return -1;
1327 }
1328 }
1329
paul718e3742002-12-13 20:15:29 +00001330 /* Lookup peer from Open packet. */
1331 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1332 {
1333 int as = 0;
1334
1335 realpeer = peer_lookup_with_open (&peer->su, remote_as, &remote_id, &as);
1336
1337 if (! realpeer)
1338 {
1339 /* Peer's source IP address is check in bgp_accept(), so this
1340 must be AS number mismatch or remote-id configuration
1341 mismatch. */
1342 if (as)
1343 {
1344 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001345 zlog_debug ("%s bad OPEN, wrong router identifier %s",
1346 peer->host, inet_ntoa (remote_id));
1347 bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
1348 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
1349 notify_data_remote_id, 4);
paul718e3742002-12-13 20:15:29 +00001350 }
1351 else
1352 {
1353 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001354 zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
ajs6b514742004-12-08 21:03:23 +00001355 peer->host, remote_as, peer->as);
1356 bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
1357 BGP_NOTIFY_OPEN_BAD_PEER_AS,
1358 notify_data_remote_as, 2);
paul718e3742002-12-13 20:15:29 +00001359 }
1360 return -1;
1361 }
1362 }
1363
1364 /* When collision is detected and this peer is closed. Retrun
1365 immidiately. */
1366 ret = bgp_collision_detect (peer, remote_id);
1367 if (ret < 0)
1368 return ret;
1369
pauleb821182004-05-01 08:44:08 +00001370 /* Hack part. */
1371 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1372 {
hasso93406d82005-02-02 14:40:33 +00001373 if (realpeer->status == Established
1374 && CHECK_FLAG (realpeer->sflags, PEER_STATUS_NSF_MODE))
1375 {
1376 realpeer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
1377 SET_FLAG (realpeer->sflags, PEER_STATUS_NSF_WAIT);
1378 }
1379 else if (ret == 0 && realpeer->status != Active
1380 && realpeer->status != OpenSent
Paul Jakma6e199262008-09-09 17:14:33 +01001381 && realpeer->status != OpenConfirm
1382 && realpeer->status != Connect)
pauleb821182004-05-01 08:44:08 +00001383 {
Paul Jakma2b2fc562008-09-06 13:09:35 +01001384 /* XXX: This is an awful problem..
1385 *
1386 * According to the RFC we should just let this connection (of the
1387 * accepted 'peer') continue on to Established if the other
1388 * connection (the 'realpeer' one) is in state Connect, and deal
1389 * with the more larval FSM as/when it gets far enough to receive
1390 * an Open. We don't do that though, we instead close the (more
1391 * developed) accepted connection.
1392 *
1393 * This means there's a race, which if hit, can loop:
1394 *
1395 * FSM for A FSM for B
1396 * realpeer accept-peer realpeer accept-peer
1397 *
1398 * Connect Connect
1399 * Active
1400 * OpenSent OpenSent
1401 * <arrive here,
1402 * Notify, delete>
1403 * Idle Active
1404 * OpenSent OpenSent
1405 * <arrive here,
1406 * Notify, delete>
1407 * Idle
1408 * <wait> <wait>
1409 * Connect Connect
1410 *
1411 *
1412 * If both sides are Quagga, they're almost certain to wait for
1413 * the same amount of time of course (which doesn't preclude other
1414 * implementations also waiting for same time). The race is
1415 * exacerbated by high-latency (in bgpd and/or the network).
1416 *
1417 * The reason we do this is because our FSM is tied to our peer
1418 * structure, which carries our configuration information, etc.
1419 * I.e. we can't let the accepted-peer FSM continue on as it is,
1420 * cause it's not associated with any actual peer configuration -
1421 * it's just a dummy.
1422 *
1423 * It's possible we could hack-fix this by just bgp_stop'ing the
1424 * realpeer and continueing on with the 'transfer FSM' below.
1425 * Ideally, we need to seperate FSMs from struct peer.
1426 *
1427 * Setting one side to passive avoids the race, as a workaround.
1428 */
pauleb821182004-05-01 08:44:08 +00001429 if (BGP_DEBUG (events, EVENTS))
hasso93406d82005-02-02 14:40:33 +00001430 zlog_debug ("%s peer status is %s close connection",
1431 realpeer->host, LOOKUP (bgp_status_msg,
1432 realpeer->status));
1433 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1434 BGP_NOTIFY_CEASE_CONNECT_REJECT);
1435
pauleb821182004-05-01 08:44:08 +00001436 return -1;
1437 }
1438
1439 if (BGP_DEBUG (events, EVENTS))
Paul Jakma6e199262008-09-09 17:14:33 +01001440 zlog_debug ("%s [Event] Transfer accept BGP peer to real (state %s)",
1441 peer->host,
1442 LOOKUP (bgp_status_msg, realpeer->status));
pauleb821182004-05-01 08:44:08 +00001443
1444 bgp_stop (realpeer);
1445
1446 /* Transfer file descriptor. */
1447 realpeer->fd = peer->fd;
1448 peer->fd = -1;
1449
1450 /* Transfer input buffer. */
1451 stream_free (realpeer->ibuf);
1452 realpeer->ibuf = peer->ibuf;
1453 realpeer->packet_size = peer->packet_size;
1454 peer->ibuf = NULL;
1455
1456 /* Transfer status. */
1457 realpeer->status = peer->status;
1458 bgp_stop (peer);
paul200df112005-06-01 11:17:05 +00001459
pauleb821182004-05-01 08:44:08 +00001460 /* peer pointer change. Open packet send to neighbor. */
1461 peer = realpeer;
1462 bgp_open_send (peer);
1463 if (peer->fd < 0)
1464 {
1465 zlog_err ("bgp_open_receive peer's fd is negative value %d",
1466 peer->fd);
1467 return -1;
1468 }
1469 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
1470 }
1471
paul718e3742002-12-13 20:15:29 +00001472 /* remote router-id check. */
1473 if (remote_id.s_addr == 0
Denis Ovsienko733cd9e2011-12-17 19:39:30 +04001474 || IPV4_CLASS_DE (ntohl (remote_id.s_addr))
paul718e3742002-12-13 20:15:29 +00001475 || ntohl (peer->local_id.s_addr) == ntohl (remote_id.s_addr))
1476 {
1477 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001478 zlog_debug ("%s bad OPEN, wrong router identifier %s",
paul718e3742002-12-13 20:15:29 +00001479 peer->host, inet_ntoa (remote_id));
1480 bgp_notify_send_with_data (peer,
1481 BGP_NOTIFY_OPEN_ERR,
1482 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
1483 notify_data_remote_id, 4);
1484 return -1;
1485 }
1486
1487 /* Set remote router-id */
1488 peer->remote_id = remote_id;
1489
1490 /* Peer BGP version check. */
1491 if (version != BGP_VERSION_4)
1492 {
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001493 u_int16_t maxver = htons(BGP_VERSION_4);
1494 /* XXX this reply may not be correct if version < 4 XXX */
paul718e3742002-12-13 20:15:29 +00001495 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001496 zlog_debug ("%s bad protocol version, remote requested %d, local request %d",
paul718e3742002-12-13 20:15:29 +00001497 peer->host, version, BGP_VERSION_4);
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001498 /* Data must be in network byte order here */
paul718e3742002-12-13 20:15:29 +00001499 bgp_notify_send_with_data (peer,
1500 BGP_NOTIFY_OPEN_ERR,
1501 BGP_NOTIFY_OPEN_UNSUP_VERSION,
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001502 (u_int8_t *) &maxver, 2);
paul718e3742002-12-13 20:15:29 +00001503 return -1;
1504 }
1505
1506 /* Check neighbor as number. */
1507 if (remote_as != peer->as)
1508 {
1509 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001510 zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
paul718e3742002-12-13 20:15:29 +00001511 peer->host, remote_as, peer->as);
1512 bgp_notify_send_with_data (peer,
1513 BGP_NOTIFY_OPEN_ERR,
1514 BGP_NOTIFY_OPEN_BAD_PEER_AS,
1515 notify_data_remote_as, 2);
1516 return -1;
1517 }
1518
1519 /* From the rfc: Upon receipt of an OPEN message, a BGP speaker MUST
1520 calculate the value of the Hold Timer by using the smaller of its
1521 configured Hold Time and the Hold Time received in the OPEN message.
1522 The Hold Time MUST be either zero or at least three seconds. An
1523 implementation may reject connections on the basis of the Hold Time. */
1524
1525 if (holdtime < 3 && holdtime != 0)
1526 {
1527 bgp_notify_send (peer,
1528 BGP_NOTIFY_OPEN_ERR,
1529 BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
1530 return -1;
1531 }
1532
1533 /* From the rfc: A reasonable maximum time between KEEPALIVE messages
1534 would be one third of the Hold Time interval. KEEPALIVE messages
1535 MUST NOT be sent more frequently than one per second. An
1536 implementation MAY adjust the rate at which it sends KEEPALIVE
1537 messages as a function of the Hold Time interval. */
1538
1539 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
1540 send_holdtime = peer->holdtime;
1541 else
1542 send_holdtime = peer->bgp->default_holdtime;
1543
1544 if (holdtime < send_holdtime)
1545 peer->v_holdtime = holdtime;
1546 else
1547 peer->v_holdtime = send_holdtime;
1548
1549 peer->v_keepalive = peer->v_holdtime / 3;
1550
1551 /* Open option part parse. */
paul718e3742002-12-13 20:15:29 +00001552 if (optlen != 0)
1553 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001554 if ((ret = bgp_open_option_parse (peer, optlen, &mp_capability)) < 0)
Paul Jakma58617392012-01-09 20:59:26 +00001555 {
1556 bgp_notify_send (peer,
1557 BGP_NOTIFY_OPEN_ERR,
1558 BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
1559 return ret;
1560 }
paul718e3742002-12-13 20:15:29 +00001561 }
1562 else
1563 {
1564 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001565 zlog_debug ("%s rcvd OPEN w/ OPTION parameter len: 0",
paul718e3742002-12-13 20:15:29 +00001566 peer->host);
1567 }
1568
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001569 /*
1570 * Assume that the peer supports the locally configured set of
1571 * AFI/SAFIs if the peer did not send us any Mulitiprotocol
1572 * capabilities, or if 'override-capability' is configured.
1573 */
1574 if (! mp_capability ||
1575 CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
paul718e3742002-12-13 20:15:29 +00001576 {
1577 peer->afc_nego[AFI_IP][SAFI_UNICAST] = peer->afc[AFI_IP][SAFI_UNICAST];
1578 peer->afc_nego[AFI_IP][SAFI_MULTICAST] = peer->afc[AFI_IP][SAFI_MULTICAST];
1579 peer->afc_nego[AFI_IP6][SAFI_UNICAST] = peer->afc[AFI_IP6][SAFI_UNICAST];
1580 peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = peer->afc[AFI_IP6][SAFI_MULTICAST];
1581 }
1582
1583 /* Get sockname. */
1584 bgp_getsockname (peer);
1585
1586 BGP_EVENT_ADD (peer, Receive_OPEN_message);
1587
1588 peer->packet_size = 0;
1589 if (peer->ibuf)
1590 stream_reset (peer->ibuf);
1591
1592 return 0;
1593}
1594
1595/* Parse BGP Update packet and make attribute object. */
paul94f2b392005-06-28 12:44:16 +00001596static int
paul718e3742002-12-13 20:15:29 +00001597bgp_update_receive (struct peer *peer, bgp_size_t size)
1598{
1599 int ret;
1600 u_char *end;
1601 struct stream *s;
1602 struct attr attr;
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001603 struct attr_extra extra;
paul718e3742002-12-13 20:15:29 +00001604 bgp_size_t attribute_len;
1605 bgp_size_t update_len;
1606 bgp_size_t withdraw_len;
1607 struct bgp_nlri update;
1608 struct bgp_nlri withdraw;
1609 struct bgp_nlri mp_update;
1610 struct bgp_nlri mp_withdraw;
paul718e3742002-12-13 20:15:29 +00001611
1612 /* Status must be Established. */
1613 if (peer->status != Established)
1614 {
1615 zlog_err ("%s [FSM] Update packet received under status %s",
1616 peer->host, LOOKUP (bgp_status_msg, peer->status));
1617 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
1618 return -1;
1619 }
1620
1621 /* Set initial values. */
1622 memset (&attr, 0, sizeof (struct attr));
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001623 memset (&extra, 0, sizeof (struct attr_extra));
paul718e3742002-12-13 20:15:29 +00001624 memset (&update, 0, sizeof (struct bgp_nlri));
1625 memset (&withdraw, 0, sizeof (struct bgp_nlri));
1626 memset (&mp_update, 0, sizeof (struct bgp_nlri));
1627 memset (&mp_withdraw, 0, sizeof (struct bgp_nlri));
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001628 attr.extra = &extra;
paul718e3742002-12-13 20:15:29 +00001629
1630 s = peer->ibuf;
1631 end = stream_pnt (s) + size;
1632
1633 /* RFC1771 6.3 If the Unfeasible Routes Length or Total Attribute
1634 Length is too large (i.e., if Unfeasible Routes Length + Total
1635 Attribute Length + 23 exceeds the message Length), then the Error
1636 Subcode is set to Malformed Attribute List. */
1637 if (stream_pnt (s) + 2 > end)
1638 {
1639 zlog_err ("%s [Error] Update packet error"
1640 " (packet length is short for unfeasible length)",
1641 peer->host);
1642 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1643 BGP_NOTIFY_UPDATE_MAL_ATTR);
1644 return -1;
1645 }
1646
1647 /* Unfeasible Route Length. */
1648 withdraw_len = stream_getw (s);
1649
1650 /* Unfeasible Route Length check. */
1651 if (stream_pnt (s) + withdraw_len > end)
1652 {
1653 zlog_err ("%s [Error] Update packet error"
1654 " (packet unfeasible length overflow %d)",
1655 peer->host, withdraw_len);
1656 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1657 BGP_NOTIFY_UPDATE_MAL_ATTR);
1658 return -1;
1659 }
1660
1661 /* Unfeasible Route packet format check. */
1662 if (withdraw_len > 0)
1663 {
1664 ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), withdraw_len);
1665 if (ret < 0)
1666 return -1;
1667
1668 if (BGP_DEBUG (packet, PACKET_RECV))
ajs6b514742004-12-08 21:03:23 +00001669 zlog_debug ("%s [Update:RECV] Unfeasible NLRI received", peer->host);
paul718e3742002-12-13 20:15:29 +00001670
1671 withdraw.afi = AFI_IP;
1672 withdraw.safi = SAFI_UNICAST;
1673 withdraw.nlri = stream_pnt (s);
1674 withdraw.length = withdraw_len;
paul9985f832005-02-09 15:51:56 +00001675 stream_forward_getp (s, withdraw_len);
paul718e3742002-12-13 20:15:29 +00001676 }
1677
1678 /* Attribute total length check. */
1679 if (stream_pnt (s) + 2 > end)
1680 {
1681 zlog_warn ("%s [Error] Packet Error"
1682 " (update packet is short for attribute length)",
1683 peer->host);
1684 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1685 BGP_NOTIFY_UPDATE_MAL_ATTR);
1686 return -1;
1687 }
1688
1689 /* Fetch attribute total length. */
1690 attribute_len = stream_getw (s);
1691
1692 /* Attribute length check. */
1693 if (stream_pnt (s) + attribute_len > end)
1694 {
1695 zlog_warn ("%s [Error] Packet Error"
1696 " (update packet attribute length overflow %d)",
1697 peer->host, attribute_len);
1698 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1699 BGP_NOTIFY_UPDATE_MAL_ATTR);
1700 return -1;
1701 }
Paul Jakmab881c702010-11-23 16:35:42 +00001702
1703 /* Certain attribute parsing errors should not be considered bad enough
1704 * to reset the session for, most particularly any partial/optional
1705 * attributes that have 'tunneled' over speakers that don't understand
1706 * them. Instead we withdraw only the prefix concerned.
1707 *
1708 * Complicates the flow a little though..
1709 */
1710 bgp_attr_parse_ret_t attr_parse_ret = BGP_ATTR_PARSE_PROCEED;
1711 /* This define morphs the update case into a withdraw when lower levels
1712 * have signalled an error condition where this is best.
1713 */
1714#define NLRI_ATTR_ARG (attr_parse_ret != BGP_ATTR_PARSE_WITHDRAW ? &attr : NULL)
paul718e3742002-12-13 20:15:29 +00001715
1716 /* Parse attribute when it exists. */
1717 if (attribute_len)
1718 {
Paul Jakmab881c702010-11-23 16:35:42 +00001719 attr_parse_ret = bgp_attr_parse (peer, &attr, attribute_len,
paul718e3742002-12-13 20:15:29 +00001720 &mp_update, &mp_withdraw);
Paul Jakmab881c702010-11-23 16:35:42 +00001721 if (attr_parse_ret == BGP_ATTR_PARSE_ERROR)
David Lamparterf80f8382014-06-04 01:00:51 +02001722 {
1723 bgp_attr_unintern_sub (&attr);
1724 return -1;
1725 }
paul718e3742002-12-13 20:15:29 +00001726 }
Paul Jakmab881c702010-11-23 16:35:42 +00001727
paul718e3742002-12-13 20:15:29 +00001728 /* Logging the attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001729 if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW
1730 || BGP_DEBUG (update, UPDATE_IN))
paul718e3742002-12-13 20:15:29 +00001731 {
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +00001732 char attrstr[BUFSIZ];
1733 attrstr[0] = '\0';
1734
paule01f9cb2004-07-09 17:48:53 +00001735 ret= bgp_dump_attr (peer, &attr, attrstr, BUFSIZ);
Paul Jakmab881c702010-11-23 16:35:42 +00001736 int lvl = (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
1737 ? LOG_ERR : LOG_DEBUG;
1738
1739 if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
1740 zlog (peer->log, LOG_ERR,
1741 "%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.",
1742 peer->host);
paule01f9cb2004-07-09 17:48:53 +00001743
1744 if (ret)
Paul Jakmab881c702010-11-23 16:35:42 +00001745 zlog (peer->log, lvl, "%s rcvd UPDATE w/ attr: %s",
paule01f9cb2004-07-09 17:48:53 +00001746 peer->host, attrstr);
paul718e3742002-12-13 20:15:29 +00001747 }
Paul Jakmab881c702010-11-23 16:35:42 +00001748
paul718e3742002-12-13 20:15:29 +00001749 /* Network Layer Reachability Information. */
1750 update_len = end - stream_pnt (s);
1751
1752 if (update_len)
1753 {
1754 /* Check NLRI packet format and prefix length. */
1755 ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), update_len);
1756 if (ret < 0)
Paul Jakmab881c702010-11-23 16:35:42 +00001757 {
1758 bgp_attr_unintern_sub (&attr);
Paul Jakmab881c702010-11-23 16:35:42 +00001759 return -1;
1760 }
paul718e3742002-12-13 20:15:29 +00001761
1762 /* Set NLRI portion to structure. */
1763 update.afi = AFI_IP;
1764 update.safi = SAFI_UNICAST;
1765 update.nlri = stream_pnt (s);
1766 update.length = update_len;
paul9985f832005-02-09 15:51:56 +00001767 stream_forward_getp (s, update_len);
paul718e3742002-12-13 20:15:29 +00001768 }
1769
1770 /* NLRI is processed only when the peer is configured specific
1771 Address Family and Subsequent Address Family. */
1772 if (peer->afc[AFI_IP][SAFI_UNICAST])
1773 {
1774 if (withdraw.length)
1775 bgp_nlri_parse (peer, NULL, &withdraw);
1776
1777 if (update.length)
Paul Jakmab881c702010-11-23 16:35:42 +00001778 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &update);
paule01f9cb2004-07-09 17:48:53 +00001779
hassof4184462005-02-01 20:13:16 +00001780 if (mp_update.length
1781 && mp_update.afi == AFI_IP
1782 && mp_update.safi == SAFI_UNICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001783 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
hassof4184462005-02-01 20:13:16 +00001784
1785 if (mp_withdraw.length
1786 && mp_withdraw.afi == AFI_IP
1787 && mp_withdraw.safi == SAFI_UNICAST)
1788 bgp_nlri_parse (peer, NULL, &mp_withdraw);
1789
paule01f9cb2004-07-09 17:48:53 +00001790 if (! attribute_len && ! withdraw_len)
1791 {
1792 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001793 SET_FLAG (peer->af_sflags[AFI_IP][SAFI_UNICAST],
1794 PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001795
hasso93406d82005-02-02 14:40:33 +00001796 /* NSF delete stale route */
1797 if (peer->nsf[AFI_IP][SAFI_UNICAST])
1798 bgp_clear_stale_route (peer, AFI_IP, SAFI_UNICAST);
1799
1800 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001801 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001802 peer->host);
1803 }
paul718e3742002-12-13 20:15:29 +00001804 }
1805 if (peer->afc[AFI_IP][SAFI_MULTICAST])
1806 {
1807 if (mp_update.length
1808 && mp_update.afi == AFI_IP
1809 && mp_update.safi == SAFI_MULTICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001810 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001811
1812 if (mp_withdraw.length
1813 && mp_withdraw.afi == AFI_IP
1814 && mp_withdraw.safi == SAFI_MULTICAST)
1815 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001816
hasso93406d82005-02-02 14:40:33 +00001817 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001818 && mp_withdraw.afi == AFI_IP
1819 && mp_withdraw.safi == SAFI_MULTICAST
1820 && mp_withdraw.length == 0)
1821 {
1822 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001823 SET_FLAG (peer->af_sflags[AFI_IP][SAFI_MULTICAST],
1824 PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001825
hasso93406d82005-02-02 14:40:33 +00001826 /* NSF delete stale route */
1827 if (peer->nsf[AFI_IP][SAFI_MULTICAST])
1828 bgp_clear_stale_route (peer, AFI_IP, SAFI_MULTICAST);
1829
1830 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001831 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Multicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001832 peer->host);
1833 }
paul718e3742002-12-13 20:15:29 +00001834 }
1835 if (peer->afc[AFI_IP6][SAFI_UNICAST])
1836 {
1837 if (mp_update.length
1838 && mp_update.afi == AFI_IP6
1839 && mp_update.safi == SAFI_UNICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001840 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001841
1842 if (mp_withdraw.length
1843 && mp_withdraw.afi == AFI_IP6
1844 && mp_withdraw.safi == SAFI_UNICAST)
1845 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001846
hasso93406d82005-02-02 14:40:33 +00001847 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001848 && mp_withdraw.afi == AFI_IP6
1849 && mp_withdraw.safi == SAFI_UNICAST
1850 && mp_withdraw.length == 0)
1851 {
1852 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001853 SET_FLAG (peer->af_sflags[AFI_IP6][SAFI_UNICAST], PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001854
hasso93406d82005-02-02 14:40:33 +00001855 /* NSF delete stale route */
1856 if (peer->nsf[AFI_IP6][SAFI_UNICAST])
1857 bgp_clear_stale_route (peer, AFI_IP6, SAFI_UNICAST);
1858
1859 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001860 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001861 peer->host);
1862 }
paul718e3742002-12-13 20:15:29 +00001863 }
1864 if (peer->afc[AFI_IP6][SAFI_MULTICAST])
1865 {
1866 if (mp_update.length
1867 && mp_update.afi == AFI_IP6
1868 && mp_update.safi == SAFI_MULTICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001869 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001870
1871 if (mp_withdraw.length
1872 && mp_withdraw.afi == AFI_IP6
1873 && mp_withdraw.safi == SAFI_MULTICAST)
1874 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001875
hasso93406d82005-02-02 14:40:33 +00001876 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001877 && mp_withdraw.afi == AFI_IP6
1878 && mp_withdraw.safi == SAFI_MULTICAST
1879 && mp_withdraw.length == 0)
1880 {
1881 /* End-of-RIB received */
1882
hasso93406d82005-02-02 14:40:33 +00001883 /* NSF delete stale route */
1884 if (peer->nsf[AFI_IP6][SAFI_MULTICAST])
1885 bgp_clear_stale_route (peer, AFI_IP6, SAFI_MULTICAST);
1886
paule01f9cb2004-07-09 17:48:53 +00001887 if (BGP_DEBUG (update, UPDATE_IN))
ajs6b514742004-12-08 21:03:23 +00001888 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Multicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001889 peer->host);
1890 }
paul718e3742002-12-13 20:15:29 +00001891 }
1892 if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
1893 {
1894 if (mp_update.length
1895 && mp_update.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001896 && mp_update.safi == SAFI_MPLS_LABELED_VPN)
Paul Jakmab881c702010-11-23 16:35:42 +00001897 bgp_nlri_parse_vpnv4 (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001898
1899 if (mp_withdraw.length
1900 && mp_withdraw.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001901 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00001902 bgp_nlri_parse_vpnv4 (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001903
hasso93406d82005-02-02 14:40:33 +00001904 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001905 && mp_withdraw.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001906 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN
paule01f9cb2004-07-09 17:48:53 +00001907 && mp_withdraw.length == 0)
1908 {
1909 /* End-of-RIB received */
1910
1911 if (BGP_DEBUG (update, UPDATE_IN))
ajs6b514742004-12-08 21:03:23 +00001912 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for VPNv4 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001913 peer->host);
1914 }
paul718e3742002-12-13 20:15:29 +00001915 }
1916
1917 /* Everything is done. We unintern temporary structures which
1918 interned in bgp_attr_parse(). */
Paul Jakmab881c702010-11-23 16:35:42 +00001919 bgp_attr_unintern_sub (&attr);
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001920
paul718e3742002-12-13 20:15:29 +00001921 /* If peering is stopped due to some reason, do not generate BGP
1922 event. */
1923 if (peer->status != Established)
1924 return 0;
1925
1926 /* Increment packet counter. */
1927 peer->update_in++;
Stephen Hemminger65957882010-01-15 16:22:10 +03001928 peer->update_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00001929
Jorge Boncompte [DTI2]e2c38e62012-06-20 17:45:50 +02001930 /* Rearm holdtime timer */
Jorge Boncompte [DTI2]6a4677b2012-05-07 16:53:07 +00001931 BGP_TIMER_OFF (peer->t_holdtime);
Jorge Boncompte [DTI2]e2c38e62012-06-20 17:45:50 +02001932 bgp_timer_set (peer);
paul718e3742002-12-13 20:15:29 +00001933
1934 return 0;
1935}
1936
1937/* Notify message treatment function. */
paul94f2b392005-06-28 12:44:16 +00001938static void
paul718e3742002-12-13 20:15:29 +00001939bgp_notify_receive (struct peer *peer, bgp_size_t size)
1940{
1941 struct bgp_notify bgp_notify;
1942
1943 if (peer->notify.data)
1944 {
1945 XFREE (MTYPE_TMP, peer->notify.data);
1946 peer->notify.data = NULL;
1947 peer->notify.length = 0;
1948 }
1949
1950 bgp_notify.code = stream_getc (peer->ibuf);
1951 bgp_notify.subcode = stream_getc (peer->ibuf);
1952 bgp_notify.length = size - 2;
1953 bgp_notify.data = NULL;
1954
1955 /* Preserv notify code and sub code. */
1956 peer->notify.code = bgp_notify.code;
1957 peer->notify.subcode = bgp_notify.subcode;
1958 /* For further diagnostic record returned Data. */
1959 if (bgp_notify.length)
1960 {
1961 peer->notify.length = size - 2;
1962 peer->notify.data = XMALLOC (MTYPE_TMP, size - 2);
1963 memcpy (peer->notify.data, stream_pnt (peer->ibuf), size - 2);
1964 }
1965
1966 /* For debug */
1967 {
1968 int i;
1969 int first = 0;
1970 char c[4];
1971
1972 if (bgp_notify.length)
1973 {
1974 bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
1975 for (i = 0; i < bgp_notify.length; i++)
1976 if (first)
1977 {
1978 sprintf (c, " %02x", stream_getc (peer->ibuf));
1979 strcat (bgp_notify.data, c);
1980 }
1981 else
1982 {
1983 first = 1;
1984 sprintf (c, "%02x", stream_getc (peer->ibuf));
1985 strcpy (bgp_notify.data, c);
1986 }
1987 }
1988
1989 bgp_notify_print(peer, &bgp_notify, "received");
1990 if (bgp_notify.data)
1991 XFREE (MTYPE_TMP, bgp_notify.data);
1992 }
1993
1994 /* peer count update */
1995 peer->notify_in++;
1996
hassoe0701b72004-05-20 09:19:34 +00001997 if (peer->status == Established)
1998 peer->last_reset = PEER_DOWN_NOTIFY_RECEIVED;
1999
paul718e3742002-12-13 20:15:29 +00002000 /* We have to check for Notify with Unsupported Optional Parameter.
2001 in that case we fallback to open without the capability option.
2002 But this done in bgp_stop. We just mark it here to avoid changing
2003 the fsm tables. */
2004 if (bgp_notify.code == BGP_NOTIFY_OPEN_ERR &&
2005 bgp_notify.subcode == BGP_NOTIFY_OPEN_UNSUP_PARAM )
2006 UNSET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
2007
paul718e3742002-12-13 20:15:29 +00002008 BGP_EVENT_ADD (peer, Receive_NOTIFICATION_message);
2009}
2010
2011/* Keepalive treatment function -- get keepalive send keepalive */
paul94f2b392005-06-28 12:44:16 +00002012static void
paul718e3742002-12-13 20:15:29 +00002013bgp_keepalive_receive (struct peer *peer, bgp_size_t size)
2014{
2015 if (BGP_DEBUG (keepalive, KEEPALIVE))
ajs6b514742004-12-08 21:03:23 +00002016 zlog_debug ("%s KEEPALIVE rcvd", peer->host);
paul718e3742002-12-13 20:15:29 +00002017
2018 BGP_EVENT_ADD (peer, Receive_KEEPALIVE_message);
2019}
2020
2021/* Route refresh message is received. */
paul94f2b392005-06-28 12:44:16 +00002022static void
paul718e3742002-12-13 20:15:29 +00002023bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
2024{
2025 afi_t afi;
2026 safi_t safi;
paul718e3742002-12-13 20:15:29 +00002027 struct stream *s;
2028
2029 /* If peer does not have the capability, send notification. */
2030 if (! CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_ADV))
2031 {
2032 plog_err (peer->log, "%s [Error] BGP route refresh is not enabled",
2033 peer->host);
2034 bgp_notify_send (peer,
2035 BGP_NOTIFY_HEADER_ERR,
2036 BGP_NOTIFY_HEADER_BAD_MESTYPE);
2037 return;
2038 }
2039
2040 /* Status must be Established. */
2041 if (peer->status != Established)
2042 {
2043 plog_err (peer->log,
2044 "%s [Error] Route refresh packet received under status %s",
2045 peer->host, LOOKUP (bgp_status_msg, peer->status));
2046 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
2047 return;
2048 }
2049
2050 s = peer->ibuf;
2051
2052 /* Parse packet. */
2053 afi = stream_getw (s);
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002054 /* reserved byte */
2055 stream_getc (s);
paul718e3742002-12-13 20:15:29 +00002056 safi = stream_getc (s);
2057
2058 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002059 zlog_debug ("%s rcvd REFRESH_REQ for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00002060 peer->host, afi, safi);
2061
2062 /* Check AFI and SAFI. */
2063 if ((afi != AFI_IP && afi != AFI_IP6)
2064 || (safi != SAFI_UNICAST && safi != SAFI_MULTICAST
Denis Ovsienko42e6d742011-07-14 12:36:19 +04002065 && safi != SAFI_MPLS_LABELED_VPN))
paul718e3742002-12-13 20:15:29 +00002066 {
2067 if (BGP_DEBUG (normal, NORMAL))
2068 {
ajs6b514742004-12-08 21:03:23 +00002069 zlog_debug ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored",
paul718e3742002-12-13 20:15:29 +00002070 peer->host, afi, safi);
2071 }
2072 return;
2073 }
2074
2075 /* Adjust safi code. */
Denis Ovsienko42e6d742011-07-14 12:36:19 +04002076 if (safi == SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00002077 safi = SAFI_MPLS_VPN;
2078
2079 if (size != BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE)
2080 {
2081 u_char *end;
2082 u_char when_to_refresh;
2083 u_char orf_type;
2084 u_int16_t orf_len;
2085
2086 if (size - (BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE) < 5)
2087 {
2088 zlog_info ("%s ORF route refresh length error", peer->host);
2089 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2090 return;
2091 }
2092
2093 when_to_refresh = stream_getc (s);
2094 end = stream_pnt (s) + (size - 5);
2095
Paul Jakma370b64a2007-12-22 16:49:52 +00002096 while ((stream_pnt (s) + 2) < end)
paul718e3742002-12-13 20:15:29 +00002097 {
2098 orf_type = stream_getc (s);
2099 orf_len = stream_getw (s);
Paul Jakma370b64a2007-12-22 16:49:52 +00002100
2101 /* orf_len in bounds? */
2102 if ((stream_pnt (s) + orf_len) > end)
2103 break; /* XXX: Notify instead?? */
paul718e3742002-12-13 20:15:29 +00002104 if (orf_type == ORF_TYPE_PREFIX
2105 || orf_type == ORF_TYPE_PREFIX_OLD)
2106 {
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002107 uint8_t *p_pnt = stream_pnt (s);
2108 uint8_t *p_end = stream_pnt (s) + orf_len;
paul718e3742002-12-13 20:15:29 +00002109 struct orf_prefix orfp;
2110 u_char common = 0;
2111 u_int32_t seq;
2112 int psize;
2113 char name[BUFSIZ];
paul718e3742002-12-13 20:15:29 +00002114 int ret;
2115
2116 if (BGP_DEBUG (normal, NORMAL))
2117 {
ajs6b514742004-12-08 21:03:23 +00002118 zlog_debug ("%s rcvd Prefixlist ORF(%d) length %d",
paul718e3742002-12-13 20:15:29 +00002119 peer->host, orf_type, orf_len);
2120 }
2121
Paul Jakma370b64a2007-12-22 16:49:52 +00002122 /* we're going to read at least 1 byte of common ORF header,
2123 * and 7 bytes of ORF Address-filter entry from the stream
2124 */
2125 if (orf_len < 7)
2126 break;
2127
paul718e3742002-12-13 20:15:29 +00002128 /* ORF prefix-list name */
2129 sprintf (name, "%s.%d.%d", peer->host, afi, safi);
2130
2131 while (p_pnt < p_end)
2132 {
Chris Halld64379e2010-05-14 16:38:39 +04002133 /* If the ORF entry is malformed, want to read as much of it
2134 * as possible without going beyond the bounds of the entry,
2135 * to maximise debug information.
2136 */
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002137 int ok;
paul718e3742002-12-13 20:15:29 +00002138 memset (&orfp, 0, sizeof (struct orf_prefix));
2139 common = *p_pnt++;
Chris Halld64379e2010-05-14 16:38:39 +04002140 /* after ++: p_pnt <= p_end */
paul718e3742002-12-13 20:15:29 +00002141 if (common & ORF_COMMON_PART_REMOVE_ALL)
2142 {
2143 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002144 zlog_debug ("%s rcvd Remove-All pfxlist ORF request", peer->host);
paul718e3742002-12-13 20:15:29 +00002145 prefix_bgp_orf_remove_all (name);
2146 break;
2147 }
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002148 ok = ((size_t)(p_end - p_pnt) >= sizeof(u_int32_t)) ;
Denis Ovsienkobb915f52011-12-13 21:11:39 +04002149 if (ok)
Chris Halld64379e2010-05-14 16:38:39 +04002150 {
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002151 memcpy (&seq, p_pnt, sizeof (u_int32_t));
2152 p_pnt += sizeof (u_int32_t);
2153 orfp.seq = ntohl (seq);
Chris Halld64379e2010-05-14 16:38:39 +04002154 }
2155 else
2156 p_pnt = p_end ;
2157
2158 if ((ok = (p_pnt < p_end)))
2159 orfp.ge = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */
2160 if ((ok = (p_pnt < p_end)))
2161 orfp.le = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */
2162 if ((ok = (p_pnt < p_end)))
2163 orfp.p.prefixlen = *p_pnt++ ;
2164 orfp.p.family = afi2family (afi); /* afi checked already */
2165
2166 psize = PSIZE (orfp.p.prefixlen); /* 0 if not ok */
2167 if (psize > prefix_blen(&orfp.p)) /* valid for family ? */
2168 {
2169 ok = 0 ;
2170 psize = prefix_blen(&orfp.p) ;
2171 }
2172 if (psize > (p_end - p_pnt)) /* valid for packet ? */
2173 {
2174 ok = 0 ;
2175 psize = p_end - p_pnt ;
2176 }
2177
2178 if (psize > 0)
2179 memcpy (&orfp.p.u.prefix, p_pnt, psize);
paul718e3742002-12-13 20:15:29 +00002180 p_pnt += psize;
2181
2182 if (BGP_DEBUG (normal, NORMAL))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +00002183 {
2184 char buf[INET6_BUFSIZ];
2185
2186 zlog_debug ("%s rcvd %s %s seq %u %s/%d ge %d le %d%s",
2187 peer->host,
2188 (common & ORF_COMMON_PART_REMOVE ? "Remove" : "Add"),
2189 (common & ORF_COMMON_PART_DENY ? "deny" : "permit"),
2190 orfp.seq,
2191 inet_ntop (orfp.p.family, &orfp.p.u.prefix, buf, INET6_BUFSIZ),
2192 orfp.p.prefixlen, orfp.ge, orfp.le,
2193 ok ? "" : " MALFORMED");
2194 }
2195
Chris Halld64379e2010-05-14 16:38:39 +04002196 if (ok)
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002197 ret = prefix_bgp_orf_set (name, afi, &orfp,
2198 (common & ORF_COMMON_PART_DENY ? 0 : 1 ),
2199 (common & ORF_COMMON_PART_REMOVE ? 0 : 1));
Paul Jakma7aa9dce2014-09-19 14:42:23 +01002200
2201 if (!ok || (ok && ret != CMD_SUCCESS))
paul718e3742002-12-13 20:15:29 +00002202 {
2203 if (BGP_DEBUG (normal, NORMAL))
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002204 zlog_debug ("%s Received misformatted prefixlist ORF."
2205 " Remove All pfxlist", peer->host);
paul718e3742002-12-13 20:15:29 +00002206 prefix_bgp_orf_remove_all (name);
2207 break;
2208 }
2209 }
2210 peer->orf_plist[afi][safi] =
2211 prefix_list_lookup (AFI_ORF_PREFIX, name);
2212 }
paul9985f832005-02-09 15:51:56 +00002213 stream_forward_getp (s, orf_len);
paul718e3742002-12-13 20:15:29 +00002214 }
2215 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002216 zlog_debug ("%s rcvd Refresh %s ORF request", peer->host,
paul718e3742002-12-13 20:15:29 +00002217 when_to_refresh == REFRESH_DEFER ? "Defer" : "Immediate");
2218 if (when_to_refresh == REFRESH_DEFER)
2219 return;
2220 }
2221
2222 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2223 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH))
2224 UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
2225
2226 /* Perform route refreshment to the peer */
2227 bgp_announce_route (peer, afi, safi);
2228}
2229
paul94f2b392005-06-28 12:44:16 +00002230static int
paul718e3742002-12-13 20:15:29 +00002231bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
2232{
2233 u_char *end;
Paul Jakma6d582722007-08-06 15:21:45 +00002234 struct capability_mp_data mpc;
2235 struct capability_header *hdr;
paul718e3742002-12-13 20:15:29 +00002236 u_char action;
paul718e3742002-12-13 20:15:29 +00002237 afi_t afi;
2238 safi_t safi;
2239
paul718e3742002-12-13 20:15:29 +00002240 end = pnt + length;
2241
2242 while (pnt < end)
Paul Jakma6d582722007-08-06 15:21:45 +00002243 {
paul718e3742002-12-13 20:15:29 +00002244 /* We need at least action, capability code and capability length. */
2245 if (pnt + 3 > end)
2246 {
2247 zlog_info ("%s Capability length error", peer->host);
2248 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2249 return -1;
2250 }
paul718e3742002-12-13 20:15:29 +00002251 action = *pnt;
Paul Jakma6d582722007-08-06 15:21:45 +00002252 hdr = (struct capability_header *)(pnt + 1);
2253
paul718e3742002-12-13 20:15:29 +00002254 /* Action value check. */
2255 if (action != CAPABILITY_ACTION_SET
2256 && action != CAPABILITY_ACTION_UNSET)
2257 {
2258 zlog_info ("%s Capability Action Value error %d",
2259 peer->host, action);
2260 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2261 return -1;
2262 }
2263
2264 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002265 zlog_debug ("%s CAPABILITY has action: %d, code: %u, length %u",
Paul Jakma6d582722007-08-06 15:21:45 +00002266 peer->host, action, hdr->code, hdr->length);
paul718e3742002-12-13 20:15:29 +00002267
2268 /* Capability length check. */
Paul Jakma6d582722007-08-06 15:21:45 +00002269 if ((pnt + hdr->length + 3) > end)
paul718e3742002-12-13 20:15:29 +00002270 {
2271 zlog_info ("%s Capability length error", peer->host);
2272 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2273 return -1;
2274 }
2275
Paul Jakma6d582722007-08-06 15:21:45 +00002276 /* Fetch structure to the byte stream. */
2277 memcpy (&mpc, pnt + 3, sizeof (struct capability_mp_data));
2278
paul718e3742002-12-13 20:15:29 +00002279 /* We know MP Capability Code. */
Paul Jakma6d582722007-08-06 15:21:45 +00002280 if (hdr->code == CAPABILITY_CODE_MP)
paul718e3742002-12-13 20:15:29 +00002281 {
Paul Jakma6d582722007-08-06 15:21:45 +00002282 afi = ntohs (mpc.afi);
2283 safi = mpc.safi;
paul718e3742002-12-13 20:15:29 +00002284
2285 /* Ignore capability when override-capability is set. */
2286 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
2287 continue;
Paul Jakma6d582722007-08-06 15:21:45 +00002288
2289 if (!bgp_afi_safi_valid_indices (afi, &safi))
2290 {
2291 if (BGP_DEBUG (normal, NORMAL))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002292 zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid "
2293 "(%u/%u)", peer->host, afi, safi);
Paul Jakma6d582722007-08-06 15:21:45 +00002294 continue;
2295 }
2296
paul718e3742002-12-13 20:15:29 +00002297 /* Address family check. */
Paul Jakma6d582722007-08-06 15:21:45 +00002298 if (BGP_DEBUG (normal, NORMAL))
2299 zlog_debug ("%s CAPABILITY has %s MP_EXT CAP for afi/safi: %u/%u",
2300 peer->host,
2301 action == CAPABILITY_ACTION_SET
2302 ? "Advertising" : "Removing",
2303 ntohs(mpc.afi) , mpc.safi);
2304
2305 if (action == CAPABILITY_ACTION_SET)
2306 {
2307 peer->afc_recv[afi][safi] = 1;
2308 if (peer->afc[afi][safi])
2309 {
2310 peer->afc_nego[afi][safi] = 1;
2311 bgp_announce_route (peer, afi, safi);
2312 }
2313 }
2314 else
2315 {
2316 peer->afc_recv[afi][safi] = 0;
2317 peer->afc_nego[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00002318
Paul Jakma6d582722007-08-06 15:21:45 +00002319 if (peer_active_nego (peer))
Chris Caputo228da422009-07-18 05:44:03 +00002320 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
Paul Jakma6d582722007-08-06 15:21:45 +00002321 else
2322 BGP_EVENT_ADD (peer, BGP_Stop);
2323 }
paul718e3742002-12-13 20:15:29 +00002324 }
paul718e3742002-12-13 20:15:29 +00002325 else
2326 {
2327 zlog_warn ("%s unrecognized capability code: %d - ignored",
Paul Jakma6d582722007-08-06 15:21:45 +00002328 peer->host, hdr->code);
paul718e3742002-12-13 20:15:29 +00002329 }
Paul Jakma6d582722007-08-06 15:21:45 +00002330 pnt += hdr->length + 3;
paul718e3742002-12-13 20:15:29 +00002331 }
2332 return 0;
2333}
2334
Paul Jakma01b7ce22009-06-18 12:34:43 +01002335/* Dynamic Capability is received.
2336 *
2337 * This is exported for unit-test purposes
2338 */
Paul Jakma6d582722007-08-06 15:21:45 +00002339int
paul718e3742002-12-13 20:15:29 +00002340bgp_capability_receive (struct peer *peer, bgp_size_t size)
2341{
2342 u_char *pnt;
paul718e3742002-12-13 20:15:29 +00002343
2344 /* Fetch pointer. */
2345 pnt = stream_pnt (peer->ibuf);
2346
2347 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002348 zlog_debug ("%s rcv CAPABILITY", peer->host);
paul718e3742002-12-13 20:15:29 +00002349
2350 /* If peer does not have the capability, send notification. */
2351 if (! CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV))
2352 {
2353 plog_err (peer->log, "%s [Error] BGP dynamic capability is not enabled",
2354 peer->host);
2355 bgp_notify_send (peer,
2356 BGP_NOTIFY_HEADER_ERR,
2357 BGP_NOTIFY_HEADER_BAD_MESTYPE);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002358 return -1;
paul718e3742002-12-13 20:15:29 +00002359 }
2360
2361 /* Status must be Established. */
2362 if (peer->status != Established)
2363 {
2364 plog_err (peer->log,
2365 "%s [Error] Dynamic capability packet received under status %s", peer->host, LOOKUP (bgp_status_msg, peer->status));
2366 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002367 return -1;
paul718e3742002-12-13 20:15:29 +00002368 }
2369
2370 /* Parse packet. */
Paul Jakma6d582722007-08-06 15:21:45 +00002371 return bgp_capability_msg_parse (peer, pnt, size);
paul718e3742002-12-13 20:15:29 +00002372}
David Lamparter6b0655a2014-06-04 06:53:35 +02002373
paul718e3742002-12-13 20:15:29 +00002374/* BGP read utility function. */
paul94f2b392005-06-28 12:44:16 +00002375static int
paul718e3742002-12-13 20:15:29 +00002376bgp_read_packet (struct peer *peer)
2377{
2378 int nbytes;
2379 int readsize;
2380
paul9985f832005-02-09 15:51:56 +00002381 readsize = peer->packet_size - stream_get_endp (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00002382
2383 /* If size is zero then return. */
2384 if (! readsize)
2385 return 0;
2386
2387 /* Read packet from fd. */
Stephen Hemminger35398582010-08-05 10:26:23 -07002388 nbytes = stream_read_try (peer->ibuf, peer->fd, readsize);
paul718e3742002-12-13 20:15:29 +00002389
2390 /* If read byte is smaller than zero then error occured. */
2391 if (nbytes < 0)
2392 {
Stephen Hemminger35398582010-08-05 10:26:23 -07002393 /* Transient error should retry */
2394 if (nbytes == -2)
paul718e3742002-12-13 20:15:29 +00002395 return -1;
2396
2397 plog_err (peer->log, "%s [Error] bgp_read_packet error: %s",
ajs6099b3b2004-11-20 02:06:59 +00002398 peer->host, safe_strerror (errno));
hasso93406d82005-02-02 14:40:33 +00002399
2400 if (peer->status == Established)
2401 {
2402 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
2403 {
2404 peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
2405 SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
2406 }
2407 else
2408 peer->last_reset = PEER_DOWN_CLOSE_SESSION;
2409 }
2410
paul718e3742002-12-13 20:15:29 +00002411 BGP_EVENT_ADD (peer, TCP_fatal_error);
2412 return -1;
2413 }
2414
2415 /* When read byte is zero : clear bgp peer and return */
2416 if (nbytes == 0)
2417 {
2418 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +00002419 plog_debug (peer->log, "%s [Event] BGP connection closed fd %d",
pauleb821182004-05-01 08:44:08 +00002420 peer->host, peer->fd);
hassoe0701b72004-05-20 09:19:34 +00002421
2422 if (peer->status == Established)
hasso93406d82005-02-02 14:40:33 +00002423 {
2424 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
2425 {
2426 peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
2427 SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
2428 }
2429 else
2430 peer->last_reset = PEER_DOWN_CLOSE_SESSION;
2431 }
hassoe0701b72004-05-20 09:19:34 +00002432
paul718e3742002-12-13 20:15:29 +00002433 BGP_EVENT_ADD (peer, TCP_connection_closed);
2434 return -1;
2435 }
2436
2437 /* We read partial packet. */
paul9985f832005-02-09 15:51:56 +00002438 if (stream_get_endp (peer->ibuf) != peer->packet_size)
paul718e3742002-12-13 20:15:29 +00002439 return -1;
2440
2441 return 0;
2442}
2443
2444/* Marker check. */
paul94f2b392005-06-28 12:44:16 +00002445static int
paul718e3742002-12-13 20:15:29 +00002446bgp_marker_all_one (struct stream *s, int length)
2447{
2448 int i;
2449
2450 for (i = 0; i < length; i++)
2451 if (s->data[i] != 0xff)
2452 return 0;
2453
2454 return 1;
2455}
2456
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002457/* Recent thread time.
2458 On same clock base as bgp_clock (MONOTONIC)
2459 but can be time of last context switch to bgp_read thread. */
2460static time_t
2461bgp_recent_clock (void)
2462{
2463 return recent_relative_time().tv_sec;
2464}
2465
paul718e3742002-12-13 20:15:29 +00002466/* Starting point of packet process function. */
2467int
2468bgp_read (struct thread *thread)
2469{
2470 int ret;
2471 u_char type = 0;
2472 struct peer *peer;
2473 bgp_size_t size;
2474 char notify_data_length[2];
2475
2476 /* Yes first of all get peer pointer. */
2477 peer = THREAD_ARG (thread);
2478 peer->t_read = NULL;
2479
2480 /* For non-blocking IO check. */
2481 if (peer->status == Connect)
2482 {
2483 bgp_connect_check (peer);
2484 goto done;
2485 }
2486 else
2487 {
pauleb821182004-05-01 08:44:08 +00002488 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +00002489 {
pauleb821182004-05-01 08:44:08 +00002490 zlog_err ("bgp_read peer's fd is negative value %d", peer->fd);
paul718e3742002-12-13 20:15:29 +00002491 return -1;
2492 }
pauleb821182004-05-01 08:44:08 +00002493 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
paul718e3742002-12-13 20:15:29 +00002494 }
2495
2496 /* Read packet header to determine type of the packet */
2497 if (peer->packet_size == 0)
2498 peer->packet_size = BGP_HEADER_SIZE;
2499
paul9985f832005-02-09 15:51:56 +00002500 if (stream_get_endp (peer->ibuf) < BGP_HEADER_SIZE)
paul718e3742002-12-13 20:15:29 +00002501 {
2502 ret = bgp_read_packet (peer);
2503
2504 /* Header read error or partial read packet. */
2505 if (ret < 0)
2506 goto done;
2507
2508 /* Get size and type. */
paul9985f832005-02-09 15:51:56 +00002509 stream_forward_getp (peer->ibuf, BGP_MARKER_SIZE);
paul718e3742002-12-13 20:15:29 +00002510 memcpy (notify_data_length, stream_pnt (peer->ibuf), 2);
2511 size = stream_getw (peer->ibuf);
2512 type = stream_getc (peer->ibuf);
2513
2514 if (BGP_DEBUG (normal, NORMAL) && type != 2 && type != 0)
ajs6b514742004-12-08 21:03:23 +00002515 zlog_debug ("%s rcv message type %d, length (excl. header) %d",
paul718e3742002-12-13 20:15:29 +00002516 peer->host, type, size - BGP_HEADER_SIZE);
2517
2518 /* Marker check */
paulf5ba3872004-07-09 12:11:31 +00002519 if (((type == BGP_MSG_OPEN) || (type == BGP_MSG_KEEPALIVE))
paul718e3742002-12-13 20:15:29 +00002520 && ! bgp_marker_all_one (peer->ibuf, BGP_MARKER_SIZE))
2521 {
2522 bgp_notify_send (peer,
2523 BGP_NOTIFY_HEADER_ERR,
2524 BGP_NOTIFY_HEADER_NOT_SYNC);
2525 goto done;
2526 }
2527
2528 /* BGP type check. */
2529 if (type != BGP_MSG_OPEN && type != BGP_MSG_UPDATE
2530 && type != BGP_MSG_NOTIFY && type != BGP_MSG_KEEPALIVE
2531 && type != BGP_MSG_ROUTE_REFRESH_NEW
2532 && type != BGP_MSG_ROUTE_REFRESH_OLD
2533 && type != BGP_MSG_CAPABILITY)
2534 {
2535 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002536 plog_debug (peer->log,
paul718e3742002-12-13 20:15:29 +00002537 "%s unknown message type 0x%02x",
2538 peer->host, type);
2539 bgp_notify_send_with_data (peer,
2540 BGP_NOTIFY_HEADER_ERR,
2541 BGP_NOTIFY_HEADER_BAD_MESTYPE,
2542 &type, 1);
2543 goto done;
2544 }
2545 /* Mimimum packet length check. */
2546 if ((size < BGP_HEADER_SIZE)
2547 || (size > BGP_MAX_PACKET_SIZE)
2548 || (type == BGP_MSG_OPEN && size < BGP_MSG_OPEN_MIN_SIZE)
2549 || (type == BGP_MSG_UPDATE && size < BGP_MSG_UPDATE_MIN_SIZE)
2550 || (type == BGP_MSG_NOTIFY && size < BGP_MSG_NOTIFY_MIN_SIZE)
2551 || (type == BGP_MSG_KEEPALIVE && size != BGP_MSG_KEEPALIVE_MIN_SIZE)
2552 || (type == BGP_MSG_ROUTE_REFRESH_NEW && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
2553 || (type == BGP_MSG_ROUTE_REFRESH_OLD && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
2554 || (type == BGP_MSG_CAPABILITY && size < BGP_MSG_CAPABILITY_MIN_SIZE))
2555 {
2556 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002557 plog_debug (peer->log,
paul718e3742002-12-13 20:15:29 +00002558 "%s bad message length - %d for %s",
2559 peer->host, size,
2560 type == 128 ? "ROUTE-REFRESH" :
2561 bgp_type_str[(int) type]);
2562 bgp_notify_send_with_data (peer,
2563 BGP_NOTIFY_HEADER_ERR,
2564 BGP_NOTIFY_HEADER_BAD_MESLEN,
hassoc9e52be2004-09-26 16:09:34 +00002565 (u_char *) notify_data_length, 2);
paul718e3742002-12-13 20:15:29 +00002566 goto done;
2567 }
2568
2569 /* Adjust size to message length. */
2570 peer->packet_size = size;
2571 }
2572
2573 ret = bgp_read_packet (peer);
2574 if (ret < 0)
2575 goto done;
2576
2577 /* Get size and type again. */
2578 size = stream_getw_from (peer->ibuf, BGP_MARKER_SIZE);
2579 type = stream_getc_from (peer->ibuf, BGP_MARKER_SIZE + 2);
2580
2581 /* BGP packet dump function. */
2582 bgp_dump_packet (peer, type, peer->ibuf);
2583
2584 size = (peer->packet_size - BGP_HEADER_SIZE);
2585
2586 /* Read rest of the packet and call each sort of packet routine */
2587 switch (type)
2588 {
2589 case BGP_MSG_OPEN:
2590 peer->open_in++;
paulf5ba3872004-07-09 12:11:31 +00002591 bgp_open_receive (peer, size); /* XXX return value ignored! */
paul718e3742002-12-13 20:15:29 +00002592 break;
2593 case BGP_MSG_UPDATE:
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002594 peer->readtime = bgp_recent_clock ();
paul718e3742002-12-13 20:15:29 +00002595 bgp_update_receive (peer, size);
2596 break;
2597 case BGP_MSG_NOTIFY:
2598 bgp_notify_receive (peer, size);
2599 break;
2600 case BGP_MSG_KEEPALIVE:
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002601 peer->readtime = bgp_recent_clock ();
paul718e3742002-12-13 20:15:29 +00002602 bgp_keepalive_receive (peer, size);
2603 break;
2604 case BGP_MSG_ROUTE_REFRESH_NEW:
2605 case BGP_MSG_ROUTE_REFRESH_OLD:
2606 peer->refresh_in++;
2607 bgp_route_refresh_receive (peer, size);
2608 break;
2609 case BGP_MSG_CAPABILITY:
2610 peer->dynamic_cap_in++;
2611 bgp_capability_receive (peer, size);
2612 break;
2613 }
2614
2615 /* Clear input buffer. */
2616 peer->packet_size = 0;
2617 if (peer->ibuf)
2618 stream_reset (peer->ibuf);
2619
2620 done:
2621 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2622 {
2623 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +00002624 zlog_debug ("%s [Event] Accepting BGP peer delete", peer->host);
paul718e3742002-12-13 20:15:29 +00002625 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00002626 }
2627 return 0;
2628}