blob: d71df0823ffe3254563319e4a5d3405f220afc61 [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 *);
52
53/* 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;
145 struct bgp_adj_out *adj;
146 struct bgp_advertise *adv;
147 struct stream *packet;
148 struct bgp_node *rn = NULL;
149 struct bgp_info *binfo = NULL;
150 bgp_size_t total_attr_len = 0;
151 unsigned long pos;
paul718e3742002-12-13 20:15:29 +0000152
153 s = peer->work;
154 stream_reset (s);
155
156 adv = FIFO_HEAD (&peer->sync[afi][safi]->update);
157
158 while (adv)
159 {
Paul Jakmaed3ebfa2006-10-15 23:50:16 +0000160 assert (adv->rn);
161 rn = adv->rn;
paul718e3742002-12-13 20:15:29 +0000162 adj = adv->adj;
163 if (adv->binfo)
164 binfo = adv->binfo;
paul718e3742002-12-13 20:15:29 +0000165
166 /* When remaining space can't include NLRI and it's length. */
Paul Jakmaed3ebfa2006-10-15 23:50:16 +0000167 if (STREAM_REMAIN (s) <= BGP_NLRI_LENGTH + PSIZE (rn->p.prefixlen))
paul718e3742002-12-13 20:15:29 +0000168 break;
169
170 /* If packet is empty, set attribute. */
171 if (stream_empty (s))
172 {
Paul Jakmaa3b6ea52006-05-04 07:52:12 +0000173 struct prefix_rd *prd = NULL;
174 u_char *tag = NULL;
Paul Jakmaed3ebfa2006-10-15 23:50:16 +0000175 struct peer *from = NULL;
Paul Jakmaa3b6ea52006-05-04 07:52:12 +0000176
177 if (rn->prn)
178 prd = (struct prefix_rd *) &rn->prn->p;
Greg Troxeld3ddb222010-09-17 10:47:49 -0400179 if (binfo)
Paul Jakmaed3ebfa2006-10-15 23:50:16 +0000180 {
Paul Jakmaed3ebfa2006-10-15 23:50:16 +0000181 from = binfo->peer;
Greg Troxeld3ddb222010-09-17 10:47:49 -0400182 if (binfo->extra)
183 tag = binfo->extra->tag;
Paul Jakmaed3ebfa2006-10-15 23:50:16 +0000184 }
Paul Jakmaa3b6ea52006-05-04 07:52:12 +0000185
paul718e3742002-12-13 20:15:29 +0000186 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
187 stream_putw (s, 0);
paul9985f832005-02-09 15:51:56 +0000188 pos = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000189 stream_putw (s, 0);
paul5228ad22004-06-04 17:58:18 +0000190 total_attr_len = bgp_packet_attribute (NULL, peer, s,
191 adv->baa->attr,
192 &rn->p, afi, safi,
Paul Jakmaed3ebfa2006-10-15 23:50:16 +0000193 from, prd, tag);
paul718e3742002-12-13 20:15:29 +0000194 stream_putw_at (s, pos, total_attr_len);
195 }
196
197 if (afi == AFI_IP && safi == SAFI_UNICAST)
198 stream_put_prefix (s, &rn->p);
199
200 if (BGP_DEBUG (update, UPDATE_OUT))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000201 {
202 char buf[INET6_BUFSIZ];
203
204 zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d",
205 peer->host,
206 inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ),
207 rn->p.prefixlen);
208 }
paul718e3742002-12-13 20:15:29 +0000209
210 /* Synchnorize attribute. */
211 if (adj->attr)
Paul Jakmaf6f434b2010-11-23 21:28:03 +0000212 bgp_attr_unintern (&adj->attr);
paul718e3742002-12-13 20:15:29 +0000213 else
214 peer->scount[afi][safi]++;
215
216 adj->attr = bgp_attr_intern (adv->baa->attr);
217
218 adv = bgp_advertise_clean (peer, adj, afi, safi);
219
220 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
221 break;
222 }
223
224 if (! stream_empty (s))
225 {
226 bgp_packet_set_size (s);
paule83e2082005-05-19 02:12:25 +0000227 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +0000228 bgp_packet_add (peer, packet);
pauleb821182004-05-01 08:44:08 +0000229 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000230 stream_reset (s);
231 return packet;
232 }
233 return NULL;
hasso93406d82005-02-02 14:40:33 +0000234}
paul718e3742002-12-13 20:15:29 +0000235
paul94f2b392005-06-28 12:44:16 +0000236static struct stream *
hasso93406d82005-02-02 14:40:33 +0000237bgp_update_packet_eor (struct peer *peer, afi_t afi, safi_t safi)
238{
239 struct stream *s;
240 struct stream *packet;
241
Paul Jakma750e8142008-07-22 21:11:48 +0000242 if (DISABLE_BGP_ANNOUNCE)
243 return NULL;
hasso93406d82005-02-02 14:40:33 +0000244
245 if (BGP_DEBUG (normal, NORMAL))
246 zlog_debug ("send End-of-RIB for %s to %s", afi_safi_print (afi, safi), peer->host);
247
248 s = stream_new (BGP_MAX_PACKET_SIZE);
249
250 /* Make BGP update packet. */
251 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
252
253 /* Unfeasible Routes Length */
254 stream_putw (s, 0);
255
256 if (afi == AFI_IP && safi == SAFI_UNICAST)
257 {
258 /* Total Path Attribute Length */
259 stream_putw (s, 0);
260 }
261 else
262 {
263 /* Total Path Attribute Length */
264 stream_putw (s, 6);
265 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
266 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
267 stream_putc (s, 3);
268 stream_putw (s, afi);
269 stream_putc (s, safi);
270 }
271
272 bgp_packet_set_size (s);
paule83e2082005-05-19 02:12:25 +0000273 packet = stream_dup (s);
hasso93406d82005-02-02 14:40:33 +0000274 bgp_packet_add (peer, packet);
275 stream_free (s);
276 return packet;
paul718e3742002-12-13 20:15:29 +0000277}
278
279/* Make BGP withdraw packet. */
paul94f2b392005-06-28 12:44:16 +0000280static struct stream *
paul718e3742002-12-13 20:15:29 +0000281bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi)
282{
283 struct stream *s;
284 struct stream *packet;
285 struct bgp_adj_out *adj;
286 struct bgp_advertise *adv;
287 struct bgp_node *rn;
288 unsigned long pos;
289 bgp_size_t unfeasible_len;
290 bgp_size_t total_attr_len;
paul718e3742002-12-13 20:15:29 +0000291
292 s = peer->work;
293 stream_reset (s);
294
295 while ((adv = FIFO_HEAD (&peer->sync[afi][safi]->withdraw)) != NULL)
296 {
Paul Jakmaed3ebfa2006-10-15 23:50:16 +0000297 assert (adv->rn);
paul718e3742002-12-13 20:15:29 +0000298 adj = adv->adj;
299 rn = adv->rn;
paul718e3742002-12-13 20:15:29 +0000300
301 if (STREAM_REMAIN (s)
hasso4372df72004-05-20 10:20:02 +0000302 < (BGP_NLRI_LENGTH + BGP_TOTAL_ATTR_LEN + PSIZE (rn->p.prefixlen)))
paul718e3742002-12-13 20:15:29 +0000303 break;
304
305 if (stream_empty (s))
306 {
307 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
308 stream_putw (s, 0);
309 }
310
311 if (afi == AFI_IP && safi == SAFI_UNICAST)
312 stream_put_prefix (s, &rn->p);
313 else
314 {
Paul Jakmaa3b6ea52006-05-04 07:52:12 +0000315 struct prefix_rd *prd = NULL;
316
317 if (rn->prn)
318 prd = (struct prefix_rd *) &rn->prn->p;
paul9985f832005-02-09 15:51:56 +0000319 pos = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000320 stream_putw (s, 0);
321 total_attr_len
322 = bgp_packet_withdraw (peer, s, &rn->p, afi, safi, prd, NULL);
323
324 /* Set total path attribute length. */
325 stream_putw_at (s, pos, total_attr_len);
326 }
327
328 if (BGP_DEBUG (update, UPDATE_OUT))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000329 {
330 char buf[INET6_BUFSIZ];
331
332 zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d -- unreachable",
333 peer->host,
334 inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, INET6_BUFSIZ),
335 rn->p.prefixlen);
336 }
paul718e3742002-12-13 20:15:29 +0000337
338 peer->scount[afi][safi]--;
339
340 bgp_adj_out_remove (rn, adj, peer, afi, safi);
341 bgp_unlock_node (rn);
342
343 if (! (afi == AFI_IP && safi == SAFI_UNICAST))
344 break;
345 }
346
347 if (! stream_empty (s))
348 {
349 if (afi == AFI_IP && safi == SAFI_UNICAST)
350 {
351 unfeasible_len
paul9985f832005-02-09 15:51:56 +0000352 = stream_get_endp (s) - BGP_HEADER_SIZE - BGP_UNFEASIBLE_LEN;
paul718e3742002-12-13 20:15:29 +0000353 stream_putw_at (s, BGP_HEADER_SIZE, unfeasible_len);
354 stream_putw (s, 0);
355 }
356 bgp_packet_set_size (s);
paule83e2082005-05-19 02:12:25 +0000357 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +0000358 bgp_packet_add (peer, packet);
359 stream_reset (s);
360 return packet;
361 }
362
363 return NULL;
364}
365
366void
367bgp_default_update_send (struct peer *peer, struct attr *attr,
368 afi_t afi, safi_t safi, struct peer *from)
369{
370 struct stream *s;
371 struct stream *packet;
372 struct prefix p;
373 unsigned long pos;
374 bgp_size_t total_attr_len;
paul718e3742002-12-13 20:15:29 +0000375
Paul Jakma750e8142008-07-22 21:11:48 +0000376 if (DISABLE_BGP_ANNOUNCE)
377 return;
paul718e3742002-12-13 20:15:29 +0000378
379 if (afi == AFI_IP)
380 str2prefix ("0.0.0.0/0", &p);
381#ifdef HAVE_IPV6
382 else
383 str2prefix ("::/0", &p);
384#endif /* HAVE_IPV6 */
385
386 /* Logging the attribute. */
387 if (BGP_DEBUG (update, UPDATE_OUT))
388 {
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000389 char attrstr[BUFSIZ];
390 char buf[INET6_BUFSIZ];
391 attrstr[0] = '\0';
392
paul718e3742002-12-13 20:15:29 +0000393 bgp_dump_attr (peer, attr, attrstr, BUFSIZ);
ajs6b514742004-12-08 21:03:23 +0000394 zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d %s",
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000395 peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ),
paul718e3742002-12-13 20:15:29 +0000396 p.prefixlen, attrstr);
397 }
398
399 s = stream_new (BGP_MAX_PACKET_SIZE);
400
401 /* Make BGP update packet. */
402 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
403
404 /* Unfeasible Routes Length. */
405 stream_putw (s, 0);
406
407 /* Make place for total attribute length. */
paul9985f832005-02-09 15:51:56 +0000408 pos = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000409 stream_putw (s, 0);
410 total_attr_len = bgp_packet_attribute (NULL, peer, s, attr, &p, afi, safi, from, NULL, NULL);
411
412 /* Set Total Path Attribute Length. */
413 stream_putw_at (s, pos, total_attr_len);
414
415 /* NLRI set. */
416 if (p.family == AF_INET && safi == SAFI_UNICAST)
417 stream_put_prefix (s, &p);
418
419 /* Set size. */
420 bgp_packet_set_size (s);
421
paule83e2082005-05-19 02:12:25 +0000422 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +0000423 stream_free (s);
424
425 /* Dump packet if debug option is set. */
426#ifdef DEBUG
jardin2d74db52005-10-01 00:07:50 +0000427 /* bgp_packet_dump (packet); */
paul718e3742002-12-13 20:15:29 +0000428#endif /* DEBUG */
429
430 /* Add packet to the peer. */
431 bgp_packet_add (peer, packet);
432
pauleb821182004-05-01 08:44:08 +0000433 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000434}
435
436void
437bgp_default_withdraw_send (struct peer *peer, afi_t afi, safi_t safi)
438{
439 struct stream *s;
440 struct stream *packet;
441 struct prefix p;
442 unsigned long pos;
443 unsigned long cp;
444 bgp_size_t unfeasible_len;
445 bgp_size_t total_attr_len;
paul718e3742002-12-13 20:15:29 +0000446
Paul Jakma750e8142008-07-22 21:11:48 +0000447 if (DISABLE_BGP_ANNOUNCE)
448 return;
paul718e3742002-12-13 20:15:29 +0000449
450 if (afi == AFI_IP)
451 str2prefix ("0.0.0.0/0", &p);
452#ifdef HAVE_IPV6
453 else
454 str2prefix ("::/0", &p);
455#endif /* HAVE_IPV6 */
456
457 total_attr_len = 0;
458 pos = 0;
459
460 if (BGP_DEBUG (update, UPDATE_OUT))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +0000461 {
462 char buf[INET6_BUFSIZ];
463
464 zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d -- unreachable",
465 peer->host, inet_ntop(p.family, &(p.u.prefix), buf, INET6_BUFSIZ),
466 p.prefixlen);
467 }
paul718e3742002-12-13 20:15:29 +0000468
469 s = stream_new (BGP_MAX_PACKET_SIZE);
470
471 /* Make BGP update packet. */
472 bgp_packet_set_marker (s, BGP_MSG_UPDATE);
473
474 /* Unfeasible Routes Length. */;
paul9985f832005-02-09 15:51:56 +0000475 cp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000476 stream_putw (s, 0);
477
478 /* Withdrawn Routes. */
479 if (p.family == AF_INET && safi == SAFI_UNICAST)
480 {
481 stream_put_prefix (s, &p);
482
paul9985f832005-02-09 15:51:56 +0000483 unfeasible_len = stream_get_endp (s) - cp - 2;
paul718e3742002-12-13 20:15:29 +0000484
485 /* Set unfeasible len. */
486 stream_putw_at (s, cp, unfeasible_len);
487
488 /* Set total path attribute length. */
489 stream_putw (s, 0);
490 }
491 else
492 {
paul9985f832005-02-09 15:51:56 +0000493 pos = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000494 stream_putw (s, 0);
495 total_attr_len = bgp_packet_withdraw (peer, s, &p, afi, safi, NULL, NULL);
496
497 /* Set total path attribute length. */
498 stream_putw_at (s, pos, total_attr_len);
499 }
500
501 bgp_packet_set_size (s);
502
paule83e2082005-05-19 02:12:25 +0000503 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +0000504 stream_free (s);
505
506 /* Add packet to the peer. */
507 bgp_packet_add (peer, packet);
508
pauleb821182004-05-01 08:44:08 +0000509 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000510}
511
512/* Get next packet to be written. */
paul94f2b392005-06-28 12:44:16 +0000513static struct stream *
paul718e3742002-12-13 20:15:29 +0000514bgp_write_packet (struct peer *peer)
515{
516 afi_t afi;
517 safi_t safi;
518 struct stream *s = NULL;
519 struct bgp_advertise *adv;
520
521 s = stream_fifo_head (peer->obuf);
522 if (s)
523 return s;
524
525 for (afi = AFI_IP; afi < AFI_MAX; afi++)
526 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
527 {
528 adv = FIFO_HEAD (&peer->sync[afi][safi]->withdraw);
529 if (adv)
530 {
531 s = bgp_withdraw_packet (peer, afi, safi);
532 if (s)
533 return s;
534 }
535 }
536
537 for (afi = AFI_IP; afi < AFI_MAX; afi++)
538 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
539 {
540 adv = FIFO_HEAD (&peer->sync[afi][safi]->update);
541 if (adv)
542 {
543 if (adv->binfo && adv->binfo->uptime < peer->synctime)
hasso93406d82005-02-02 14:40:33 +0000544 {
545 if (CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_RCV)
546 && CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_ADV)
547 && ! CHECK_FLAG (adv->binfo->flags, BGP_INFO_STALE)
548 && safi != SAFI_MPLS_VPN)
549 {
550 if (CHECK_FLAG (adv->binfo->peer->af_sflags[afi][safi],
551 PEER_STATUS_EOR_RECEIVED))
552 s = bgp_update_packet (peer, afi, safi);
553 }
554 else
555 s = bgp_update_packet (peer, afi, safi);
556 }
paul718e3742002-12-13 20:15:29 +0000557
558 if (s)
559 return s;
560 }
hasso93406d82005-02-02 14:40:33 +0000561
562 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV))
563 {
564 if (peer->afc_nego[afi][safi] && peer->synctime
565 && ! CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND)
566 && safi != SAFI_MPLS_VPN)
567 {
568 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND);
569 return bgp_update_packet_eor (peer, afi, safi);
570 }
571 }
paul718e3742002-12-13 20:15:29 +0000572 }
573
574 return NULL;
575}
576
577/* Is there partially written packet or updates we can send right
578 now. */
paul94f2b392005-06-28 12:44:16 +0000579static int
paul718e3742002-12-13 20:15:29 +0000580bgp_write_proceed (struct peer *peer)
581{
582 afi_t afi;
583 safi_t safi;
584 struct bgp_advertise *adv;
585
586 if (stream_fifo_head (peer->obuf))
587 return 1;
588
589 for (afi = AFI_IP; afi < AFI_MAX; afi++)
590 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
591 if (FIFO_HEAD (&peer->sync[afi][safi]->withdraw))
592 return 1;
593
594 for (afi = AFI_IP; afi < AFI_MAX; afi++)
595 for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
596 if ((adv = FIFO_HEAD (&peer->sync[afi][safi]->update)) != NULL)
597 if (adv->binfo->uptime < peer->synctime)
598 return 1;
599
600 return 0;
601}
602
603/* Write packet to the peer. */
604int
605bgp_write (struct thread *thread)
606{
607 struct peer *peer;
608 u_char type;
609 struct stream *s;
610 int num;
paulfd79ac92004-10-13 05:06:08 +0000611 unsigned int count = 0;
paul718e3742002-12-13 20:15:29 +0000612
613 /* Yes first of all get peer pointer. */
614 peer = THREAD_ARG (thread);
615 peer->t_write = NULL;
616
617 /* For non-blocking IO check. */
618 if (peer->status == Connect)
619 {
620 bgp_connect_check (peer);
621 return 0;
622 }
623
Stephen Hemmingereac57022010-08-05 10:26:25 -0700624 s = bgp_write_packet (peer);
625 if (!s)
626 return 0; /* nothing to send */
627
628 sockopt_cork (peer->fd, 1);
629
630 /* Nonblocking write until TCP output buffer is full. */
631 do
paul718e3742002-12-13 20:15:29 +0000632 {
633 int writenum;
paul718e3742002-12-13 20:15:29 +0000634
635 /* Number of bytes to be sent. */
636 writenum = stream_get_endp (s) - stream_get_getp (s);
637
638 /* Call write() system call. */
pauleb821182004-05-01 08:44:08 +0000639 num = write (peer->fd, STREAM_PNT (s), writenum);
Stephen Hemminger35398582010-08-05 10:26:23 -0700640 if (num < 0)
paul718e3742002-12-13 20:15:29 +0000641 {
Stephen Hemmingereac57022010-08-05 10:26:25 -0700642 /* write failed either retry needed or error */
643 if (ERRNO_IO_RETRY(errno))
644 break;
645
646 BGP_EVENT_ADD (peer, TCP_fatal_error);
paul718e3742002-12-13 20:15:29 +0000647 return 0;
648 }
Stephen Hemminger35398582010-08-05 10:26:23 -0700649
paul718e3742002-12-13 20:15:29 +0000650 if (num != writenum)
651 {
Stephen Hemminger35398582010-08-05 10:26:23 -0700652 /* Partial write */
paul9985f832005-02-09 15:51:56 +0000653 stream_forward_getp (s, num);
Stephen Hemmingereac57022010-08-05 10:26:25 -0700654 break;
paul718e3742002-12-13 20:15:29 +0000655 }
656
657 /* Retrieve BGP packet type. */
658 stream_set_getp (s, BGP_MARKER_SIZE + 2);
659 type = stream_getc (s);
660
661 switch (type)
662 {
663 case BGP_MSG_OPEN:
664 peer->open_out++;
665 break;
666 case BGP_MSG_UPDATE:
667 peer->update_out++;
668 break;
669 case BGP_MSG_NOTIFY:
670 peer->notify_out++;
671 /* Double start timer. */
672 peer->v_start *= 2;
673
674 /* Overflow check. */
675 if (peer->v_start >= (60 * 2))
676 peer->v_start = (60 * 2);
677
Paul Jakmaca058a32006-09-14 02:58:49 +0000678 /* Flush any existing events */
Paul Jakmadcdf3992006-10-15 23:39:59 +0000679 BGP_EVENT_ADD (peer, BGP_Stop);
Stephen Hemminger3a69f742013-01-11 18:27:23 +0000680 goto done;
681
paul718e3742002-12-13 20:15:29 +0000682 case BGP_MSG_KEEPALIVE:
683 peer->keepalive_out++;
684 break;
685 case BGP_MSG_ROUTE_REFRESH_NEW:
686 case BGP_MSG_ROUTE_REFRESH_OLD:
687 peer->refresh_out++;
688 break;
689 case BGP_MSG_CAPABILITY:
690 peer->dynamic_cap_out++;
691 break;
692 }
693
694 /* OK we send packet so delete it. */
695 bgp_packet_delete (peer);
paul718e3742002-12-13 20:15:29 +0000696 }
Stephen Hemmingereac57022010-08-05 10:26:25 -0700697 while (++count < BGP_WRITE_PACKET_MAX &&
698 (s = bgp_write_packet (peer)) != NULL);
paul718e3742002-12-13 20:15:29 +0000699
700 if (bgp_write_proceed (peer))
pauleb821182004-05-01 08:44:08 +0000701 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
Stephen Hemminger3a69f742013-01-11 18:27:23 +0000702
703 done:
704 sockopt_cork (peer->fd, 0);
paul718e3742002-12-13 20:15:29 +0000705 return 0;
706}
707
708/* This is only for sending NOTIFICATION message to neighbor. */
paul94f2b392005-06-28 12:44:16 +0000709static int
paul718e3742002-12-13 20:15:29 +0000710bgp_write_notify (struct peer *peer)
711{
Stephen Hemminger35398582010-08-05 10:26:23 -0700712 int ret, val;
paul718e3742002-12-13 20:15:29 +0000713 u_char type;
714 struct stream *s;
715
716 /* There should be at least one packet. */
717 s = stream_fifo_head (peer->obuf);
718 if (!s)
719 return 0;
720 assert (stream_get_endp (s) >= BGP_HEADER_SIZE);
721
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000722 /* Stop collecting data within the socket */
723 sockopt_cork (peer->fd, 0);
724
David Lamparter8ff202e2013-07-31 14:39:41 +0200725 /* socket is in nonblocking mode, if we can't deliver the NOTIFY, well,
726 * we only care about getting a clean shutdown at this point. */
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000727 ret = write (peer->fd, STREAM_DATA (s), stream_get_endp (s));
David Lamparter8ff202e2013-07-31 14:39:41 +0200728
729 /* only connection reset/close gets counted as TCP_fatal_error, failure
730 * to write the entire NOTIFY doesn't get different FSM treatment */
paul718e3742002-12-13 20:15:29 +0000731 if (ret <= 0)
732 {
Paul Jakmadcdf3992006-10-15 23:39:59 +0000733 BGP_EVENT_ADD (peer, TCP_fatal_error);
paul718e3742002-12-13 20:15:29 +0000734 return 0;
735 }
736
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000737 /* Disable Nagle, make NOTIFY packet go out right away */
738 val = 1;
739 (void) setsockopt (peer->fd, IPPROTO_TCP, TCP_NODELAY,
740 (char *) &val, sizeof (val));
741
paul718e3742002-12-13 20:15:29 +0000742 /* Retrieve BGP packet type. */
743 stream_set_getp (s, BGP_MARKER_SIZE + 2);
744 type = stream_getc (s);
745
746 assert (type == BGP_MSG_NOTIFY);
747
748 /* Type should be notify. */
749 peer->notify_out++;
750
751 /* Double start timer. */
752 peer->v_start *= 2;
753
754 /* Overflow check. */
755 if (peer->v_start >= (60 * 2))
756 peer->v_start = (60 * 2);
757
Paul Jakmadcdf3992006-10-15 23:39:59 +0000758 BGP_EVENT_ADD (peer, BGP_Stop);
paul718e3742002-12-13 20:15:29 +0000759
760 return 0;
761}
762
763/* Make keepalive packet and send it to the peer. */
764void
765bgp_keepalive_send (struct peer *peer)
766{
767 struct stream *s;
768 int length;
769
770 s = stream_new (BGP_MAX_PACKET_SIZE);
771
772 /* Make keepalive packet. */
773 bgp_packet_set_marker (s, BGP_MSG_KEEPALIVE);
774
775 /* Set packet size. */
776 length = bgp_packet_set_size (s);
777
778 /* Dump packet if debug option is set. */
779 /* bgp_packet_dump (s); */
780
781 if (BGP_DEBUG (keepalive, KEEPALIVE))
ajs6b514742004-12-08 21:03:23 +0000782 zlog_debug ("%s sending KEEPALIVE", peer->host);
paul718e3742002-12-13 20:15:29 +0000783 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000784 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000785 peer->host, BGP_MSG_KEEPALIVE, length);
786
787 /* Add packet to the peer. */
788 bgp_packet_add (peer, s);
789
pauleb821182004-05-01 08:44:08 +0000790 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000791}
792
793/* Make open packet and send it to the peer. */
794void
795bgp_open_send (struct peer *peer)
796{
797 struct stream *s;
798 int length;
799 u_int16_t send_holdtime;
800 as_t local_as;
801
802 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
803 send_holdtime = peer->holdtime;
804 else
805 send_holdtime = peer->bgp->default_holdtime;
806
807 /* local-as Change */
808 if (peer->change_local_as)
809 local_as = peer->change_local_as;
810 else
811 local_as = peer->local_as;
812
813 s = stream_new (BGP_MAX_PACKET_SIZE);
814
815 /* Make open packet. */
816 bgp_packet_set_marker (s, BGP_MSG_OPEN);
817
818 /* Set open packet values. */
819 stream_putc (s, BGP_VERSION_4); /* BGP version */
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000820 stream_putw (s, (local_as <= BGP_AS_MAX) ? (u_int16_t) local_as
821 : BGP_AS_TRANS);
paul718e3742002-12-13 20:15:29 +0000822 stream_putw (s, send_holdtime); /* Hold Time */
823 stream_put_in_addr (s, &peer->local_id); /* BGP Identifier */
824
825 /* Set capability code. */
826 bgp_open_capability (s, peer);
827
828 /* Set BGP packet length. */
829 length = bgp_packet_set_size (s);
830
831 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +0400832 zlog_debug ("%s sending OPEN, version %d, my as %u, holdtime %d, id %s",
paul718e3742002-12-13 20:15:29 +0000833 peer->host, BGP_VERSION_4, local_as,
834 send_holdtime, inet_ntoa (peer->local_id));
835
836 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000837 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000838 peer->host, BGP_MSG_OPEN, length);
839
840 /* Dump packet if debug option is set. */
841 /* bgp_packet_dump (s); */
842
843 /* Add packet to the peer. */
844 bgp_packet_add (peer, s);
845
pauleb821182004-05-01 08:44:08 +0000846 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000847}
848
849/* Send BGP notify packet with data potion. */
850void
851bgp_notify_send_with_data (struct peer *peer, u_char code, u_char sub_code,
852 u_char *data, size_t datalen)
853{
854 struct stream *s;
855 int length;
856
857 /* Allocate new stream. */
858 s = stream_new (BGP_MAX_PACKET_SIZE);
859
860 /* Make nitify packet. */
861 bgp_packet_set_marker (s, BGP_MSG_NOTIFY);
862
863 /* Set notify packet values. */
864 stream_putc (s, code); /* BGP notify code */
865 stream_putc (s, sub_code); /* BGP notify sub_code */
866
867 /* If notify data is present. */
868 if (data)
869 stream_write (s, data, datalen);
870
871 /* Set BGP packet length. */
872 length = bgp_packet_set_size (s);
873
874 /* Add packet to the peer. */
875 stream_fifo_clean (peer->obuf);
876 bgp_packet_add (peer, s);
877
878 /* For debug */
879 {
880 struct bgp_notify bgp_notify;
881 int first = 0;
882 int i;
883 char c[4];
884
885 bgp_notify.code = code;
886 bgp_notify.subcode = sub_code;
887 bgp_notify.data = NULL;
888 bgp_notify.length = length - BGP_MSG_NOTIFY_MIN_SIZE;
889
890 if (bgp_notify.length)
891 {
892 bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
893 for (i = 0; i < bgp_notify.length; i++)
894 if (first)
895 {
896 sprintf (c, " %02x", data[i]);
897 strcat (bgp_notify.data, c);
898 }
899 else
900 {
901 first = 1;
902 sprintf (c, "%02x", data[i]);
903 strcpy (bgp_notify.data, c);
904 }
905 }
906 bgp_notify_print (peer, &bgp_notify, "sending");
907 if (bgp_notify.data)
908 XFREE (MTYPE_TMP, bgp_notify.data);
909 }
910
911 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000912 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000913 peer->host, BGP_MSG_NOTIFY, length);
914
hassoe0701b72004-05-20 09:19:34 +0000915 /* peer reset cause */
916 if (sub_code != BGP_NOTIFY_CEASE_CONFIG_CHANGE)
917 {
918 if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET)
heasley1212dc12011-09-12 13:27:52 +0400919 {
920 peer->last_reset = PEER_DOWN_USER_RESET;
921 zlog_info ("Notification sent to neighbor %s: User reset", peer->host);
922 }
hassoe0701b72004-05-20 09:19:34 +0000923 else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN)
heasley1212dc12011-09-12 13:27:52 +0400924 {
925 peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
926 zlog_info ("Notification sent to neighbor %s: shutdown", peer->host);
927 }
hassoe0701b72004-05-20 09:19:34 +0000928 else
heasley1212dc12011-09-12 13:27:52 +0400929 {
930 peer->last_reset = PEER_DOWN_NOTIFY_SEND;
931 zlog_info ("Notification sent to neighbor %s: type %u/%u",
932 peer->host, code, sub_code);
933 }
hassoe0701b72004-05-20 09:19:34 +0000934 }
heasley1212dc12011-09-12 13:27:52 +0400935 else
936 zlog_info ("Notification sent to neighbor %s: configuration change",
937 peer->host);
hassoe0701b72004-05-20 09:19:34 +0000938
Denis Ovsienko7ccf5e52011-09-10 16:53:30 +0400939 /* Call immediately. */
paul718e3742002-12-13 20:15:29 +0000940 BGP_WRITE_OFF (peer->t_write);
941
942 bgp_write_notify (peer);
943}
944
945/* Send BGP notify packet. */
946void
947bgp_notify_send (struct peer *peer, u_char code, u_char sub_code)
948{
949 bgp_notify_send_with_data (peer, code, sub_code, NULL, 0);
950}
951
paul718e3742002-12-13 20:15:29 +0000952/* Send route refresh message to the peer. */
953void
954bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
955 u_char orf_type, u_char when_to_refresh, int remove)
956{
957 struct stream *s;
958 struct stream *packet;
959 int length;
960 struct bgp_filter *filter;
961 int orf_refresh = 0;
962
Paul Jakma750e8142008-07-22 21:11:48 +0000963 if (DISABLE_BGP_ANNOUNCE)
964 return;
paul718e3742002-12-13 20:15:29 +0000965
966 filter = &peer->filter[afi][safi];
967
968 /* Adjust safi code. */
969 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +0400970 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +0000971
972 s = stream_new (BGP_MAX_PACKET_SIZE);
973
974 /* Make BGP update packet. */
975 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
976 bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_NEW);
977 else
978 bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_OLD);
979
980 /* Encode Route Refresh message. */
981 stream_putw (s, afi);
982 stream_putc (s, 0);
983 stream_putc (s, safi);
984
985 if (orf_type == ORF_TYPE_PREFIX
986 || orf_type == ORF_TYPE_PREFIX_OLD)
987 if (remove || filter->plist[FILTER_IN].plist)
988 {
989 u_int16_t orf_len;
990 unsigned long orfp;
991
992 orf_refresh = 1;
993 stream_putc (s, when_to_refresh);
994 stream_putc (s, orf_type);
paul9985f832005-02-09 15:51:56 +0000995 orfp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000996 stream_putw (s, 0);
997
998 if (remove)
999 {
1000 UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
1001 stream_putc (s, ORF_COMMON_PART_REMOVE_ALL);
1002 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001003 zlog_debug ("%s sending REFRESH_REQ to remove ORF(%d) (%s) for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001004 peer->host, orf_type,
1005 (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
1006 afi, safi);
1007 }
1008 else
1009 {
1010 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
1011 prefix_bgp_orf_entry (s, filter->plist[FILTER_IN].plist,
1012 ORF_COMMON_PART_ADD, ORF_COMMON_PART_PERMIT,
1013 ORF_COMMON_PART_DENY);
1014 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001015 zlog_debug ("%s sending REFRESH_REQ with pfxlist ORF(%d) (%s) for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001016 peer->host, orf_type,
1017 (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
1018 afi, safi);
1019 }
1020
1021 /* Total ORF Entry Len. */
paul9985f832005-02-09 15:51:56 +00001022 orf_len = stream_get_endp (s) - orfp - 2;
paul718e3742002-12-13 20:15:29 +00001023 stream_putw_at (s, orfp, orf_len);
1024 }
1025
1026 /* Set packet size. */
1027 length = bgp_packet_set_size (s);
1028
1029 if (BGP_DEBUG (normal, NORMAL))
1030 {
1031 if (! orf_refresh)
ajs6b514742004-12-08 21:03:23 +00001032 zlog_debug ("%s sending REFRESH_REQ for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001033 peer->host, afi, safi);
ajs6b514742004-12-08 21:03:23 +00001034 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +00001035 peer->host, CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV) ?
1036 BGP_MSG_ROUTE_REFRESH_NEW : BGP_MSG_ROUTE_REFRESH_OLD, length);
1037 }
1038
1039 /* Make real packet. */
paule83e2082005-05-19 02:12:25 +00001040 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +00001041 stream_free (s);
1042
1043 /* Add packet to the peer. */
1044 bgp_packet_add (peer, packet);
1045
pauleb821182004-05-01 08:44:08 +00001046 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +00001047}
1048
1049/* Send capability message to the peer. */
1050void
1051bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi,
1052 int capability_code, int action)
1053{
1054 struct stream *s;
1055 struct stream *packet;
1056 int length;
1057
1058 /* Adjust safi code. */
1059 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001060 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +00001061
1062 s = stream_new (BGP_MAX_PACKET_SIZE);
1063
1064 /* Make BGP update packet. */
1065 bgp_packet_set_marker (s, BGP_MSG_CAPABILITY);
1066
1067 /* Encode MP_EXT capability. */
1068 if (capability_code == CAPABILITY_CODE_MP)
1069 {
1070 stream_putc (s, action);
1071 stream_putc (s, CAPABILITY_CODE_MP);
1072 stream_putc (s, CAPABILITY_CODE_MP_LEN);
1073 stream_putw (s, afi);
1074 stream_putc (s, 0);
1075 stream_putc (s, safi);
1076
1077 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001078 zlog_debug ("%s sending CAPABILITY has %s MP_EXT CAP for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001079 peer->host, action == CAPABILITY_ACTION_SET ?
1080 "Advertising" : "Removing", afi, safi);
1081 }
1082
paul718e3742002-12-13 20:15:29 +00001083 /* Set packet size. */
1084 length = bgp_packet_set_size (s);
1085
1086 /* Make real packet. */
paule83e2082005-05-19 02:12:25 +00001087 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +00001088 stream_free (s);
1089
1090 /* Add packet to the peer. */
1091 bgp_packet_add (peer, packet);
1092
1093 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001094 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +00001095 peer->host, BGP_MSG_CAPABILITY, length);
1096
pauleb821182004-05-01 08:44:08 +00001097 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +00001098}
1099
1100/* RFC1771 6.8 Connection collision detection. */
paul94f2b392005-06-28 12:44:16 +00001101static int
pauleb821182004-05-01 08:44:08 +00001102bgp_collision_detect (struct peer *new, struct in_addr remote_id)
paul718e3742002-12-13 20:15:29 +00001103{
pauleb821182004-05-01 08:44:08 +00001104 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001105 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001106 struct bgp *bgp;
1107
1108 bgp = bgp_get_default ();
1109 if (! bgp)
1110 return 0;
1111
1112 /* Upon receipt of an OPEN message, the local system must examine
1113 all of its connections that are in the OpenConfirm state. A BGP
1114 speaker may also examine connections in an OpenSent state if it
1115 knows the BGP Identifier of the peer by means outside of the
1116 protocol. If among these connections there is a connection to a
1117 remote BGP speaker whose BGP Identifier equals the one in the
1118 OPEN message, then the local system performs the following
1119 collision resolution procedure: */
1120
paul1eb8ef22005-04-07 07:30:20 +00001121 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001122 {
1123 /* Under OpenConfirm status, local peer structure already hold
1124 remote router ID. */
pauleb821182004-05-01 08:44:08 +00001125
1126 if (peer != new
1127 && (peer->status == OpenConfirm || peer->status == OpenSent)
1128 && sockunion_same (&peer->su, &new->su))
1129 {
paul718e3742002-12-13 20:15:29 +00001130 /* 1. The BGP Identifier of the local system is compared to
1131 the BGP Identifier of the remote system (as specified in
1132 the OPEN message). */
1133
1134 if (ntohl (peer->local_id.s_addr) < ntohl (remote_id.s_addr))
1135 {
1136 /* 2. If the value of the local BGP Identifier is less
1137 than the remote one, the local system closes BGP
1138 connection that already exists (the one that is
1139 already in the OpenConfirm state), and accepts BGP
1140 connection initiated by the remote system. */
1141
pauleb821182004-05-01 08:44:08 +00001142 if (peer->fd >= 0)
hassoe0701b72004-05-20 09:19:34 +00001143 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
paul718e3742002-12-13 20:15:29 +00001144 return 1;
1145 }
1146 else
1147 {
1148 /* 3. Otherwise, the local system closes newly created
1149 BGP connection (the one associated with the newly
1150 received OPEN message), and continues to use the
1151 existing one (the one that is already in the
1152 OpenConfirm state). */
1153
pauleb821182004-05-01 08:44:08 +00001154 if (new->fd >= 0)
paulf5ba3872004-07-09 12:11:31 +00001155 bgp_notify_send (new, BGP_NOTIFY_CEASE,
1156 BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
paul718e3742002-12-13 20:15:29 +00001157 return -1;
1158 }
pauleb821182004-05-01 08:44:08 +00001159 }
1160 }
paul718e3742002-12-13 20:15:29 +00001161 return 0;
1162}
1163
paul94f2b392005-06-28 12:44:16 +00001164static int
paul718e3742002-12-13 20:15:29 +00001165bgp_open_receive (struct peer *peer, bgp_size_t size)
1166{
1167 int ret;
1168 u_char version;
1169 u_char optlen;
1170 u_int16_t holdtime;
1171 u_int16_t send_holdtime;
1172 as_t remote_as;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001173 as_t as4 = 0;
paul718e3742002-12-13 20:15:29 +00001174 struct peer *realpeer;
1175 struct in_addr remote_id;
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001176 int mp_capability;
paul5228ad22004-06-04 17:58:18 +00001177 u_int8_t notify_data_remote_as[2];
1178 u_int8_t notify_data_remote_id[4];
paul718e3742002-12-13 20:15:29 +00001179
1180 realpeer = NULL;
1181
1182 /* Parse open packet. */
1183 version = stream_getc (peer->ibuf);
1184 memcpy (notify_data_remote_as, stream_pnt (peer->ibuf), 2);
1185 remote_as = stream_getw (peer->ibuf);
1186 holdtime = stream_getw (peer->ibuf);
1187 memcpy (notify_data_remote_id, stream_pnt (peer->ibuf), 4);
1188 remote_id.s_addr = stream_get_ipv4 (peer->ibuf);
1189
1190 /* Receive OPEN message log */
1191 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001192 zlog_debug ("%s rcv OPEN, version %d, remote-as (in open) %u,"
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001193 " holdtime %d, id %s",
1194 peer->host, version, remote_as, holdtime,
1195 inet_ntoa (remote_id));
1196
1197 /* BEGIN to read the capability here, but dont do it yet */
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001198 mp_capability = 0;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001199 optlen = stream_getc (peer->ibuf);
1200
1201 if (optlen != 0)
1202 {
1203 /* We need the as4 capability value *right now* because
1204 * if it is there, we have not got the remote_as yet, and without
1205 * that we do not know which peer is connecting to us now.
1206 */
1207 as4 = peek_for_as4_capability (peer, optlen);
1208 }
1209
1210 /* Just in case we have a silly peer who sends AS4 capability set to 0 */
1211 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) && !as4)
1212 {
1213 zlog_err ("%s bad OPEN, got AS4 capability, but AS4 set to 0",
1214 peer->host);
1215 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1216 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1217 return -1;
1218 }
1219
1220 if (remote_as == BGP_AS_TRANS)
1221 {
1222 /* Take the AS4 from the capability. We must have received the
1223 * capability now! Otherwise we have a asn16 peer who uses
1224 * BGP_AS_TRANS, for some unknown reason.
1225 */
1226 if (as4 == BGP_AS_TRANS)
1227 {
1228 zlog_err ("%s [AS4] NEW speaker using AS_TRANS for AS4, not allowed",
1229 peer->host);
1230 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1231 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1232 return -1;
1233 }
1234
1235 if (!as4 && BGP_DEBUG (as4, AS4))
1236 zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but no AS4."
1237 " Odd, but proceeding.", peer->host);
1238 else if (as4 < BGP_AS_MAX && BGP_DEBUG (as4, AS4))
Paul Jakma0df7c912008-07-21 21:02:49 +00001239 zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but AS4 (%u) fits "
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001240 "in 2-bytes, very odd peer.", peer->host, as4);
1241 if (as4)
1242 remote_as = as4;
1243 }
1244 else
1245 {
1246 /* We may have a partner with AS4 who has an asno < BGP_AS_MAX */
1247 /* If we have got the capability, peer->as4cap must match remote_as */
1248 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)
1249 && as4 != remote_as)
1250 {
1251 /* raise error, log this, close session */
1252 zlog_err ("%s bad OPEN, got AS4 capability, but remote_as %u"
1253 " mismatch with 16bit 'myasn' %u in open",
1254 peer->host, as4, remote_as);
1255 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1256 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1257 return -1;
1258 }
1259 }
1260
paul718e3742002-12-13 20:15:29 +00001261 /* Lookup peer from Open packet. */
1262 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1263 {
1264 int as = 0;
1265
1266 realpeer = peer_lookup_with_open (&peer->su, remote_as, &remote_id, &as);
1267
1268 if (! realpeer)
1269 {
1270 /* Peer's source IP address is check in bgp_accept(), so this
1271 must be AS number mismatch or remote-id configuration
1272 mismatch. */
1273 if (as)
1274 {
1275 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001276 zlog_debug ("%s bad OPEN, wrong router identifier %s",
1277 peer->host, inet_ntoa (remote_id));
1278 bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
1279 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
1280 notify_data_remote_id, 4);
paul718e3742002-12-13 20:15:29 +00001281 }
1282 else
1283 {
1284 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001285 zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
ajs6b514742004-12-08 21:03:23 +00001286 peer->host, remote_as, peer->as);
1287 bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
1288 BGP_NOTIFY_OPEN_BAD_PEER_AS,
1289 notify_data_remote_as, 2);
paul718e3742002-12-13 20:15:29 +00001290 }
1291 return -1;
1292 }
1293 }
1294
1295 /* When collision is detected and this peer is closed. Retrun
1296 immidiately. */
1297 ret = bgp_collision_detect (peer, remote_id);
1298 if (ret < 0)
1299 return ret;
1300
pauleb821182004-05-01 08:44:08 +00001301 /* Hack part. */
1302 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1303 {
hasso93406d82005-02-02 14:40:33 +00001304 if (realpeer->status == Established
1305 && CHECK_FLAG (realpeer->sflags, PEER_STATUS_NSF_MODE))
1306 {
1307 realpeer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
1308 SET_FLAG (realpeer->sflags, PEER_STATUS_NSF_WAIT);
1309 }
1310 else if (ret == 0 && realpeer->status != Active
1311 && realpeer->status != OpenSent
Paul Jakma6e199262008-09-09 17:14:33 +01001312 && realpeer->status != OpenConfirm
1313 && realpeer->status != Connect)
pauleb821182004-05-01 08:44:08 +00001314 {
Paul Jakma2b2fc562008-09-06 13:09:35 +01001315 /* XXX: This is an awful problem..
1316 *
1317 * According to the RFC we should just let this connection (of the
1318 * accepted 'peer') continue on to Established if the other
1319 * connection (the 'realpeer' one) is in state Connect, and deal
1320 * with the more larval FSM as/when it gets far enough to receive
1321 * an Open. We don't do that though, we instead close the (more
1322 * developed) accepted connection.
1323 *
1324 * This means there's a race, which if hit, can loop:
1325 *
1326 * FSM for A FSM for B
1327 * realpeer accept-peer realpeer accept-peer
1328 *
1329 * Connect Connect
1330 * Active
1331 * OpenSent OpenSent
1332 * <arrive here,
1333 * Notify, delete>
1334 * Idle Active
1335 * OpenSent OpenSent
1336 * <arrive here,
1337 * Notify, delete>
1338 * Idle
1339 * <wait> <wait>
1340 * Connect Connect
1341 *
1342 *
1343 * If both sides are Quagga, they're almost certain to wait for
1344 * the same amount of time of course (which doesn't preclude other
1345 * implementations also waiting for same time). The race is
1346 * exacerbated by high-latency (in bgpd and/or the network).
1347 *
1348 * The reason we do this is because our FSM is tied to our peer
1349 * structure, which carries our configuration information, etc.
1350 * I.e. we can't let the accepted-peer FSM continue on as it is,
1351 * cause it's not associated with any actual peer configuration -
1352 * it's just a dummy.
1353 *
1354 * It's possible we could hack-fix this by just bgp_stop'ing the
1355 * realpeer and continueing on with the 'transfer FSM' below.
1356 * Ideally, we need to seperate FSMs from struct peer.
1357 *
1358 * Setting one side to passive avoids the race, as a workaround.
1359 */
pauleb821182004-05-01 08:44:08 +00001360 if (BGP_DEBUG (events, EVENTS))
hasso93406d82005-02-02 14:40:33 +00001361 zlog_debug ("%s peer status is %s close connection",
1362 realpeer->host, LOOKUP (bgp_status_msg,
1363 realpeer->status));
1364 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1365 BGP_NOTIFY_CEASE_CONNECT_REJECT);
1366
pauleb821182004-05-01 08:44:08 +00001367 return -1;
1368 }
1369
1370 if (BGP_DEBUG (events, EVENTS))
Paul Jakma6e199262008-09-09 17:14:33 +01001371 zlog_debug ("%s [Event] Transfer accept BGP peer to real (state %s)",
1372 peer->host,
1373 LOOKUP (bgp_status_msg, realpeer->status));
pauleb821182004-05-01 08:44:08 +00001374
1375 bgp_stop (realpeer);
1376
1377 /* Transfer file descriptor. */
1378 realpeer->fd = peer->fd;
1379 peer->fd = -1;
1380
1381 /* Transfer input buffer. */
1382 stream_free (realpeer->ibuf);
1383 realpeer->ibuf = peer->ibuf;
1384 realpeer->packet_size = peer->packet_size;
1385 peer->ibuf = NULL;
1386
1387 /* Transfer status. */
1388 realpeer->status = peer->status;
1389 bgp_stop (peer);
paul200df112005-06-01 11:17:05 +00001390
pauleb821182004-05-01 08:44:08 +00001391 /* peer pointer change. Open packet send to neighbor. */
1392 peer = realpeer;
1393 bgp_open_send (peer);
1394 if (peer->fd < 0)
1395 {
1396 zlog_err ("bgp_open_receive peer's fd is negative value %d",
1397 peer->fd);
1398 return -1;
1399 }
1400 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
1401 }
1402
paul718e3742002-12-13 20:15:29 +00001403 /* remote router-id check. */
1404 if (remote_id.s_addr == 0
Denis Ovsienko733cd9e2011-12-17 19:39:30 +04001405 || IPV4_CLASS_DE (ntohl (remote_id.s_addr))
paul718e3742002-12-13 20:15:29 +00001406 || ntohl (peer->local_id.s_addr) == ntohl (remote_id.s_addr))
1407 {
1408 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001409 zlog_debug ("%s bad OPEN, wrong router identifier %s",
paul718e3742002-12-13 20:15:29 +00001410 peer->host, inet_ntoa (remote_id));
1411 bgp_notify_send_with_data (peer,
1412 BGP_NOTIFY_OPEN_ERR,
1413 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
1414 notify_data_remote_id, 4);
1415 return -1;
1416 }
1417
1418 /* Set remote router-id */
1419 peer->remote_id = remote_id;
1420
1421 /* Peer BGP version check. */
1422 if (version != BGP_VERSION_4)
1423 {
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001424 u_int16_t maxver = htons(BGP_VERSION_4);
1425 /* XXX this reply may not be correct if version < 4 XXX */
paul718e3742002-12-13 20:15:29 +00001426 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001427 zlog_debug ("%s bad protocol version, remote requested %d, local request %d",
paul718e3742002-12-13 20:15:29 +00001428 peer->host, version, BGP_VERSION_4);
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001429 /* Data must be in network byte order here */
paul718e3742002-12-13 20:15:29 +00001430 bgp_notify_send_with_data (peer,
1431 BGP_NOTIFY_OPEN_ERR,
1432 BGP_NOTIFY_OPEN_UNSUP_VERSION,
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001433 (u_int8_t *) &maxver, 2);
paul718e3742002-12-13 20:15:29 +00001434 return -1;
1435 }
1436
1437 /* Check neighbor as number. */
1438 if (remote_as != peer->as)
1439 {
1440 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001441 zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
paul718e3742002-12-13 20:15:29 +00001442 peer->host, remote_as, peer->as);
1443 bgp_notify_send_with_data (peer,
1444 BGP_NOTIFY_OPEN_ERR,
1445 BGP_NOTIFY_OPEN_BAD_PEER_AS,
1446 notify_data_remote_as, 2);
1447 return -1;
1448 }
1449
1450 /* From the rfc: Upon receipt of an OPEN message, a BGP speaker MUST
1451 calculate the value of the Hold Timer by using the smaller of its
1452 configured Hold Time and the Hold Time received in the OPEN message.
1453 The Hold Time MUST be either zero or at least three seconds. An
1454 implementation may reject connections on the basis of the Hold Time. */
1455
1456 if (holdtime < 3 && holdtime != 0)
1457 {
1458 bgp_notify_send (peer,
1459 BGP_NOTIFY_OPEN_ERR,
1460 BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
1461 return -1;
1462 }
1463
1464 /* From the rfc: A reasonable maximum time between KEEPALIVE messages
1465 would be one third of the Hold Time interval. KEEPALIVE messages
1466 MUST NOT be sent more frequently than one per second. An
1467 implementation MAY adjust the rate at which it sends KEEPALIVE
1468 messages as a function of the Hold Time interval. */
1469
1470 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
1471 send_holdtime = peer->holdtime;
1472 else
1473 send_holdtime = peer->bgp->default_holdtime;
1474
1475 if (holdtime < send_holdtime)
1476 peer->v_holdtime = holdtime;
1477 else
1478 peer->v_holdtime = send_holdtime;
1479
1480 peer->v_keepalive = peer->v_holdtime / 3;
1481
1482 /* Open option part parse. */
paul718e3742002-12-13 20:15:29 +00001483 if (optlen != 0)
1484 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001485 if ((ret = bgp_open_option_parse (peer, optlen, &mp_capability)) < 0)
Paul Jakma58617392012-01-09 20:59:26 +00001486 {
1487 bgp_notify_send (peer,
1488 BGP_NOTIFY_OPEN_ERR,
1489 BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
1490 return ret;
1491 }
paul718e3742002-12-13 20:15:29 +00001492 }
1493 else
1494 {
1495 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001496 zlog_debug ("%s rcvd OPEN w/ OPTION parameter len: 0",
paul718e3742002-12-13 20:15:29 +00001497 peer->host);
1498 }
1499
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001500 /*
1501 * Assume that the peer supports the locally configured set of
1502 * AFI/SAFIs if the peer did not send us any Mulitiprotocol
1503 * capabilities, or if 'override-capability' is configured.
1504 */
1505 if (! mp_capability ||
1506 CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
paul718e3742002-12-13 20:15:29 +00001507 {
1508 peer->afc_nego[AFI_IP][SAFI_UNICAST] = peer->afc[AFI_IP][SAFI_UNICAST];
1509 peer->afc_nego[AFI_IP][SAFI_MULTICAST] = peer->afc[AFI_IP][SAFI_MULTICAST];
1510 peer->afc_nego[AFI_IP6][SAFI_UNICAST] = peer->afc[AFI_IP6][SAFI_UNICAST];
1511 peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = peer->afc[AFI_IP6][SAFI_MULTICAST];
1512 }
1513
1514 /* Get sockname. */
1515 bgp_getsockname (peer);
1516
1517 BGP_EVENT_ADD (peer, Receive_OPEN_message);
1518
1519 peer->packet_size = 0;
1520 if (peer->ibuf)
1521 stream_reset (peer->ibuf);
1522
1523 return 0;
1524}
1525
1526/* Parse BGP Update packet and make attribute object. */
paul94f2b392005-06-28 12:44:16 +00001527static int
paul718e3742002-12-13 20:15:29 +00001528bgp_update_receive (struct peer *peer, bgp_size_t size)
1529{
1530 int ret;
1531 u_char *end;
1532 struct stream *s;
1533 struct attr attr;
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001534 struct attr_extra extra;
paul718e3742002-12-13 20:15:29 +00001535 bgp_size_t attribute_len;
1536 bgp_size_t update_len;
1537 bgp_size_t withdraw_len;
1538 struct bgp_nlri update;
1539 struct bgp_nlri withdraw;
1540 struct bgp_nlri mp_update;
1541 struct bgp_nlri mp_withdraw;
paul718e3742002-12-13 20:15:29 +00001542
1543 /* Status must be Established. */
1544 if (peer->status != Established)
1545 {
1546 zlog_err ("%s [FSM] Update packet received under status %s",
1547 peer->host, LOOKUP (bgp_status_msg, peer->status));
1548 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
1549 return -1;
1550 }
1551
1552 /* Set initial values. */
1553 memset (&attr, 0, sizeof (struct attr));
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001554 memset (&extra, 0, sizeof (struct attr_extra));
paul718e3742002-12-13 20:15:29 +00001555 memset (&update, 0, sizeof (struct bgp_nlri));
1556 memset (&withdraw, 0, sizeof (struct bgp_nlri));
1557 memset (&mp_update, 0, sizeof (struct bgp_nlri));
1558 memset (&mp_withdraw, 0, sizeof (struct bgp_nlri));
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001559 attr.extra = &extra;
paul718e3742002-12-13 20:15:29 +00001560
1561 s = peer->ibuf;
1562 end = stream_pnt (s) + size;
1563
1564 /* RFC1771 6.3 If the Unfeasible Routes Length or Total Attribute
1565 Length is too large (i.e., if Unfeasible Routes Length + Total
1566 Attribute Length + 23 exceeds the message Length), then the Error
1567 Subcode is set to Malformed Attribute List. */
1568 if (stream_pnt (s) + 2 > end)
1569 {
1570 zlog_err ("%s [Error] Update packet error"
1571 " (packet length is short for unfeasible length)",
1572 peer->host);
1573 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1574 BGP_NOTIFY_UPDATE_MAL_ATTR);
1575 return -1;
1576 }
1577
1578 /* Unfeasible Route Length. */
1579 withdraw_len = stream_getw (s);
1580
1581 /* Unfeasible Route Length check. */
1582 if (stream_pnt (s) + withdraw_len > end)
1583 {
1584 zlog_err ("%s [Error] Update packet error"
1585 " (packet unfeasible length overflow %d)",
1586 peer->host, withdraw_len);
1587 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1588 BGP_NOTIFY_UPDATE_MAL_ATTR);
1589 return -1;
1590 }
1591
1592 /* Unfeasible Route packet format check. */
1593 if (withdraw_len > 0)
1594 {
1595 ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), withdraw_len);
1596 if (ret < 0)
1597 return -1;
1598
1599 if (BGP_DEBUG (packet, PACKET_RECV))
ajs6b514742004-12-08 21:03:23 +00001600 zlog_debug ("%s [Update:RECV] Unfeasible NLRI received", peer->host);
paul718e3742002-12-13 20:15:29 +00001601
1602 withdraw.afi = AFI_IP;
1603 withdraw.safi = SAFI_UNICAST;
1604 withdraw.nlri = stream_pnt (s);
1605 withdraw.length = withdraw_len;
paul9985f832005-02-09 15:51:56 +00001606 stream_forward_getp (s, withdraw_len);
paul718e3742002-12-13 20:15:29 +00001607 }
1608
1609 /* Attribute total length check. */
1610 if (stream_pnt (s) + 2 > end)
1611 {
1612 zlog_warn ("%s [Error] Packet Error"
1613 " (update packet is short for attribute length)",
1614 peer->host);
1615 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1616 BGP_NOTIFY_UPDATE_MAL_ATTR);
1617 return -1;
1618 }
1619
1620 /* Fetch attribute total length. */
1621 attribute_len = stream_getw (s);
1622
1623 /* Attribute length check. */
1624 if (stream_pnt (s) + attribute_len > end)
1625 {
1626 zlog_warn ("%s [Error] Packet Error"
1627 " (update packet attribute length overflow %d)",
1628 peer->host, attribute_len);
1629 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1630 BGP_NOTIFY_UPDATE_MAL_ATTR);
1631 return -1;
1632 }
Paul Jakmab881c702010-11-23 16:35:42 +00001633
1634 /* Certain attribute parsing errors should not be considered bad enough
1635 * to reset the session for, most particularly any partial/optional
1636 * attributes that have 'tunneled' over speakers that don't understand
1637 * them. Instead we withdraw only the prefix concerned.
1638 *
1639 * Complicates the flow a little though..
1640 */
1641 bgp_attr_parse_ret_t attr_parse_ret = BGP_ATTR_PARSE_PROCEED;
1642 /* This define morphs the update case into a withdraw when lower levels
1643 * have signalled an error condition where this is best.
1644 */
1645#define NLRI_ATTR_ARG (attr_parse_ret != BGP_ATTR_PARSE_WITHDRAW ? &attr : NULL)
paul718e3742002-12-13 20:15:29 +00001646
1647 /* Parse attribute when it exists. */
1648 if (attribute_len)
1649 {
Paul Jakmab881c702010-11-23 16:35:42 +00001650 attr_parse_ret = bgp_attr_parse (peer, &attr, attribute_len,
paul718e3742002-12-13 20:15:29 +00001651 &mp_update, &mp_withdraw);
Paul Jakmab881c702010-11-23 16:35:42 +00001652 if (attr_parse_ret == BGP_ATTR_PARSE_ERROR)
paul718e3742002-12-13 20:15:29 +00001653 return -1;
1654 }
Paul Jakmab881c702010-11-23 16:35:42 +00001655
paul718e3742002-12-13 20:15:29 +00001656 /* Logging the attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001657 if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW
1658 || BGP_DEBUG (update, UPDATE_IN))
paul718e3742002-12-13 20:15:29 +00001659 {
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +00001660 char attrstr[BUFSIZ];
1661 attrstr[0] = '\0';
1662
paule01f9cb2004-07-09 17:48:53 +00001663 ret= bgp_dump_attr (peer, &attr, attrstr, BUFSIZ);
Paul Jakmab881c702010-11-23 16:35:42 +00001664 int lvl = (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
1665 ? LOG_ERR : LOG_DEBUG;
1666
1667 if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
1668 zlog (peer->log, LOG_ERR,
1669 "%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.",
1670 peer->host);
paule01f9cb2004-07-09 17:48:53 +00001671
1672 if (ret)
Paul Jakmab881c702010-11-23 16:35:42 +00001673 zlog (peer->log, lvl, "%s rcvd UPDATE w/ attr: %s",
paule01f9cb2004-07-09 17:48:53 +00001674 peer->host, attrstr);
paul718e3742002-12-13 20:15:29 +00001675 }
Paul Jakmab881c702010-11-23 16:35:42 +00001676
paul718e3742002-12-13 20:15:29 +00001677 /* Network Layer Reachability Information. */
1678 update_len = end - stream_pnt (s);
1679
1680 if (update_len)
1681 {
1682 /* Check NLRI packet format and prefix length. */
1683 ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), update_len);
1684 if (ret < 0)
Paul Jakmab881c702010-11-23 16:35:42 +00001685 {
1686 bgp_attr_unintern_sub (&attr);
Paul Jakmab881c702010-11-23 16:35:42 +00001687 return -1;
1688 }
paul718e3742002-12-13 20:15:29 +00001689
1690 /* Set NLRI portion to structure. */
1691 update.afi = AFI_IP;
1692 update.safi = SAFI_UNICAST;
1693 update.nlri = stream_pnt (s);
1694 update.length = update_len;
paul9985f832005-02-09 15:51:56 +00001695 stream_forward_getp (s, update_len);
paul718e3742002-12-13 20:15:29 +00001696 }
1697
1698 /* NLRI is processed only when the peer is configured specific
1699 Address Family and Subsequent Address Family. */
1700 if (peer->afc[AFI_IP][SAFI_UNICAST])
1701 {
1702 if (withdraw.length)
1703 bgp_nlri_parse (peer, NULL, &withdraw);
1704
1705 if (update.length)
1706 {
1707 /* We check well-known attribute only for IPv4 unicast
1708 update. */
1709 ret = bgp_attr_check (peer, &attr);
1710 if (ret < 0)
Paul Jakmab881c702010-11-23 16:35:42 +00001711 {
1712 bgp_attr_unintern_sub (&attr);
Paul Jakmab881c702010-11-23 16:35:42 +00001713 return -1;
1714 }
paul718e3742002-12-13 20:15:29 +00001715
Paul Jakmab881c702010-11-23 16:35:42 +00001716 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &update);
paul718e3742002-12-13 20:15:29 +00001717 }
paule01f9cb2004-07-09 17:48:53 +00001718
hassof4184462005-02-01 20:13:16 +00001719 if (mp_update.length
1720 && mp_update.afi == AFI_IP
1721 && mp_update.safi == SAFI_UNICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001722 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
hassof4184462005-02-01 20:13:16 +00001723
1724 if (mp_withdraw.length
1725 && mp_withdraw.afi == AFI_IP
1726 && mp_withdraw.safi == SAFI_UNICAST)
1727 bgp_nlri_parse (peer, NULL, &mp_withdraw);
1728
paule01f9cb2004-07-09 17:48:53 +00001729 if (! attribute_len && ! withdraw_len)
1730 {
1731 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001732 SET_FLAG (peer->af_sflags[AFI_IP][SAFI_UNICAST],
1733 PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001734
hasso93406d82005-02-02 14:40:33 +00001735 /* NSF delete stale route */
1736 if (peer->nsf[AFI_IP][SAFI_UNICAST])
1737 bgp_clear_stale_route (peer, AFI_IP, SAFI_UNICAST);
1738
1739 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001740 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001741 peer->host);
1742 }
paul718e3742002-12-13 20:15:29 +00001743 }
1744 if (peer->afc[AFI_IP][SAFI_MULTICAST])
1745 {
1746 if (mp_update.length
1747 && mp_update.afi == AFI_IP
1748 && mp_update.safi == SAFI_MULTICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001749 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001750
1751 if (mp_withdraw.length
1752 && mp_withdraw.afi == AFI_IP
1753 && mp_withdraw.safi == SAFI_MULTICAST)
1754 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001755
hasso93406d82005-02-02 14:40:33 +00001756 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001757 && mp_withdraw.afi == AFI_IP
1758 && mp_withdraw.safi == SAFI_MULTICAST
1759 && mp_withdraw.length == 0)
1760 {
1761 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001762 SET_FLAG (peer->af_sflags[AFI_IP][SAFI_MULTICAST],
1763 PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001764
hasso93406d82005-02-02 14:40:33 +00001765 /* NSF delete stale route */
1766 if (peer->nsf[AFI_IP][SAFI_MULTICAST])
1767 bgp_clear_stale_route (peer, AFI_IP, SAFI_MULTICAST);
1768
1769 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001770 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Multicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001771 peer->host);
1772 }
paul718e3742002-12-13 20:15:29 +00001773 }
1774 if (peer->afc[AFI_IP6][SAFI_UNICAST])
1775 {
1776 if (mp_update.length
1777 && mp_update.afi == AFI_IP6
1778 && mp_update.safi == SAFI_UNICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001779 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001780
1781 if (mp_withdraw.length
1782 && mp_withdraw.afi == AFI_IP6
1783 && mp_withdraw.safi == SAFI_UNICAST)
1784 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001785
hasso93406d82005-02-02 14:40:33 +00001786 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001787 && mp_withdraw.afi == AFI_IP6
1788 && mp_withdraw.safi == SAFI_UNICAST
1789 && mp_withdraw.length == 0)
1790 {
1791 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001792 SET_FLAG (peer->af_sflags[AFI_IP6][SAFI_UNICAST], PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001793
hasso93406d82005-02-02 14:40:33 +00001794 /* NSF delete stale route */
1795 if (peer->nsf[AFI_IP6][SAFI_UNICAST])
1796 bgp_clear_stale_route (peer, AFI_IP6, SAFI_UNICAST);
1797
1798 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001799 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001800 peer->host);
1801 }
paul718e3742002-12-13 20:15:29 +00001802 }
1803 if (peer->afc[AFI_IP6][SAFI_MULTICAST])
1804 {
1805 if (mp_update.length
1806 && mp_update.afi == AFI_IP6
1807 && mp_update.safi == SAFI_MULTICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001808 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001809
1810 if (mp_withdraw.length
1811 && mp_withdraw.afi == AFI_IP6
1812 && mp_withdraw.safi == SAFI_MULTICAST)
1813 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001814
hasso93406d82005-02-02 14:40:33 +00001815 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001816 && mp_withdraw.afi == AFI_IP6
1817 && mp_withdraw.safi == SAFI_MULTICAST
1818 && mp_withdraw.length == 0)
1819 {
1820 /* End-of-RIB received */
1821
hasso93406d82005-02-02 14:40:33 +00001822 /* NSF delete stale route */
1823 if (peer->nsf[AFI_IP6][SAFI_MULTICAST])
1824 bgp_clear_stale_route (peer, AFI_IP6, SAFI_MULTICAST);
1825
paule01f9cb2004-07-09 17:48:53 +00001826 if (BGP_DEBUG (update, UPDATE_IN))
ajs6b514742004-12-08 21:03:23 +00001827 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Multicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001828 peer->host);
1829 }
paul718e3742002-12-13 20:15:29 +00001830 }
1831 if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
1832 {
1833 if (mp_update.length
1834 && mp_update.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001835 && mp_update.safi == SAFI_MPLS_LABELED_VPN)
Paul Jakmab881c702010-11-23 16:35:42 +00001836 bgp_nlri_parse_vpnv4 (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001837
1838 if (mp_withdraw.length
1839 && mp_withdraw.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001840 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00001841 bgp_nlri_parse_vpnv4 (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001842
hasso93406d82005-02-02 14:40:33 +00001843 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001844 && mp_withdraw.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001845 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN
paule01f9cb2004-07-09 17:48:53 +00001846 && mp_withdraw.length == 0)
1847 {
1848 /* End-of-RIB received */
1849
1850 if (BGP_DEBUG (update, UPDATE_IN))
ajs6b514742004-12-08 21:03:23 +00001851 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for VPNv4 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001852 peer->host);
1853 }
paul718e3742002-12-13 20:15:29 +00001854 }
1855
1856 /* Everything is done. We unintern temporary structures which
1857 interned in bgp_attr_parse(). */
Paul Jakmab881c702010-11-23 16:35:42 +00001858 bgp_attr_unintern_sub (&attr);
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001859
paul718e3742002-12-13 20:15:29 +00001860 /* If peering is stopped due to some reason, do not generate BGP
1861 event. */
1862 if (peer->status != Established)
1863 return 0;
1864
1865 /* Increment packet counter. */
1866 peer->update_in++;
Stephen Hemminger65957882010-01-15 16:22:10 +03001867 peer->update_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00001868
Jorge Boncompte [DTI2]e2c38e62012-06-20 17:45:50 +02001869 /* Rearm holdtime timer */
Jorge Boncompte [DTI2]6a4677b2012-05-07 16:53:07 +00001870 BGP_TIMER_OFF (peer->t_holdtime);
Jorge Boncompte [DTI2]e2c38e62012-06-20 17:45:50 +02001871 bgp_timer_set (peer);
paul718e3742002-12-13 20:15:29 +00001872
1873 return 0;
1874}
1875
1876/* Notify message treatment function. */
paul94f2b392005-06-28 12:44:16 +00001877static void
paul718e3742002-12-13 20:15:29 +00001878bgp_notify_receive (struct peer *peer, bgp_size_t size)
1879{
1880 struct bgp_notify bgp_notify;
1881
1882 if (peer->notify.data)
1883 {
1884 XFREE (MTYPE_TMP, peer->notify.data);
1885 peer->notify.data = NULL;
1886 peer->notify.length = 0;
1887 }
1888
1889 bgp_notify.code = stream_getc (peer->ibuf);
1890 bgp_notify.subcode = stream_getc (peer->ibuf);
1891 bgp_notify.length = size - 2;
1892 bgp_notify.data = NULL;
1893
1894 /* Preserv notify code and sub code. */
1895 peer->notify.code = bgp_notify.code;
1896 peer->notify.subcode = bgp_notify.subcode;
1897 /* For further diagnostic record returned Data. */
1898 if (bgp_notify.length)
1899 {
1900 peer->notify.length = size - 2;
1901 peer->notify.data = XMALLOC (MTYPE_TMP, size - 2);
1902 memcpy (peer->notify.data, stream_pnt (peer->ibuf), size - 2);
1903 }
1904
1905 /* For debug */
1906 {
1907 int i;
1908 int first = 0;
1909 char c[4];
1910
1911 if (bgp_notify.length)
1912 {
1913 bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
1914 for (i = 0; i < bgp_notify.length; i++)
1915 if (first)
1916 {
1917 sprintf (c, " %02x", stream_getc (peer->ibuf));
1918 strcat (bgp_notify.data, c);
1919 }
1920 else
1921 {
1922 first = 1;
1923 sprintf (c, "%02x", stream_getc (peer->ibuf));
1924 strcpy (bgp_notify.data, c);
1925 }
1926 }
1927
1928 bgp_notify_print(peer, &bgp_notify, "received");
1929 if (bgp_notify.data)
1930 XFREE (MTYPE_TMP, bgp_notify.data);
1931 }
1932
1933 /* peer count update */
1934 peer->notify_in++;
1935
hassoe0701b72004-05-20 09:19:34 +00001936 if (peer->status == Established)
1937 peer->last_reset = PEER_DOWN_NOTIFY_RECEIVED;
1938
paul718e3742002-12-13 20:15:29 +00001939 /* We have to check for Notify with Unsupported Optional Parameter.
1940 in that case we fallback to open without the capability option.
1941 But this done in bgp_stop. We just mark it here to avoid changing
1942 the fsm tables. */
1943 if (bgp_notify.code == BGP_NOTIFY_OPEN_ERR &&
1944 bgp_notify.subcode == BGP_NOTIFY_OPEN_UNSUP_PARAM )
1945 UNSET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
1946
paul718e3742002-12-13 20:15:29 +00001947 BGP_EVENT_ADD (peer, Receive_NOTIFICATION_message);
1948}
1949
1950/* Keepalive treatment function -- get keepalive send keepalive */
paul94f2b392005-06-28 12:44:16 +00001951static void
paul718e3742002-12-13 20:15:29 +00001952bgp_keepalive_receive (struct peer *peer, bgp_size_t size)
1953{
1954 if (BGP_DEBUG (keepalive, KEEPALIVE))
ajs6b514742004-12-08 21:03:23 +00001955 zlog_debug ("%s KEEPALIVE rcvd", peer->host);
paul718e3742002-12-13 20:15:29 +00001956
1957 BGP_EVENT_ADD (peer, Receive_KEEPALIVE_message);
1958}
1959
1960/* Route refresh message is received. */
paul94f2b392005-06-28 12:44:16 +00001961static void
paul718e3742002-12-13 20:15:29 +00001962bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
1963{
1964 afi_t afi;
1965 safi_t safi;
1966 u_char reserved;
1967 struct stream *s;
1968
1969 /* If peer does not have the capability, send notification. */
1970 if (! CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_ADV))
1971 {
1972 plog_err (peer->log, "%s [Error] BGP route refresh is not enabled",
1973 peer->host);
1974 bgp_notify_send (peer,
1975 BGP_NOTIFY_HEADER_ERR,
1976 BGP_NOTIFY_HEADER_BAD_MESTYPE);
1977 return;
1978 }
1979
1980 /* Status must be Established. */
1981 if (peer->status != Established)
1982 {
1983 plog_err (peer->log,
1984 "%s [Error] Route refresh packet received under status %s",
1985 peer->host, LOOKUP (bgp_status_msg, peer->status));
1986 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
1987 return;
1988 }
1989
1990 s = peer->ibuf;
1991
1992 /* Parse packet. */
1993 afi = stream_getw (s);
1994 reserved = stream_getc (s);
1995 safi = stream_getc (s);
1996
1997 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001998 zlog_debug ("%s rcvd REFRESH_REQ for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001999 peer->host, afi, safi);
2000
2001 /* Check AFI and SAFI. */
2002 if ((afi != AFI_IP && afi != AFI_IP6)
2003 || (safi != SAFI_UNICAST && safi != SAFI_MULTICAST
Denis Ovsienko42e6d742011-07-14 12:36:19 +04002004 && safi != SAFI_MPLS_LABELED_VPN))
paul718e3742002-12-13 20:15:29 +00002005 {
2006 if (BGP_DEBUG (normal, NORMAL))
2007 {
ajs6b514742004-12-08 21:03:23 +00002008 zlog_debug ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored",
paul718e3742002-12-13 20:15:29 +00002009 peer->host, afi, safi);
2010 }
2011 return;
2012 }
2013
2014 /* Adjust safi code. */
Denis Ovsienko42e6d742011-07-14 12:36:19 +04002015 if (safi == SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00002016 safi = SAFI_MPLS_VPN;
2017
2018 if (size != BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE)
2019 {
2020 u_char *end;
2021 u_char when_to_refresh;
2022 u_char orf_type;
2023 u_int16_t orf_len;
2024
2025 if (size - (BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE) < 5)
2026 {
2027 zlog_info ("%s ORF route refresh length error", peer->host);
2028 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2029 return;
2030 }
2031
2032 when_to_refresh = stream_getc (s);
2033 end = stream_pnt (s) + (size - 5);
2034
Paul Jakma370b64a2007-12-22 16:49:52 +00002035 while ((stream_pnt (s) + 2) < end)
paul718e3742002-12-13 20:15:29 +00002036 {
2037 orf_type = stream_getc (s);
2038 orf_len = stream_getw (s);
Paul Jakma370b64a2007-12-22 16:49:52 +00002039
2040 /* orf_len in bounds? */
2041 if ((stream_pnt (s) + orf_len) > end)
2042 break; /* XXX: Notify instead?? */
paul718e3742002-12-13 20:15:29 +00002043 if (orf_type == ORF_TYPE_PREFIX
2044 || orf_type == ORF_TYPE_PREFIX_OLD)
2045 {
2046 u_char *p_pnt = stream_pnt (s);
2047 u_char *p_end = stream_pnt (s) + orf_len;
2048 struct orf_prefix orfp;
2049 u_char common = 0;
2050 u_int32_t seq;
2051 int psize;
2052 char name[BUFSIZ];
paul718e3742002-12-13 20:15:29 +00002053 int ret;
2054
2055 if (BGP_DEBUG (normal, NORMAL))
2056 {
ajs6b514742004-12-08 21:03:23 +00002057 zlog_debug ("%s rcvd Prefixlist ORF(%d) length %d",
paul718e3742002-12-13 20:15:29 +00002058 peer->host, orf_type, orf_len);
2059 }
2060
Paul Jakma370b64a2007-12-22 16:49:52 +00002061 /* we're going to read at least 1 byte of common ORF header,
2062 * and 7 bytes of ORF Address-filter entry from the stream
2063 */
2064 if (orf_len < 7)
2065 break;
2066
paul718e3742002-12-13 20:15:29 +00002067 /* ORF prefix-list name */
2068 sprintf (name, "%s.%d.%d", peer->host, afi, safi);
2069
2070 while (p_pnt < p_end)
2071 {
Chris Halld64379e2010-05-14 16:38:39 +04002072 /* If the ORF entry is malformed, want to read as much of it
2073 * as possible without going beyond the bounds of the entry,
2074 * to maximise debug information.
2075 */
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002076 int ok;
paul718e3742002-12-13 20:15:29 +00002077 memset (&orfp, 0, sizeof (struct orf_prefix));
2078 common = *p_pnt++;
Chris Halld64379e2010-05-14 16:38:39 +04002079 /* after ++: p_pnt <= p_end */
paul718e3742002-12-13 20:15:29 +00002080 if (common & ORF_COMMON_PART_REMOVE_ALL)
2081 {
2082 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002083 zlog_debug ("%s rcvd Remove-All pfxlist ORF request", peer->host);
paul718e3742002-12-13 20:15:29 +00002084 prefix_bgp_orf_remove_all (name);
2085 break;
2086 }
Chris Halld64379e2010-05-14 16:38:39 +04002087 ok = ((p_end - p_pnt) >= sizeof(u_int32_t)) ;
Denis Ovsienkobb915f52011-12-13 21:11:39 +04002088 if (ok)
Chris Halld64379e2010-05-14 16:38:39 +04002089 {
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002090 memcpy (&seq, p_pnt, sizeof (u_int32_t));
2091 p_pnt += sizeof (u_int32_t);
2092 orfp.seq = ntohl (seq);
Chris Halld64379e2010-05-14 16:38:39 +04002093 }
2094 else
2095 p_pnt = p_end ;
2096
2097 if ((ok = (p_pnt < p_end)))
2098 orfp.ge = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */
2099 if ((ok = (p_pnt < p_end)))
2100 orfp.le = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */
2101 if ((ok = (p_pnt < p_end)))
2102 orfp.p.prefixlen = *p_pnt++ ;
2103 orfp.p.family = afi2family (afi); /* afi checked already */
2104
2105 psize = PSIZE (orfp.p.prefixlen); /* 0 if not ok */
2106 if (psize > prefix_blen(&orfp.p)) /* valid for family ? */
2107 {
2108 ok = 0 ;
2109 psize = prefix_blen(&orfp.p) ;
2110 }
2111 if (psize > (p_end - p_pnt)) /* valid for packet ? */
2112 {
2113 ok = 0 ;
2114 psize = p_end - p_pnt ;
2115 }
2116
2117 if (psize > 0)
2118 memcpy (&orfp.p.u.prefix, p_pnt, psize);
paul718e3742002-12-13 20:15:29 +00002119 p_pnt += psize;
2120
2121 if (BGP_DEBUG (normal, NORMAL))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +00002122 {
2123 char buf[INET6_BUFSIZ];
2124
2125 zlog_debug ("%s rcvd %s %s seq %u %s/%d ge %d le %d%s",
2126 peer->host,
2127 (common & ORF_COMMON_PART_REMOVE ? "Remove" : "Add"),
2128 (common & ORF_COMMON_PART_DENY ? "deny" : "permit"),
2129 orfp.seq,
2130 inet_ntop (orfp.p.family, &orfp.p.u.prefix, buf, INET6_BUFSIZ),
2131 orfp.p.prefixlen, orfp.ge, orfp.le,
2132 ok ? "" : " MALFORMED");
2133 }
2134
Chris Halld64379e2010-05-14 16:38:39 +04002135 if (ok)
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002136 ret = prefix_bgp_orf_set (name, afi, &orfp,
2137 (common & ORF_COMMON_PART_DENY ? 0 : 1 ),
2138 (common & ORF_COMMON_PART_REMOVE ? 0 : 1));
paul718e3742002-12-13 20:15:29 +00002139
Chris Halld64379e2010-05-14 16:38:39 +04002140 if (!ok || (ret != CMD_SUCCESS))
paul718e3742002-12-13 20:15:29 +00002141 {
2142 if (BGP_DEBUG (normal, NORMAL))
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002143 zlog_debug ("%s Received misformatted prefixlist ORF."
2144 " Remove All pfxlist", peer->host);
paul718e3742002-12-13 20:15:29 +00002145 prefix_bgp_orf_remove_all (name);
2146 break;
2147 }
2148 }
2149 peer->orf_plist[afi][safi] =
2150 prefix_list_lookup (AFI_ORF_PREFIX, name);
2151 }
paul9985f832005-02-09 15:51:56 +00002152 stream_forward_getp (s, orf_len);
paul718e3742002-12-13 20:15:29 +00002153 }
2154 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002155 zlog_debug ("%s rcvd Refresh %s ORF request", peer->host,
paul718e3742002-12-13 20:15:29 +00002156 when_to_refresh == REFRESH_DEFER ? "Defer" : "Immediate");
2157 if (when_to_refresh == REFRESH_DEFER)
2158 return;
2159 }
2160
2161 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2162 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH))
2163 UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
2164
2165 /* Perform route refreshment to the peer */
2166 bgp_announce_route (peer, afi, safi);
2167}
2168
paul94f2b392005-06-28 12:44:16 +00002169static int
paul718e3742002-12-13 20:15:29 +00002170bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
2171{
2172 u_char *end;
Paul Jakma6d582722007-08-06 15:21:45 +00002173 struct capability_mp_data mpc;
2174 struct capability_header *hdr;
paul718e3742002-12-13 20:15:29 +00002175 u_char action;
2176 struct bgp *bgp;
2177 afi_t afi;
2178 safi_t safi;
2179
2180 bgp = peer->bgp;
2181 end = pnt + length;
2182
2183 while (pnt < end)
Paul Jakma6d582722007-08-06 15:21:45 +00002184 {
paul718e3742002-12-13 20:15:29 +00002185 /* We need at least action, capability code and capability length. */
2186 if (pnt + 3 > end)
2187 {
2188 zlog_info ("%s Capability length error", peer->host);
2189 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2190 return -1;
2191 }
paul718e3742002-12-13 20:15:29 +00002192 action = *pnt;
Paul Jakma6d582722007-08-06 15:21:45 +00002193 hdr = (struct capability_header *)(pnt + 1);
2194
paul718e3742002-12-13 20:15:29 +00002195 /* Action value check. */
2196 if (action != CAPABILITY_ACTION_SET
2197 && action != CAPABILITY_ACTION_UNSET)
2198 {
2199 zlog_info ("%s Capability Action Value error %d",
2200 peer->host, action);
2201 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2202 return -1;
2203 }
2204
2205 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002206 zlog_debug ("%s CAPABILITY has action: %d, code: %u, length %u",
Paul Jakma6d582722007-08-06 15:21:45 +00002207 peer->host, action, hdr->code, hdr->length);
paul718e3742002-12-13 20:15:29 +00002208
2209 /* Capability length check. */
Paul Jakma6d582722007-08-06 15:21:45 +00002210 if ((pnt + hdr->length + 3) > end)
paul718e3742002-12-13 20:15:29 +00002211 {
2212 zlog_info ("%s Capability length error", peer->host);
2213 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2214 return -1;
2215 }
2216
Paul Jakma6d582722007-08-06 15:21:45 +00002217 /* Fetch structure to the byte stream. */
2218 memcpy (&mpc, pnt + 3, sizeof (struct capability_mp_data));
2219
paul718e3742002-12-13 20:15:29 +00002220 /* We know MP Capability Code. */
Paul Jakma6d582722007-08-06 15:21:45 +00002221 if (hdr->code == CAPABILITY_CODE_MP)
paul718e3742002-12-13 20:15:29 +00002222 {
Paul Jakma6d582722007-08-06 15:21:45 +00002223 afi = ntohs (mpc.afi);
2224 safi = mpc.safi;
paul718e3742002-12-13 20:15:29 +00002225
2226 /* Ignore capability when override-capability is set. */
2227 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
2228 continue;
Paul Jakma6d582722007-08-06 15:21:45 +00002229
2230 if (!bgp_afi_safi_valid_indices (afi, &safi))
2231 {
2232 if (BGP_DEBUG (normal, NORMAL))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002233 zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid "
2234 "(%u/%u)", peer->host, afi, safi);
Paul Jakma6d582722007-08-06 15:21:45 +00002235 continue;
2236 }
2237
paul718e3742002-12-13 20:15:29 +00002238 /* Address family check. */
Paul Jakma6d582722007-08-06 15:21:45 +00002239 if (BGP_DEBUG (normal, NORMAL))
2240 zlog_debug ("%s CAPABILITY has %s MP_EXT CAP for afi/safi: %u/%u",
2241 peer->host,
2242 action == CAPABILITY_ACTION_SET
2243 ? "Advertising" : "Removing",
2244 ntohs(mpc.afi) , mpc.safi);
2245
2246 if (action == CAPABILITY_ACTION_SET)
2247 {
2248 peer->afc_recv[afi][safi] = 1;
2249 if (peer->afc[afi][safi])
2250 {
2251 peer->afc_nego[afi][safi] = 1;
2252 bgp_announce_route (peer, afi, safi);
2253 }
2254 }
2255 else
2256 {
2257 peer->afc_recv[afi][safi] = 0;
2258 peer->afc_nego[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00002259
Paul Jakma6d582722007-08-06 15:21:45 +00002260 if (peer_active_nego (peer))
Chris Caputo228da422009-07-18 05:44:03 +00002261 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
Paul Jakma6d582722007-08-06 15:21:45 +00002262 else
2263 BGP_EVENT_ADD (peer, BGP_Stop);
2264 }
paul718e3742002-12-13 20:15:29 +00002265 }
paul718e3742002-12-13 20:15:29 +00002266 else
2267 {
2268 zlog_warn ("%s unrecognized capability code: %d - ignored",
Paul Jakma6d582722007-08-06 15:21:45 +00002269 peer->host, hdr->code);
paul718e3742002-12-13 20:15:29 +00002270 }
Paul Jakma6d582722007-08-06 15:21:45 +00002271 pnt += hdr->length + 3;
paul718e3742002-12-13 20:15:29 +00002272 }
2273 return 0;
2274}
2275
Paul Jakma01b7ce22009-06-18 12:34:43 +01002276/* Dynamic Capability is received.
2277 *
2278 * This is exported for unit-test purposes
2279 */
Paul Jakma6d582722007-08-06 15:21:45 +00002280int
paul718e3742002-12-13 20:15:29 +00002281bgp_capability_receive (struct peer *peer, bgp_size_t size)
2282{
2283 u_char *pnt;
paul718e3742002-12-13 20:15:29 +00002284
2285 /* Fetch pointer. */
2286 pnt = stream_pnt (peer->ibuf);
2287
2288 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002289 zlog_debug ("%s rcv CAPABILITY", peer->host);
paul718e3742002-12-13 20:15:29 +00002290
2291 /* If peer does not have the capability, send notification. */
2292 if (! CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV))
2293 {
2294 plog_err (peer->log, "%s [Error] BGP dynamic capability is not enabled",
2295 peer->host);
2296 bgp_notify_send (peer,
2297 BGP_NOTIFY_HEADER_ERR,
2298 BGP_NOTIFY_HEADER_BAD_MESTYPE);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002299 return -1;
paul718e3742002-12-13 20:15:29 +00002300 }
2301
2302 /* Status must be Established. */
2303 if (peer->status != Established)
2304 {
2305 plog_err (peer->log,
2306 "%s [Error] Dynamic capability packet received under status %s", peer->host, LOOKUP (bgp_status_msg, peer->status));
2307 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002308 return -1;
paul718e3742002-12-13 20:15:29 +00002309 }
2310
2311 /* Parse packet. */
Paul Jakma6d582722007-08-06 15:21:45 +00002312 return bgp_capability_msg_parse (peer, pnt, size);
paul718e3742002-12-13 20:15:29 +00002313}
2314
2315/* BGP read utility function. */
paul94f2b392005-06-28 12:44:16 +00002316static int
paul718e3742002-12-13 20:15:29 +00002317bgp_read_packet (struct peer *peer)
2318{
2319 int nbytes;
2320 int readsize;
2321
paul9985f832005-02-09 15:51:56 +00002322 readsize = peer->packet_size - stream_get_endp (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00002323
2324 /* If size is zero then return. */
2325 if (! readsize)
2326 return 0;
2327
2328 /* Read packet from fd. */
Stephen Hemminger35398582010-08-05 10:26:23 -07002329 nbytes = stream_read_try (peer->ibuf, peer->fd, readsize);
paul718e3742002-12-13 20:15:29 +00002330
2331 /* If read byte is smaller than zero then error occured. */
2332 if (nbytes < 0)
2333 {
Stephen Hemminger35398582010-08-05 10:26:23 -07002334 /* Transient error should retry */
2335 if (nbytes == -2)
paul718e3742002-12-13 20:15:29 +00002336 return -1;
2337
2338 plog_err (peer->log, "%s [Error] bgp_read_packet error: %s",
ajs6099b3b2004-11-20 02:06:59 +00002339 peer->host, safe_strerror (errno));
hasso93406d82005-02-02 14:40:33 +00002340
2341 if (peer->status == Established)
2342 {
2343 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
2344 {
2345 peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
2346 SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
2347 }
2348 else
2349 peer->last_reset = PEER_DOWN_CLOSE_SESSION;
2350 }
2351
paul718e3742002-12-13 20:15:29 +00002352 BGP_EVENT_ADD (peer, TCP_fatal_error);
2353 return -1;
2354 }
2355
2356 /* When read byte is zero : clear bgp peer and return */
2357 if (nbytes == 0)
2358 {
2359 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +00002360 plog_debug (peer->log, "%s [Event] BGP connection closed fd %d",
pauleb821182004-05-01 08:44:08 +00002361 peer->host, peer->fd);
hassoe0701b72004-05-20 09:19:34 +00002362
2363 if (peer->status == Established)
hasso93406d82005-02-02 14:40:33 +00002364 {
2365 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
2366 {
2367 peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
2368 SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
2369 }
2370 else
2371 peer->last_reset = PEER_DOWN_CLOSE_SESSION;
2372 }
hassoe0701b72004-05-20 09:19:34 +00002373
paul718e3742002-12-13 20:15:29 +00002374 BGP_EVENT_ADD (peer, TCP_connection_closed);
2375 return -1;
2376 }
2377
2378 /* We read partial packet. */
paul9985f832005-02-09 15:51:56 +00002379 if (stream_get_endp (peer->ibuf) != peer->packet_size)
paul718e3742002-12-13 20:15:29 +00002380 return -1;
2381
2382 return 0;
2383}
2384
2385/* Marker check. */
paul94f2b392005-06-28 12:44:16 +00002386static int
paul718e3742002-12-13 20:15:29 +00002387bgp_marker_all_one (struct stream *s, int length)
2388{
2389 int i;
2390
2391 for (i = 0; i < length; i++)
2392 if (s->data[i] != 0xff)
2393 return 0;
2394
2395 return 1;
2396}
2397
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002398/* Recent thread time.
2399 On same clock base as bgp_clock (MONOTONIC)
2400 but can be time of last context switch to bgp_read thread. */
2401static time_t
2402bgp_recent_clock (void)
2403{
2404 return recent_relative_time().tv_sec;
2405}
2406
paul718e3742002-12-13 20:15:29 +00002407/* Starting point of packet process function. */
2408int
2409bgp_read (struct thread *thread)
2410{
2411 int ret;
2412 u_char type = 0;
2413 struct peer *peer;
2414 bgp_size_t size;
2415 char notify_data_length[2];
2416
2417 /* Yes first of all get peer pointer. */
2418 peer = THREAD_ARG (thread);
2419 peer->t_read = NULL;
2420
2421 /* For non-blocking IO check. */
2422 if (peer->status == Connect)
2423 {
2424 bgp_connect_check (peer);
2425 goto done;
2426 }
2427 else
2428 {
pauleb821182004-05-01 08:44:08 +00002429 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +00002430 {
pauleb821182004-05-01 08:44:08 +00002431 zlog_err ("bgp_read peer's fd is negative value %d", peer->fd);
paul718e3742002-12-13 20:15:29 +00002432 return -1;
2433 }
pauleb821182004-05-01 08:44:08 +00002434 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
paul718e3742002-12-13 20:15:29 +00002435 }
2436
2437 /* Read packet header to determine type of the packet */
2438 if (peer->packet_size == 0)
2439 peer->packet_size = BGP_HEADER_SIZE;
2440
paul9985f832005-02-09 15:51:56 +00002441 if (stream_get_endp (peer->ibuf) < BGP_HEADER_SIZE)
paul718e3742002-12-13 20:15:29 +00002442 {
2443 ret = bgp_read_packet (peer);
2444
2445 /* Header read error or partial read packet. */
2446 if (ret < 0)
2447 goto done;
2448
2449 /* Get size and type. */
paul9985f832005-02-09 15:51:56 +00002450 stream_forward_getp (peer->ibuf, BGP_MARKER_SIZE);
paul718e3742002-12-13 20:15:29 +00002451 memcpy (notify_data_length, stream_pnt (peer->ibuf), 2);
2452 size = stream_getw (peer->ibuf);
2453 type = stream_getc (peer->ibuf);
2454
2455 if (BGP_DEBUG (normal, NORMAL) && type != 2 && type != 0)
ajs6b514742004-12-08 21:03:23 +00002456 zlog_debug ("%s rcv message type %d, length (excl. header) %d",
paul718e3742002-12-13 20:15:29 +00002457 peer->host, type, size - BGP_HEADER_SIZE);
2458
2459 /* Marker check */
paulf5ba3872004-07-09 12:11:31 +00002460 if (((type == BGP_MSG_OPEN) || (type == BGP_MSG_KEEPALIVE))
paul718e3742002-12-13 20:15:29 +00002461 && ! bgp_marker_all_one (peer->ibuf, BGP_MARKER_SIZE))
2462 {
2463 bgp_notify_send (peer,
2464 BGP_NOTIFY_HEADER_ERR,
2465 BGP_NOTIFY_HEADER_NOT_SYNC);
2466 goto done;
2467 }
2468
2469 /* BGP type check. */
2470 if (type != BGP_MSG_OPEN && type != BGP_MSG_UPDATE
2471 && type != BGP_MSG_NOTIFY && type != BGP_MSG_KEEPALIVE
2472 && type != BGP_MSG_ROUTE_REFRESH_NEW
2473 && type != BGP_MSG_ROUTE_REFRESH_OLD
2474 && type != BGP_MSG_CAPABILITY)
2475 {
2476 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002477 plog_debug (peer->log,
paul718e3742002-12-13 20:15:29 +00002478 "%s unknown message type 0x%02x",
2479 peer->host, type);
2480 bgp_notify_send_with_data (peer,
2481 BGP_NOTIFY_HEADER_ERR,
2482 BGP_NOTIFY_HEADER_BAD_MESTYPE,
2483 &type, 1);
2484 goto done;
2485 }
2486 /* Mimimum packet length check. */
2487 if ((size < BGP_HEADER_SIZE)
2488 || (size > BGP_MAX_PACKET_SIZE)
2489 || (type == BGP_MSG_OPEN && size < BGP_MSG_OPEN_MIN_SIZE)
2490 || (type == BGP_MSG_UPDATE && size < BGP_MSG_UPDATE_MIN_SIZE)
2491 || (type == BGP_MSG_NOTIFY && size < BGP_MSG_NOTIFY_MIN_SIZE)
2492 || (type == BGP_MSG_KEEPALIVE && size != BGP_MSG_KEEPALIVE_MIN_SIZE)
2493 || (type == BGP_MSG_ROUTE_REFRESH_NEW && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
2494 || (type == BGP_MSG_ROUTE_REFRESH_OLD && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
2495 || (type == BGP_MSG_CAPABILITY && size < BGP_MSG_CAPABILITY_MIN_SIZE))
2496 {
2497 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002498 plog_debug (peer->log,
paul718e3742002-12-13 20:15:29 +00002499 "%s bad message length - %d for %s",
2500 peer->host, size,
2501 type == 128 ? "ROUTE-REFRESH" :
2502 bgp_type_str[(int) type]);
2503 bgp_notify_send_with_data (peer,
2504 BGP_NOTIFY_HEADER_ERR,
2505 BGP_NOTIFY_HEADER_BAD_MESLEN,
hassoc9e52be2004-09-26 16:09:34 +00002506 (u_char *) notify_data_length, 2);
paul718e3742002-12-13 20:15:29 +00002507 goto done;
2508 }
2509
2510 /* Adjust size to message length. */
2511 peer->packet_size = size;
2512 }
2513
2514 ret = bgp_read_packet (peer);
2515 if (ret < 0)
2516 goto done;
2517
2518 /* Get size and type again. */
2519 size = stream_getw_from (peer->ibuf, BGP_MARKER_SIZE);
2520 type = stream_getc_from (peer->ibuf, BGP_MARKER_SIZE + 2);
2521
2522 /* BGP packet dump function. */
2523 bgp_dump_packet (peer, type, peer->ibuf);
2524
2525 size = (peer->packet_size - BGP_HEADER_SIZE);
2526
2527 /* Read rest of the packet and call each sort of packet routine */
2528 switch (type)
2529 {
2530 case BGP_MSG_OPEN:
2531 peer->open_in++;
paulf5ba3872004-07-09 12:11:31 +00002532 bgp_open_receive (peer, size); /* XXX return value ignored! */
paul718e3742002-12-13 20:15:29 +00002533 break;
2534 case BGP_MSG_UPDATE:
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002535 peer->readtime = bgp_recent_clock ();
paul718e3742002-12-13 20:15:29 +00002536 bgp_update_receive (peer, size);
2537 break;
2538 case BGP_MSG_NOTIFY:
2539 bgp_notify_receive (peer, size);
2540 break;
2541 case BGP_MSG_KEEPALIVE:
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002542 peer->readtime = bgp_recent_clock ();
paul718e3742002-12-13 20:15:29 +00002543 bgp_keepalive_receive (peer, size);
2544 break;
2545 case BGP_MSG_ROUTE_REFRESH_NEW:
2546 case BGP_MSG_ROUTE_REFRESH_OLD:
2547 peer->refresh_in++;
2548 bgp_route_refresh_receive (peer, size);
2549 break;
2550 case BGP_MSG_CAPABILITY:
2551 peer->dynamic_cap_in++;
2552 bgp_capability_receive (peer, size);
2553 break;
2554 }
2555
2556 /* Clear input buffer. */
2557 peer->packet_size = 0;
2558 if (peer->ibuf)
2559 stream_reset (peer->ibuf);
2560
2561 done:
2562 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2563 {
2564 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +00002565 zlog_debug ("%s [Event] Accepting BGP peer delete", peer->host);
paul718e3742002-12-13 20:15:29 +00002566 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00002567 }
2568 return 0;
2569}