blob: d115353f8ba8ef822ca747374c634e41328aa0c8 [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
Stephen Hemminger35398582010-08-05 10:26:23 -0700722 /* Put socket in blocking mode. */
723 val = fcntl (peer->fd, F_GETFL, 0);
724 fcntl (peer->fd, F_SETFL, val & ~O_NONBLOCK);
725
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000726 /* Stop collecting data within the socket */
727 sockopt_cork (peer->fd, 0);
728
729 ret = write (peer->fd, STREAM_DATA (s), stream_get_endp (s));
paul718e3742002-12-13 20:15:29 +0000730 if (ret <= 0)
731 {
Paul Jakmadcdf3992006-10-15 23:39:59 +0000732 BGP_EVENT_ADD (peer, TCP_fatal_error);
paul718e3742002-12-13 20:15:29 +0000733 return 0;
734 }
735
Leonid Rosenboim86998bc2012-12-14 19:12:17 +0000736 /* Disable Nagle, make NOTIFY packet go out right away */
737 val = 1;
738 (void) setsockopt (peer->fd, IPPROTO_TCP, TCP_NODELAY,
739 (char *) &val, sizeof (val));
740
paul718e3742002-12-13 20:15:29 +0000741 /* Retrieve BGP packet type. */
742 stream_set_getp (s, BGP_MARKER_SIZE + 2);
743 type = stream_getc (s);
744
745 assert (type == BGP_MSG_NOTIFY);
746
747 /* Type should be notify. */
748 peer->notify_out++;
749
750 /* Double start timer. */
751 peer->v_start *= 2;
752
753 /* Overflow check. */
754 if (peer->v_start >= (60 * 2))
755 peer->v_start = (60 * 2);
756
Paul Jakmadcdf3992006-10-15 23:39:59 +0000757 BGP_EVENT_ADD (peer, BGP_Stop);
paul718e3742002-12-13 20:15:29 +0000758
759 return 0;
760}
761
762/* Make keepalive packet and send it to the peer. */
763void
764bgp_keepalive_send (struct peer *peer)
765{
766 struct stream *s;
767 int length;
768
769 s = stream_new (BGP_MAX_PACKET_SIZE);
770
771 /* Make keepalive packet. */
772 bgp_packet_set_marker (s, BGP_MSG_KEEPALIVE);
773
774 /* Set packet size. */
775 length = bgp_packet_set_size (s);
776
777 /* Dump packet if debug option is set. */
778 /* bgp_packet_dump (s); */
779
780 if (BGP_DEBUG (keepalive, KEEPALIVE))
ajs6b514742004-12-08 21:03:23 +0000781 zlog_debug ("%s sending KEEPALIVE", peer->host);
paul718e3742002-12-13 20:15:29 +0000782 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000783 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000784 peer->host, BGP_MSG_KEEPALIVE, length);
785
786 /* Add packet to the peer. */
787 bgp_packet_add (peer, s);
788
pauleb821182004-05-01 08:44:08 +0000789 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000790}
791
792/* Make open packet and send it to the peer. */
793void
794bgp_open_send (struct peer *peer)
795{
796 struct stream *s;
797 int length;
798 u_int16_t send_holdtime;
799 as_t local_as;
800
801 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
802 send_holdtime = peer->holdtime;
803 else
804 send_holdtime = peer->bgp->default_holdtime;
805
806 /* local-as Change */
807 if (peer->change_local_as)
808 local_as = peer->change_local_as;
809 else
810 local_as = peer->local_as;
811
812 s = stream_new (BGP_MAX_PACKET_SIZE);
813
814 /* Make open packet. */
815 bgp_packet_set_marker (s, BGP_MSG_OPEN);
816
817 /* Set open packet values. */
818 stream_putc (s, BGP_VERSION_4); /* BGP version */
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000819 stream_putw (s, (local_as <= BGP_AS_MAX) ? (u_int16_t) local_as
820 : BGP_AS_TRANS);
paul718e3742002-12-13 20:15:29 +0000821 stream_putw (s, send_holdtime); /* Hold Time */
822 stream_put_in_addr (s, &peer->local_id); /* BGP Identifier */
823
824 /* Set capability code. */
825 bgp_open_capability (s, peer);
826
827 /* Set BGP packet length. */
828 length = bgp_packet_set_size (s);
829
830 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +0400831 zlog_debug ("%s sending OPEN, version %d, my as %u, holdtime %d, id %s",
paul718e3742002-12-13 20:15:29 +0000832 peer->host, BGP_VERSION_4, local_as,
833 send_holdtime, inet_ntoa (peer->local_id));
834
835 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000836 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000837 peer->host, BGP_MSG_OPEN, length);
838
839 /* Dump packet if debug option is set. */
840 /* bgp_packet_dump (s); */
841
842 /* Add packet to the peer. */
843 bgp_packet_add (peer, s);
844
pauleb821182004-05-01 08:44:08 +0000845 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000846}
847
848/* Send BGP notify packet with data potion. */
849void
850bgp_notify_send_with_data (struct peer *peer, u_char code, u_char sub_code,
851 u_char *data, size_t datalen)
852{
853 struct stream *s;
854 int length;
855
856 /* Allocate new stream. */
857 s = stream_new (BGP_MAX_PACKET_SIZE);
858
859 /* Make nitify packet. */
860 bgp_packet_set_marker (s, BGP_MSG_NOTIFY);
861
862 /* Set notify packet values. */
863 stream_putc (s, code); /* BGP notify code */
864 stream_putc (s, sub_code); /* BGP notify sub_code */
865
866 /* If notify data is present. */
867 if (data)
868 stream_write (s, data, datalen);
869
870 /* Set BGP packet length. */
871 length = bgp_packet_set_size (s);
872
873 /* Add packet to the peer. */
874 stream_fifo_clean (peer->obuf);
875 bgp_packet_add (peer, s);
876
877 /* For debug */
878 {
879 struct bgp_notify bgp_notify;
880 int first = 0;
881 int i;
882 char c[4];
883
884 bgp_notify.code = code;
885 bgp_notify.subcode = sub_code;
886 bgp_notify.data = NULL;
887 bgp_notify.length = length - BGP_MSG_NOTIFY_MIN_SIZE;
888
889 if (bgp_notify.length)
890 {
891 bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
892 for (i = 0; i < bgp_notify.length; i++)
893 if (first)
894 {
895 sprintf (c, " %02x", data[i]);
896 strcat (bgp_notify.data, c);
897 }
898 else
899 {
900 first = 1;
901 sprintf (c, "%02x", data[i]);
902 strcpy (bgp_notify.data, c);
903 }
904 }
905 bgp_notify_print (peer, &bgp_notify, "sending");
906 if (bgp_notify.data)
907 XFREE (MTYPE_TMP, bgp_notify.data);
908 }
909
910 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000911 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000912 peer->host, BGP_MSG_NOTIFY, length);
913
hassoe0701b72004-05-20 09:19:34 +0000914 /* peer reset cause */
915 if (sub_code != BGP_NOTIFY_CEASE_CONFIG_CHANGE)
916 {
917 if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET)
heasley1212dc12011-09-12 13:27:52 +0400918 {
919 peer->last_reset = PEER_DOWN_USER_RESET;
920 zlog_info ("Notification sent to neighbor %s: User reset", peer->host);
921 }
hassoe0701b72004-05-20 09:19:34 +0000922 else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN)
heasley1212dc12011-09-12 13:27:52 +0400923 {
924 peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
925 zlog_info ("Notification sent to neighbor %s: shutdown", peer->host);
926 }
hassoe0701b72004-05-20 09:19:34 +0000927 else
heasley1212dc12011-09-12 13:27:52 +0400928 {
929 peer->last_reset = PEER_DOWN_NOTIFY_SEND;
930 zlog_info ("Notification sent to neighbor %s: type %u/%u",
931 peer->host, code, sub_code);
932 }
hassoe0701b72004-05-20 09:19:34 +0000933 }
heasley1212dc12011-09-12 13:27:52 +0400934 else
935 zlog_info ("Notification sent to neighbor %s: configuration change",
936 peer->host);
hassoe0701b72004-05-20 09:19:34 +0000937
Denis Ovsienko7ccf5e52011-09-10 16:53:30 +0400938 /* Call immediately. */
paul718e3742002-12-13 20:15:29 +0000939 BGP_WRITE_OFF (peer->t_write);
940
941 bgp_write_notify (peer);
942}
943
944/* Send BGP notify packet. */
945void
946bgp_notify_send (struct peer *peer, u_char code, u_char sub_code)
947{
948 bgp_notify_send_with_data (peer, code, sub_code, NULL, 0);
949}
950
paul718e3742002-12-13 20:15:29 +0000951/* Send route refresh message to the peer. */
952void
953bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
954 u_char orf_type, u_char when_to_refresh, int remove)
955{
956 struct stream *s;
957 struct stream *packet;
958 int length;
959 struct bgp_filter *filter;
960 int orf_refresh = 0;
961
Paul Jakma750e8142008-07-22 21:11:48 +0000962 if (DISABLE_BGP_ANNOUNCE)
963 return;
paul718e3742002-12-13 20:15:29 +0000964
965 filter = &peer->filter[afi][safi];
966
967 /* Adjust safi code. */
968 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +0400969 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +0000970
971 s = stream_new (BGP_MAX_PACKET_SIZE);
972
973 /* Make BGP update packet. */
974 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
975 bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_NEW);
976 else
977 bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_OLD);
978
979 /* Encode Route Refresh message. */
980 stream_putw (s, afi);
981 stream_putc (s, 0);
982 stream_putc (s, safi);
983
984 if (orf_type == ORF_TYPE_PREFIX
985 || orf_type == ORF_TYPE_PREFIX_OLD)
986 if (remove || filter->plist[FILTER_IN].plist)
987 {
988 u_int16_t orf_len;
989 unsigned long orfp;
990
991 orf_refresh = 1;
992 stream_putc (s, when_to_refresh);
993 stream_putc (s, orf_type);
paul9985f832005-02-09 15:51:56 +0000994 orfp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000995 stream_putw (s, 0);
996
997 if (remove)
998 {
999 UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
1000 stream_putc (s, ORF_COMMON_PART_REMOVE_ALL);
1001 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001002 zlog_debug ("%s sending REFRESH_REQ to remove ORF(%d) (%s) for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001003 peer->host, orf_type,
1004 (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
1005 afi, safi);
1006 }
1007 else
1008 {
1009 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
1010 prefix_bgp_orf_entry (s, filter->plist[FILTER_IN].plist,
1011 ORF_COMMON_PART_ADD, ORF_COMMON_PART_PERMIT,
1012 ORF_COMMON_PART_DENY);
1013 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001014 zlog_debug ("%s sending REFRESH_REQ with pfxlist ORF(%d) (%s) for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001015 peer->host, orf_type,
1016 (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
1017 afi, safi);
1018 }
1019
1020 /* Total ORF Entry Len. */
paul9985f832005-02-09 15:51:56 +00001021 orf_len = stream_get_endp (s) - orfp - 2;
paul718e3742002-12-13 20:15:29 +00001022 stream_putw_at (s, orfp, orf_len);
1023 }
1024
1025 /* Set packet size. */
1026 length = bgp_packet_set_size (s);
1027
1028 if (BGP_DEBUG (normal, NORMAL))
1029 {
1030 if (! orf_refresh)
ajs6b514742004-12-08 21:03:23 +00001031 zlog_debug ("%s sending REFRESH_REQ for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001032 peer->host, afi, safi);
ajs6b514742004-12-08 21:03:23 +00001033 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +00001034 peer->host, CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV) ?
1035 BGP_MSG_ROUTE_REFRESH_NEW : BGP_MSG_ROUTE_REFRESH_OLD, length);
1036 }
1037
1038 /* Make real packet. */
paule83e2082005-05-19 02:12:25 +00001039 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +00001040 stream_free (s);
1041
1042 /* Add packet to the peer. */
1043 bgp_packet_add (peer, packet);
1044
pauleb821182004-05-01 08:44:08 +00001045 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +00001046}
1047
1048/* Send capability message to the peer. */
1049void
1050bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi,
1051 int capability_code, int action)
1052{
1053 struct stream *s;
1054 struct stream *packet;
1055 int length;
1056
1057 /* Adjust safi code. */
1058 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001059 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +00001060
1061 s = stream_new (BGP_MAX_PACKET_SIZE);
1062
1063 /* Make BGP update packet. */
1064 bgp_packet_set_marker (s, BGP_MSG_CAPABILITY);
1065
1066 /* Encode MP_EXT capability. */
1067 if (capability_code == CAPABILITY_CODE_MP)
1068 {
1069 stream_putc (s, action);
1070 stream_putc (s, CAPABILITY_CODE_MP);
1071 stream_putc (s, CAPABILITY_CODE_MP_LEN);
1072 stream_putw (s, afi);
1073 stream_putc (s, 0);
1074 stream_putc (s, safi);
1075
1076 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001077 zlog_debug ("%s sending CAPABILITY has %s MP_EXT CAP for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001078 peer->host, action == CAPABILITY_ACTION_SET ?
1079 "Advertising" : "Removing", afi, safi);
1080 }
1081
paul718e3742002-12-13 20:15:29 +00001082 /* Set packet size. */
1083 length = bgp_packet_set_size (s);
1084
1085 /* Make real packet. */
paule83e2082005-05-19 02:12:25 +00001086 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +00001087 stream_free (s);
1088
1089 /* Add packet to the peer. */
1090 bgp_packet_add (peer, packet);
1091
1092 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001093 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +00001094 peer->host, BGP_MSG_CAPABILITY, length);
1095
pauleb821182004-05-01 08:44:08 +00001096 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +00001097}
1098
1099/* RFC1771 6.8 Connection collision detection. */
paul94f2b392005-06-28 12:44:16 +00001100static int
pauleb821182004-05-01 08:44:08 +00001101bgp_collision_detect (struct peer *new, struct in_addr remote_id)
paul718e3742002-12-13 20:15:29 +00001102{
pauleb821182004-05-01 08:44:08 +00001103 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001104 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001105 struct bgp *bgp;
1106
1107 bgp = bgp_get_default ();
1108 if (! bgp)
1109 return 0;
1110
1111 /* Upon receipt of an OPEN message, the local system must examine
1112 all of its connections that are in the OpenConfirm state. A BGP
1113 speaker may also examine connections in an OpenSent state if it
1114 knows the BGP Identifier of the peer by means outside of the
1115 protocol. If among these connections there is a connection to a
1116 remote BGP speaker whose BGP Identifier equals the one in the
1117 OPEN message, then the local system performs the following
1118 collision resolution procedure: */
1119
paul1eb8ef22005-04-07 07:30:20 +00001120 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001121 {
1122 /* Under OpenConfirm status, local peer structure already hold
1123 remote router ID. */
pauleb821182004-05-01 08:44:08 +00001124
1125 if (peer != new
1126 && (peer->status == OpenConfirm || peer->status == OpenSent)
1127 && sockunion_same (&peer->su, &new->su))
1128 {
paul718e3742002-12-13 20:15:29 +00001129 /* 1. The BGP Identifier of the local system is compared to
1130 the BGP Identifier of the remote system (as specified in
1131 the OPEN message). */
1132
1133 if (ntohl (peer->local_id.s_addr) < ntohl (remote_id.s_addr))
1134 {
1135 /* 2. If the value of the local BGP Identifier is less
1136 than the remote one, the local system closes BGP
1137 connection that already exists (the one that is
1138 already in the OpenConfirm state), and accepts BGP
1139 connection initiated by the remote system. */
1140
pauleb821182004-05-01 08:44:08 +00001141 if (peer->fd >= 0)
hassoe0701b72004-05-20 09:19:34 +00001142 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
paul718e3742002-12-13 20:15:29 +00001143 return 1;
1144 }
1145 else
1146 {
1147 /* 3. Otherwise, the local system closes newly created
1148 BGP connection (the one associated with the newly
1149 received OPEN message), and continues to use the
1150 existing one (the one that is already in the
1151 OpenConfirm state). */
1152
pauleb821182004-05-01 08:44:08 +00001153 if (new->fd >= 0)
paulf5ba3872004-07-09 12:11:31 +00001154 bgp_notify_send (new, BGP_NOTIFY_CEASE,
1155 BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
paul718e3742002-12-13 20:15:29 +00001156 return -1;
1157 }
pauleb821182004-05-01 08:44:08 +00001158 }
1159 }
paul718e3742002-12-13 20:15:29 +00001160 return 0;
1161}
1162
paul94f2b392005-06-28 12:44:16 +00001163static int
paul718e3742002-12-13 20:15:29 +00001164bgp_open_receive (struct peer *peer, bgp_size_t size)
1165{
1166 int ret;
1167 u_char version;
1168 u_char optlen;
1169 u_int16_t holdtime;
1170 u_int16_t send_holdtime;
1171 as_t remote_as;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001172 as_t as4 = 0;
paul718e3742002-12-13 20:15:29 +00001173 struct peer *realpeer;
1174 struct in_addr remote_id;
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001175 int mp_capability;
paul5228ad22004-06-04 17:58:18 +00001176 u_int8_t notify_data_remote_as[2];
1177 u_int8_t notify_data_remote_id[4];
paul718e3742002-12-13 20:15:29 +00001178
1179 realpeer = NULL;
1180
1181 /* Parse open packet. */
1182 version = stream_getc (peer->ibuf);
1183 memcpy (notify_data_remote_as, stream_pnt (peer->ibuf), 2);
1184 remote_as = stream_getw (peer->ibuf);
1185 holdtime = stream_getw (peer->ibuf);
1186 memcpy (notify_data_remote_id, stream_pnt (peer->ibuf), 4);
1187 remote_id.s_addr = stream_get_ipv4 (peer->ibuf);
1188
1189 /* Receive OPEN message log */
1190 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001191 zlog_debug ("%s rcv OPEN, version %d, remote-as (in open) %u,"
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001192 " holdtime %d, id %s",
1193 peer->host, version, remote_as, holdtime,
1194 inet_ntoa (remote_id));
1195
1196 /* BEGIN to read the capability here, but dont do it yet */
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001197 mp_capability = 0;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001198 optlen = stream_getc (peer->ibuf);
1199
1200 if (optlen != 0)
1201 {
1202 /* We need the as4 capability value *right now* because
1203 * if it is there, we have not got the remote_as yet, and without
1204 * that we do not know which peer is connecting to us now.
1205 */
1206 as4 = peek_for_as4_capability (peer, optlen);
1207 }
1208
1209 /* Just in case we have a silly peer who sends AS4 capability set to 0 */
1210 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) && !as4)
1211 {
1212 zlog_err ("%s bad OPEN, got AS4 capability, but AS4 set to 0",
1213 peer->host);
1214 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1215 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1216 return -1;
1217 }
1218
1219 if (remote_as == BGP_AS_TRANS)
1220 {
1221 /* Take the AS4 from the capability. We must have received the
1222 * capability now! Otherwise we have a asn16 peer who uses
1223 * BGP_AS_TRANS, for some unknown reason.
1224 */
1225 if (as4 == BGP_AS_TRANS)
1226 {
1227 zlog_err ("%s [AS4] NEW speaker using AS_TRANS for AS4, not allowed",
1228 peer->host);
1229 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1230 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1231 return -1;
1232 }
1233
1234 if (!as4 && BGP_DEBUG (as4, AS4))
1235 zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but no AS4."
1236 " Odd, but proceeding.", peer->host);
1237 else if (as4 < BGP_AS_MAX && BGP_DEBUG (as4, AS4))
Paul Jakma0df7c912008-07-21 21:02:49 +00001238 zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but AS4 (%u) fits "
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001239 "in 2-bytes, very odd peer.", peer->host, as4);
1240 if (as4)
1241 remote_as = as4;
1242 }
1243 else
1244 {
1245 /* We may have a partner with AS4 who has an asno < BGP_AS_MAX */
1246 /* If we have got the capability, peer->as4cap must match remote_as */
1247 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)
1248 && as4 != remote_as)
1249 {
1250 /* raise error, log this, close session */
1251 zlog_err ("%s bad OPEN, got AS4 capability, but remote_as %u"
1252 " mismatch with 16bit 'myasn' %u in open",
1253 peer->host, as4, remote_as);
1254 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1255 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1256 return -1;
1257 }
1258 }
1259
paul718e3742002-12-13 20:15:29 +00001260 /* Lookup peer from Open packet. */
1261 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1262 {
1263 int as = 0;
1264
1265 realpeer = peer_lookup_with_open (&peer->su, remote_as, &remote_id, &as);
1266
1267 if (! realpeer)
1268 {
1269 /* Peer's source IP address is check in bgp_accept(), so this
1270 must be AS number mismatch or remote-id configuration
1271 mismatch. */
1272 if (as)
1273 {
1274 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001275 zlog_debug ("%s bad OPEN, wrong router identifier %s",
1276 peer->host, inet_ntoa (remote_id));
1277 bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
1278 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
1279 notify_data_remote_id, 4);
paul718e3742002-12-13 20:15:29 +00001280 }
1281 else
1282 {
1283 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001284 zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
ajs6b514742004-12-08 21:03:23 +00001285 peer->host, remote_as, peer->as);
1286 bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
1287 BGP_NOTIFY_OPEN_BAD_PEER_AS,
1288 notify_data_remote_as, 2);
paul718e3742002-12-13 20:15:29 +00001289 }
1290 return -1;
1291 }
1292 }
1293
1294 /* When collision is detected and this peer is closed. Retrun
1295 immidiately. */
1296 ret = bgp_collision_detect (peer, remote_id);
1297 if (ret < 0)
1298 return ret;
1299
pauleb821182004-05-01 08:44:08 +00001300 /* Hack part. */
1301 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1302 {
hasso93406d82005-02-02 14:40:33 +00001303 if (realpeer->status == Established
1304 && CHECK_FLAG (realpeer->sflags, PEER_STATUS_NSF_MODE))
1305 {
1306 realpeer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
1307 SET_FLAG (realpeer->sflags, PEER_STATUS_NSF_WAIT);
1308 }
1309 else if (ret == 0 && realpeer->status != Active
1310 && realpeer->status != OpenSent
Paul Jakma6e199262008-09-09 17:14:33 +01001311 && realpeer->status != OpenConfirm
1312 && realpeer->status != Connect)
pauleb821182004-05-01 08:44:08 +00001313 {
Paul Jakma2b2fc562008-09-06 13:09:35 +01001314 /* XXX: This is an awful problem..
1315 *
1316 * According to the RFC we should just let this connection (of the
1317 * accepted 'peer') continue on to Established if the other
1318 * connection (the 'realpeer' one) is in state Connect, and deal
1319 * with the more larval FSM as/when it gets far enough to receive
1320 * an Open. We don't do that though, we instead close the (more
1321 * developed) accepted connection.
1322 *
1323 * This means there's a race, which if hit, can loop:
1324 *
1325 * FSM for A FSM for B
1326 * realpeer accept-peer realpeer accept-peer
1327 *
1328 * Connect Connect
1329 * Active
1330 * OpenSent OpenSent
1331 * <arrive here,
1332 * Notify, delete>
1333 * Idle Active
1334 * OpenSent OpenSent
1335 * <arrive here,
1336 * Notify, delete>
1337 * Idle
1338 * <wait> <wait>
1339 * Connect Connect
1340 *
1341 *
1342 * If both sides are Quagga, they're almost certain to wait for
1343 * the same amount of time of course (which doesn't preclude other
1344 * implementations also waiting for same time). The race is
1345 * exacerbated by high-latency (in bgpd and/or the network).
1346 *
1347 * The reason we do this is because our FSM is tied to our peer
1348 * structure, which carries our configuration information, etc.
1349 * I.e. we can't let the accepted-peer FSM continue on as it is,
1350 * cause it's not associated with any actual peer configuration -
1351 * it's just a dummy.
1352 *
1353 * It's possible we could hack-fix this by just bgp_stop'ing the
1354 * realpeer and continueing on with the 'transfer FSM' below.
1355 * Ideally, we need to seperate FSMs from struct peer.
1356 *
1357 * Setting one side to passive avoids the race, as a workaround.
1358 */
pauleb821182004-05-01 08:44:08 +00001359 if (BGP_DEBUG (events, EVENTS))
hasso93406d82005-02-02 14:40:33 +00001360 zlog_debug ("%s peer status is %s close connection",
1361 realpeer->host, LOOKUP (bgp_status_msg,
1362 realpeer->status));
1363 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1364 BGP_NOTIFY_CEASE_CONNECT_REJECT);
1365
pauleb821182004-05-01 08:44:08 +00001366 return -1;
1367 }
1368
1369 if (BGP_DEBUG (events, EVENTS))
Paul Jakma6e199262008-09-09 17:14:33 +01001370 zlog_debug ("%s [Event] Transfer accept BGP peer to real (state %s)",
1371 peer->host,
1372 LOOKUP (bgp_status_msg, realpeer->status));
pauleb821182004-05-01 08:44:08 +00001373
1374 bgp_stop (realpeer);
1375
1376 /* Transfer file descriptor. */
1377 realpeer->fd = peer->fd;
1378 peer->fd = -1;
1379
1380 /* Transfer input buffer. */
1381 stream_free (realpeer->ibuf);
1382 realpeer->ibuf = peer->ibuf;
1383 realpeer->packet_size = peer->packet_size;
1384 peer->ibuf = NULL;
1385
1386 /* Transfer status. */
1387 realpeer->status = peer->status;
1388 bgp_stop (peer);
paul200df112005-06-01 11:17:05 +00001389
pauleb821182004-05-01 08:44:08 +00001390 /* peer pointer change. Open packet send to neighbor. */
1391 peer = realpeer;
1392 bgp_open_send (peer);
1393 if (peer->fd < 0)
1394 {
1395 zlog_err ("bgp_open_receive peer's fd is negative value %d",
1396 peer->fd);
1397 return -1;
1398 }
1399 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
1400 }
1401
paul718e3742002-12-13 20:15:29 +00001402 /* remote router-id check. */
1403 if (remote_id.s_addr == 0
Denis Ovsienko733cd9e2011-12-17 19:39:30 +04001404 || IPV4_CLASS_DE (ntohl (remote_id.s_addr))
paul718e3742002-12-13 20:15:29 +00001405 || ntohl (peer->local_id.s_addr) == ntohl (remote_id.s_addr))
1406 {
1407 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001408 zlog_debug ("%s bad OPEN, wrong router identifier %s",
paul718e3742002-12-13 20:15:29 +00001409 peer->host, inet_ntoa (remote_id));
1410 bgp_notify_send_with_data (peer,
1411 BGP_NOTIFY_OPEN_ERR,
1412 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
1413 notify_data_remote_id, 4);
1414 return -1;
1415 }
1416
1417 /* Set remote router-id */
1418 peer->remote_id = remote_id;
1419
1420 /* Peer BGP version check. */
1421 if (version != BGP_VERSION_4)
1422 {
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001423 u_int16_t maxver = htons(BGP_VERSION_4);
1424 /* XXX this reply may not be correct if version < 4 XXX */
paul718e3742002-12-13 20:15:29 +00001425 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001426 zlog_debug ("%s bad protocol version, remote requested %d, local request %d",
paul718e3742002-12-13 20:15:29 +00001427 peer->host, version, BGP_VERSION_4);
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001428 /* Data must be in network byte order here */
paul718e3742002-12-13 20:15:29 +00001429 bgp_notify_send_with_data (peer,
1430 BGP_NOTIFY_OPEN_ERR,
1431 BGP_NOTIFY_OPEN_UNSUP_VERSION,
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001432 (u_int8_t *) &maxver, 2);
paul718e3742002-12-13 20:15:29 +00001433 return -1;
1434 }
1435
1436 /* Check neighbor as number. */
1437 if (remote_as != peer->as)
1438 {
1439 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001440 zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
paul718e3742002-12-13 20:15:29 +00001441 peer->host, remote_as, peer->as);
1442 bgp_notify_send_with_data (peer,
1443 BGP_NOTIFY_OPEN_ERR,
1444 BGP_NOTIFY_OPEN_BAD_PEER_AS,
1445 notify_data_remote_as, 2);
1446 return -1;
1447 }
1448
1449 /* From the rfc: Upon receipt of an OPEN message, a BGP speaker MUST
1450 calculate the value of the Hold Timer by using the smaller of its
1451 configured Hold Time and the Hold Time received in the OPEN message.
1452 The Hold Time MUST be either zero or at least three seconds. An
1453 implementation may reject connections on the basis of the Hold Time. */
1454
1455 if (holdtime < 3 && holdtime != 0)
1456 {
1457 bgp_notify_send (peer,
1458 BGP_NOTIFY_OPEN_ERR,
1459 BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
1460 return -1;
1461 }
1462
1463 /* From the rfc: A reasonable maximum time between KEEPALIVE messages
1464 would be one third of the Hold Time interval. KEEPALIVE messages
1465 MUST NOT be sent more frequently than one per second. An
1466 implementation MAY adjust the rate at which it sends KEEPALIVE
1467 messages as a function of the Hold Time interval. */
1468
1469 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
1470 send_holdtime = peer->holdtime;
1471 else
1472 send_holdtime = peer->bgp->default_holdtime;
1473
1474 if (holdtime < send_holdtime)
1475 peer->v_holdtime = holdtime;
1476 else
1477 peer->v_holdtime = send_holdtime;
1478
1479 peer->v_keepalive = peer->v_holdtime / 3;
1480
1481 /* Open option part parse. */
paul718e3742002-12-13 20:15:29 +00001482 if (optlen != 0)
1483 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001484 if ((ret = bgp_open_option_parse (peer, optlen, &mp_capability)) < 0)
Paul Jakma58617392012-01-09 20:59:26 +00001485 {
1486 bgp_notify_send (peer,
1487 BGP_NOTIFY_OPEN_ERR,
1488 BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
1489 return ret;
1490 }
paul718e3742002-12-13 20:15:29 +00001491 }
1492 else
1493 {
1494 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001495 zlog_debug ("%s rcvd OPEN w/ OPTION parameter len: 0",
paul718e3742002-12-13 20:15:29 +00001496 peer->host);
1497 }
1498
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001499 /*
1500 * Assume that the peer supports the locally configured set of
1501 * AFI/SAFIs if the peer did not send us any Mulitiprotocol
1502 * capabilities, or if 'override-capability' is configured.
1503 */
1504 if (! mp_capability ||
1505 CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
paul718e3742002-12-13 20:15:29 +00001506 {
1507 peer->afc_nego[AFI_IP][SAFI_UNICAST] = peer->afc[AFI_IP][SAFI_UNICAST];
1508 peer->afc_nego[AFI_IP][SAFI_MULTICAST] = peer->afc[AFI_IP][SAFI_MULTICAST];
1509 peer->afc_nego[AFI_IP6][SAFI_UNICAST] = peer->afc[AFI_IP6][SAFI_UNICAST];
1510 peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = peer->afc[AFI_IP6][SAFI_MULTICAST];
1511 }
1512
1513 /* Get sockname. */
1514 bgp_getsockname (peer);
1515
1516 BGP_EVENT_ADD (peer, Receive_OPEN_message);
1517
1518 peer->packet_size = 0;
1519 if (peer->ibuf)
1520 stream_reset (peer->ibuf);
1521
1522 return 0;
1523}
1524
1525/* Parse BGP Update packet and make attribute object. */
paul94f2b392005-06-28 12:44:16 +00001526static int
paul718e3742002-12-13 20:15:29 +00001527bgp_update_receive (struct peer *peer, bgp_size_t size)
1528{
1529 int ret;
1530 u_char *end;
1531 struct stream *s;
1532 struct attr attr;
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001533 struct attr_extra extra;
paul718e3742002-12-13 20:15:29 +00001534 bgp_size_t attribute_len;
1535 bgp_size_t update_len;
1536 bgp_size_t withdraw_len;
1537 struct bgp_nlri update;
1538 struct bgp_nlri withdraw;
1539 struct bgp_nlri mp_update;
1540 struct bgp_nlri mp_withdraw;
paul718e3742002-12-13 20:15:29 +00001541
1542 /* Status must be Established. */
1543 if (peer->status != Established)
1544 {
1545 zlog_err ("%s [FSM] Update packet received under status %s",
1546 peer->host, LOOKUP (bgp_status_msg, peer->status));
1547 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
1548 return -1;
1549 }
1550
1551 /* Set initial values. */
1552 memset (&attr, 0, sizeof (struct attr));
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001553 memset (&extra, 0, sizeof (struct attr_extra));
paul718e3742002-12-13 20:15:29 +00001554 memset (&update, 0, sizeof (struct bgp_nlri));
1555 memset (&withdraw, 0, sizeof (struct bgp_nlri));
1556 memset (&mp_update, 0, sizeof (struct bgp_nlri));
1557 memset (&mp_withdraw, 0, sizeof (struct bgp_nlri));
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001558 attr.extra = &extra;
paul718e3742002-12-13 20:15:29 +00001559
1560 s = peer->ibuf;
1561 end = stream_pnt (s) + size;
1562
1563 /* RFC1771 6.3 If the Unfeasible Routes Length or Total Attribute
1564 Length is too large (i.e., if Unfeasible Routes Length + Total
1565 Attribute Length + 23 exceeds the message Length), then the Error
1566 Subcode is set to Malformed Attribute List. */
1567 if (stream_pnt (s) + 2 > end)
1568 {
1569 zlog_err ("%s [Error] Update packet error"
1570 " (packet length is short for unfeasible length)",
1571 peer->host);
1572 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1573 BGP_NOTIFY_UPDATE_MAL_ATTR);
1574 return -1;
1575 }
1576
1577 /* Unfeasible Route Length. */
1578 withdraw_len = stream_getw (s);
1579
1580 /* Unfeasible Route Length check. */
1581 if (stream_pnt (s) + withdraw_len > end)
1582 {
1583 zlog_err ("%s [Error] Update packet error"
1584 " (packet unfeasible length overflow %d)",
1585 peer->host, withdraw_len);
1586 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1587 BGP_NOTIFY_UPDATE_MAL_ATTR);
1588 return -1;
1589 }
1590
1591 /* Unfeasible Route packet format check. */
1592 if (withdraw_len > 0)
1593 {
1594 ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), withdraw_len);
1595 if (ret < 0)
1596 return -1;
1597
1598 if (BGP_DEBUG (packet, PACKET_RECV))
ajs6b514742004-12-08 21:03:23 +00001599 zlog_debug ("%s [Update:RECV] Unfeasible NLRI received", peer->host);
paul718e3742002-12-13 20:15:29 +00001600
1601 withdraw.afi = AFI_IP;
1602 withdraw.safi = SAFI_UNICAST;
1603 withdraw.nlri = stream_pnt (s);
1604 withdraw.length = withdraw_len;
paul9985f832005-02-09 15:51:56 +00001605 stream_forward_getp (s, withdraw_len);
paul718e3742002-12-13 20:15:29 +00001606 }
1607
1608 /* Attribute total length check. */
1609 if (stream_pnt (s) + 2 > end)
1610 {
1611 zlog_warn ("%s [Error] Packet Error"
1612 " (update packet is short for attribute length)",
1613 peer->host);
1614 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1615 BGP_NOTIFY_UPDATE_MAL_ATTR);
1616 return -1;
1617 }
1618
1619 /* Fetch attribute total length. */
1620 attribute_len = stream_getw (s);
1621
1622 /* Attribute length check. */
1623 if (stream_pnt (s) + attribute_len > end)
1624 {
1625 zlog_warn ("%s [Error] Packet Error"
1626 " (update packet attribute length overflow %d)",
1627 peer->host, attribute_len);
1628 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1629 BGP_NOTIFY_UPDATE_MAL_ATTR);
1630 return -1;
1631 }
Paul Jakmab881c702010-11-23 16:35:42 +00001632
1633 /* Certain attribute parsing errors should not be considered bad enough
1634 * to reset the session for, most particularly any partial/optional
1635 * attributes that have 'tunneled' over speakers that don't understand
1636 * them. Instead we withdraw only the prefix concerned.
1637 *
1638 * Complicates the flow a little though..
1639 */
1640 bgp_attr_parse_ret_t attr_parse_ret = BGP_ATTR_PARSE_PROCEED;
1641 /* This define morphs the update case into a withdraw when lower levels
1642 * have signalled an error condition where this is best.
1643 */
1644#define NLRI_ATTR_ARG (attr_parse_ret != BGP_ATTR_PARSE_WITHDRAW ? &attr : NULL)
paul718e3742002-12-13 20:15:29 +00001645
1646 /* Parse attribute when it exists. */
1647 if (attribute_len)
1648 {
Paul Jakmab881c702010-11-23 16:35:42 +00001649 attr_parse_ret = bgp_attr_parse (peer, &attr, attribute_len,
paul718e3742002-12-13 20:15:29 +00001650 &mp_update, &mp_withdraw);
Paul Jakmab881c702010-11-23 16:35:42 +00001651 if (attr_parse_ret == BGP_ATTR_PARSE_ERROR)
paul718e3742002-12-13 20:15:29 +00001652 return -1;
1653 }
Paul Jakmab881c702010-11-23 16:35:42 +00001654
paul718e3742002-12-13 20:15:29 +00001655 /* Logging the attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001656 if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW
1657 || BGP_DEBUG (update, UPDATE_IN))
paul718e3742002-12-13 20:15:29 +00001658 {
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +00001659 char attrstr[BUFSIZ];
1660 attrstr[0] = '\0';
1661
paule01f9cb2004-07-09 17:48:53 +00001662 ret= bgp_dump_attr (peer, &attr, attrstr, BUFSIZ);
Paul Jakmab881c702010-11-23 16:35:42 +00001663 int lvl = (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
1664 ? LOG_ERR : LOG_DEBUG;
1665
1666 if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
1667 zlog (peer->log, LOG_ERR,
1668 "%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.",
1669 peer->host);
paule01f9cb2004-07-09 17:48:53 +00001670
1671 if (ret)
Paul Jakmab881c702010-11-23 16:35:42 +00001672 zlog (peer->log, lvl, "%s rcvd UPDATE w/ attr: %s",
paule01f9cb2004-07-09 17:48:53 +00001673 peer->host, attrstr);
paul718e3742002-12-13 20:15:29 +00001674 }
Paul Jakmab881c702010-11-23 16:35:42 +00001675
paul718e3742002-12-13 20:15:29 +00001676 /* Network Layer Reachability Information. */
1677 update_len = end - stream_pnt (s);
1678
1679 if (update_len)
1680 {
1681 /* Check NLRI packet format and prefix length. */
1682 ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), update_len);
1683 if (ret < 0)
Paul Jakmab881c702010-11-23 16:35:42 +00001684 {
1685 bgp_attr_unintern_sub (&attr);
Paul Jakmab881c702010-11-23 16:35:42 +00001686 return -1;
1687 }
paul718e3742002-12-13 20:15:29 +00001688
1689 /* Set NLRI portion to structure. */
1690 update.afi = AFI_IP;
1691 update.safi = SAFI_UNICAST;
1692 update.nlri = stream_pnt (s);
1693 update.length = update_len;
paul9985f832005-02-09 15:51:56 +00001694 stream_forward_getp (s, update_len);
paul718e3742002-12-13 20:15:29 +00001695 }
1696
1697 /* NLRI is processed only when the peer is configured specific
1698 Address Family and Subsequent Address Family. */
1699 if (peer->afc[AFI_IP][SAFI_UNICAST])
1700 {
1701 if (withdraw.length)
1702 bgp_nlri_parse (peer, NULL, &withdraw);
1703
1704 if (update.length)
1705 {
1706 /* We check well-known attribute only for IPv4 unicast
1707 update. */
1708 ret = bgp_attr_check (peer, &attr);
1709 if (ret < 0)
Paul Jakmab881c702010-11-23 16:35:42 +00001710 {
1711 bgp_attr_unintern_sub (&attr);
Paul Jakmab881c702010-11-23 16:35:42 +00001712 return -1;
1713 }
paul718e3742002-12-13 20:15:29 +00001714
Paul Jakmab881c702010-11-23 16:35:42 +00001715 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &update);
paul718e3742002-12-13 20:15:29 +00001716 }
paule01f9cb2004-07-09 17:48:53 +00001717
hassof4184462005-02-01 20:13:16 +00001718 if (mp_update.length
1719 && mp_update.afi == AFI_IP
1720 && mp_update.safi == SAFI_UNICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001721 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
hassof4184462005-02-01 20:13:16 +00001722
1723 if (mp_withdraw.length
1724 && mp_withdraw.afi == AFI_IP
1725 && mp_withdraw.safi == SAFI_UNICAST)
1726 bgp_nlri_parse (peer, NULL, &mp_withdraw);
1727
paule01f9cb2004-07-09 17:48:53 +00001728 if (! attribute_len && ! withdraw_len)
1729 {
1730 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001731 SET_FLAG (peer->af_sflags[AFI_IP][SAFI_UNICAST],
1732 PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001733
hasso93406d82005-02-02 14:40:33 +00001734 /* NSF delete stale route */
1735 if (peer->nsf[AFI_IP][SAFI_UNICAST])
1736 bgp_clear_stale_route (peer, AFI_IP, SAFI_UNICAST);
1737
1738 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001739 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001740 peer->host);
1741 }
paul718e3742002-12-13 20:15:29 +00001742 }
1743 if (peer->afc[AFI_IP][SAFI_MULTICAST])
1744 {
1745 if (mp_update.length
1746 && mp_update.afi == AFI_IP
1747 && mp_update.safi == SAFI_MULTICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001748 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001749
1750 if (mp_withdraw.length
1751 && mp_withdraw.afi == AFI_IP
1752 && mp_withdraw.safi == SAFI_MULTICAST)
1753 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001754
hasso93406d82005-02-02 14:40:33 +00001755 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001756 && mp_withdraw.afi == AFI_IP
1757 && mp_withdraw.safi == SAFI_MULTICAST
1758 && mp_withdraw.length == 0)
1759 {
1760 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001761 SET_FLAG (peer->af_sflags[AFI_IP][SAFI_MULTICAST],
1762 PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001763
hasso93406d82005-02-02 14:40:33 +00001764 /* NSF delete stale route */
1765 if (peer->nsf[AFI_IP][SAFI_MULTICAST])
1766 bgp_clear_stale_route (peer, AFI_IP, SAFI_MULTICAST);
1767
1768 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001769 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Multicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001770 peer->host);
1771 }
paul718e3742002-12-13 20:15:29 +00001772 }
1773 if (peer->afc[AFI_IP6][SAFI_UNICAST])
1774 {
1775 if (mp_update.length
1776 && mp_update.afi == AFI_IP6
1777 && mp_update.safi == SAFI_UNICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001778 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001779
1780 if (mp_withdraw.length
1781 && mp_withdraw.afi == AFI_IP6
1782 && mp_withdraw.safi == SAFI_UNICAST)
1783 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001784
hasso93406d82005-02-02 14:40:33 +00001785 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001786 && mp_withdraw.afi == AFI_IP6
1787 && mp_withdraw.safi == SAFI_UNICAST
1788 && mp_withdraw.length == 0)
1789 {
1790 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001791 SET_FLAG (peer->af_sflags[AFI_IP6][SAFI_UNICAST], PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001792
hasso93406d82005-02-02 14:40:33 +00001793 /* NSF delete stale route */
1794 if (peer->nsf[AFI_IP6][SAFI_UNICAST])
1795 bgp_clear_stale_route (peer, AFI_IP6, SAFI_UNICAST);
1796
1797 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001798 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001799 peer->host);
1800 }
paul718e3742002-12-13 20:15:29 +00001801 }
1802 if (peer->afc[AFI_IP6][SAFI_MULTICAST])
1803 {
1804 if (mp_update.length
1805 && mp_update.afi == AFI_IP6
1806 && mp_update.safi == SAFI_MULTICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001807 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001808
1809 if (mp_withdraw.length
1810 && mp_withdraw.afi == AFI_IP6
1811 && mp_withdraw.safi == SAFI_MULTICAST)
1812 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001813
hasso93406d82005-02-02 14:40:33 +00001814 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001815 && mp_withdraw.afi == AFI_IP6
1816 && mp_withdraw.safi == SAFI_MULTICAST
1817 && mp_withdraw.length == 0)
1818 {
1819 /* End-of-RIB received */
1820
hasso93406d82005-02-02 14:40:33 +00001821 /* NSF delete stale route */
1822 if (peer->nsf[AFI_IP6][SAFI_MULTICAST])
1823 bgp_clear_stale_route (peer, AFI_IP6, SAFI_MULTICAST);
1824
paule01f9cb2004-07-09 17:48:53 +00001825 if (BGP_DEBUG (update, UPDATE_IN))
ajs6b514742004-12-08 21:03:23 +00001826 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Multicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001827 peer->host);
1828 }
paul718e3742002-12-13 20:15:29 +00001829 }
1830 if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
1831 {
1832 if (mp_update.length
1833 && mp_update.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001834 && mp_update.safi == SAFI_MPLS_LABELED_VPN)
Paul Jakmab881c702010-11-23 16:35:42 +00001835 bgp_nlri_parse_vpnv4 (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001836
1837 if (mp_withdraw.length
1838 && mp_withdraw.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001839 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00001840 bgp_nlri_parse_vpnv4 (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001841
hasso93406d82005-02-02 14:40:33 +00001842 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001843 && mp_withdraw.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001844 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN
paule01f9cb2004-07-09 17:48:53 +00001845 && mp_withdraw.length == 0)
1846 {
1847 /* End-of-RIB received */
1848
1849 if (BGP_DEBUG (update, UPDATE_IN))
ajs6b514742004-12-08 21:03:23 +00001850 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for VPNv4 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001851 peer->host);
1852 }
paul718e3742002-12-13 20:15:29 +00001853 }
1854
1855 /* Everything is done. We unintern temporary structures which
1856 interned in bgp_attr_parse(). */
Paul Jakmab881c702010-11-23 16:35:42 +00001857 bgp_attr_unintern_sub (&attr);
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001858
paul718e3742002-12-13 20:15:29 +00001859 /* If peering is stopped due to some reason, do not generate BGP
1860 event. */
1861 if (peer->status != Established)
1862 return 0;
1863
1864 /* Increment packet counter. */
1865 peer->update_in++;
Stephen Hemminger65957882010-01-15 16:22:10 +03001866 peer->update_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00001867
Jorge Boncompte [DTI2]e2c38e62012-06-20 17:45:50 +02001868 /* Rearm holdtime timer */
Jorge Boncompte [DTI2]6a4677b2012-05-07 16:53:07 +00001869 BGP_TIMER_OFF (peer->t_holdtime);
Jorge Boncompte [DTI2]e2c38e62012-06-20 17:45:50 +02001870 bgp_timer_set (peer);
paul718e3742002-12-13 20:15:29 +00001871
1872 return 0;
1873}
1874
1875/* Notify message treatment function. */
paul94f2b392005-06-28 12:44:16 +00001876static void
paul718e3742002-12-13 20:15:29 +00001877bgp_notify_receive (struct peer *peer, bgp_size_t size)
1878{
1879 struct bgp_notify bgp_notify;
1880
1881 if (peer->notify.data)
1882 {
1883 XFREE (MTYPE_TMP, peer->notify.data);
1884 peer->notify.data = NULL;
1885 peer->notify.length = 0;
1886 }
1887
1888 bgp_notify.code = stream_getc (peer->ibuf);
1889 bgp_notify.subcode = stream_getc (peer->ibuf);
1890 bgp_notify.length = size - 2;
1891 bgp_notify.data = NULL;
1892
1893 /* Preserv notify code and sub code. */
1894 peer->notify.code = bgp_notify.code;
1895 peer->notify.subcode = bgp_notify.subcode;
1896 /* For further diagnostic record returned Data. */
1897 if (bgp_notify.length)
1898 {
1899 peer->notify.length = size - 2;
1900 peer->notify.data = XMALLOC (MTYPE_TMP, size - 2);
1901 memcpy (peer->notify.data, stream_pnt (peer->ibuf), size - 2);
1902 }
1903
1904 /* For debug */
1905 {
1906 int i;
1907 int first = 0;
1908 char c[4];
1909
1910 if (bgp_notify.length)
1911 {
1912 bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
1913 for (i = 0; i < bgp_notify.length; i++)
1914 if (first)
1915 {
1916 sprintf (c, " %02x", stream_getc (peer->ibuf));
1917 strcat (bgp_notify.data, c);
1918 }
1919 else
1920 {
1921 first = 1;
1922 sprintf (c, "%02x", stream_getc (peer->ibuf));
1923 strcpy (bgp_notify.data, c);
1924 }
1925 }
1926
1927 bgp_notify_print(peer, &bgp_notify, "received");
1928 if (bgp_notify.data)
1929 XFREE (MTYPE_TMP, bgp_notify.data);
1930 }
1931
1932 /* peer count update */
1933 peer->notify_in++;
1934
hassoe0701b72004-05-20 09:19:34 +00001935 if (peer->status == Established)
1936 peer->last_reset = PEER_DOWN_NOTIFY_RECEIVED;
1937
paul718e3742002-12-13 20:15:29 +00001938 /* We have to check for Notify with Unsupported Optional Parameter.
1939 in that case we fallback to open without the capability option.
1940 But this done in bgp_stop. We just mark it here to avoid changing
1941 the fsm tables. */
1942 if (bgp_notify.code == BGP_NOTIFY_OPEN_ERR &&
1943 bgp_notify.subcode == BGP_NOTIFY_OPEN_UNSUP_PARAM )
1944 UNSET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
1945
paul718e3742002-12-13 20:15:29 +00001946 BGP_EVENT_ADD (peer, Receive_NOTIFICATION_message);
1947}
1948
1949/* Keepalive treatment function -- get keepalive send keepalive */
paul94f2b392005-06-28 12:44:16 +00001950static void
paul718e3742002-12-13 20:15:29 +00001951bgp_keepalive_receive (struct peer *peer, bgp_size_t size)
1952{
1953 if (BGP_DEBUG (keepalive, KEEPALIVE))
ajs6b514742004-12-08 21:03:23 +00001954 zlog_debug ("%s KEEPALIVE rcvd", peer->host);
paul718e3742002-12-13 20:15:29 +00001955
1956 BGP_EVENT_ADD (peer, Receive_KEEPALIVE_message);
1957}
1958
1959/* Route refresh message is received. */
paul94f2b392005-06-28 12:44:16 +00001960static void
paul718e3742002-12-13 20:15:29 +00001961bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
1962{
1963 afi_t afi;
1964 safi_t safi;
1965 u_char reserved;
1966 struct stream *s;
1967
1968 /* If peer does not have the capability, send notification. */
1969 if (! CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_ADV))
1970 {
1971 plog_err (peer->log, "%s [Error] BGP route refresh is not enabled",
1972 peer->host);
1973 bgp_notify_send (peer,
1974 BGP_NOTIFY_HEADER_ERR,
1975 BGP_NOTIFY_HEADER_BAD_MESTYPE);
1976 return;
1977 }
1978
1979 /* Status must be Established. */
1980 if (peer->status != Established)
1981 {
1982 plog_err (peer->log,
1983 "%s [Error] Route refresh packet received under status %s",
1984 peer->host, LOOKUP (bgp_status_msg, peer->status));
1985 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
1986 return;
1987 }
1988
1989 s = peer->ibuf;
1990
1991 /* Parse packet. */
1992 afi = stream_getw (s);
1993 reserved = stream_getc (s);
1994 safi = stream_getc (s);
1995
1996 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001997 zlog_debug ("%s rcvd REFRESH_REQ for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001998 peer->host, afi, safi);
1999
2000 /* Check AFI and SAFI. */
2001 if ((afi != AFI_IP && afi != AFI_IP6)
2002 || (safi != SAFI_UNICAST && safi != SAFI_MULTICAST
Denis Ovsienko42e6d742011-07-14 12:36:19 +04002003 && safi != SAFI_MPLS_LABELED_VPN))
paul718e3742002-12-13 20:15:29 +00002004 {
2005 if (BGP_DEBUG (normal, NORMAL))
2006 {
ajs6b514742004-12-08 21:03:23 +00002007 zlog_debug ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored",
paul718e3742002-12-13 20:15:29 +00002008 peer->host, afi, safi);
2009 }
2010 return;
2011 }
2012
2013 /* Adjust safi code. */
Denis Ovsienko42e6d742011-07-14 12:36:19 +04002014 if (safi == SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00002015 safi = SAFI_MPLS_VPN;
2016
2017 if (size != BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE)
2018 {
2019 u_char *end;
2020 u_char when_to_refresh;
2021 u_char orf_type;
2022 u_int16_t orf_len;
2023
2024 if (size - (BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE) < 5)
2025 {
2026 zlog_info ("%s ORF route refresh length error", peer->host);
2027 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2028 return;
2029 }
2030
2031 when_to_refresh = stream_getc (s);
2032 end = stream_pnt (s) + (size - 5);
2033
Paul Jakma370b64a2007-12-22 16:49:52 +00002034 while ((stream_pnt (s) + 2) < end)
paul718e3742002-12-13 20:15:29 +00002035 {
2036 orf_type = stream_getc (s);
2037 orf_len = stream_getw (s);
Paul Jakma370b64a2007-12-22 16:49:52 +00002038
2039 /* orf_len in bounds? */
2040 if ((stream_pnt (s) + orf_len) > end)
2041 break; /* XXX: Notify instead?? */
paul718e3742002-12-13 20:15:29 +00002042 if (orf_type == ORF_TYPE_PREFIX
2043 || orf_type == ORF_TYPE_PREFIX_OLD)
2044 {
2045 u_char *p_pnt = stream_pnt (s);
2046 u_char *p_end = stream_pnt (s) + orf_len;
2047 struct orf_prefix orfp;
2048 u_char common = 0;
2049 u_int32_t seq;
2050 int psize;
2051 char name[BUFSIZ];
paul718e3742002-12-13 20:15:29 +00002052 int ret;
2053
2054 if (BGP_DEBUG (normal, NORMAL))
2055 {
ajs6b514742004-12-08 21:03:23 +00002056 zlog_debug ("%s rcvd Prefixlist ORF(%d) length %d",
paul718e3742002-12-13 20:15:29 +00002057 peer->host, orf_type, orf_len);
2058 }
2059
Paul Jakma370b64a2007-12-22 16:49:52 +00002060 /* we're going to read at least 1 byte of common ORF header,
2061 * and 7 bytes of ORF Address-filter entry from the stream
2062 */
2063 if (orf_len < 7)
2064 break;
2065
paul718e3742002-12-13 20:15:29 +00002066 /* ORF prefix-list name */
2067 sprintf (name, "%s.%d.%d", peer->host, afi, safi);
2068
2069 while (p_pnt < p_end)
2070 {
Chris Halld64379e2010-05-14 16:38:39 +04002071 /* If the ORF entry is malformed, want to read as much of it
2072 * as possible without going beyond the bounds of the entry,
2073 * to maximise debug information.
2074 */
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002075 int ok;
paul718e3742002-12-13 20:15:29 +00002076 memset (&orfp, 0, sizeof (struct orf_prefix));
2077 common = *p_pnt++;
Chris Halld64379e2010-05-14 16:38:39 +04002078 /* after ++: p_pnt <= p_end */
paul718e3742002-12-13 20:15:29 +00002079 if (common & ORF_COMMON_PART_REMOVE_ALL)
2080 {
2081 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002082 zlog_debug ("%s rcvd Remove-All pfxlist ORF request", peer->host);
paul718e3742002-12-13 20:15:29 +00002083 prefix_bgp_orf_remove_all (name);
2084 break;
2085 }
Chris Halld64379e2010-05-14 16:38:39 +04002086 ok = ((p_end - p_pnt) >= sizeof(u_int32_t)) ;
Denis Ovsienkobb915f52011-12-13 21:11:39 +04002087 if (ok)
Chris Halld64379e2010-05-14 16:38:39 +04002088 {
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002089 memcpy (&seq, p_pnt, sizeof (u_int32_t));
2090 p_pnt += sizeof (u_int32_t);
2091 orfp.seq = ntohl (seq);
Chris Halld64379e2010-05-14 16:38:39 +04002092 }
2093 else
2094 p_pnt = p_end ;
2095
2096 if ((ok = (p_pnt < p_end)))
2097 orfp.ge = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */
2098 if ((ok = (p_pnt < p_end)))
2099 orfp.le = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */
2100 if ((ok = (p_pnt < p_end)))
2101 orfp.p.prefixlen = *p_pnt++ ;
2102 orfp.p.family = afi2family (afi); /* afi checked already */
2103
2104 psize = PSIZE (orfp.p.prefixlen); /* 0 if not ok */
2105 if (psize > prefix_blen(&orfp.p)) /* valid for family ? */
2106 {
2107 ok = 0 ;
2108 psize = prefix_blen(&orfp.p) ;
2109 }
2110 if (psize > (p_end - p_pnt)) /* valid for packet ? */
2111 {
2112 ok = 0 ;
2113 psize = p_end - p_pnt ;
2114 }
2115
2116 if (psize > 0)
2117 memcpy (&orfp.p.u.prefix, p_pnt, psize);
paul718e3742002-12-13 20:15:29 +00002118 p_pnt += psize;
2119
2120 if (BGP_DEBUG (normal, NORMAL))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +00002121 {
2122 char buf[INET6_BUFSIZ];
2123
2124 zlog_debug ("%s rcvd %s %s seq %u %s/%d ge %d le %d%s",
2125 peer->host,
2126 (common & ORF_COMMON_PART_REMOVE ? "Remove" : "Add"),
2127 (common & ORF_COMMON_PART_DENY ? "deny" : "permit"),
2128 orfp.seq,
2129 inet_ntop (orfp.p.family, &orfp.p.u.prefix, buf, INET6_BUFSIZ),
2130 orfp.p.prefixlen, orfp.ge, orfp.le,
2131 ok ? "" : " MALFORMED");
2132 }
2133
Chris Halld64379e2010-05-14 16:38:39 +04002134 if (ok)
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002135 ret = prefix_bgp_orf_set (name, afi, &orfp,
2136 (common & ORF_COMMON_PART_DENY ? 0 : 1 ),
2137 (common & ORF_COMMON_PART_REMOVE ? 0 : 1));
paul718e3742002-12-13 20:15:29 +00002138
Chris Halld64379e2010-05-14 16:38:39 +04002139 if (!ok || (ret != CMD_SUCCESS))
paul718e3742002-12-13 20:15:29 +00002140 {
2141 if (BGP_DEBUG (normal, NORMAL))
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002142 zlog_debug ("%s Received misformatted prefixlist ORF."
2143 " Remove All pfxlist", peer->host);
paul718e3742002-12-13 20:15:29 +00002144 prefix_bgp_orf_remove_all (name);
2145 break;
2146 }
2147 }
2148 peer->orf_plist[afi][safi] =
2149 prefix_list_lookup (AFI_ORF_PREFIX, name);
2150 }
paul9985f832005-02-09 15:51:56 +00002151 stream_forward_getp (s, orf_len);
paul718e3742002-12-13 20:15:29 +00002152 }
2153 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002154 zlog_debug ("%s rcvd Refresh %s ORF request", peer->host,
paul718e3742002-12-13 20:15:29 +00002155 when_to_refresh == REFRESH_DEFER ? "Defer" : "Immediate");
2156 if (when_to_refresh == REFRESH_DEFER)
2157 return;
2158 }
2159
2160 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2161 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH))
2162 UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
2163
2164 /* Perform route refreshment to the peer */
2165 bgp_announce_route (peer, afi, safi);
2166}
2167
paul94f2b392005-06-28 12:44:16 +00002168static int
paul718e3742002-12-13 20:15:29 +00002169bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
2170{
2171 u_char *end;
Paul Jakma6d582722007-08-06 15:21:45 +00002172 struct capability_mp_data mpc;
2173 struct capability_header *hdr;
paul718e3742002-12-13 20:15:29 +00002174 u_char action;
2175 struct bgp *bgp;
2176 afi_t afi;
2177 safi_t safi;
2178
2179 bgp = peer->bgp;
2180 end = pnt + length;
2181
2182 while (pnt < end)
Paul Jakma6d582722007-08-06 15:21:45 +00002183 {
paul718e3742002-12-13 20:15:29 +00002184 /* We need at least action, capability code and capability length. */
2185 if (pnt + 3 > end)
2186 {
2187 zlog_info ("%s Capability length error", peer->host);
2188 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2189 return -1;
2190 }
paul718e3742002-12-13 20:15:29 +00002191 action = *pnt;
Paul Jakma6d582722007-08-06 15:21:45 +00002192 hdr = (struct capability_header *)(pnt + 1);
2193
paul718e3742002-12-13 20:15:29 +00002194 /* Action value check. */
2195 if (action != CAPABILITY_ACTION_SET
2196 && action != CAPABILITY_ACTION_UNSET)
2197 {
2198 zlog_info ("%s Capability Action Value error %d",
2199 peer->host, action);
2200 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2201 return -1;
2202 }
2203
2204 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002205 zlog_debug ("%s CAPABILITY has action: %d, code: %u, length %u",
Paul Jakma6d582722007-08-06 15:21:45 +00002206 peer->host, action, hdr->code, hdr->length);
paul718e3742002-12-13 20:15:29 +00002207
2208 /* Capability length check. */
Paul Jakma6d582722007-08-06 15:21:45 +00002209 if ((pnt + hdr->length + 3) > end)
paul718e3742002-12-13 20:15:29 +00002210 {
2211 zlog_info ("%s Capability length error", peer->host);
2212 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2213 return -1;
2214 }
2215
Paul Jakma6d582722007-08-06 15:21:45 +00002216 /* Fetch structure to the byte stream. */
2217 memcpy (&mpc, pnt + 3, sizeof (struct capability_mp_data));
2218
paul718e3742002-12-13 20:15:29 +00002219 /* We know MP Capability Code. */
Paul Jakma6d582722007-08-06 15:21:45 +00002220 if (hdr->code == CAPABILITY_CODE_MP)
paul718e3742002-12-13 20:15:29 +00002221 {
Paul Jakma6d582722007-08-06 15:21:45 +00002222 afi = ntohs (mpc.afi);
2223 safi = mpc.safi;
paul718e3742002-12-13 20:15:29 +00002224
2225 /* Ignore capability when override-capability is set. */
2226 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
2227 continue;
Paul Jakma6d582722007-08-06 15:21:45 +00002228
2229 if (!bgp_afi_safi_valid_indices (afi, &safi))
2230 {
2231 if (BGP_DEBUG (normal, NORMAL))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002232 zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid "
2233 "(%u/%u)", peer->host, afi, safi);
Paul Jakma6d582722007-08-06 15:21:45 +00002234 continue;
2235 }
2236
paul718e3742002-12-13 20:15:29 +00002237 /* Address family check. */
Paul Jakma6d582722007-08-06 15:21:45 +00002238 if (BGP_DEBUG (normal, NORMAL))
2239 zlog_debug ("%s CAPABILITY has %s MP_EXT CAP for afi/safi: %u/%u",
2240 peer->host,
2241 action == CAPABILITY_ACTION_SET
2242 ? "Advertising" : "Removing",
2243 ntohs(mpc.afi) , mpc.safi);
2244
2245 if (action == CAPABILITY_ACTION_SET)
2246 {
2247 peer->afc_recv[afi][safi] = 1;
2248 if (peer->afc[afi][safi])
2249 {
2250 peer->afc_nego[afi][safi] = 1;
2251 bgp_announce_route (peer, afi, safi);
2252 }
2253 }
2254 else
2255 {
2256 peer->afc_recv[afi][safi] = 0;
2257 peer->afc_nego[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00002258
Paul Jakma6d582722007-08-06 15:21:45 +00002259 if (peer_active_nego (peer))
Chris Caputo228da422009-07-18 05:44:03 +00002260 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
Paul Jakma6d582722007-08-06 15:21:45 +00002261 else
2262 BGP_EVENT_ADD (peer, BGP_Stop);
2263 }
paul718e3742002-12-13 20:15:29 +00002264 }
paul718e3742002-12-13 20:15:29 +00002265 else
2266 {
2267 zlog_warn ("%s unrecognized capability code: %d - ignored",
Paul Jakma6d582722007-08-06 15:21:45 +00002268 peer->host, hdr->code);
paul718e3742002-12-13 20:15:29 +00002269 }
Paul Jakma6d582722007-08-06 15:21:45 +00002270 pnt += hdr->length + 3;
paul718e3742002-12-13 20:15:29 +00002271 }
2272 return 0;
2273}
2274
Paul Jakma01b7ce22009-06-18 12:34:43 +01002275/* Dynamic Capability is received.
2276 *
2277 * This is exported for unit-test purposes
2278 */
Paul Jakma6d582722007-08-06 15:21:45 +00002279int
paul718e3742002-12-13 20:15:29 +00002280bgp_capability_receive (struct peer *peer, bgp_size_t size)
2281{
2282 u_char *pnt;
paul718e3742002-12-13 20:15:29 +00002283
2284 /* Fetch pointer. */
2285 pnt = stream_pnt (peer->ibuf);
2286
2287 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002288 zlog_debug ("%s rcv CAPABILITY", peer->host);
paul718e3742002-12-13 20:15:29 +00002289
2290 /* If peer does not have the capability, send notification. */
2291 if (! CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV))
2292 {
2293 plog_err (peer->log, "%s [Error] BGP dynamic capability is not enabled",
2294 peer->host);
2295 bgp_notify_send (peer,
2296 BGP_NOTIFY_HEADER_ERR,
2297 BGP_NOTIFY_HEADER_BAD_MESTYPE);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002298 return -1;
paul718e3742002-12-13 20:15:29 +00002299 }
2300
2301 /* Status must be Established. */
2302 if (peer->status != Established)
2303 {
2304 plog_err (peer->log,
2305 "%s [Error] Dynamic capability packet received under status %s", peer->host, LOOKUP (bgp_status_msg, peer->status));
2306 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002307 return -1;
paul718e3742002-12-13 20:15:29 +00002308 }
2309
2310 /* Parse packet. */
Paul Jakma6d582722007-08-06 15:21:45 +00002311 return bgp_capability_msg_parse (peer, pnt, size);
paul718e3742002-12-13 20:15:29 +00002312}
2313
2314/* BGP read utility function. */
paul94f2b392005-06-28 12:44:16 +00002315static int
paul718e3742002-12-13 20:15:29 +00002316bgp_read_packet (struct peer *peer)
2317{
2318 int nbytes;
2319 int readsize;
2320
paul9985f832005-02-09 15:51:56 +00002321 readsize = peer->packet_size - stream_get_endp (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00002322
2323 /* If size is zero then return. */
2324 if (! readsize)
2325 return 0;
2326
2327 /* Read packet from fd. */
Stephen Hemminger35398582010-08-05 10:26:23 -07002328 nbytes = stream_read_try (peer->ibuf, peer->fd, readsize);
paul718e3742002-12-13 20:15:29 +00002329
2330 /* If read byte is smaller than zero then error occured. */
2331 if (nbytes < 0)
2332 {
Stephen Hemminger35398582010-08-05 10:26:23 -07002333 /* Transient error should retry */
2334 if (nbytes == -2)
paul718e3742002-12-13 20:15:29 +00002335 return -1;
2336
2337 plog_err (peer->log, "%s [Error] bgp_read_packet error: %s",
ajs6099b3b2004-11-20 02:06:59 +00002338 peer->host, safe_strerror (errno));
hasso93406d82005-02-02 14:40:33 +00002339
2340 if (peer->status == Established)
2341 {
2342 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
2343 {
2344 peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
2345 SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
2346 }
2347 else
2348 peer->last_reset = PEER_DOWN_CLOSE_SESSION;
2349 }
2350
paul718e3742002-12-13 20:15:29 +00002351 BGP_EVENT_ADD (peer, TCP_fatal_error);
2352 return -1;
2353 }
2354
2355 /* When read byte is zero : clear bgp peer and return */
2356 if (nbytes == 0)
2357 {
2358 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +00002359 plog_debug (peer->log, "%s [Event] BGP connection closed fd %d",
pauleb821182004-05-01 08:44:08 +00002360 peer->host, peer->fd);
hassoe0701b72004-05-20 09:19:34 +00002361
2362 if (peer->status == Established)
hasso93406d82005-02-02 14:40:33 +00002363 {
2364 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
2365 {
2366 peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
2367 SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
2368 }
2369 else
2370 peer->last_reset = PEER_DOWN_CLOSE_SESSION;
2371 }
hassoe0701b72004-05-20 09:19:34 +00002372
paul718e3742002-12-13 20:15:29 +00002373 BGP_EVENT_ADD (peer, TCP_connection_closed);
2374 return -1;
2375 }
2376
2377 /* We read partial packet. */
paul9985f832005-02-09 15:51:56 +00002378 if (stream_get_endp (peer->ibuf) != peer->packet_size)
paul718e3742002-12-13 20:15:29 +00002379 return -1;
2380
2381 return 0;
2382}
2383
2384/* Marker check. */
paul94f2b392005-06-28 12:44:16 +00002385static int
paul718e3742002-12-13 20:15:29 +00002386bgp_marker_all_one (struct stream *s, int length)
2387{
2388 int i;
2389
2390 for (i = 0; i < length; i++)
2391 if (s->data[i] != 0xff)
2392 return 0;
2393
2394 return 1;
2395}
2396
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002397/* Recent thread time.
2398 On same clock base as bgp_clock (MONOTONIC)
2399 but can be time of last context switch to bgp_read thread. */
2400static time_t
2401bgp_recent_clock (void)
2402{
2403 return recent_relative_time().tv_sec;
2404}
2405
paul718e3742002-12-13 20:15:29 +00002406/* Starting point of packet process function. */
2407int
2408bgp_read (struct thread *thread)
2409{
2410 int ret;
2411 u_char type = 0;
2412 struct peer *peer;
2413 bgp_size_t size;
2414 char notify_data_length[2];
2415
2416 /* Yes first of all get peer pointer. */
2417 peer = THREAD_ARG (thread);
2418 peer->t_read = NULL;
2419
2420 /* For non-blocking IO check. */
2421 if (peer->status == Connect)
2422 {
2423 bgp_connect_check (peer);
2424 goto done;
2425 }
2426 else
2427 {
pauleb821182004-05-01 08:44:08 +00002428 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +00002429 {
pauleb821182004-05-01 08:44:08 +00002430 zlog_err ("bgp_read peer's fd is negative value %d", peer->fd);
paul718e3742002-12-13 20:15:29 +00002431 return -1;
2432 }
pauleb821182004-05-01 08:44:08 +00002433 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
paul718e3742002-12-13 20:15:29 +00002434 }
2435
2436 /* Read packet header to determine type of the packet */
2437 if (peer->packet_size == 0)
2438 peer->packet_size = BGP_HEADER_SIZE;
2439
paul9985f832005-02-09 15:51:56 +00002440 if (stream_get_endp (peer->ibuf) < BGP_HEADER_SIZE)
paul718e3742002-12-13 20:15:29 +00002441 {
2442 ret = bgp_read_packet (peer);
2443
2444 /* Header read error or partial read packet. */
2445 if (ret < 0)
2446 goto done;
2447
2448 /* Get size and type. */
paul9985f832005-02-09 15:51:56 +00002449 stream_forward_getp (peer->ibuf, BGP_MARKER_SIZE);
paul718e3742002-12-13 20:15:29 +00002450 memcpy (notify_data_length, stream_pnt (peer->ibuf), 2);
2451 size = stream_getw (peer->ibuf);
2452 type = stream_getc (peer->ibuf);
2453
2454 if (BGP_DEBUG (normal, NORMAL) && type != 2 && type != 0)
ajs6b514742004-12-08 21:03:23 +00002455 zlog_debug ("%s rcv message type %d, length (excl. header) %d",
paul718e3742002-12-13 20:15:29 +00002456 peer->host, type, size - BGP_HEADER_SIZE);
2457
2458 /* Marker check */
paulf5ba3872004-07-09 12:11:31 +00002459 if (((type == BGP_MSG_OPEN) || (type == BGP_MSG_KEEPALIVE))
paul718e3742002-12-13 20:15:29 +00002460 && ! bgp_marker_all_one (peer->ibuf, BGP_MARKER_SIZE))
2461 {
2462 bgp_notify_send (peer,
2463 BGP_NOTIFY_HEADER_ERR,
2464 BGP_NOTIFY_HEADER_NOT_SYNC);
2465 goto done;
2466 }
2467
2468 /* BGP type check. */
2469 if (type != BGP_MSG_OPEN && type != BGP_MSG_UPDATE
2470 && type != BGP_MSG_NOTIFY && type != BGP_MSG_KEEPALIVE
2471 && type != BGP_MSG_ROUTE_REFRESH_NEW
2472 && type != BGP_MSG_ROUTE_REFRESH_OLD
2473 && type != BGP_MSG_CAPABILITY)
2474 {
2475 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002476 plog_debug (peer->log,
paul718e3742002-12-13 20:15:29 +00002477 "%s unknown message type 0x%02x",
2478 peer->host, type);
2479 bgp_notify_send_with_data (peer,
2480 BGP_NOTIFY_HEADER_ERR,
2481 BGP_NOTIFY_HEADER_BAD_MESTYPE,
2482 &type, 1);
2483 goto done;
2484 }
2485 /* Mimimum packet length check. */
2486 if ((size < BGP_HEADER_SIZE)
2487 || (size > BGP_MAX_PACKET_SIZE)
2488 || (type == BGP_MSG_OPEN && size < BGP_MSG_OPEN_MIN_SIZE)
2489 || (type == BGP_MSG_UPDATE && size < BGP_MSG_UPDATE_MIN_SIZE)
2490 || (type == BGP_MSG_NOTIFY && size < BGP_MSG_NOTIFY_MIN_SIZE)
2491 || (type == BGP_MSG_KEEPALIVE && size != BGP_MSG_KEEPALIVE_MIN_SIZE)
2492 || (type == BGP_MSG_ROUTE_REFRESH_NEW && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
2493 || (type == BGP_MSG_ROUTE_REFRESH_OLD && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
2494 || (type == BGP_MSG_CAPABILITY && size < BGP_MSG_CAPABILITY_MIN_SIZE))
2495 {
2496 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002497 plog_debug (peer->log,
paul718e3742002-12-13 20:15:29 +00002498 "%s bad message length - %d for %s",
2499 peer->host, size,
2500 type == 128 ? "ROUTE-REFRESH" :
2501 bgp_type_str[(int) type]);
2502 bgp_notify_send_with_data (peer,
2503 BGP_NOTIFY_HEADER_ERR,
2504 BGP_NOTIFY_HEADER_BAD_MESLEN,
hassoc9e52be2004-09-26 16:09:34 +00002505 (u_char *) notify_data_length, 2);
paul718e3742002-12-13 20:15:29 +00002506 goto done;
2507 }
2508
2509 /* Adjust size to message length. */
2510 peer->packet_size = size;
2511 }
2512
2513 ret = bgp_read_packet (peer);
2514 if (ret < 0)
2515 goto done;
2516
2517 /* Get size and type again. */
2518 size = stream_getw_from (peer->ibuf, BGP_MARKER_SIZE);
2519 type = stream_getc_from (peer->ibuf, BGP_MARKER_SIZE + 2);
2520
2521 /* BGP packet dump function. */
2522 bgp_dump_packet (peer, type, peer->ibuf);
2523
2524 size = (peer->packet_size - BGP_HEADER_SIZE);
2525
2526 /* Read rest of the packet and call each sort of packet routine */
2527 switch (type)
2528 {
2529 case BGP_MSG_OPEN:
2530 peer->open_in++;
paulf5ba3872004-07-09 12:11:31 +00002531 bgp_open_receive (peer, size); /* XXX return value ignored! */
paul718e3742002-12-13 20:15:29 +00002532 break;
2533 case BGP_MSG_UPDATE:
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002534 peer->readtime = bgp_recent_clock ();
paul718e3742002-12-13 20:15:29 +00002535 bgp_update_receive (peer, size);
2536 break;
2537 case BGP_MSG_NOTIFY:
2538 bgp_notify_receive (peer, size);
2539 break;
2540 case BGP_MSG_KEEPALIVE:
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002541 peer->readtime = bgp_recent_clock ();
paul718e3742002-12-13 20:15:29 +00002542 bgp_keepalive_receive (peer, size);
2543 break;
2544 case BGP_MSG_ROUTE_REFRESH_NEW:
2545 case BGP_MSG_ROUTE_REFRESH_OLD:
2546 peer->refresh_in++;
2547 bgp_route_refresh_receive (peer, size);
2548 break;
2549 case BGP_MSG_CAPABILITY:
2550 peer->dynamic_cap_in++;
2551 bgp_capability_receive (peer, size);
2552 break;
2553 }
2554
2555 /* Clear input buffer. */
2556 peer->packet_size = 0;
2557 if (peer->ibuf)
2558 stream_reset (peer->ibuf);
2559
2560 done:
2561 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2562 {
2563 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +00002564 zlog_debug ("%s [Event] Accepting BGP peer delete", peer->host);
paul718e3742002-12-13 20:15:29 +00002565 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00002566 }
2567 return 0;
2568}