blob: 80651f155a45f8be7c88279e2ed553f710e4cbe2 [file] [log] [blame]
paul718e3742002-12-13 20:15:29 +00001/* BGP packet management routine.
2 Copyright (C) 1999 Kunihiro Ishiguro
3
4This file is part of GNU Zebra.
5
6GNU Zebra is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 2, or (at your option) any
9later version.
10
11GNU Zebra is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Zebra; see the file COPYING. If not, write to the Free
18Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21#include <zebra.h>
22
23#include "thread.h"
24#include "stream.h"
25#include "network.h"
26#include "prefix.h"
27#include "command.h"
28#include "log.h"
29#include "memory.h"
30#include "sockunion.h" /* for inet_ntop () */
31#include "linklist.h"
32#include "plist.h"
33
34#include "bgpd/bgpd.h"
35#include "bgpd/bgp_table.h"
36#include "bgpd/bgp_dump.h"
37#include "bgpd/bgp_attr.h"
38#include "bgpd/bgp_debug.h"
39#include "bgpd/bgp_fsm.h"
40#include "bgpd/bgp_route.h"
41#include "bgpd/bgp_packet.h"
42#include "bgpd/bgp_open.h"
43#include "bgpd/bgp_aspath.h"
44#include "bgpd/bgp_community.h"
45#include "bgpd/bgp_ecommunity.h"
46#include "bgpd/bgp_network.h"
47#include "bgpd/bgp_mplsvpn.h"
48#include "bgpd/bgp_advertise.h"
hasso93406d82005-02-02 14:40:33 +000049#include "bgpd/bgp_vty.h"
paul718e3742002-12-13 20:15:29 +000050
51int stream_put_prefix (struct stream *, struct prefix *);
David Lamparter6b0655a2014-06-04 06:53:35 +020052
paul718e3742002-12-13 20:15:29 +000053/* Set up BGP packet marker and packet type. */
54static int
55bgp_packet_set_marker (struct stream *s, u_char type)
56{
57 int i;
58
59 /* Fill in marker. */
60 for (i = 0; i < BGP_MARKER_SIZE; i++)
61 stream_putc (s, 0xff);
62
63 /* Dummy total length. This field is should be filled in later on. */
64 stream_putw (s, 0);
65
66 /* BGP packet type. */
67 stream_putc (s, type);
68
69 /* Return current stream size. */
paul9985f832005-02-09 15:51:56 +000070 return stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +000071}
72
73/* Set BGP packet header size entry. If size is zero then use current
74 stream size. */
75static int
76bgp_packet_set_size (struct stream *s)
77{
78 int cp;
79
80 /* Preserve current pointer. */
paul9985f832005-02-09 15:51:56 +000081 cp = stream_get_endp (s);
82 stream_putw_at (s, BGP_MARKER_SIZE, cp);
paul718e3742002-12-13 20:15:29 +000083
84 return cp;
85}
86
87/* Add new packet to the peer. */
paul94f2b392005-06-28 12:44:16 +000088static void
paul718e3742002-12-13 20:15:29 +000089bgp_packet_add (struct peer *peer, struct stream *s)
90{
91 /* Add packet to the end of list. */
92 stream_fifo_push (peer->obuf, s);
93}
94
95/* Free first packet. */
paul94f2b392005-06-28 12:44:16 +000096static void
paul718e3742002-12-13 20:15:29 +000097bgp_packet_delete (struct peer *peer)
98{
99 stream_free (stream_fifo_pop (peer->obuf));
100}
101
paul718e3742002-12-13 20:15:29 +0000102/* Check file descriptor whether connect is established. */
103static void
104bgp_connect_check (struct peer *peer)
105{
106 int status;
paul5228ad22004-06-04 17:58:18 +0000107 socklen_t slen;
paul718e3742002-12-13 20:15:29 +0000108 int ret;
109
110 /* Anyway I have to reset read and write thread. */
111 BGP_READ_OFF (peer->t_read);
112 BGP_WRITE_OFF (peer->t_write);
113
114 /* Check file descriptor. */
115 slen = sizeof (status);
pauleb821182004-05-01 08:44:08 +0000116 ret = getsockopt(peer->fd, SOL_SOCKET, SO_ERROR, (void *) &status, &slen);
paul718e3742002-12-13 20:15:29 +0000117
118 /* If getsockopt is fail, this is fatal error. */
119 if (ret < 0)
120 {
121 zlog (peer->log, LOG_INFO, "can't get sockopt for nonblocking connect");
122 BGP_EVENT_ADD (peer, TCP_fatal_error);
123 return;
124 }
125
126 /* When status is 0 then TCP connection is established. */
127 if (status == 0)
128 {
129 BGP_EVENT_ADD (peer, TCP_connection_open);
130 }
131 else
132 {
133 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +0000134 plog_debug (peer->log, "%s [Event] Connect failed (%s)",
ajs6099b3b2004-11-20 02:06:59 +0000135 peer->host, safe_strerror (errno));
paul718e3742002-12-13 20:15:29 +0000136 BGP_EVENT_ADD (peer, TCP_connection_open_failed);
137 }
138}
139
140/* Make BGP update packet. */
paul94f2b392005-06-28 12:44:16 +0000141static struct stream *
paul718e3742002-12-13 20:15:29 +0000142bgp_update_packet (struct peer *peer, afi_t afi, safi_t safi)
143{
144 struct stream *s;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000145 struct stream *snlri;
paul718e3742002-12-13 20:15:29 +0000146 struct bgp_adj_out *adj;
147 struct bgp_advertise *adv;
148 struct stream *packet;
149 struct bgp_node *rn = NULL;
150 struct bgp_info *binfo = NULL;
151 bgp_size_t total_attr_len = 0;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000152 unsigned long attrlen_pos = 0;
153 size_t mpattrlen_pos = 0;
154 size_t mpattr_pos = 0;
paul718e3742002-12-13 20:15:29 +0000155
156 s = peer->work;
157 stream_reset (s);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000158 snlri = peer->scratch;
159 stream_reset (snlri);
paul718e3742002-12-13 20:15:29 +0000160
161 adv = FIFO_HEAD (&peer->sync[afi][safi]->update);
162
163 while (adv)
164 {
Paul Jakmaed3ebfa2006-10-15 23:50:16 +0000165 assert (adv->rn);
166 rn = adv->rn;
paul718e3742002-12-13 20:15:29 +0000167 adj = adv->adj;
168 if (adv->binfo)
169 binfo = adv->binfo;
paul718e3742002-12-13 20:15:29 +0000170
171 /* When remaining space can't include NLRI and it's length. */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000172 if (STREAM_CONCAT_REMAIN (s, snlri, STREAM_SIZE(s)) <=
173 (BGP_NLRI_LENGTH + PSIZE (rn->p.prefixlen)))
paul718e3742002-12-13 20:15:29 +0000174 break;
175
176 /* If packet is empty, set attribute. */
177 if (stream_empty (s))
178 {
Paul Jakmaed3ebfa2006-10-15 23:50:16 +0000179 struct peer *from = NULL;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000180
Greg Troxeld3ddb222010-09-17 10:47:49 -0400181 if (binfo)
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000182 from = binfo->peer;
183
184 /* 1: Write the BGP message header - 16 bytes marker, 2 bytes length,
185 * one byte message type.
186 */
paul718e3742002-12-13 20:15:29 +0000187 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000188
189 /* 2: withdrawn routes length */
paul718e3742002-12-13 20:15:29 +0000190 stream_putw (s, 0);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000191
192 /* 3: total attributes length - attrlen_pos stores the position */
193 attrlen_pos = stream_get_endp (s);
194 stream_putw (s, 0);
195
196 /* 4: if there is MP_REACH_NLRI attribute, that should be the first
197 * attribute, according to draft-ietf-idr-error-handling. Save the
198 * position.
199 */
200 mpattr_pos = stream_get_endp(s);
201
202 /* 5: Encode all the attributes, except MP_REACH_NLRI attr. */
203 total_attr_len = bgp_packet_attribute (NULL, peer, s,
paul5228ad22004-06-04 17:58:18 +0000204 adv->baa->attr,
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000205 NULL, afi, safi,
206 from, NULL, NULL);
paul718e3742002-12-13 20:15:29 +0000207 }
208
209 if (afi == AFI_IP && safi == SAFI_UNICAST)
210 stream_put_prefix (s, &rn->p);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000211 else
212 {
213 /* Encode the prefix in MP_REACH_NLRI attribute */
214 struct prefix_rd *prd = NULL;
215 u_char *tag = NULL;
216
217 if (rn->prn)
218 prd = (struct prefix_rd *) &rn->prn->p;
219 if (binfo && binfo->extra)
220 tag = binfo->extra->tag;
221
222 if (stream_empty(snlri))
223 mpattrlen_pos = bgp_packet_mpattr_start(snlri, afi, safi,
224 adv->baa->attr);
225 bgp_packet_mpattr_prefix(snlri, afi, safi, &rn->p, prd, tag);
226 }
paul718e3742002-12-13 20:15:29 +0000227 if (BGP_DEBUG (update, UPDATE_OUT))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000228 {
229 char buf[INET6_BUFSIZ];
230
231 zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d",
232 peer->host,
233 inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ),
234 rn->p.prefixlen);
235 }
paul718e3742002-12-13 20:15:29 +0000236
237 /* Synchnorize attribute. */
238 if (adj->attr)
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000239 bgp_attr_unintern (&adj->attr);
paul718e3742002-12-13 20:15:29 +0000240 else
241 peer->scount[afi][safi]++;
242
243 adj->attr = bgp_attr_intern (adv->baa->attr);
244
245 adv = bgp_advertise_clean (peer, adj, afi, safi);
paul718e3742002-12-13 20:15:29 +0000246 }
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000247
paul718e3742002-12-13 20:15:29 +0000248 if (! stream_empty (s))
249 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000250 if (!stream_empty(snlri))
251 {
252 bgp_packet_mpattr_end(snlri, mpattrlen_pos);
253 total_attr_len += stream_get_endp(snlri);
254 }
255
256 /* set the total attribute length correctly */
257 stream_putw_at (s, attrlen_pos, total_attr_len);
258
259 if (!stream_empty(snlri))
260 packet = stream_dupcat(s, snlri, mpattr_pos);
261 else
262 packet = stream_dup (s);
263 bgp_packet_set_size (packet);
paul718e3742002-12-13 20:15:29 +0000264 bgp_packet_add (peer, packet);
pauleb821182004-05-01 08:44:08 +0000265 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000266 stream_reset (s);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000267 stream_reset (snlri);
paul718e3742002-12-13 20:15:29 +0000268 return packet;
269 }
270 return NULL;
hasso93406d82005-02-02 14:40:33 +0000271}
paul718e3742002-12-13 20:15:29 +0000272
paul94f2b392005-06-28 12:44:16 +0000273static struct stream *
hasso93406d82005-02-02 14:40:33 +0000274bgp_update_packet_eor (struct peer *peer, afi_t afi, safi_t safi)
275{
276 struct stream *s;
277 struct stream *packet;
278
Paul Jakma750e8142008-07-22 21:11:48 +0000279 if (DISABLE_BGP_ANNOUNCE)
280 return NULL;
hasso93406d82005-02-02 14:40:33 +0000281
282 if (BGP_DEBUG (normal, NORMAL))
283 zlog_debug ("send End-of-RIB for %s to %s", afi_safi_print (afi, safi), peer->host);
284
285 s = stream_new (BGP_MAX_PACKET_SIZE);
286
287 /* Make BGP update packet. */
288 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
289
290 /* Unfeasible Routes Length */
291 stream_putw (s, 0);
292
293 if (afi == AFI_IP && safi == SAFI_UNICAST)
294 {
295 /* Total Path Attribute Length */
296 stream_putw (s, 0);
297 }
298 else
299 {
300 /* Total Path Attribute Length */
301 stream_putw (s, 6);
302 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
303 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
304 stream_putc (s, 3);
305 stream_putw (s, afi);
306 stream_putc (s, safi);
307 }
308
309 bgp_packet_set_size (s);
paule83e2082005-05-19 02:12:25 +0000310 packet = stream_dup (s);
hasso93406d82005-02-02 14:40:33 +0000311 bgp_packet_add (peer, packet);
312 stream_free (s);
313 return packet;
paul718e3742002-12-13 20:15:29 +0000314}
315
316/* Make BGP withdraw packet. */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000317/* For ipv4 unicast:
318 16-octet marker | 2-octet length | 1-octet type |
319 2-octet withdrawn route length | withdrawn prefixes | 2-octet attrlen (=0)
320*/
321/* For other afi/safis:
322 16-octet marker | 2-octet length | 1-octet type |
323 2-octet withdrawn route length (=0) | 2-octet attrlen |
324 mp_unreach attr type | attr len | afi | safi | withdrawn prefixes
325*/
paul94f2b392005-06-28 12:44:16 +0000326static struct stream *
paul718e3742002-12-13 20:15:29 +0000327bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi)
328{
329 struct stream *s;
330 struct stream *packet;
331 struct bgp_adj_out *adj;
332 struct bgp_advertise *adv;
333 struct bgp_node *rn;
334 unsigned long pos;
335 bgp_size_t unfeasible_len;
336 bgp_size_t total_attr_len;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000337 size_t mp_start = 0;
338 size_t attrlen_pos = 0;
339 size_t mplen_pos = 0;
340 u_char first_time = 1;
paul718e3742002-12-13 20:15:29 +0000341
342 s = peer->work;
343 stream_reset (s);
344
345 while ((adv = FIFO_HEAD (&peer->sync[afi][safi]->withdraw)) != NULL)
346 {
Paul Jakmaed3ebfa2006-10-15 23:50:16 +0000347 assert (adv->rn);
paul718e3742002-12-13 20:15:29 +0000348 adj = adv->adj;
349 rn = adv->rn;
paul718e3742002-12-13 20:15:29 +0000350
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000351 if (STREAM_REMAIN (s)
hasso4372df72004-05-20 10:20:02 +0000352 < (BGP_NLRI_LENGTH + BGP_TOTAL_ATTR_LEN + PSIZE (rn->p.prefixlen)))
paul718e3742002-12-13 20:15:29 +0000353 break;
354
355 if (stream_empty (s))
356 {
357 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000358 stream_putw (s, 0); /* unfeasible routes length */
paul718e3742002-12-13 20:15:29 +0000359 }
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000360 else
361 first_time = 0;
paul718e3742002-12-13 20:15:29 +0000362
363 if (afi == AFI_IP && safi == SAFI_UNICAST)
364 stream_put_prefix (s, &rn->p);
365 else
366 {
Paul Jakmaa3b6ea52006-05-04 07:52:12 +0000367 struct prefix_rd *prd = NULL;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000368
Paul Jakmaa3b6ea52006-05-04 07:52:12 +0000369 if (rn->prn)
370 prd = (struct prefix_rd *) &rn->prn->p;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000371
372 /* If first time, format the MP_UNREACH header */
373 if (first_time)
374 {
375 attrlen_pos = stream_get_endp (s);
376 /* total attr length = 0 for now. reevaluate later */
377 stream_putw (s, 0);
378 mp_start = stream_get_endp (s);
379 mplen_pos = bgp_packet_mpunreach_start(s, afi, safi);
380 }
381
382 bgp_packet_mpunreach_prefix(s, &rn->p, afi, safi, prd, NULL);
paul718e3742002-12-13 20:15:29 +0000383 }
384
385 if (BGP_DEBUG (update, UPDATE_OUT))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000386 {
387 char buf[INET6_BUFSIZ];
388
389 zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d -- unreachable",
390 peer->host,
391 inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ),
392 rn->p.prefixlen);
393 }
paul718e3742002-12-13 20:15:29 +0000394
395 peer->scount[afi][safi]--;
396
397 bgp_adj_out_remove (rn, adj, peer, afi, safi);
398 bgp_unlock_node (rn);
paul718e3742002-12-13 20:15:29 +0000399 }
400
401 if (! stream_empty (s))
402 {
403 if (afi == AFI_IP && safi == SAFI_UNICAST)
404 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000405 unfeasible_len
paul9985f832005-02-09 15:51:56 +0000406 = stream_get_endp (s) - BGP_HEADER_SIZE - BGP_UNFEASIBLE_LEN;
paul718e3742002-12-13 20:15:29 +0000407 stream_putw_at (s, BGP_HEADER_SIZE, unfeasible_len);
408 stream_putw (s, 0);
409 }
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000410 else
411 {
412 /* Set the mp_unreach attr's length */
413 bgp_packet_mpunreach_end(s, mplen_pos);
414
415 /* Set total path attribute length. */
416 total_attr_len = stream_get_endp(s) - mp_start;
417 stream_putw_at (s, attrlen_pos, total_attr_len);
418 }
paul718e3742002-12-13 20:15:29 +0000419 bgp_packet_set_size (s);
paule83e2082005-05-19 02:12:25 +0000420 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +0000421 bgp_packet_add (peer, packet);
422 stream_reset (s);
423 return packet;
424 }
425
426 return NULL;
427}
428
429void
430bgp_default_update_send (struct peer *peer, struct attr *attr,
431 afi_t afi, safi_t safi, struct peer *from)
432{
433 struct stream *s;
434 struct stream *packet;
435 struct prefix p;
436 unsigned long pos;
437 bgp_size_t total_attr_len;
paul718e3742002-12-13 20:15:29 +0000438
Paul Jakma750e8142008-07-22 21:11:48 +0000439 if (DISABLE_BGP_ANNOUNCE)
440 return;
paul718e3742002-12-13 20:15:29 +0000441
442 if (afi == AFI_IP)
443 str2prefix ("0.0.0.0/0", &p);
444#ifdef HAVE_IPV6
445 else
446 str2prefix ("::/0", &p);
447#endif /* HAVE_IPV6 */
448
449 /* Logging the attribute. */
450 if (BGP_DEBUG (update, UPDATE_OUT))
451 {
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000452 char attrstr[BUFSIZ];
453 char buf[INET6_BUFSIZ];
454 attrstr[0] = '\0';
455
paul718e3742002-12-13 20:15:29 +0000456 bgp_dump_attr (peer, attr, attrstr, BUFSIZ);
ajs6b514742004-12-08 21:03:23 +0000457 zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d %s",
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000458 peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ),
paul718e3742002-12-13 20:15:29 +0000459 p.prefixlen, attrstr);
460 }
461
462 s = stream_new (BGP_MAX_PACKET_SIZE);
463
464 /* Make BGP update packet. */
465 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
466
467 /* Unfeasible Routes Length. */
468 stream_putw (s, 0);
469
470 /* Make place for total attribute length. */
paul9985f832005-02-09 15:51:56 +0000471 pos = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000472 stream_putw (s, 0);
473 total_attr_len = bgp_packet_attribute (NULL, peer, s, attr, &p, afi, safi, from, NULL, NULL);
474
475 /* Set Total Path Attribute Length. */
476 stream_putw_at (s, pos, total_attr_len);
477
478 /* NLRI set. */
479 if (p.family == AF_INET && safi == SAFI_UNICAST)
480 stream_put_prefix (s, &p);
481
482 /* Set size. */
483 bgp_packet_set_size (s);
484
paule83e2082005-05-19 02:12:25 +0000485 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +0000486 stream_free (s);
487
488 /* Dump packet if debug option is set. */
489#ifdef DEBUG
jardin2d74db52005-10-01 00:07:50 +0000490 /* bgp_packet_dump (packet); */
paul718e3742002-12-13 20:15:29 +0000491#endif /* DEBUG */
492
493 /* Add packet to the peer. */
494 bgp_packet_add (peer, packet);
495
pauleb821182004-05-01 08:44:08 +0000496 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000497}
498
499void
500bgp_default_withdraw_send (struct peer *peer, afi_t afi, safi_t safi)
501{
502 struct stream *s;
503 struct stream *packet;
504 struct prefix p;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000505 unsigned long attrlen_pos = 0;
paul718e3742002-12-13 20:15:29 +0000506 unsigned long cp;
507 bgp_size_t unfeasible_len;
508 bgp_size_t total_attr_len;
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000509 size_t mp_start = 0;
510 size_t mplen_pos = 0;
paul718e3742002-12-13 20:15:29 +0000511
Paul Jakma750e8142008-07-22 21:11:48 +0000512 if (DISABLE_BGP_ANNOUNCE)
513 return;
paul718e3742002-12-13 20:15:29 +0000514
515 if (afi == AFI_IP)
516 str2prefix ("0.0.0.0/0", &p);
517#ifdef HAVE_IPV6
518 else
519 str2prefix ("::/0", &p);
520#endif /* HAVE_IPV6 */
521
522 total_attr_len = 0;
paul718e3742002-12-13 20:15:29 +0000523
524 if (BGP_DEBUG (update, UPDATE_OUT))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000525 {
526 char buf[INET6_BUFSIZ];
527
528 zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d -- unreachable",
529 peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ),
530 p.prefixlen);
531 }
paul718e3742002-12-13 20:15:29 +0000532
533 s = stream_new (BGP_MAX_PACKET_SIZE);
534
535 /* Make BGP update packet. */
536 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
537
538 /* Unfeasible Routes Length. */;
paul9985f832005-02-09 15:51:56 +0000539 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000540 stream_putw (s, 0);
541
542 /* Withdrawn Routes. */
543 if (p.family == AF_INET && safi == SAFI_UNICAST)
544 {
545 stream_put_prefix (s, &p);
546
paul9985f832005-02-09 15:51:56 +0000547 unfeasible_len = stream_get_endp (s) - cp - 2;
paul718e3742002-12-13 20:15:29 +0000548
549 /* Set unfeasible len. */
550 stream_putw_at (s, cp, unfeasible_len);
551
552 /* Set total path attribute length. */
553 stream_putw (s, 0);
554 }
555 else
556 {
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000557 attrlen_pos = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000558 stream_putw (s, 0);
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000559 mp_start = stream_get_endp (s);
560 mplen_pos = bgp_packet_mpunreach_start(s, afi, safi);
561 bgp_packet_mpunreach_prefix(s, &p, afi, safi, NULL, NULL);
562
563 /* Set the mp_unreach attr's length */
564 bgp_packet_mpunreach_end(s, mplen_pos);
paul718e3742002-12-13 20:15:29 +0000565
566 /* Set total path attribute length. */
Pradosh Mohapatra8c71e482014-01-15 06:57:57 +0000567 total_attr_len = stream_get_endp(s) - mp_start;
568 stream_putw_at (s, attrlen_pos, total_attr_len);
paul718e3742002-12-13 20:15:29 +0000569 }
570
571 bgp_packet_set_size (s);
572
paule83e2082005-05-19 02:12:25 +0000573 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +0000574 stream_free (s);
575
576 /* Add packet to the peer. */
577 bgp_packet_add (peer, packet);
578
pauleb821182004-05-01 08:44:08 +0000579 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000580}
581
582/* Get next packet to be written. */
paul94f2b392005-06-28 12:44:16 +0000583static struct stream *
paul718e3742002-12-13 20:15:29 +0000584bgp_write_packet (struct peer *peer)
585{
586 afi_t afi;
587 safi_t safi;
588 struct stream *s = NULL;
589 struct bgp_advertise *adv;
590
591 s = stream_fifo_head (peer->obuf);
592 if (s)
593 return s;
594
595 for (afi = AFI_IP; afi < AFI_MAX; afi++)
596 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
597 {
598 adv = FIFO_HEAD (&peer->sync[afi][safi]->withdraw);
599 if (adv)
600 {
601 s = bgp_withdraw_packet (peer, afi, safi);
602 if (s)
603 return s;
604 }
605 }
606
607 for (afi = AFI_IP; afi < AFI_MAX; afi++)
608 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
609 {
610 adv = FIFO_HEAD (&peer->sync[afi][safi]->update);
611 if (adv)
612 {
613 if (adv->binfo && adv->binfo->uptime < peer->synctime)
hasso93406d82005-02-02 14:40:33 +0000614 {
615 if (CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_RCV)
616 && CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_ADV)
617 && ! CHECK_FLAG (adv->binfo->flags, BGP_INFO_STALE)
618 && safi != SAFI_MPLS_VPN)
619 {
620 if (CHECK_FLAG (adv->binfo->peer->af_sflags[afi][safi],
621 PEER_STATUS_EOR_RECEIVED))
622 s = bgp_update_packet (peer, afi, safi);
623 }
624 else
625 s = bgp_update_packet (peer, afi, safi);
626 }
paul718e3742002-12-13 20:15:29 +0000627
628 if (s)
629 return s;
630 }
hasso93406d82005-02-02 14:40:33 +0000631
632 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV))
633 {
634 if (peer->afc_nego[afi][safi] && peer->synctime
635 && ! CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND)
636 && safi != SAFI_MPLS_VPN)
637 {
638 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND);
639 return bgp_update_packet_eor (peer, afi, safi);
640 }
641 }
paul718e3742002-12-13 20:15:29 +0000642 }
643
644 return NULL;
645}
646
647/* Is there partially written packet or updates we can send right
648 now. */
paul94f2b392005-06-28 12:44:16 +0000649static int
paul718e3742002-12-13 20:15:29 +0000650bgp_write_proceed (struct peer *peer)
651{
652 afi_t afi;
653 safi_t safi;
654 struct bgp_advertise *adv;
655
656 if (stream_fifo_head (peer->obuf))
657 return 1;
658
659 for (afi = AFI_IP; afi < AFI_MAX; afi++)
660 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
661 if (FIFO_HEAD (&peer->sync[afi][safi]->withdraw))
662 return 1;
663
664 for (afi = AFI_IP; afi < AFI_MAX; afi++)
665 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
666 if ((adv = FIFO_HEAD (&peer->sync[afi][safi]->update)) != NULL)
667 if (adv->binfo->uptime < peer->synctime)
668 return 1;
669
670 return 0;
671}
672
673/* Write packet to the peer. */
674int
675bgp_write (struct thread *thread)
676{
677 struct peer *peer;
678 u_char type;
679 struct stream *s;
680 int num;
paulfd79ac92004-10-13 05:06:08 +0000681 unsigned int count = 0;
paul718e3742002-12-13 20:15:29 +0000682
683 /* Yes first of all get peer pointer. */
684 peer = THREAD_ARG (thread);
685 peer->t_write = NULL;
686
687 /* For non-blocking IO check. */
688 if (peer->status == Connect)
689 {
690 bgp_connect_check (peer);
691 return 0;
692 }
693
Stephen Hemmingereac57022010-08-05 10:26:25 -0700694 s = bgp_write_packet (peer);
695 if (!s)
696 return 0; /* nothing to send */
697
698 sockopt_cork (peer->fd, 1);
699
700 /* Nonblocking write until TCP output buffer is full. */
701 do
paul718e3742002-12-13 20:15:29 +0000702 {
703 int writenum;
paul718e3742002-12-13 20:15:29 +0000704
705 /* Number of bytes to be sent. */
706 writenum = stream_get_endp (s) - stream_get_getp (s);
707
708 /* Call write() system call. */
pauleb821182004-05-01 08:44:08 +0000709 num = write (peer->fd, STREAM_PNT (s), writenum);
Stephen Hemminger35398582010-08-05 10:26:23 -0700710 if (num < 0)
paul718e3742002-12-13 20:15:29 +0000711 {
Stephen Hemmingereac57022010-08-05 10:26:25 -0700712 /* write failed either retry needed or error */
713 if (ERRNO_IO_RETRY(errno))
714 break;
715
716 BGP_EVENT_ADD (peer, TCP_fatal_error);
paul718e3742002-12-13 20:15:29 +0000717 return 0;
718 }
Stephen Hemminger35398582010-08-05 10:26:23 -0700719
paul718e3742002-12-13 20:15:29 +0000720 if (num != writenum)
721 {
Stephen Hemminger35398582010-08-05 10:26:23 -0700722 /* Partial write */
paul9985f832005-02-09 15:51:56 +0000723 stream_forward_getp (s, num);
Stephen Hemmingereac57022010-08-05 10:26:25 -0700724 break;
paul718e3742002-12-13 20:15:29 +0000725 }
726
727 /* Retrieve BGP packet type. */
728 stream_set_getp (s, BGP_MARKER_SIZE + 2);
729 type = stream_getc (s);
730
731 switch (type)
732 {
733 case BGP_MSG_OPEN:
734 peer->open_out++;
735 break;
736 case BGP_MSG_UPDATE:
737 peer->update_out++;
738 break;
739 case BGP_MSG_NOTIFY:
740 peer->notify_out++;
741 /* Double start timer. */
742 peer->v_start *= 2;
743
744 /* Overflow check. */
745 if (peer->v_start >= (60 * 2))
746 peer->v_start = (60 * 2);
747
Paul Jakmaca058a32006-09-14 02:58:49 +0000748 /* Flush any existing events */
Paul Jakmadcdf3992006-10-15 23:39:59 +0000749 BGP_EVENT_ADD (peer, BGP_Stop);
Stephen Hemminger3a69f742013-01-11 18:27:23 +0000750 goto done;
751
paul718e3742002-12-13 20:15:29 +0000752 case BGP_MSG_KEEPALIVE:
753 peer->keepalive_out++;
754 break;
755 case BGP_MSG_ROUTE_REFRESH_NEW:
756 case BGP_MSG_ROUTE_REFRESH_OLD:
757 peer->refresh_out++;
758 break;
759 case BGP_MSG_CAPABILITY:
760 peer->dynamic_cap_out++;
761 break;
762 }
763
764 /* OK we send packet so delete it. */
765 bgp_packet_delete (peer);
paul718e3742002-12-13 20:15:29 +0000766 }
Stephen Hemmingereac57022010-08-05 10:26:25 -0700767 while (++count < BGP_WRITE_PACKET_MAX &&
768 (s = bgp_write_packet (peer)) != NULL);
paul718e3742002-12-13 20:15:29 +0000769
770 if (bgp_write_proceed (peer))
pauleb821182004-05-01 08:44:08 +0000771 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
Stephen Hemminger3a69f742013-01-11 18:27:23 +0000772
773 done:
774 sockopt_cork (peer->fd, 0);
paul718e3742002-12-13 20:15:29 +0000775 return 0;
776}
777
778/* This is only for sending NOTIFICATION message to neighbor. */
paul94f2b392005-06-28 12:44:16 +0000779static int
paul718e3742002-12-13 20:15:29 +0000780bgp_write_notify (struct peer *peer)
781{
Stephen Hemminger35398582010-08-05 10:26:23 -0700782 int ret, val;
paul718e3742002-12-13 20:15:29 +0000783 u_char type;
784 struct stream *s;
785
786 /* There should be at least one packet. */
787 s = stream_fifo_head (peer->obuf);
788 if (!s)
789 return 0;
790 assert (stream_get_endp (s) >= BGP_HEADER_SIZE);
791
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000792 /* Stop collecting data within the socket */
793 sockopt_cork (peer->fd, 0);
794
David Lamparter8ff202e2013-07-31 14:39:41 +0200795 /* socket is in nonblocking mode, if we can't deliver the NOTIFY, well,
796 * we only care about getting a clean shutdown at this point. */
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000797 ret = write (peer->fd, STREAM_DATA (s), stream_get_endp (s));
David Lamparter8ff202e2013-07-31 14:39:41 +0200798
799 /* only connection reset/close gets counted as TCP_fatal_error, failure
800 * to write the entire NOTIFY doesn't get different FSM treatment */
paul718e3742002-12-13 20:15:29 +0000801 if (ret <= 0)
802 {
Paul Jakmadcdf3992006-10-15 23:39:59 +0000803 BGP_EVENT_ADD (peer, TCP_fatal_error);
paul718e3742002-12-13 20:15:29 +0000804 return 0;
805 }
806
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000807 /* Disable Nagle, make NOTIFY packet go out right away */
808 val = 1;
809 (void) setsockopt (peer->fd, IPPROTO_TCP, TCP_NODELAY,
810 (char *) &val, sizeof (val));
811
paul718e3742002-12-13 20:15:29 +0000812 /* Retrieve BGP packet type. */
813 stream_set_getp (s, BGP_MARKER_SIZE + 2);
814 type = stream_getc (s);
815
816 assert (type == BGP_MSG_NOTIFY);
817
818 /* Type should be notify. */
819 peer->notify_out++;
820
821 /* Double start timer. */
822 peer->v_start *= 2;
823
824 /* Overflow check. */
825 if (peer->v_start >= (60 * 2))
826 peer->v_start = (60 * 2);
827
Paul Jakmadcdf3992006-10-15 23:39:59 +0000828 BGP_EVENT_ADD (peer, BGP_Stop);
paul718e3742002-12-13 20:15:29 +0000829
830 return 0;
831}
832
833/* Make keepalive packet and send it to the peer. */
834void
835bgp_keepalive_send (struct peer *peer)
836{
837 struct stream *s;
838 int length;
839
840 s = stream_new (BGP_MAX_PACKET_SIZE);
841
842 /* Make keepalive packet. */
843 bgp_packet_set_marker (s, BGP_MSG_KEEPALIVE);
844
845 /* Set packet size. */
846 length = bgp_packet_set_size (s);
847
848 /* Dump packet if debug option is set. */
849 /* bgp_packet_dump (s); */
850
851 if (BGP_DEBUG (keepalive, KEEPALIVE))
ajs6b514742004-12-08 21:03:23 +0000852 zlog_debug ("%s sending KEEPALIVE", peer->host);
paul718e3742002-12-13 20:15:29 +0000853 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000854 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000855 peer->host, BGP_MSG_KEEPALIVE, length);
856
857 /* Add packet to the peer. */
858 bgp_packet_add (peer, s);
859
pauleb821182004-05-01 08:44:08 +0000860 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000861}
862
863/* Make open packet and send it to the peer. */
864void
865bgp_open_send (struct peer *peer)
866{
867 struct stream *s;
868 int length;
869 u_int16_t send_holdtime;
870 as_t local_as;
871
872 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
873 send_holdtime = peer->holdtime;
874 else
875 send_holdtime = peer->bgp->default_holdtime;
876
877 /* local-as Change */
878 if (peer->change_local_as)
879 local_as = peer->change_local_as;
880 else
881 local_as = peer->local_as;
882
883 s = stream_new (BGP_MAX_PACKET_SIZE);
884
885 /* Make open packet. */
886 bgp_packet_set_marker (s, BGP_MSG_OPEN);
887
888 /* Set open packet values. */
889 stream_putc (s, BGP_VERSION_4); /* BGP version */
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000890 stream_putw (s, (local_as <= BGP_AS_MAX) ? (u_int16_t) local_as
891 : BGP_AS_TRANS);
paul718e3742002-12-13 20:15:29 +0000892 stream_putw (s, send_holdtime); /* Hold Time */
893 stream_put_in_addr (s, &peer->local_id); /* BGP Identifier */
894
895 /* Set capability code. */
896 bgp_open_capability (s, peer);
897
898 /* Set BGP packet length. */
899 length = bgp_packet_set_size (s);
900
901 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +0400902 zlog_debug ("%s sending OPEN, version %d, my as %u, holdtime %d, id %s",
paul718e3742002-12-13 20:15:29 +0000903 peer->host, BGP_VERSION_4, local_as,
904 send_holdtime, inet_ntoa (peer->local_id));
905
906 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000907 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000908 peer->host, BGP_MSG_OPEN, length);
909
910 /* Dump packet if debug option is set. */
911 /* bgp_packet_dump (s); */
912
913 /* Add packet to the peer. */
914 bgp_packet_add (peer, s);
915
pauleb821182004-05-01 08:44:08 +0000916 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000917}
918
919/* Send BGP notify packet with data potion. */
920void
921bgp_notify_send_with_data (struct peer *peer, u_char code, u_char sub_code,
922 u_char *data, size_t datalen)
923{
924 struct stream *s;
925 int length;
926
927 /* Allocate new stream. */
928 s = stream_new (BGP_MAX_PACKET_SIZE);
929
930 /* Make nitify packet. */
931 bgp_packet_set_marker (s, BGP_MSG_NOTIFY);
932
933 /* Set notify packet values. */
934 stream_putc (s, code); /* BGP notify code */
935 stream_putc (s, sub_code); /* BGP notify sub_code */
936
937 /* If notify data is present. */
938 if (data)
939 stream_write (s, data, datalen);
940
941 /* Set BGP packet length. */
942 length = bgp_packet_set_size (s);
943
944 /* Add packet to the peer. */
945 stream_fifo_clean (peer->obuf);
946 bgp_packet_add (peer, s);
947
948 /* For debug */
949 {
950 struct bgp_notify bgp_notify;
951 int first = 0;
952 int i;
953 char c[4];
954
955 bgp_notify.code = code;
956 bgp_notify.subcode = sub_code;
957 bgp_notify.data = NULL;
958 bgp_notify.length = length - BGP_MSG_NOTIFY_MIN_SIZE;
959
960 if (bgp_notify.length)
961 {
962 bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
963 for (i = 0; i < bgp_notify.length; i++)
964 if (first)
965 {
966 sprintf (c, " %02x", data[i]);
967 strcat (bgp_notify.data, c);
968 }
969 else
970 {
971 first = 1;
972 sprintf (c, "%02x", data[i]);
973 strcpy (bgp_notify.data, c);
974 }
975 }
976 bgp_notify_print (peer, &bgp_notify, "sending");
977 if (bgp_notify.data)
978 XFREE (MTYPE_TMP, bgp_notify.data);
979 }
980
981 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000982 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000983 peer->host, BGP_MSG_NOTIFY, length);
984
hassoe0701b72004-05-20 09:19:34 +0000985 /* peer reset cause */
986 if (sub_code != BGP_NOTIFY_CEASE_CONFIG_CHANGE)
987 {
988 if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET)
heasley1212dc12011-09-12 13:27:52 +0400989 {
990 peer->last_reset = PEER_DOWN_USER_RESET;
991 zlog_info ("Notification sent to neighbor %s: User reset", peer->host);
992 }
hassoe0701b72004-05-20 09:19:34 +0000993 else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN)
heasley1212dc12011-09-12 13:27:52 +0400994 {
995 peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
996 zlog_info ("Notification sent to neighbor %s: shutdown", peer->host);
997 }
hassoe0701b72004-05-20 09:19:34 +0000998 else
heasley1212dc12011-09-12 13:27:52 +0400999 {
1000 peer->last_reset = PEER_DOWN_NOTIFY_SEND;
1001 zlog_info ("Notification sent to neighbor %s: type %u/%u",
1002 peer->host, code, sub_code);
1003 }
hassoe0701b72004-05-20 09:19:34 +00001004 }
heasley1212dc12011-09-12 13:27:52 +04001005 else
1006 zlog_info ("Notification sent to neighbor %s: configuration change",
1007 peer->host);
hassoe0701b72004-05-20 09:19:34 +00001008
Denis Ovsienko7ccf5e52011-09-10 16:53:30 +04001009 /* Call immediately. */
paul718e3742002-12-13 20:15:29 +00001010 BGP_WRITE_OFF (peer->t_write);
1011
1012 bgp_write_notify (peer);
1013}
1014
1015/* Send BGP notify packet. */
1016void
1017bgp_notify_send (struct peer *peer, u_char code, u_char sub_code)
1018{
1019 bgp_notify_send_with_data (peer, code, sub_code, NULL, 0);
1020}
1021
paul718e3742002-12-13 20:15:29 +00001022/* Send route refresh message to the peer. */
1023void
1024bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
1025 u_char orf_type, u_char when_to_refresh, int remove)
1026{
1027 struct stream *s;
1028 struct stream *packet;
1029 int length;
1030 struct bgp_filter *filter;
1031 int orf_refresh = 0;
1032
Paul Jakma750e8142008-07-22 21:11:48 +00001033 if (DISABLE_BGP_ANNOUNCE)
1034 return;
paul718e3742002-12-13 20:15:29 +00001035
1036 filter = &peer->filter[afi][safi];
1037
1038 /* Adjust safi code. */
1039 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001040 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +00001041
1042 s = stream_new (BGP_MAX_PACKET_SIZE);
1043
1044 /* Make BGP update packet. */
1045 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
1046 bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_NEW);
1047 else
1048 bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_OLD);
1049
1050 /* Encode Route Refresh message. */
1051 stream_putw (s, afi);
1052 stream_putc (s, 0);
1053 stream_putc (s, safi);
1054
1055 if (orf_type == ORF_TYPE_PREFIX
1056 || orf_type == ORF_TYPE_PREFIX_OLD)
1057 if (remove || filter->plist[FILTER_IN].plist)
1058 {
1059 u_int16_t orf_len;
1060 unsigned long orfp;
1061
1062 orf_refresh = 1;
1063 stream_putc (s, when_to_refresh);
1064 stream_putc (s, orf_type);
paul9985f832005-02-09 15:51:56 +00001065 orfp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +00001066 stream_putw (s, 0);
1067
1068 if (remove)
1069 {
1070 UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
1071 stream_putc (s, ORF_COMMON_PART_REMOVE_ALL);
1072 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001073 zlog_debug ("%s sending REFRESH_REQ to remove ORF(%d) (%s) for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001074 peer->host, orf_type,
1075 (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
1076 afi, safi);
1077 }
1078 else
1079 {
1080 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
1081 prefix_bgp_orf_entry (s, filter->plist[FILTER_IN].plist,
1082 ORF_COMMON_PART_ADD, ORF_COMMON_PART_PERMIT,
1083 ORF_COMMON_PART_DENY);
1084 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001085 zlog_debug ("%s sending REFRESH_REQ with pfxlist ORF(%d) (%s) for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001086 peer->host, orf_type,
1087 (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
1088 afi, safi);
1089 }
1090
1091 /* Total ORF Entry Len. */
paul9985f832005-02-09 15:51:56 +00001092 orf_len = stream_get_endp (s) - orfp - 2;
paul718e3742002-12-13 20:15:29 +00001093 stream_putw_at (s, orfp, orf_len);
1094 }
1095
1096 /* Set packet size. */
1097 length = bgp_packet_set_size (s);
1098
1099 if (BGP_DEBUG (normal, NORMAL))
1100 {
1101 if (! orf_refresh)
ajs6b514742004-12-08 21:03:23 +00001102 zlog_debug ("%s sending REFRESH_REQ for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001103 peer->host, afi, safi);
ajs6b514742004-12-08 21:03:23 +00001104 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +00001105 peer->host, CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV) ?
1106 BGP_MSG_ROUTE_REFRESH_NEW : BGP_MSG_ROUTE_REFRESH_OLD, length);
1107 }
1108
1109 /* Make real packet. */
paule83e2082005-05-19 02:12:25 +00001110 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +00001111 stream_free (s);
1112
1113 /* Add packet to the peer. */
1114 bgp_packet_add (peer, packet);
1115
pauleb821182004-05-01 08:44:08 +00001116 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +00001117}
1118
1119/* Send capability message to the peer. */
1120void
1121bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi,
1122 int capability_code, int action)
1123{
1124 struct stream *s;
1125 struct stream *packet;
1126 int length;
1127
1128 /* Adjust safi code. */
1129 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001130 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +00001131
1132 s = stream_new (BGP_MAX_PACKET_SIZE);
1133
1134 /* Make BGP update packet. */
1135 bgp_packet_set_marker (s, BGP_MSG_CAPABILITY);
1136
1137 /* Encode MP_EXT capability. */
1138 if (capability_code == CAPABILITY_CODE_MP)
1139 {
1140 stream_putc (s, action);
1141 stream_putc (s, CAPABILITY_CODE_MP);
1142 stream_putc (s, CAPABILITY_CODE_MP_LEN);
1143 stream_putw (s, afi);
1144 stream_putc (s, 0);
1145 stream_putc (s, safi);
1146
1147 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001148 zlog_debug ("%s sending CAPABILITY has %s MP_EXT CAP for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001149 peer->host, action == CAPABILITY_ACTION_SET ?
1150 "Advertising" : "Removing", afi, safi);
1151 }
1152
paul718e3742002-12-13 20:15:29 +00001153 /* Set packet size. */
1154 length = bgp_packet_set_size (s);
1155
1156 /* Make real packet. */
paule83e2082005-05-19 02:12:25 +00001157 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +00001158 stream_free (s);
1159
1160 /* Add packet to the peer. */
1161 bgp_packet_add (peer, packet);
1162
1163 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001164 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +00001165 peer->host, BGP_MSG_CAPABILITY, length);
1166
pauleb821182004-05-01 08:44:08 +00001167 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +00001168}
David Lamparter6b0655a2014-06-04 06:53:35 +02001169
paul718e3742002-12-13 20:15:29 +00001170/* RFC1771 6.8 Connection collision detection. */
paul94f2b392005-06-28 12:44:16 +00001171static int
pauleb821182004-05-01 08:44:08 +00001172bgp_collision_detect (struct peer *new, struct in_addr remote_id)
paul718e3742002-12-13 20:15:29 +00001173{
pauleb821182004-05-01 08:44:08 +00001174 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001175 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001176 struct bgp *bgp;
1177
1178 bgp = bgp_get_default ();
1179 if (! bgp)
1180 return 0;
1181
1182 /* Upon receipt of an OPEN message, the local system must examine
1183 all of its connections that are in the OpenConfirm state. A BGP
1184 speaker may also examine connections in an OpenSent state if it
1185 knows the BGP Identifier of the peer by means outside of the
1186 protocol. If among these connections there is a connection to a
1187 remote BGP speaker whose BGP Identifier equals the one in the
1188 OPEN message, then the local system performs the following
1189 collision resolution procedure: */
1190
paul1eb8ef22005-04-07 07:30:20 +00001191 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001192 {
1193 /* Under OpenConfirm status, local peer structure already hold
1194 remote router ID. */
pauleb821182004-05-01 08:44:08 +00001195
1196 if (peer != new
1197 && (peer->status == OpenConfirm || peer->status == OpenSent)
1198 && sockunion_same (&peer->su, &new->su))
1199 {
paul718e3742002-12-13 20:15:29 +00001200 /* 1. The BGP Identifier of the local system is compared to
1201 the BGP Identifier of the remote system (as specified in
1202 the OPEN message). */
1203
1204 if (ntohl (peer->local_id.s_addr) < ntohl (remote_id.s_addr))
1205 {
1206 /* 2. If the value of the local BGP Identifier is less
1207 than the remote one, the local system closes BGP
1208 connection that already exists (the one that is
1209 already in the OpenConfirm state), and accepts BGP
1210 connection initiated by the remote system. */
1211
pauleb821182004-05-01 08:44:08 +00001212 if (peer->fd >= 0)
hassoe0701b72004-05-20 09:19:34 +00001213 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
paul718e3742002-12-13 20:15:29 +00001214 return 1;
1215 }
1216 else
1217 {
1218 /* 3. Otherwise, the local system closes newly created
1219 BGP connection (the one associated with the newly
1220 received OPEN message), and continues to use the
1221 existing one (the one that is already in the
1222 OpenConfirm state). */
1223
pauleb821182004-05-01 08:44:08 +00001224 if (new->fd >= 0)
paulf5ba3872004-07-09 12:11:31 +00001225 bgp_notify_send (new, BGP_NOTIFY_CEASE,
1226 BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
paul718e3742002-12-13 20:15:29 +00001227 return -1;
1228 }
pauleb821182004-05-01 08:44:08 +00001229 }
1230 }
paul718e3742002-12-13 20:15:29 +00001231 return 0;
1232}
1233
paul94f2b392005-06-28 12:44:16 +00001234static int
paul718e3742002-12-13 20:15:29 +00001235bgp_open_receive (struct peer *peer, bgp_size_t size)
1236{
1237 int ret;
1238 u_char version;
1239 u_char optlen;
1240 u_int16_t holdtime;
1241 u_int16_t send_holdtime;
1242 as_t remote_as;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001243 as_t as4 = 0;
paul718e3742002-12-13 20:15:29 +00001244 struct peer *realpeer;
1245 struct in_addr remote_id;
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001246 int mp_capability;
paul5228ad22004-06-04 17:58:18 +00001247 u_int8_t notify_data_remote_as[2];
1248 u_int8_t notify_data_remote_id[4];
paul718e3742002-12-13 20:15:29 +00001249
1250 realpeer = NULL;
1251
1252 /* Parse open packet. */
1253 version = stream_getc (peer->ibuf);
1254 memcpy (notify_data_remote_as, stream_pnt (peer->ibuf), 2);
1255 remote_as = stream_getw (peer->ibuf);
1256 holdtime = stream_getw (peer->ibuf);
1257 memcpy (notify_data_remote_id, stream_pnt (peer->ibuf), 4);
1258 remote_id.s_addr = stream_get_ipv4 (peer->ibuf);
1259
1260 /* Receive OPEN message log */
1261 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001262 zlog_debug ("%s rcv OPEN, version %d, remote-as (in open) %u,"
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001263 " holdtime %d, id %s",
1264 peer->host, version, remote_as, holdtime,
1265 inet_ntoa (remote_id));
1266
1267 /* BEGIN to read the capability here, but dont do it yet */
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001268 mp_capability = 0;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001269 optlen = stream_getc (peer->ibuf);
1270
1271 if (optlen != 0)
1272 {
1273 /* We need the as4 capability value *right now* because
1274 * if it is there, we have not got the remote_as yet, and without
1275 * that we do not know which peer is connecting to us now.
1276 */
1277 as4 = peek_for_as4_capability (peer, optlen);
1278 }
1279
1280 /* Just in case we have a silly peer who sends AS4 capability set to 0 */
1281 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) && !as4)
1282 {
1283 zlog_err ("%s bad OPEN, got AS4 capability, but AS4 set to 0",
1284 peer->host);
1285 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1286 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1287 return -1;
1288 }
1289
1290 if (remote_as == BGP_AS_TRANS)
1291 {
1292 /* Take the AS4 from the capability. We must have received the
1293 * capability now! Otherwise we have a asn16 peer who uses
1294 * BGP_AS_TRANS, for some unknown reason.
1295 */
1296 if (as4 == BGP_AS_TRANS)
1297 {
1298 zlog_err ("%s [AS4] NEW speaker using AS_TRANS for AS4, not allowed",
1299 peer->host);
1300 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1301 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1302 return -1;
1303 }
1304
1305 if (!as4 && BGP_DEBUG (as4, AS4))
1306 zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but no AS4."
1307 " Odd, but proceeding.", peer->host);
1308 else if (as4 < BGP_AS_MAX && BGP_DEBUG (as4, AS4))
Paul Jakma0df7c912008-07-21 21:02:49 +00001309 zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but AS4 (%u) fits "
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001310 "in 2-bytes, very odd peer.", peer->host, as4);
1311 if (as4)
1312 remote_as = as4;
1313 }
1314 else
1315 {
1316 /* We may have a partner with AS4 who has an asno < BGP_AS_MAX */
1317 /* If we have got the capability, peer->as4cap must match remote_as */
1318 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)
1319 && as4 != remote_as)
1320 {
1321 /* raise error, log this, close session */
1322 zlog_err ("%s bad OPEN, got AS4 capability, but remote_as %u"
1323 " mismatch with 16bit 'myasn' %u in open",
1324 peer->host, as4, remote_as);
1325 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1326 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1327 return -1;
1328 }
1329 }
1330
paul718e3742002-12-13 20:15:29 +00001331 /* Lookup peer from Open packet. */
1332 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1333 {
1334 int as = 0;
1335
1336 realpeer = peer_lookup_with_open (&peer->su, remote_as, &remote_id, &as);
1337
1338 if (! realpeer)
1339 {
1340 /* Peer's source IP address is check in bgp_accept(), so this
1341 must be AS number mismatch or remote-id configuration
1342 mismatch. */
1343 if (as)
1344 {
1345 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001346 zlog_debug ("%s bad OPEN, wrong router identifier %s",
1347 peer->host, inet_ntoa (remote_id));
1348 bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
1349 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
1350 notify_data_remote_id, 4);
paul718e3742002-12-13 20:15:29 +00001351 }
1352 else
1353 {
1354 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001355 zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
ajs6b514742004-12-08 21:03:23 +00001356 peer->host, remote_as, peer->as);
1357 bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
1358 BGP_NOTIFY_OPEN_BAD_PEER_AS,
1359 notify_data_remote_as, 2);
paul718e3742002-12-13 20:15:29 +00001360 }
1361 return -1;
1362 }
1363 }
1364
1365 /* When collision is detected and this peer is closed. Retrun
1366 immidiately. */
1367 ret = bgp_collision_detect (peer, remote_id);
1368 if (ret < 0)
1369 return ret;
1370
pauleb821182004-05-01 08:44:08 +00001371 /* Hack part. */
1372 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1373 {
hasso93406d82005-02-02 14:40:33 +00001374 if (realpeer->status == Established
1375 && CHECK_FLAG (realpeer->sflags, PEER_STATUS_NSF_MODE))
1376 {
1377 realpeer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
1378 SET_FLAG (realpeer->sflags, PEER_STATUS_NSF_WAIT);
1379 }
1380 else if (ret == 0 && realpeer->status != Active
1381 && realpeer->status != OpenSent
Paul Jakma6e199262008-09-09 17:14:33 +01001382 && realpeer->status != OpenConfirm
1383 && realpeer->status != Connect)
pauleb821182004-05-01 08:44:08 +00001384 {
Paul Jakma2b2fc562008-09-06 13:09:35 +01001385 /* XXX: This is an awful problem..
1386 *
1387 * According to the RFC we should just let this connection (of the
1388 * accepted 'peer') continue on to Established if the other
1389 * connection (the 'realpeer' one) is in state Connect, and deal
1390 * with the more larval FSM as/when it gets far enough to receive
1391 * an Open. We don't do that though, we instead close the (more
1392 * developed) accepted connection.
1393 *
1394 * This means there's a race, which if hit, can loop:
1395 *
1396 * FSM for A FSM for B
1397 * realpeer accept-peer realpeer accept-peer
1398 *
1399 * Connect Connect
1400 * Active
1401 * OpenSent OpenSent
1402 * <arrive here,
1403 * Notify, delete>
1404 * Idle Active
1405 * OpenSent OpenSent
1406 * <arrive here,
1407 * Notify, delete>
1408 * Idle
1409 * <wait> <wait>
1410 * Connect Connect
1411 *
1412 *
1413 * If both sides are Quagga, they're almost certain to wait for
1414 * the same amount of time of course (which doesn't preclude other
1415 * implementations also waiting for same time). The race is
1416 * exacerbated by high-latency (in bgpd and/or the network).
1417 *
1418 * The reason we do this is because our FSM is tied to our peer
1419 * structure, which carries our configuration information, etc.
1420 * I.e. we can't let the accepted-peer FSM continue on as it is,
1421 * cause it's not associated with any actual peer configuration -
1422 * it's just a dummy.
1423 *
1424 * It's possible we could hack-fix this by just bgp_stop'ing the
1425 * realpeer and continueing on with the 'transfer FSM' below.
1426 * Ideally, we need to seperate FSMs from struct peer.
1427 *
1428 * Setting one side to passive avoids the race, as a workaround.
1429 */
pauleb821182004-05-01 08:44:08 +00001430 if (BGP_DEBUG (events, EVENTS))
hasso93406d82005-02-02 14:40:33 +00001431 zlog_debug ("%s peer status is %s close connection",
1432 realpeer->host, LOOKUP (bgp_status_msg,
1433 realpeer->status));
1434 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1435 BGP_NOTIFY_CEASE_CONNECT_REJECT);
1436
pauleb821182004-05-01 08:44:08 +00001437 return -1;
1438 }
1439
1440 if (BGP_DEBUG (events, EVENTS))
Paul Jakma6e199262008-09-09 17:14:33 +01001441 zlog_debug ("%s [Event] Transfer accept BGP peer to real (state %s)",
1442 peer->host,
1443 LOOKUP (bgp_status_msg, realpeer->status));
pauleb821182004-05-01 08:44:08 +00001444
1445 bgp_stop (realpeer);
1446
1447 /* Transfer file descriptor. */
1448 realpeer->fd = peer->fd;
1449 peer->fd = -1;
1450
1451 /* Transfer input buffer. */
1452 stream_free (realpeer->ibuf);
1453 realpeer->ibuf = peer->ibuf;
1454 realpeer->packet_size = peer->packet_size;
1455 peer->ibuf = NULL;
1456
1457 /* Transfer status. */
1458 realpeer->status = peer->status;
1459 bgp_stop (peer);
paul200df112005-06-01 11:17:05 +00001460
pauleb821182004-05-01 08:44:08 +00001461 /* peer pointer change. Open packet send to neighbor. */
1462 peer = realpeer;
1463 bgp_open_send (peer);
1464 if (peer->fd < 0)
1465 {
1466 zlog_err ("bgp_open_receive peer's fd is negative value %d",
1467 peer->fd);
1468 return -1;
1469 }
1470 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
1471 }
1472
paul718e3742002-12-13 20:15:29 +00001473 /* remote router-id check. */
1474 if (remote_id.s_addr == 0
Denis Ovsienko733cd9e2011-12-17 19:39:30 +04001475 || IPV4_CLASS_DE (ntohl (remote_id.s_addr))
paul718e3742002-12-13 20:15:29 +00001476 || ntohl (peer->local_id.s_addr) == ntohl (remote_id.s_addr))
1477 {
1478 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001479 zlog_debug ("%s bad OPEN, wrong router identifier %s",
paul718e3742002-12-13 20:15:29 +00001480 peer->host, inet_ntoa (remote_id));
1481 bgp_notify_send_with_data (peer,
1482 BGP_NOTIFY_OPEN_ERR,
1483 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
1484 notify_data_remote_id, 4);
1485 return -1;
1486 }
1487
1488 /* Set remote router-id */
1489 peer->remote_id = remote_id;
1490
1491 /* Peer BGP version check. */
1492 if (version != BGP_VERSION_4)
1493 {
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001494 u_int16_t maxver = htons(BGP_VERSION_4);
1495 /* XXX this reply may not be correct if version < 4 XXX */
paul718e3742002-12-13 20:15:29 +00001496 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001497 zlog_debug ("%s bad protocol version, remote requested %d, local request %d",
paul718e3742002-12-13 20:15:29 +00001498 peer->host, version, BGP_VERSION_4);
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001499 /* Data must be in network byte order here */
paul718e3742002-12-13 20:15:29 +00001500 bgp_notify_send_with_data (peer,
1501 BGP_NOTIFY_OPEN_ERR,
1502 BGP_NOTIFY_OPEN_UNSUP_VERSION,
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001503 (u_int8_t *) &maxver, 2);
paul718e3742002-12-13 20:15:29 +00001504 return -1;
1505 }
1506
1507 /* Check neighbor as number. */
1508 if (remote_as != peer->as)
1509 {
1510 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001511 zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
paul718e3742002-12-13 20:15:29 +00001512 peer->host, remote_as, peer->as);
1513 bgp_notify_send_with_data (peer,
1514 BGP_NOTIFY_OPEN_ERR,
1515 BGP_NOTIFY_OPEN_BAD_PEER_AS,
1516 notify_data_remote_as, 2);
1517 return -1;
1518 }
1519
1520 /* From the rfc: Upon receipt of an OPEN message, a BGP speaker MUST
1521 calculate the value of the Hold Timer by using the smaller of its
1522 configured Hold Time and the Hold Time received in the OPEN message.
1523 The Hold Time MUST be either zero or at least three seconds. An
1524 implementation may reject connections on the basis of the Hold Time. */
1525
1526 if (holdtime < 3 && holdtime != 0)
1527 {
1528 bgp_notify_send (peer,
1529 BGP_NOTIFY_OPEN_ERR,
1530 BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
1531 return -1;
1532 }
1533
1534 /* From the rfc: A reasonable maximum time between KEEPALIVE messages
1535 would be one third of the Hold Time interval. KEEPALIVE messages
1536 MUST NOT be sent more frequently than one per second. An
1537 implementation MAY adjust the rate at which it sends KEEPALIVE
1538 messages as a function of the Hold Time interval. */
1539
1540 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
1541 send_holdtime = peer->holdtime;
1542 else
1543 send_holdtime = peer->bgp->default_holdtime;
1544
1545 if (holdtime < send_holdtime)
1546 peer->v_holdtime = holdtime;
1547 else
1548 peer->v_holdtime = send_holdtime;
1549
1550 peer->v_keepalive = peer->v_holdtime / 3;
1551
1552 /* Open option part parse. */
paul718e3742002-12-13 20:15:29 +00001553 if (optlen != 0)
1554 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001555 if ((ret = bgp_open_option_parse (peer, optlen, &mp_capability)) < 0)
Paul Jakma58617392012-01-09 20:59:26 +00001556 {
1557 bgp_notify_send (peer,
1558 BGP_NOTIFY_OPEN_ERR,
1559 BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
1560 return ret;
1561 }
paul718e3742002-12-13 20:15:29 +00001562 }
1563 else
1564 {
1565 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001566 zlog_debug ("%s rcvd OPEN w/ OPTION parameter len: 0",
paul718e3742002-12-13 20:15:29 +00001567 peer->host);
1568 }
1569
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001570 /*
1571 * Assume that the peer supports the locally configured set of
1572 * AFI/SAFIs if the peer did not send us any Mulitiprotocol
1573 * capabilities, or if 'override-capability' is configured.
1574 */
1575 if (! mp_capability ||
1576 CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
paul718e3742002-12-13 20:15:29 +00001577 {
1578 peer->afc_nego[AFI_IP][SAFI_UNICAST] = peer->afc[AFI_IP][SAFI_UNICAST];
1579 peer->afc_nego[AFI_IP][SAFI_MULTICAST] = peer->afc[AFI_IP][SAFI_MULTICAST];
1580 peer->afc_nego[AFI_IP6][SAFI_UNICAST] = peer->afc[AFI_IP6][SAFI_UNICAST];
1581 peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = peer->afc[AFI_IP6][SAFI_MULTICAST];
1582 }
1583
1584 /* Get sockname. */
1585 bgp_getsockname (peer);
1586
1587 BGP_EVENT_ADD (peer, Receive_OPEN_message);
1588
1589 peer->packet_size = 0;
1590 if (peer->ibuf)
1591 stream_reset (peer->ibuf);
1592
1593 return 0;
1594}
1595
1596/* Parse BGP Update packet and make attribute object. */
paul94f2b392005-06-28 12:44:16 +00001597static int
paul718e3742002-12-13 20:15:29 +00001598bgp_update_receive (struct peer *peer, bgp_size_t size)
1599{
1600 int ret;
1601 u_char *end;
1602 struct stream *s;
1603 struct attr attr;
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001604 struct attr_extra extra;
paul718e3742002-12-13 20:15:29 +00001605 bgp_size_t attribute_len;
1606 bgp_size_t update_len;
1607 bgp_size_t withdraw_len;
1608 struct bgp_nlri update;
1609 struct bgp_nlri withdraw;
1610 struct bgp_nlri mp_update;
1611 struct bgp_nlri mp_withdraw;
paul718e3742002-12-13 20:15:29 +00001612
1613 /* Status must be Established. */
1614 if (peer->status != Established)
1615 {
1616 zlog_err ("%s [FSM] Update packet received under status %s",
1617 peer->host, LOOKUP (bgp_status_msg, peer->status));
1618 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
1619 return -1;
1620 }
1621
1622 /* Set initial values. */
1623 memset (&attr, 0, sizeof (struct attr));
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001624 memset (&extra, 0, sizeof (struct attr_extra));
paul718e3742002-12-13 20:15:29 +00001625 memset (&update, 0, sizeof (struct bgp_nlri));
1626 memset (&withdraw, 0, sizeof (struct bgp_nlri));
1627 memset (&mp_update, 0, sizeof (struct bgp_nlri));
1628 memset (&mp_withdraw, 0, sizeof (struct bgp_nlri));
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001629 attr.extra = &extra;
paul718e3742002-12-13 20:15:29 +00001630
1631 s = peer->ibuf;
1632 end = stream_pnt (s) + size;
1633
1634 /* RFC1771 6.3 If the Unfeasible Routes Length or Total Attribute
1635 Length is too large (i.e., if Unfeasible Routes Length + Total
1636 Attribute Length + 23 exceeds the message Length), then the Error
1637 Subcode is set to Malformed Attribute List. */
1638 if (stream_pnt (s) + 2 > end)
1639 {
1640 zlog_err ("%s [Error] Update packet error"
1641 " (packet length is short for unfeasible length)",
1642 peer->host);
1643 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1644 BGP_NOTIFY_UPDATE_MAL_ATTR);
1645 return -1;
1646 }
1647
1648 /* Unfeasible Route Length. */
1649 withdraw_len = stream_getw (s);
1650
1651 /* Unfeasible Route Length check. */
1652 if (stream_pnt (s) + withdraw_len > end)
1653 {
1654 zlog_err ("%s [Error] Update packet error"
1655 " (packet unfeasible length overflow %d)",
1656 peer->host, withdraw_len);
1657 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1658 BGP_NOTIFY_UPDATE_MAL_ATTR);
1659 return -1;
1660 }
1661
1662 /* Unfeasible Route packet format check. */
1663 if (withdraw_len > 0)
1664 {
1665 ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), withdraw_len);
1666 if (ret < 0)
1667 return -1;
1668
1669 if (BGP_DEBUG (packet, PACKET_RECV))
ajs6b514742004-12-08 21:03:23 +00001670 zlog_debug ("%s [Update:RECV] Unfeasible NLRI received", peer->host);
paul718e3742002-12-13 20:15:29 +00001671
1672 withdraw.afi = AFI_IP;
1673 withdraw.safi = SAFI_UNICAST;
1674 withdraw.nlri = stream_pnt (s);
1675 withdraw.length = withdraw_len;
paul9985f832005-02-09 15:51:56 +00001676 stream_forward_getp (s, withdraw_len);
paul718e3742002-12-13 20:15:29 +00001677 }
1678
1679 /* Attribute total length check. */
1680 if (stream_pnt (s) + 2 > end)
1681 {
1682 zlog_warn ("%s [Error] Packet Error"
1683 " (update packet is short for attribute length)",
1684 peer->host);
1685 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1686 BGP_NOTIFY_UPDATE_MAL_ATTR);
1687 return -1;
1688 }
1689
1690 /* Fetch attribute total length. */
1691 attribute_len = stream_getw (s);
1692
1693 /* Attribute length check. */
1694 if (stream_pnt (s) + attribute_len > end)
1695 {
1696 zlog_warn ("%s [Error] Packet Error"
1697 " (update packet attribute length overflow %d)",
1698 peer->host, attribute_len);
1699 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1700 BGP_NOTIFY_UPDATE_MAL_ATTR);
1701 return -1;
1702 }
Paul Jakmab881c702010-11-23 16:35:42 +00001703
1704 /* Certain attribute parsing errors should not be considered bad enough
1705 * to reset the session for, most particularly any partial/optional
1706 * attributes that have 'tunneled' over speakers that don't understand
1707 * them. Instead we withdraw only the prefix concerned.
1708 *
1709 * Complicates the flow a little though..
1710 */
1711 bgp_attr_parse_ret_t attr_parse_ret = BGP_ATTR_PARSE_PROCEED;
1712 /* This define morphs the update case into a withdraw when lower levels
1713 * have signalled an error condition where this is best.
1714 */
1715#define NLRI_ATTR_ARG (attr_parse_ret != BGP_ATTR_PARSE_WITHDRAW ? &attr : NULL)
paul718e3742002-12-13 20:15:29 +00001716
1717 /* Parse attribute when it exists. */
1718 if (attribute_len)
1719 {
Paul Jakmab881c702010-11-23 16:35:42 +00001720 attr_parse_ret = bgp_attr_parse (peer, &attr, attribute_len,
paul718e3742002-12-13 20:15:29 +00001721 &mp_update, &mp_withdraw);
Paul Jakmab881c702010-11-23 16:35:42 +00001722 if (attr_parse_ret == BGP_ATTR_PARSE_ERROR)
paul718e3742002-12-13 20:15:29 +00001723 return -1;
1724 }
Paul Jakmab881c702010-11-23 16:35:42 +00001725
paul718e3742002-12-13 20:15:29 +00001726 /* Logging the attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001727 if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW
1728 || BGP_DEBUG (update, UPDATE_IN))
paul718e3742002-12-13 20:15:29 +00001729 {
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +00001730 char attrstr[BUFSIZ];
1731 attrstr[0] = '\0';
1732
paule01f9cb2004-07-09 17:48:53 +00001733 ret= bgp_dump_attr (peer, &attr, attrstr, BUFSIZ);
Paul Jakmab881c702010-11-23 16:35:42 +00001734 int lvl = (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
1735 ? LOG_ERR : LOG_DEBUG;
1736
1737 if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
1738 zlog (peer->log, LOG_ERR,
1739 "%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.",
1740 peer->host);
paule01f9cb2004-07-09 17:48:53 +00001741
1742 if (ret)
Paul Jakmab881c702010-11-23 16:35:42 +00001743 zlog (peer->log, lvl, "%s rcvd UPDATE w/ attr: %s",
paule01f9cb2004-07-09 17:48:53 +00001744 peer->host, attrstr);
paul718e3742002-12-13 20:15:29 +00001745 }
Paul Jakmab881c702010-11-23 16:35:42 +00001746
paul718e3742002-12-13 20:15:29 +00001747 /* Network Layer Reachability Information. */
1748 update_len = end - stream_pnt (s);
1749
1750 if (update_len)
1751 {
1752 /* Check NLRI packet format and prefix length. */
1753 ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), update_len);
1754 if (ret < 0)
Paul Jakmab881c702010-11-23 16:35:42 +00001755 {
1756 bgp_attr_unintern_sub (&attr);
Paul Jakmab881c702010-11-23 16:35:42 +00001757 return -1;
1758 }
paul718e3742002-12-13 20:15:29 +00001759
1760 /* Set NLRI portion to structure. */
1761 update.afi = AFI_IP;
1762 update.safi = SAFI_UNICAST;
1763 update.nlri = stream_pnt (s);
1764 update.length = update_len;
paul9985f832005-02-09 15:51:56 +00001765 stream_forward_getp (s, update_len);
paul718e3742002-12-13 20:15:29 +00001766 }
1767
1768 /* NLRI is processed only when the peer is configured specific
1769 Address Family and Subsequent Address Family. */
1770 if (peer->afc[AFI_IP][SAFI_UNICAST])
1771 {
1772 if (withdraw.length)
1773 bgp_nlri_parse (peer, NULL, &withdraw);
1774
1775 if (update.length)
1776 {
1777 /* We check well-known attribute only for IPv4 unicast
1778 update. */
1779 ret = bgp_attr_check (peer, &attr);
1780 if (ret < 0)
Paul Jakmab881c702010-11-23 16:35:42 +00001781 {
1782 bgp_attr_unintern_sub (&attr);
Paul Jakmab881c702010-11-23 16:35:42 +00001783 return -1;
1784 }
paul718e3742002-12-13 20:15:29 +00001785
Paul Jakmab881c702010-11-23 16:35:42 +00001786 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &update);
paul718e3742002-12-13 20:15:29 +00001787 }
paule01f9cb2004-07-09 17:48:53 +00001788
hassof4184462005-02-01 20:13:16 +00001789 if (mp_update.length
1790 && mp_update.afi == AFI_IP
1791 && mp_update.safi == SAFI_UNICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001792 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
hassof4184462005-02-01 20:13:16 +00001793
1794 if (mp_withdraw.length
1795 && mp_withdraw.afi == AFI_IP
1796 && mp_withdraw.safi == SAFI_UNICAST)
1797 bgp_nlri_parse (peer, NULL, &mp_withdraw);
1798
paule01f9cb2004-07-09 17:48:53 +00001799 if (! attribute_len && ! withdraw_len)
1800 {
1801 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001802 SET_FLAG (peer->af_sflags[AFI_IP][SAFI_UNICAST],
1803 PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001804
hasso93406d82005-02-02 14:40:33 +00001805 /* NSF delete stale route */
1806 if (peer->nsf[AFI_IP][SAFI_UNICAST])
1807 bgp_clear_stale_route (peer, AFI_IP, SAFI_UNICAST);
1808
1809 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001810 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001811 peer->host);
1812 }
paul718e3742002-12-13 20:15:29 +00001813 }
1814 if (peer->afc[AFI_IP][SAFI_MULTICAST])
1815 {
1816 if (mp_update.length
1817 && mp_update.afi == AFI_IP
1818 && mp_update.safi == SAFI_MULTICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001819 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001820
1821 if (mp_withdraw.length
1822 && mp_withdraw.afi == AFI_IP
1823 && mp_withdraw.safi == SAFI_MULTICAST)
1824 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001825
hasso93406d82005-02-02 14:40:33 +00001826 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001827 && mp_withdraw.afi == AFI_IP
1828 && mp_withdraw.safi == SAFI_MULTICAST
1829 && mp_withdraw.length == 0)
1830 {
1831 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001832 SET_FLAG (peer->af_sflags[AFI_IP][SAFI_MULTICAST],
1833 PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001834
hasso93406d82005-02-02 14:40:33 +00001835 /* NSF delete stale route */
1836 if (peer->nsf[AFI_IP][SAFI_MULTICAST])
1837 bgp_clear_stale_route (peer, AFI_IP, SAFI_MULTICAST);
1838
1839 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001840 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Multicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001841 peer->host);
1842 }
paul718e3742002-12-13 20:15:29 +00001843 }
1844 if (peer->afc[AFI_IP6][SAFI_UNICAST])
1845 {
1846 if (mp_update.length
1847 && mp_update.afi == AFI_IP6
1848 && mp_update.safi == SAFI_UNICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001849 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001850
1851 if (mp_withdraw.length
1852 && mp_withdraw.afi == AFI_IP6
1853 && mp_withdraw.safi == SAFI_UNICAST)
1854 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001855
hasso93406d82005-02-02 14:40:33 +00001856 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001857 && mp_withdraw.afi == AFI_IP6
1858 && mp_withdraw.safi == SAFI_UNICAST
1859 && mp_withdraw.length == 0)
1860 {
1861 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001862 SET_FLAG (peer->af_sflags[AFI_IP6][SAFI_UNICAST], PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001863
hasso93406d82005-02-02 14:40:33 +00001864 /* NSF delete stale route */
1865 if (peer->nsf[AFI_IP6][SAFI_UNICAST])
1866 bgp_clear_stale_route (peer, AFI_IP6, SAFI_UNICAST);
1867
1868 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001869 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001870 peer->host);
1871 }
paul718e3742002-12-13 20:15:29 +00001872 }
1873 if (peer->afc[AFI_IP6][SAFI_MULTICAST])
1874 {
1875 if (mp_update.length
1876 && mp_update.afi == AFI_IP6
1877 && mp_update.safi == SAFI_MULTICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001878 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001879
1880 if (mp_withdraw.length
1881 && mp_withdraw.afi == AFI_IP6
1882 && mp_withdraw.safi == SAFI_MULTICAST)
1883 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001884
hasso93406d82005-02-02 14:40:33 +00001885 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001886 && mp_withdraw.afi == AFI_IP6
1887 && mp_withdraw.safi == SAFI_MULTICAST
1888 && mp_withdraw.length == 0)
1889 {
1890 /* End-of-RIB received */
1891
hasso93406d82005-02-02 14:40:33 +00001892 /* NSF delete stale route */
1893 if (peer->nsf[AFI_IP6][SAFI_MULTICAST])
1894 bgp_clear_stale_route (peer, AFI_IP6, SAFI_MULTICAST);
1895
paule01f9cb2004-07-09 17:48:53 +00001896 if (BGP_DEBUG (update, UPDATE_IN))
ajs6b514742004-12-08 21:03:23 +00001897 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Multicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001898 peer->host);
1899 }
paul718e3742002-12-13 20:15:29 +00001900 }
1901 if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
1902 {
1903 if (mp_update.length
1904 && mp_update.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001905 && mp_update.safi == SAFI_MPLS_LABELED_VPN)
Paul Jakmab881c702010-11-23 16:35:42 +00001906 bgp_nlri_parse_vpnv4 (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001907
1908 if (mp_withdraw.length
1909 && mp_withdraw.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001910 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00001911 bgp_nlri_parse_vpnv4 (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001912
hasso93406d82005-02-02 14:40:33 +00001913 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001914 && mp_withdraw.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001915 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN
paule01f9cb2004-07-09 17:48:53 +00001916 && mp_withdraw.length == 0)
1917 {
1918 /* End-of-RIB received */
1919
1920 if (BGP_DEBUG (update, UPDATE_IN))
ajs6b514742004-12-08 21:03:23 +00001921 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for VPNv4 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001922 peer->host);
1923 }
paul718e3742002-12-13 20:15:29 +00001924 }
1925
1926 /* Everything is done. We unintern temporary structures which
1927 interned in bgp_attr_parse(). */
Paul Jakmab881c702010-11-23 16:35:42 +00001928 bgp_attr_unintern_sub (&attr);
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001929
paul718e3742002-12-13 20:15:29 +00001930 /* If peering is stopped due to some reason, do not generate BGP
1931 event. */
1932 if (peer->status != Established)
1933 return 0;
1934
1935 /* Increment packet counter. */
1936 peer->update_in++;
Stephen Hemminger65957882010-01-15 16:22:10 +03001937 peer->update_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00001938
Jorge Boncompte [DTI2]e2c38e62012-06-20 17:45:50 +02001939 /* Rearm holdtime timer */
Jorge Boncompte [DTI2]6a4677b2012-05-07 16:53:07 +00001940 BGP_TIMER_OFF (peer->t_holdtime);
Jorge Boncompte [DTI2]e2c38e62012-06-20 17:45:50 +02001941 bgp_timer_set (peer);
paul718e3742002-12-13 20:15:29 +00001942
1943 return 0;
1944}
1945
1946/* Notify message treatment function. */
paul94f2b392005-06-28 12:44:16 +00001947static void
paul718e3742002-12-13 20:15:29 +00001948bgp_notify_receive (struct peer *peer, bgp_size_t size)
1949{
1950 struct bgp_notify bgp_notify;
1951
1952 if (peer->notify.data)
1953 {
1954 XFREE (MTYPE_TMP, peer->notify.data);
1955 peer->notify.data = NULL;
1956 peer->notify.length = 0;
1957 }
1958
1959 bgp_notify.code = stream_getc (peer->ibuf);
1960 bgp_notify.subcode = stream_getc (peer->ibuf);
1961 bgp_notify.length = size - 2;
1962 bgp_notify.data = NULL;
1963
1964 /* Preserv notify code and sub code. */
1965 peer->notify.code = bgp_notify.code;
1966 peer->notify.subcode = bgp_notify.subcode;
1967 /* For further diagnostic record returned Data. */
1968 if (bgp_notify.length)
1969 {
1970 peer->notify.length = size - 2;
1971 peer->notify.data = XMALLOC (MTYPE_TMP, size - 2);
1972 memcpy (peer->notify.data, stream_pnt (peer->ibuf), size - 2);
1973 }
1974
1975 /* For debug */
1976 {
1977 int i;
1978 int first = 0;
1979 char c[4];
1980
1981 if (bgp_notify.length)
1982 {
1983 bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
1984 for (i = 0; i < bgp_notify.length; i++)
1985 if (first)
1986 {
1987 sprintf (c, " %02x", stream_getc (peer->ibuf));
1988 strcat (bgp_notify.data, c);
1989 }
1990 else
1991 {
1992 first = 1;
1993 sprintf (c, "%02x", stream_getc (peer->ibuf));
1994 strcpy (bgp_notify.data, c);
1995 }
1996 }
1997
1998 bgp_notify_print(peer, &bgp_notify, "received");
1999 if (bgp_notify.data)
2000 XFREE (MTYPE_TMP, bgp_notify.data);
2001 }
2002
2003 /* peer count update */
2004 peer->notify_in++;
2005
hassoe0701b72004-05-20 09:19:34 +00002006 if (peer->status == Established)
2007 peer->last_reset = PEER_DOWN_NOTIFY_RECEIVED;
2008
paul718e3742002-12-13 20:15:29 +00002009 /* We have to check for Notify with Unsupported Optional Parameter.
2010 in that case we fallback to open without the capability option.
2011 But this done in bgp_stop. We just mark it here to avoid changing
2012 the fsm tables. */
2013 if (bgp_notify.code == BGP_NOTIFY_OPEN_ERR &&
2014 bgp_notify.subcode == BGP_NOTIFY_OPEN_UNSUP_PARAM )
2015 UNSET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
2016
paul718e3742002-12-13 20:15:29 +00002017 BGP_EVENT_ADD (peer, Receive_NOTIFICATION_message);
2018}
2019
2020/* Keepalive treatment function -- get keepalive send keepalive */
paul94f2b392005-06-28 12:44:16 +00002021static void
paul718e3742002-12-13 20:15:29 +00002022bgp_keepalive_receive (struct peer *peer, bgp_size_t size)
2023{
2024 if (BGP_DEBUG (keepalive, KEEPALIVE))
ajs6b514742004-12-08 21:03:23 +00002025 zlog_debug ("%s KEEPALIVE rcvd", peer->host);
paul718e3742002-12-13 20:15:29 +00002026
2027 BGP_EVENT_ADD (peer, Receive_KEEPALIVE_message);
2028}
2029
2030/* Route refresh message is received. */
paul94f2b392005-06-28 12:44:16 +00002031static void
paul718e3742002-12-13 20:15:29 +00002032bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
2033{
2034 afi_t afi;
2035 safi_t safi;
2036 u_char reserved;
2037 struct stream *s;
2038
2039 /* If peer does not have the capability, send notification. */
2040 if (! CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_ADV))
2041 {
2042 plog_err (peer->log, "%s [Error] BGP route refresh is not enabled",
2043 peer->host);
2044 bgp_notify_send (peer,
2045 BGP_NOTIFY_HEADER_ERR,
2046 BGP_NOTIFY_HEADER_BAD_MESTYPE);
2047 return;
2048 }
2049
2050 /* Status must be Established. */
2051 if (peer->status != Established)
2052 {
2053 plog_err (peer->log,
2054 "%s [Error] Route refresh packet received under status %s",
2055 peer->host, LOOKUP (bgp_status_msg, peer->status));
2056 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
2057 return;
2058 }
2059
2060 s = peer->ibuf;
2061
2062 /* Parse packet. */
2063 afi = stream_getw (s);
2064 reserved = stream_getc (s);
2065 safi = stream_getc (s);
2066
2067 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002068 zlog_debug ("%s rcvd REFRESH_REQ for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00002069 peer->host, afi, safi);
2070
2071 /* Check AFI and SAFI. */
2072 if ((afi != AFI_IP && afi != AFI_IP6)
2073 || (safi != SAFI_UNICAST && safi != SAFI_MULTICAST
Denis Ovsienko42e6d742011-07-14 12:36:19 +04002074 && safi != SAFI_MPLS_LABELED_VPN))
paul718e3742002-12-13 20:15:29 +00002075 {
2076 if (BGP_DEBUG (normal, NORMAL))
2077 {
ajs6b514742004-12-08 21:03:23 +00002078 zlog_debug ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored",
paul718e3742002-12-13 20:15:29 +00002079 peer->host, afi, safi);
2080 }
2081 return;
2082 }
2083
2084 /* Adjust safi code. */
Denis Ovsienko42e6d742011-07-14 12:36:19 +04002085 if (safi == SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00002086 safi = SAFI_MPLS_VPN;
2087
2088 if (size != BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE)
2089 {
2090 u_char *end;
2091 u_char when_to_refresh;
2092 u_char orf_type;
2093 u_int16_t orf_len;
2094
2095 if (size - (BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE) < 5)
2096 {
2097 zlog_info ("%s ORF route refresh length error", peer->host);
2098 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2099 return;
2100 }
2101
2102 when_to_refresh = stream_getc (s);
2103 end = stream_pnt (s) + (size - 5);
2104
Paul Jakma370b64a2007-12-22 16:49:52 +00002105 while ((stream_pnt (s) + 2) < end)
paul718e3742002-12-13 20:15:29 +00002106 {
2107 orf_type = stream_getc (s);
2108 orf_len = stream_getw (s);
Paul Jakma370b64a2007-12-22 16:49:52 +00002109
2110 /* orf_len in bounds? */
2111 if ((stream_pnt (s) + orf_len) > end)
2112 break; /* XXX: Notify instead?? */
paul718e3742002-12-13 20:15:29 +00002113 if (orf_type == ORF_TYPE_PREFIX
2114 || orf_type == ORF_TYPE_PREFIX_OLD)
2115 {
2116 u_char *p_pnt = stream_pnt (s);
2117 u_char *p_end = stream_pnt (s) + orf_len;
2118 struct orf_prefix orfp;
2119 u_char common = 0;
2120 u_int32_t seq;
2121 int psize;
2122 char name[BUFSIZ];
paul718e3742002-12-13 20:15:29 +00002123 int ret;
2124
2125 if (BGP_DEBUG (normal, NORMAL))
2126 {
ajs6b514742004-12-08 21:03:23 +00002127 zlog_debug ("%s rcvd Prefixlist ORF(%d) length %d",
paul718e3742002-12-13 20:15:29 +00002128 peer->host, orf_type, orf_len);
2129 }
2130
Paul Jakma370b64a2007-12-22 16:49:52 +00002131 /* we're going to read at least 1 byte of common ORF header,
2132 * and 7 bytes of ORF Address-filter entry from the stream
2133 */
2134 if (orf_len < 7)
2135 break;
2136
paul718e3742002-12-13 20:15:29 +00002137 /* ORF prefix-list name */
2138 sprintf (name, "%s.%d.%d", peer->host, afi, safi);
2139
2140 while (p_pnt < p_end)
2141 {
Chris Halld64379e2010-05-14 16:38:39 +04002142 /* If the ORF entry is malformed, want to read as much of it
2143 * as possible without going beyond the bounds of the entry,
2144 * to maximise debug information.
2145 */
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002146 int ok;
paul718e3742002-12-13 20:15:29 +00002147 memset (&orfp, 0, sizeof (struct orf_prefix));
2148 common = *p_pnt++;
Chris Halld64379e2010-05-14 16:38:39 +04002149 /* after ++: p_pnt <= p_end */
paul718e3742002-12-13 20:15:29 +00002150 if (common & ORF_COMMON_PART_REMOVE_ALL)
2151 {
2152 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002153 zlog_debug ("%s rcvd Remove-All pfxlist ORF request", peer->host);
paul718e3742002-12-13 20:15:29 +00002154 prefix_bgp_orf_remove_all (name);
2155 break;
2156 }
Chris Halld64379e2010-05-14 16:38:39 +04002157 ok = ((p_end - p_pnt) >= sizeof(u_int32_t)) ;
Denis Ovsienkobb915f52011-12-13 21:11:39 +04002158 if (ok)
Chris Halld64379e2010-05-14 16:38:39 +04002159 {
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002160 memcpy (&seq, p_pnt, sizeof (u_int32_t));
2161 p_pnt += sizeof (u_int32_t);
2162 orfp.seq = ntohl (seq);
Chris Halld64379e2010-05-14 16:38:39 +04002163 }
2164 else
2165 p_pnt = p_end ;
2166
2167 if ((ok = (p_pnt < p_end)))
2168 orfp.ge = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */
2169 if ((ok = (p_pnt < p_end)))
2170 orfp.le = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */
2171 if ((ok = (p_pnt < p_end)))
2172 orfp.p.prefixlen = *p_pnt++ ;
2173 orfp.p.family = afi2family (afi); /* afi checked already */
2174
2175 psize = PSIZE (orfp.p.prefixlen); /* 0 if not ok */
2176 if (psize > prefix_blen(&orfp.p)) /* valid for family ? */
2177 {
2178 ok = 0 ;
2179 psize = prefix_blen(&orfp.p) ;
2180 }
2181 if (psize > (p_end - p_pnt)) /* valid for packet ? */
2182 {
2183 ok = 0 ;
2184 psize = p_end - p_pnt ;
2185 }
2186
2187 if (psize > 0)
2188 memcpy (&orfp.p.u.prefix, p_pnt, psize);
paul718e3742002-12-13 20:15:29 +00002189 p_pnt += psize;
2190
2191 if (BGP_DEBUG (normal, NORMAL))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +00002192 {
2193 char buf[INET6_BUFSIZ];
2194
2195 zlog_debug ("%s rcvd %s %s seq %u %s/%d ge %d le %d%s",
2196 peer->host,
2197 (common & ORF_COMMON_PART_REMOVE ? "Remove" : "Add"),
2198 (common & ORF_COMMON_PART_DENY ? "deny" : "permit"),
2199 orfp.seq,
2200 inet_ntop (orfp.p.family, &orfp.p.u.prefix, buf, INET6_BUFSIZ),
2201 orfp.p.prefixlen, orfp.ge, orfp.le,
2202 ok ? "" : " MALFORMED");
2203 }
2204
Chris Halld64379e2010-05-14 16:38:39 +04002205 if (ok)
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002206 ret = prefix_bgp_orf_set (name, afi, &orfp,
2207 (common & ORF_COMMON_PART_DENY ? 0 : 1 ),
2208 (common & ORF_COMMON_PART_REMOVE ? 0 : 1));
paul718e3742002-12-13 20:15:29 +00002209
Chris Halld64379e2010-05-14 16:38:39 +04002210 if (!ok || (ret != CMD_SUCCESS))
paul718e3742002-12-13 20:15:29 +00002211 {
2212 if (BGP_DEBUG (normal, NORMAL))
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002213 zlog_debug ("%s Received misformatted prefixlist ORF."
2214 " Remove All pfxlist", peer->host);
paul718e3742002-12-13 20:15:29 +00002215 prefix_bgp_orf_remove_all (name);
2216 break;
2217 }
2218 }
2219 peer->orf_plist[afi][safi] =
2220 prefix_list_lookup (AFI_ORF_PREFIX, name);
2221 }
paul9985f832005-02-09 15:51:56 +00002222 stream_forward_getp (s, orf_len);
paul718e3742002-12-13 20:15:29 +00002223 }
2224 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002225 zlog_debug ("%s rcvd Refresh %s ORF request", peer->host,
paul718e3742002-12-13 20:15:29 +00002226 when_to_refresh == REFRESH_DEFER ? "Defer" : "Immediate");
2227 if (when_to_refresh == REFRESH_DEFER)
2228 return;
2229 }
2230
2231 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2232 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH))
2233 UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
2234
2235 /* Perform route refreshment to the peer */
2236 bgp_announce_route (peer, afi, safi);
2237}
2238
paul94f2b392005-06-28 12:44:16 +00002239static int
paul718e3742002-12-13 20:15:29 +00002240bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
2241{
2242 u_char *end;
Paul Jakma6d582722007-08-06 15:21:45 +00002243 struct capability_mp_data mpc;
2244 struct capability_header *hdr;
paul718e3742002-12-13 20:15:29 +00002245 u_char action;
2246 struct bgp *bgp;
2247 afi_t afi;
2248 safi_t safi;
2249
2250 bgp = peer->bgp;
2251 end = pnt + length;
2252
2253 while (pnt < end)
Paul Jakma6d582722007-08-06 15:21:45 +00002254 {
paul718e3742002-12-13 20:15:29 +00002255 /* We need at least action, capability code and capability length. */
2256 if (pnt + 3 > end)
2257 {
2258 zlog_info ("%s Capability length error", peer->host);
2259 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2260 return -1;
2261 }
paul718e3742002-12-13 20:15:29 +00002262 action = *pnt;
Paul Jakma6d582722007-08-06 15:21:45 +00002263 hdr = (struct capability_header *)(pnt + 1);
2264
paul718e3742002-12-13 20:15:29 +00002265 /* Action value check. */
2266 if (action != CAPABILITY_ACTION_SET
2267 && action != CAPABILITY_ACTION_UNSET)
2268 {
2269 zlog_info ("%s Capability Action Value error %d",
2270 peer->host, action);
2271 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2272 return -1;
2273 }
2274
2275 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002276 zlog_debug ("%s CAPABILITY has action: %d, code: %u, length %u",
Paul Jakma6d582722007-08-06 15:21:45 +00002277 peer->host, action, hdr->code, hdr->length);
paul718e3742002-12-13 20:15:29 +00002278
2279 /* Capability length check. */
Paul Jakma6d582722007-08-06 15:21:45 +00002280 if ((pnt + hdr->length + 3) > end)
paul718e3742002-12-13 20:15:29 +00002281 {
2282 zlog_info ("%s Capability length error", peer->host);
2283 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2284 return -1;
2285 }
2286
Paul Jakma6d582722007-08-06 15:21:45 +00002287 /* Fetch structure to the byte stream. */
2288 memcpy (&mpc, pnt + 3, sizeof (struct capability_mp_data));
2289
paul718e3742002-12-13 20:15:29 +00002290 /* We know MP Capability Code. */
Paul Jakma6d582722007-08-06 15:21:45 +00002291 if (hdr->code == CAPABILITY_CODE_MP)
paul718e3742002-12-13 20:15:29 +00002292 {
Paul Jakma6d582722007-08-06 15:21:45 +00002293 afi = ntohs (mpc.afi);
2294 safi = mpc.safi;
paul718e3742002-12-13 20:15:29 +00002295
2296 /* Ignore capability when override-capability is set. */
2297 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
2298 continue;
Paul Jakma6d582722007-08-06 15:21:45 +00002299
2300 if (!bgp_afi_safi_valid_indices (afi, &safi))
2301 {
2302 if (BGP_DEBUG (normal, NORMAL))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002303 zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid "
2304 "(%u/%u)", peer->host, afi, safi);
Paul Jakma6d582722007-08-06 15:21:45 +00002305 continue;
2306 }
2307
paul718e3742002-12-13 20:15:29 +00002308 /* Address family check. */
Paul Jakma6d582722007-08-06 15:21:45 +00002309 if (BGP_DEBUG (normal, NORMAL))
2310 zlog_debug ("%s CAPABILITY has %s MP_EXT CAP for afi/safi: %u/%u",
2311 peer->host,
2312 action == CAPABILITY_ACTION_SET
2313 ? "Advertising" : "Removing",
2314 ntohs(mpc.afi) , mpc.safi);
2315
2316 if (action == CAPABILITY_ACTION_SET)
2317 {
2318 peer->afc_recv[afi][safi] = 1;
2319 if (peer->afc[afi][safi])
2320 {
2321 peer->afc_nego[afi][safi] = 1;
2322 bgp_announce_route (peer, afi, safi);
2323 }
2324 }
2325 else
2326 {
2327 peer->afc_recv[afi][safi] = 0;
2328 peer->afc_nego[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00002329
Paul Jakma6d582722007-08-06 15:21:45 +00002330 if (peer_active_nego (peer))
Chris Caputo228da422009-07-18 05:44:03 +00002331 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
Paul Jakma6d582722007-08-06 15:21:45 +00002332 else
2333 BGP_EVENT_ADD (peer, BGP_Stop);
2334 }
paul718e3742002-12-13 20:15:29 +00002335 }
paul718e3742002-12-13 20:15:29 +00002336 else
2337 {
2338 zlog_warn ("%s unrecognized capability code: %d - ignored",
Paul Jakma6d582722007-08-06 15:21:45 +00002339 peer->host, hdr->code);
paul718e3742002-12-13 20:15:29 +00002340 }
Paul Jakma6d582722007-08-06 15:21:45 +00002341 pnt += hdr->length + 3;
paul718e3742002-12-13 20:15:29 +00002342 }
2343 return 0;
2344}
2345
Paul Jakma01b7ce22009-06-18 12:34:43 +01002346/* Dynamic Capability is received.
2347 *
2348 * This is exported for unit-test purposes
2349 */
Paul Jakma6d582722007-08-06 15:21:45 +00002350int
paul718e3742002-12-13 20:15:29 +00002351bgp_capability_receive (struct peer *peer, bgp_size_t size)
2352{
2353 u_char *pnt;
paul718e3742002-12-13 20:15:29 +00002354
2355 /* Fetch pointer. */
2356 pnt = stream_pnt (peer->ibuf);
2357
2358 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002359 zlog_debug ("%s rcv CAPABILITY", peer->host);
paul718e3742002-12-13 20:15:29 +00002360
2361 /* If peer does not have the capability, send notification. */
2362 if (! CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV))
2363 {
2364 plog_err (peer->log, "%s [Error] BGP dynamic capability is not enabled",
2365 peer->host);
2366 bgp_notify_send (peer,
2367 BGP_NOTIFY_HEADER_ERR,
2368 BGP_NOTIFY_HEADER_BAD_MESTYPE);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002369 return -1;
paul718e3742002-12-13 20:15:29 +00002370 }
2371
2372 /* Status must be Established. */
2373 if (peer->status != Established)
2374 {
2375 plog_err (peer->log,
2376 "%s [Error] Dynamic capability packet received under status %s", peer->host, LOOKUP (bgp_status_msg, peer->status));
2377 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002378 return -1;
paul718e3742002-12-13 20:15:29 +00002379 }
2380
2381 /* Parse packet. */
Paul Jakma6d582722007-08-06 15:21:45 +00002382 return bgp_capability_msg_parse (peer, pnt, size);
paul718e3742002-12-13 20:15:29 +00002383}
David Lamparter6b0655a2014-06-04 06:53:35 +02002384
paul718e3742002-12-13 20:15:29 +00002385/* BGP read utility function. */
paul94f2b392005-06-28 12:44:16 +00002386static int
paul718e3742002-12-13 20:15:29 +00002387bgp_read_packet (struct peer *peer)
2388{
2389 int nbytes;
2390 int readsize;
2391
paul9985f832005-02-09 15:51:56 +00002392 readsize = peer->packet_size - stream_get_endp (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00002393
2394 /* If size is zero then return. */
2395 if (! readsize)
2396 return 0;
2397
2398 /* Read packet from fd. */
Stephen Hemminger35398582010-08-05 10:26:23 -07002399 nbytes = stream_read_try (peer->ibuf, peer->fd, readsize);
paul718e3742002-12-13 20:15:29 +00002400
2401 /* If read byte is smaller than zero then error occured. */
2402 if (nbytes < 0)
2403 {
Stephen Hemminger35398582010-08-05 10:26:23 -07002404 /* Transient error should retry */
2405 if (nbytes == -2)
paul718e3742002-12-13 20:15:29 +00002406 return -1;
2407
2408 plog_err (peer->log, "%s [Error] bgp_read_packet error: %s",
ajs6099b3b2004-11-20 02:06:59 +00002409 peer->host, safe_strerror (errno));
hasso93406d82005-02-02 14:40:33 +00002410
2411 if (peer->status == Established)
2412 {
2413 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
2414 {
2415 peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
2416 SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
2417 }
2418 else
2419 peer->last_reset = PEER_DOWN_CLOSE_SESSION;
2420 }
2421
paul718e3742002-12-13 20:15:29 +00002422 BGP_EVENT_ADD (peer, TCP_fatal_error);
2423 return -1;
2424 }
2425
2426 /* When read byte is zero : clear bgp peer and return */
2427 if (nbytes == 0)
2428 {
2429 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +00002430 plog_debug (peer->log, "%s [Event] BGP connection closed fd %d",
pauleb821182004-05-01 08:44:08 +00002431 peer->host, peer->fd);
hassoe0701b72004-05-20 09:19:34 +00002432
2433 if (peer->status == Established)
hasso93406d82005-02-02 14:40:33 +00002434 {
2435 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
2436 {
2437 peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
2438 SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
2439 }
2440 else
2441 peer->last_reset = PEER_DOWN_CLOSE_SESSION;
2442 }
hassoe0701b72004-05-20 09:19:34 +00002443
paul718e3742002-12-13 20:15:29 +00002444 BGP_EVENT_ADD (peer, TCP_connection_closed);
2445 return -1;
2446 }
2447
2448 /* We read partial packet. */
paul9985f832005-02-09 15:51:56 +00002449 if (stream_get_endp (peer->ibuf) != peer->packet_size)
paul718e3742002-12-13 20:15:29 +00002450 return -1;
2451
2452 return 0;
2453}
2454
2455/* Marker check. */
paul94f2b392005-06-28 12:44:16 +00002456static int
paul718e3742002-12-13 20:15:29 +00002457bgp_marker_all_one (struct stream *s, int length)
2458{
2459 int i;
2460
2461 for (i = 0; i < length; i++)
2462 if (s->data[i] != 0xff)
2463 return 0;
2464
2465 return 1;
2466}
2467
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002468/* Recent thread time.
2469 On same clock base as bgp_clock (MONOTONIC)
2470 but can be time of last context switch to bgp_read thread. */
2471static time_t
2472bgp_recent_clock (void)
2473{
2474 return recent_relative_time().tv_sec;
2475}
2476
paul718e3742002-12-13 20:15:29 +00002477/* Starting point of packet process function. */
2478int
2479bgp_read (struct thread *thread)
2480{
2481 int ret;
2482 u_char type = 0;
2483 struct peer *peer;
2484 bgp_size_t size;
2485 char notify_data_length[2];
2486
2487 /* Yes first of all get peer pointer. */
2488 peer = THREAD_ARG (thread);
2489 peer->t_read = NULL;
2490
2491 /* For non-blocking IO check. */
2492 if (peer->status == Connect)
2493 {
2494 bgp_connect_check (peer);
2495 goto done;
2496 }
2497 else
2498 {
pauleb821182004-05-01 08:44:08 +00002499 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +00002500 {
pauleb821182004-05-01 08:44:08 +00002501 zlog_err ("bgp_read peer's fd is negative value %d", peer->fd);
paul718e3742002-12-13 20:15:29 +00002502 return -1;
2503 }
pauleb821182004-05-01 08:44:08 +00002504 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
paul718e3742002-12-13 20:15:29 +00002505 }
2506
2507 /* Read packet header to determine type of the packet */
2508 if (peer->packet_size == 0)
2509 peer->packet_size = BGP_HEADER_SIZE;
2510
paul9985f832005-02-09 15:51:56 +00002511 if (stream_get_endp (peer->ibuf) < BGP_HEADER_SIZE)
paul718e3742002-12-13 20:15:29 +00002512 {
2513 ret = bgp_read_packet (peer);
2514
2515 /* Header read error or partial read packet. */
2516 if (ret < 0)
2517 goto done;
2518
2519 /* Get size and type. */
paul9985f832005-02-09 15:51:56 +00002520 stream_forward_getp (peer->ibuf, BGP_MARKER_SIZE);
paul718e3742002-12-13 20:15:29 +00002521 memcpy (notify_data_length, stream_pnt (peer->ibuf), 2);
2522 size = stream_getw (peer->ibuf);
2523 type = stream_getc (peer->ibuf);
2524
2525 if (BGP_DEBUG (normal, NORMAL) && type != 2 && type != 0)
ajs6b514742004-12-08 21:03:23 +00002526 zlog_debug ("%s rcv message type %d, length (excl. header) %d",
paul718e3742002-12-13 20:15:29 +00002527 peer->host, type, size - BGP_HEADER_SIZE);
2528
2529 /* Marker check */
paulf5ba3872004-07-09 12:11:31 +00002530 if (((type == BGP_MSG_OPEN) || (type == BGP_MSG_KEEPALIVE))
paul718e3742002-12-13 20:15:29 +00002531 && ! bgp_marker_all_one (peer->ibuf, BGP_MARKER_SIZE))
2532 {
2533 bgp_notify_send (peer,
2534 BGP_NOTIFY_HEADER_ERR,
2535 BGP_NOTIFY_HEADER_NOT_SYNC);
2536 goto done;
2537 }
2538
2539 /* BGP type check. */
2540 if (type != BGP_MSG_OPEN && type != BGP_MSG_UPDATE
2541 && type != BGP_MSG_NOTIFY && type != BGP_MSG_KEEPALIVE
2542 && type != BGP_MSG_ROUTE_REFRESH_NEW
2543 && type != BGP_MSG_ROUTE_REFRESH_OLD
2544 && type != BGP_MSG_CAPABILITY)
2545 {
2546 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002547 plog_debug (peer->log,
paul718e3742002-12-13 20:15:29 +00002548 "%s unknown message type 0x%02x",
2549 peer->host, type);
2550 bgp_notify_send_with_data (peer,
2551 BGP_NOTIFY_HEADER_ERR,
2552 BGP_NOTIFY_HEADER_BAD_MESTYPE,
2553 &type, 1);
2554 goto done;
2555 }
2556 /* Mimimum packet length check. */
2557 if ((size < BGP_HEADER_SIZE)
2558 || (size > BGP_MAX_PACKET_SIZE)
2559 || (type == BGP_MSG_OPEN && size < BGP_MSG_OPEN_MIN_SIZE)
2560 || (type == BGP_MSG_UPDATE && size < BGP_MSG_UPDATE_MIN_SIZE)
2561 || (type == BGP_MSG_NOTIFY && size < BGP_MSG_NOTIFY_MIN_SIZE)
2562 || (type == BGP_MSG_KEEPALIVE && size != BGP_MSG_KEEPALIVE_MIN_SIZE)
2563 || (type == BGP_MSG_ROUTE_REFRESH_NEW && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
2564 || (type == BGP_MSG_ROUTE_REFRESH_OLD && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
2565 || (type == BGP_MSG_CAPABILITY && size < BGP_MSG_CAPABILITY_MIN_SIZE))
2566 {
2567 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002568 plog_debug (peer->log,
paul718e3742002-12-13 20:15:29 +00002569 "%s bad message length - %d for %s",
2570 peer->host, size,
2571 type == 128 ? "ROUTE-REFRESH" :
2572 bgp_type_str[(int) type]);
2573 bgp_notify_send_with_data (peer,
2574 BGP_NOTIFY_HEADER_ERR,
2575 BGP_NOTIFY_HEADER_BAD_MESLEN,
hassoc9e52be2004-09-26 16:09:34 +00002576 (u_char *) notify_data_length, 2);
paul718e3742002-12-13 20:15:29 +00002577 goto done;
2578 }
2579
2580 /* Adjust size to message length. */
2581 peer->packet_size = size;
2582 }
2583
2584 ret = bgp_read_packet (peer);
2585 if (ret < 0)
2586 goto done;
2587
2588 /* Get size and type again. */
2589 size = stream_getw_from (peer->ibuf, BGP_MARKER_SIZE);
2590 type = stream_getc_from (peer->ibuf, BGP_MARKER_SIZE + 2);
2591
2592 /* BGP packet dump function. */
2593 bgp_dump_packet (peer, type, peer->ibuf);
2594
2595 size = (peer->packet_size - BGP_HEADER_SIZE);
2596
2597 /* Read rest of the packet and call each sort of packet routine */
2598 switch (type)
2599 {
2600 case BGP_MSG_OPEN:
2601 peer->open_in++;
paulf5ba3872004-07-09 12:11:31 +00002602 bgp_open_receive (peer, size); /* XXX return value ignored! */
paul718e3742002-12-13 20:15:29 +00002603 break;
2604 case BGP_MSG_UPDATE:
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002605 peer->readtime = bgp_recent_clock ();
paul718e3742002-12-13 20:15:29 +00002606 bgp_update_receive (peer, size);
2607 break;
2608 case BGP_MSG_NOTIFY:
2609 bgp_notify_receive (peer, size);
2610 break;
2611 case BGP_MSG_KEEPALIVE:
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002612 peer->readtime = bgp_recent_clock ();
paul718e3742002-12-13 20:15:29 +00002613 bgp_keepalive_receive (peer, size);
2614 break;
2615 case BGP_MSG_ROUTE_REFRESH_NEW:
2616 case BGP_MSG_ROUTE_REFRESH_OLD:
2617 peer->refresh_in++;
2618 bgp_route_refresh_receive (peer, size);
2619 break;
2620 case BGP_MSG_CAPABILITY:
2621 peer->dynamic_cap_in++;
2622 bgp_capability_receive (peer, size);
2623 break;
2624 }
2625
2626 /* Clear input buffer. */
2627 peer->packet_size = 0;
2628 if (peer->ibuf)
2629 stream_reset (peer->ibuf);
2630
2631 done:
2632 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2633 {
2634 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +00002635 zlog_debug ("%s [Event] Accepting BGP peer delete", peer->host);
paul718e3742002-12-13 20:15:29 +00002636 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00002637 }
2638 return 0;
2639}