blob: b0918fc52f014382bb6e59b6aac5f42eef50653f [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
pauleb821182004-05-01 08:44:08 +0000726 ret = writen (peer->fd, STREAM_DATA (s), stream_get_endp (s));
paul718e3742002-12-13 20:15:29 +0000727 if (ret <= 0)
728 {
Paul Jakmadcdf3992006-10-15 23:39:59 +0000729 BGP_EVENT_ADD (peer, TCP_fatal_error);
paul718e3742002-12-13 20:15:29 +0000730 return 0;
731 }
732
733 /* Retrieve BGP packet type. */
734 stream_set_getp (s, BGP_MARKER_SIZE + 2);
735 type = stream_getc (s);
736
737 assert (type == BGP_MSG_NOTIFY);
738
739 /* Type should be notify. */
740 peer->notify_out++;
741
742 /* Double start timer. */
743 peer->v_start *= 2;
744
745 /* Overflow check. */
746 if (peer->v_start >= (60 * 2))
747 peer->v_start = (60 * 2);
748
Paul Jakmadcdf3992006-10-15 23:39:59 +0000749 BGP_EVENT_ADD (peer, BGP_Stop);
paul718e3742002-12-13 20:15:29 +0000750
751 return 0;
752}
753
754/* Make keepalive packet and send it to the peer. */
755void
756bgp_keepalive_send (struct peer *peer)
757{
758 struct stream *s;
759 int length;
760
761 s = stream_new (BGP_MAX_PACKET_SIZE);
762
763 /* Make keepalive packet. */
764 bgp_packet_set_marker (s, BGP_MSG_KEEPALIVE);
765
766 /* Set packet size. */
767 length = bgp_packet_set_size (s);
768
769 /* Dump packet if debug option is set. */
770 /* bgp_packet_dump (s); */
771
772 if (BGP_DEBUG (keepalive, KEEPALIVE))
ajs6b514742004-12-08 21:03:23 +0000773 zlog_debug ("%s sending KEEPALIVE", peer->host);
paul718e3742002-12-13 20:15:29 +0000774 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000775 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000776 peer->host, BGP_MSG_KEEPALIVE, length);
777
778 /* Add packet to the peer. */
779 bgp_packet_add (peer, s);
780
pauleb821182004-05-01 08:44:08 +0000781 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000782}
783
784/* Make open packet and send it to the peer. */
785void
786bgp_open_send (struct peer *peer)
787{
788 struct stream *s;
789 int length;
790 u_int16_t send_holdtime;
791 as_t local_as;
792
793 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
794 send_holdtime = peer->holdtime;
795 else
796 send_holdtime = peer->bgp->default_holdtime;
797
798 /* local-as Change */
799 if (peer->change_local_as)
800 local_as = peer->change_local_as;
801 else
802 local_as = peer->local_as;
803
804 s = stream_new (BGP_MAX_PACKET_SIZE);
805
806 /* Make open packet. */
807 bgp_packet_set_marker (s, BGP_MSG_OPEN);
808
809 /* Set open packet values. */
810 stream_putc (s, BGP_VERSION_4); /* BGP version */
Paul Jakma0b2aa3a2007-10-14 22:32:21 +0000811 stream_putw (s, (local_as <= BGP_AS_MAX) ? (u_int16_t) local_as
812 : BGP_AS_TRANS);
paul718e3742002-12-13 20:15:29 +0000813 stream_putw (s, send_holdtime); /* Hold Time */
814 stream_put_in_addr (s, &peer->local_id); /* BGP Identifier */
815
816 /* Set capability code. */
817 bgp_open_capability (s, peer);
818
819 /* Set BGP packet length. */
820 length = bgp_packet_set_size (s);
821
822 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +0400823 zlog_debug ("%s sending OPEN, version %d, my as %u, holdtime %d, id %s",
paul718e3742002-12-13 20:15:29 +0000824 peer->host, BGP_VERSION_4, local_as,
825 send_holdtime, inet_ntoa (peer->local_id));
826
827 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000828 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000829 peer->host, BGP_MSG_OPEN, length);
830
831 /* Dump packet if debug option is set. */
832 /* bgp_packet_dump (s); */
833
834 /* Add packet to the peer. */
835 bgp_packet_add (peer, s);
836
pauleb821182004-05-01 08:44:08 +0000837 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +0000838}
839
840/* Send BGP notify packet with data potion. */
841void
842bgp_notify_send_with_data (struct peer *peer, u_char code, u_char sub_code,
843 u_char *data, size_t datalen)
844{
845 struct stream *s;
846 int length;
847
848 /* Allocate new stream. */
849 s = stream_new (BGP_MAX_PACKET_SIZE);
850
851 /* Make nitify packet. */
852 bgp_packet_set_marker (s, BGP_MSG_NOTIFY);
853
854 /* Set notify packet values. */
855 stream_putc (s, code); /* BGP notify code */
856 stream_putc (s, sub_code); /* BGP notify sub_code */
857
858 /* If notify data is present. */
859 if (data)
860 stream_write (s, data, datalen);
861
862 /* Set BGP packet length. */
863 length = bgp_packet_set_size (s);
864
865 /* Add packet to the peer. */
866 stream_fifo_clean (peer->obuf);
867 bgp_packet_add (peer, s);
868
869 /* For debug */
870 {
871 struct bgp_notify bgp_notify;
872 int first = 0;
873 int i;
874 char c[4];
875
876 bgp_notify.code = code;
877 bgp_notify.subcode = sub_code;
878 bgp_notify.data = NULL;
879 bgp_notify.length = length - BGP_MSG_NOTIFY_MIN_SIZE;
880
881 if (bgp_notify.length)
882 {
883 bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
884 for (i = 0; i < bgp_notify.length; i++)
885 if (first)
886 {
887 sprintf (c, " %02x", data[i]);
888 strcat (bgp_notify.data, c);
889 }
890 else
891 {
892 first = 1;
893 sprintf (c, "%02x", data[i]);
894 strcpy (bgp_notify.data, c);
895 }
896 }
897 bgp_notify_print (peer, &bgp_notify, "sending");
898 if (bgp_notify.data)
899 XFREE (MTYPE_TMP, bgp_notify.data);
900 }
901
902 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000903 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +0000904 peer->host, BGP_MSG_NOTIFY, length);
905
hassoe0701b72004-05-20 09:19:34 +0000906 /* peer reset cause */
907 if (sub_code != BGP_NOTIFY_CEASE_CONFIG_CHANGE)
908 {
909 if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET)
heasley1212dc12011-09-12 13:27:52 +0400910 {
911 peer->last_reset = PEER_DOWN_USER_RESET;
912 zlog_info ("Notification sent to neighbor %s: User reset", peer->host);
913 }
hassoe0701b72004-05-20 09:19:34 +0000914 else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN)
heasley1212dc12011-09-12 13:27:52 +0400915 {
916 peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
917 zlog_info ("Notification sent to neighbor %s: shutdown", peer->host);
918 }
hassoe0701b72004-05-20 09:19:34 +0000919 else
heasley1212dc12011-09-12 13:27:52 +0400920 {
921 peer->last_reset = PEER_DOWN_NOTIFY_SEND;
922 zlog_info ("Notification sent to neighbor %s: type %u/%u",
923 peer->host, code, sub_code);
924 }
hassoe0701b72004-05-20 09:19:34 +0000925 }
heasley1212dc12011-09-12 13:27:52 +0400926 else
927 zlog_info ("Notification sent to neighbor %s: configuration change",
928 peer->host);
hassoe0701b72004-05-20 09:19:34 +0000929
Denis Ovsienko7ccf5e52011-09-10 16:53:30 +0400930 /* Call immediately. */
paul718e3742002-12-13 20:15:29 +0000931 BGP_WRITE_OFF (peer->t_write);
932
933 bgp_write_notify (peer);
934}
935
936/* Send BGP notify packet. */
937void
938bgp_notify_send (struct peer *peer, u_char code, u_char sub_code)
939{
940 bgp_notify_send_with_data (peer, code, sub_code, NULL, 0);
941}
942
paul718e3742002-12-13 20:15:29 +0000943/* Send route refresh message to the peer. */
944void
945bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
946 u_char orf_type, u_char when_to_refresh, int remove)
947{
948 struct stream *s;
949 struct stream *packet;
950 int length;
951 struct bgp_filter *filter;
952 int orf_refresh = 0;
953
Paul Jakma750e8142008-07-22 21:11:48 +0000954 if (DISABLE_BGP_ANNOUNCE)
955 return;
paul718e3742002-12-13 20:15:29 +0000956
957 filter = &peer->filter[afi][safi];
958
959 /* Adjust safi code. */
960 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +0400961 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +0000962
963 s = stream_new (BGP_MAX_PACKET_SIZE);
964
965 /* Make BGP update packet. */
966 if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
967 bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_NEW);
968 else
969 bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_OLD);
970
971 /* Encode Route Refresh message. */
972 stream_putw (s, afi);
973 stream_putc (s, 0);
974 stream_putc (s, safi);
975
976 if (orf_type == ORF_TYPE_PREFIX
977 || orf_type == ORF_TYPE_PREFIX_OLD)
978 if (remove || filter->plist[FILTER_IN].plist)
979 {
980 u_int16_t orf_len;
981 unsigned long orfp;
982
983 orf_refresh = 1;
984 stream_putc (s, when_to_refresh);
985 stream_putc (s, orf_type);
paul9985f832005-02-09 15:51:56 +0000986 orfp = stream_get_endp (s);
paul718e3742002-12-13 20:15:29 +0000987 stream_putw (s, 0);
988
989 if (remove)
990 {
991 UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
992 stream_putc (s, ORF_COMMON_PART_REMOVE_ALL);
993 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +0000994 zlog_debug ("%s sending REFRESH_REQ to remove ORF(%d) (%s) for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +0000995 peer->host, orf_type,
996 (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
997 afi, safi);
998 }
999 else
1000 {
1001 SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
1002 prefix_bgp_orf_entry (s, filter->plist[FILTER_IN].plist,
1003 ORF_COMMON_PART_ADD, ORF_COMMON_PART_PERMIT,
1004 ORF_COMMON_PART_DENY);
1005 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001006 zlog_debug ("%s sending REFRESH_REQ with pfxlist ORF(%d) (%s) for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001007 peer->host, orf_type,
1008 (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
1009 afi, safi);
1010 }
1011
1012 /* Total ORF Entry Len. */
paul9985f832005-02-09 15:51:56 +00001013 orf_len = stream_get_endp (s) - orfp - 2;
paul718e3742002-12-13 20:15:29 +00001014 stream_putw_at (s, orfp, orf_len);
1015 }
1016
1017 /* Set packet size. */
1018 length = bgp_packet_set_size (s);
1019
1020 if (BGP_DEBUG (normal, NORMAL))
1021 {
1022 if (! orf_refresh)
ajs6b514742004-12-08 21:03:23 +00001023 zlog_debug ("%s sending REFRESH_REQ for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001024 peer->host, afi, safi);
ajs6b514742004-12-08 21:03:23 +00001025 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +00001026 peer->host, CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV) ?
1027 BGP_MSG_ROUTE_REFRESH_NEW : BGP_MSG_ROUTE_REFRESH_OLD, length);
1028 }
1029
1030 /* Make real packet. */
paule83e2082005-05-19 02:12:25 +00001031 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +00001032 stream_free (s);
1033
1034 /* Add packet to the peer. */
1035 bgp_packet_add (peer, packet);
1036
pauleb821182004-05-01 08:44:08 +00001037 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +00001038}
1039
1040/* Send capability message to the peer. */
1041void
1042bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi,
1043 int capability_code, int action)
1044{
1045 struct stream *s;
1046 struct stream *packet;
1047 int length;
1048
1049 /* Adjust safi code. */
1050 if (safi == SAFI_MPLS_VPN)
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001051 safi = SAFI_MPLS_LABELED_VPN;
paul718e3742002-12-13 20:15:29 +00001052
1053 s = stream_new (BGP_MAX_PACKET_SIZE);
1054
1055 /* Make BGP update packet. */
1056 bgp_packet_set_marker (s, BGP_MSG_CAPABILITY);
1057
1058 /* Encode MP_EXT capability. */
1059 if (capability_code == CAPABILITY_CODE_MP)
1060 {
1061 stream_putc (s, action);
1062 stream_putc (s, CAPABILITY_CODE_MP);
1063 stream_putc (s, CAPABILITY_CODE_MP_LEN);
1064 stream_putw (s, afi);
1065 stream_putc (s, 0);
1066 stream_putc (s, safi);
1067
1068 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001069 zlog_debug ("%s sending CAPABILITY has %s MP_EXT CAP for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001070 peer->host, action == CAPABILITY_ACTION_SET ?
1071 "Advertising" : "Removing", afi, safi);
1072 }
1073
paul718e3742002-12-13 20:15:29 +00001074 /* Set packet size. */
1075 length = bgp_packet_set_size (s);
1076
1077 /* Make real packet. */
paule83e2082005-05-19 02:12:25 +00001078 packet = stream_dup (s);
paul718e3742002-12-13 20:15:29 +00001079 stream_free (s);
1080
1081 /* Add packet to the peer. */
1082 bgp_packet_add (peer, packet);
1083
1084 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001085 zlog_debug ("%s send message type %d, length (incl. header) %d",
paul718e3742002-12-13 20:15:29 +00001086 peer->host, BGP_MSG_CAPABILITY, length);
1087
pauleb821182004-05-01 08:44:08 +00001088 BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
paul718e3742002-12-13 20:15:29 +00001089}
1090
1091/* RFC1771 6.8 Connection collision detection. */
paul94f2b392005-06-28 12:44:16 +00001092static int
pauleb821182004-05-01 08:44:08 +00001093bgp_collision_detect (struct peer *new, struct in_addr remote_id)
paul718e3742002-12-13 20:15:29 +00001094{
pauleb821182004-05-01 08:44:08 +00001095 struct peer *peer;
paul1eb8ef22005-04-07 07:30:20 +00001096 struct listnode *node, *nnode;
paul718e3742002-12-13 20:15:29 +00001097 struct bgp *bgp;
1098
1099 bgp = bgp_get_default ();
1100 if (! bgp)
1101 return 0;
1102
1103 /* Upon receipt of an OPEN message, the local system must examine
1104 all of its connections that are in the OpenConfirm state. A BGP
1105 speaker may also examine connections in an OpenSent state if it
1106 knows the BGP Identifier of the peer by means outside of the
1107 protocol. If among these connections there is a connection to a
1108 remote BGP speaker whose BGP Identifier equals the one in the
1109 OPEN message, then the local system performs the following
1110 collision resolution procedure: */
1111
paul1eb8ef22005-04-07 07:30:20 +00001112 for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
paul718e3742002-12-13 20:15:29 +00001113 {
1114 /* Under OpenConfirm status, local peer structure already hold
1115 remote router ID. */
pauleb821182004-05-01 08:44:08 +00001116
1117 if (peer != new
1118 && (peer->status == OpenConfirm || peer->status == OpenSent)
1119 && sockunion_same (&peer->su, &new->su))
1120 {
paul718e3742002-12-13 20:15:29 +00001121 /* 1. The BGP Identifier of the local system is compared to
1122 the BGP Identifier of the remote system (as specified in
1123 the OPEN message). */
1124
1125 if (ntohl (peer->local_id.s_addr) < ntohl (remote_id.s_addr))
1126 {
1127 /* 2. If the value of the local BGP Identifier is less
1128 than the remote one, the local system closes BGP
1129 connection that already exists (the one that is
1130 already in the OpenConfirm state), and accepts BGP
1131 connection initiated by the remote system. */
1132
pauleb821182004-05-01 08:44:08 +00001133 if (peer->fd >= 0)
hassoe0701b72004-05-20 09:19:34 +00001134 bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
paul718e3742002-12-13 20:15:29 +00001135 return 1;
1136 }
1137 else
1138 {
1139 /* 3. Otherwise, the local system closes newly created
1140 BGP connection (the one associated with the newly
1141 received OPEN message), and continues to use the
1142 existing one (the one that is already in the
1143 OpenConfirm state). */
1144
pauleb821182004-05-01 08:44:08 +00001145 if (new->fd >= 0)
paulf5ba3872004-07-09 12:11:31 +00001146 bgp_notify_send (new, BGP_NOTIFY_CEASE,
1147 BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
paul718e3742002-12-13 20:15:29 +00001148 return -1;
1149 }
pauleb821182004-05-01 08:44:08 +00001150 }
1151 }
paul718e3742002-12-13 20:15:29 +00001152 return 0;
1153}
1154
paul94f2b392005-06-28 12:44:16 +00001155static int
paul718e3742002-12-13 20:15:29 +00001156bgp_open_receive (struct peer *peer, bgp_size_t size)
1157{
1158 int ret;
1159 u_char version;
1160 u_char optlen;
1161 u_int16_t holdtime;
1162 u_int16_t send_holdtime;
1163 as_t remote_as;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001164 as_t as4 = 0;
paul718e3742002-12-13 20:15:29 +00001165 struct peer *realpeer;
1166 struct in_addr remote_id;
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001167 int mp_capability;
paul5228ad22004-06-04 17:58:18 +00001168 u_int8_t notify_data_remote_as[2];
1169 u_int8_t notify_data_remote_id[4];
paul718e3742002-12-13 20:15:29 +00001170
1171 realpeer = NULL;
1172
1173 /* Parse open packet. */
1174 version = stream_getc (peer->ibuf);
1175 memcpy (notify_data_remote_as, stream_pnt (peer->ibuf), 2);
1176 remote_as = stream_getw (peer->ibuf);
1177 holdtime = stream_getw (peer->ibuf);
1178 memcpy (notify_data_remote_id, stream_pnt (peer->ibuf), 4);
1179 remote_id.s_addr = stream_get_ipv4 (peer->ibuf);
1180
1181 /* Receive OPEN message log */
1182 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001183 zlog_debug ("%s rcv OPEN, version %d, remote-as (in open) %u,"
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001184 " holdtime %d, id %s",
1185 peer->host, version, remote_as, holdtime,
1186 inet_ntoa (remote_id));
1187
1188 /* BEGIN to read the capability here, but dont do it yet */
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001189 mp_capability = 0;
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001190 optlen = stream_getc (peer->ibuf);
1191
1192 if (optlen != 0)
1193 {
1194 /* We need the as4 capability value *right now* because
1195 * if it is there, we have not got the remote_as yet, and without
1196 * that we do not know which peer is connecting to us now.
1197 */
1198 as4 = peek_for_as4_capability (peer, optlen);
1199 }
1200
1201 /* Just in case we have a silly peer who sends AS4 capability set to 0 */
1202 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) && !as4)
1203 {
1204 zlog_err ("%s bad OPEN, got AS4 capability, but AS4 set to 0",
1205 peer->host);
1206 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1207 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1208 return -1;
1209 }
1210
1211 if (remote_as == BGP_AS_TRANS)
1212 {
1213 /* Take the AS4 from the capability. We must have received the
1214 * capability now! Otherwise we have a asn16 peer who uses
1215 * BGP_AS_TRANS, for some unknown reason.
1216 */
1217 if (as4 == BGP_AS_TRANS)
1218 {
1219 zlog_err ("%s [AS4] NEW speaker using AS_TRANS for AS4, not allowed",
1220 peer->host);
1221 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1222 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1223 return -1;
1224 }
1225
1226 if (!as4 && BGP_DEBUG (as4, AS4))
1227 zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but no AS4."
1228 " Odd, but proceeding.", peer->host);
1229 else if (as4 < BGP_AS_MAX && BGP_DEBUG (as4, AS4))
Paul Jakma0df7c912008-07-21 21:02:49 +00001230 zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but AS4 (%u) fits "
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00001231 "in 2-bytes, very odd peer.", peer->host, as4);
1232 if (as4)
1233 remote_as = as4;
1234 }
1235 else
1236 {
1237 /* We may have a partner with AS4 who has an asno < BGP_AS_MAX */
1238 /* If we have got the capability, peer->as4cap must match remote_as */
1239 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)
1240 && as4 != remote_as)
1241 {
1242 /* raise error, log this, close session */
1243 zlog_err ("%s bad OPEN, got AS4 capability, but remote_as %u"
1244 " mismatch with 16bit 'myasn' %u in open",
1245 peer->host, as4, remote_as);
1246 bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
1247 BGP_NOTIFY_OPEN_BAD_PEER_AS);
1248 return -1;
1249 }
1250 }
1251
paul718e3742002-12-13 20:15:29 +00001252 /* Lookup peer from Open packet. */
1253 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1254 {
1255 int as = 0;
1256
1257 realpeer = peer_lookup_with_open (&peer->su, remote_as, &remote_id, &as);
1258
1259 if (! realpeer)
1260 {
1261 /* Peer's source IP address is check in bgp_accept(), so this
1262 must be AS number mismatch or remote-id configuration
1263 mismatch. */
1264 if (as)
1265 {
1266 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001267 zlog_debug ("%s bad OPEN, wrong router identifier %s",
1268 peer->host, inet_ntoa (remote_id));
1269 bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
1270 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
1271 notify_data_remote_id, 4);
paul718e3742002-12-13 20:15:29 +00001272 }
1273 else
1274 {
1275 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001276 zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
ajs6b514742004-12-08 21:03:23 +00001277 peer->host, remote_as, peer->as);
1278 bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
1279 BGP_NOTIFY_OPEN_BAD_PEER_AS,
1280 notify_data_remote_as, 2);
paul718e3742002-12-13 20:15:29 +00001281 }
1282 return -1;
1283 }
1284 }
1285
1286 /* When collision is detected and this peer is closed. Retrun
1287 immidiately. */
1288 ret = bgp_collision_detect (peer, remote_id);
1289 if (ret < 0)
1290 return ret;
1291
pauleb821182004-05-01 08:44:08 +00001292 /* Hack part. */
1293 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
1294 {
hasso93406d82005-02-02 14:40:33 +00001295 if (realpeer->status == Established
1296 && CHECK_FLAG (realpeer->sflags, PEER_STATUS_NSF_MODE))
1297 {
1298 realpeer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
1299 SET_FLAG (realpeer->sflags, PEER_STATUS_NSF_WAIT);
1300 }
1301 else if (ret == 0 && realpeer->status != Active
1302 && realpeer->status != OpenSent
Paul Jakma6e199262008-09-09 17:14:33 +01001303 && realpeer->status != OpenConfirm
1304 && realpeer->status != Connect)
pauleb821182004-05-01 08:44:08 +00001305 {
Paul Jakma2b2fc562008-09-06 13:09:35 +01001306 /* XXX: This is an awful problem..
1307 *
1308 * According to the RFC we should just let this connection (of the
1309 * accepted 'peer') continue on to Established if the other
1310 * connection (the 'realpeer' one) is in state Connect, and deal
1311 * with the more larval FSM as/when it gets far enough to receive
1312 * an Open. We don't do that though, we instead close the (more
1313 * developed) accepted connection.
1314 *
1315 * This means there's a race, which if hit, can loop:
1316 *
1317 * FSM for A FSM for B
1318 * realpeer accept-peer realpeer accept-peer
1319 *
1320 * Connect Connect
1321 * Active
1322 * OpenSent OpenSent
1323 * <arrive here,
1324 * Notify, delete>
1325 * Idle Active
1326 * OpenSent OpenSent
1327 * <arrive here,
1328 * Notify, delete>
1329 * Idle
1330 * <wait> <wait>
1331 * Connect Connect
1332 *
1333 *
1334 * If both sides are Quagga, they're almost certain to wait for
1335 * the same amount of time of course (which doesn't preclude other
1336 * implementations also waiting for same time). The race is
1337 * exacerbated by high-latency (in bgpd and/or the network).
1338 *
1339 * The reason we do this is because our FSM is tied to our peer
1340 * structure, which carries our configuration information, etc.
1341 * I.e. we can't let the accepted-peer FSM continue on as it is,
1342 * cause it's not associated with any actual peer configuration -
1343 * it's just a dummy.
1344 *
1345 * It's possible we could hack-fix this by just bgp_stop'ing the
1346 * realpeer and continueing on with the 'transfer FSM' below.
1347 * Ideally, we need to seperate FSMs from struct peer.
1348 *
1349 * Setting one side to passive avoids the race, as a workaround.
1350 */
pauleb821182004-05-01 08:44:08 +00001351 if (BGP_DEBUG (events, EVENTS))
hasso93406d82005-02-02 14:40:33 +00001352 zlog_debug ("%s peer status is %s close connection",
1353 realpeer->host, LOOKUP (bgp_status_msg,
1354 realpeer->status));
1355 bgp_notify_send (peer, BGP_NOTIFY_CEASE,
1356 BGP_NOTIFY_CEASE_CONNECT_REJECT);
1357
pauleb821182004-05-01 08:44:08 +00001358 return -1;
1359 }
1360
1361 if (BGP_DEBUG (events, EVENTS))
Paul Jakma6e199262008-09-09 17:14:33 +01001362 zlog_debug ("%s [Event] Transfer accept BGP peer to real (state %s)",
1363 peer->host,
1364 LOOKUP (bgp_status_msg, realpeer->status));
pauleb821182004-05-01 08:44:08 +00001365
1366 bgp_stop (realpeer);
1367
1368 /* Transfer file descriptor. */
1369 realpeer->fd = peer->fd;
1370 peer->fd = -1;
1371
1372 /* Transfer input buffer. */
1373 stream_free (realpeer->ibuf);
1374 realpeer->ibuf = peer->ibuf;
1375 realpeer->packet_size = peer->packet_size;
1376 peer->ibuf = NULL;
1377
1378 /* Transfer status. */
1379 realpeer->status = peer->status;
1380 bgp_stop (peer);
paul200df112005-06-01 11:17:05 +00001381
pauleb821182004-05-01 08:44:08 +00001382 /* peer pointer change. Open packet send to neighbor. */
1383 peer = realpeer;
1384 bgp_open_send (peer);
1385 if (peer->fd < 0)
1386 {
1387 zlog_err ("bgp_open_receive peer's fd is negative value %d",
1388 peer->fd);
1389 return -1;
1390 }
1391 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
1392 }
1393
paul718e3742002-12-13 20:15:29 +00001394 /* remote router-id check. */
1395 if (remote_id.s_addr == 0
Denis Ovsienko733cd9e2011-12-17 19:39:30 +04001396 || IPV4_CLASS_DE (ntohl (remote_id.s_addr))
paul718e3742002-12-13 20:15:29 +00001397 || ntohl (peer->local_id.s_addr) == ntohl (remote_id.s_addr))
1398 {
1399 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001400 zlog_debug ("%s bad OPEN, wrong router identifier %s",
paul718e3742002-12-13 20:15:29 +00001401 peer->host, inet_ntoa (remote_id));
1402 bgp_notify_send_with_data (peer,
1403 BGP_NOTIFY_OPEN_ERR,
1404 BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
1405 notify_data_remote_id, 4);
1406 return -1;
1407 }
1408
1409 /* Set remote router-id */
1410 peer->remote_id = remote_id;
1411
1412 /* Peer BGP version check. */
1413 if (version != BGP_VERSION_4)
1414 {
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001415 u_int16_t maxver = htons(BGP_VERSION_4);
1416 /* XXX this reply may not be correct if version < 4 XXX */
paul718e3742002-12-13 20:15:29 +00001417 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001418 zlog_debug ("%s bad protocol version, remote requested %d, local request %d",
paul718e3742002-12-13 20:15:29 +00001419 peer->host, version, BGP_VERSION_4);
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001420 /* Data must be in network byte order here */
paul718e3742002-12-13 20:15:29 +00001421 bgp_notify_send_with_data (peer,
1422 BGP_NOTIFY_OPEN_ERR,
1423 BGP_NOTIFY_OPEN_UNSUP_VERSION,
Leonid Rosenboima689e6a2012-12-07 21:25:00 +00001424 (u_int8_t *) &maxver, 2);
paul718e3742002-12-13 20:15:29 +00001425 return -1;
1426 }
1427
1428 /* Check neighbor as number. */
1429 if (remote_as != peer->as)
1430 {
1431 if (BGP_DEBUG (normal, NORMAL))
Denis Ovsienkoaea339f2009-04-30 17:16:22 +04001432 zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
paul718e3742002-12-13 20:15:29 +00001433 peer->host, remote_as, peer->as);
1434 bgp_notify_send_with_data (peer,
1435 BGP_NOTIFY_OPEN_ERR,
1436 BGP_NOTIFY_OPEN_BAD_PEER_AS,
1437 notify_data_remote_as, 2);
1438 return -1;
1439 }
1440
1441 /* From the rfc: Upon receipt of an OPEN message, a BGP speaker MUST
1442 calculate the value of the Hold Timer by using the smaller of its
1443 configured Hold Time and the Hold Time received in the OPEN message.
1444 The Hold Time MUST be either zero or at least three seconds. An
1445 implementation may reject connections on the basis of the Hold Time. */
1446
1447 if (holdtime < 3 && holdtime != 0)
1448 {
1449 bgp_notify_send (peer,
1450 BGP_NOTIFY_OPEN_ERR,
1451 BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
1452 return -1;
1453 }
1454
1455 /* From the rfc: A reasonable maximum time between KEEPALIVE messages
1456 would be one third of the Hold Time interval. KEEPALIVE messages
1457 MUST NOT be sent more frequently than one per second. An
1458 implementation MAY adjust the rate at which it sends KEEPALIVE
1459 messages as a function of the Hold Time interval. */
1460
1461 if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
1462 send_holdtime = peer->holdtime;
1463 else
1464 send_holdtime = peer->bgp->default_holdtime;
1465
1466 if (holdtime < send_holdtime)
1467 peer->v_holdtime = holdtime;
1468 else
1469 peer->v_holdtime = send_holdtime;
1470
1471 peer->v_keepalive = peer->v_holdtime / 3;
1472
1473 /* Open option part parse. */
paul718e3742002-12-13 20:15:29 +00001474 if (optlen != 0)
1475 {
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001476 if ((ret = bgp_open_option_parse (peer, optlen, &mp_capability)) < 0)
Paul Jakma58617392012-01-09 20:59:26 +00001477 {
1478 bgp_notify_send (peer,
1479 BGP_NOTIFY_OPEN_ERR,
1480 BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
1481 return ret;
1482 }
paul718e3742002-12-13 20:15:29 +00001483 }
1484 else
1485 {
1486 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001487 zlog_debug ("%s rcvd OPEN w/ OPTION parameter len: 0",
paul718e3742002-12-13 20:15:29 +00001488 peer->host);
1489 }
1490
Avneesh Sachdev3b381c32012-02-19 10:19:52 -08001491 /*
1492 * Assume that the peer supports the locally configured set of
1493 * AFI/SAFIs if the peer did not send us any Mulitiprotocol
1494 * capabilities, or if 'override-capability' is configured.
1495 */
1496 if (! mp_capability ||
1497 CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
paul718e3742002-12-13 20:15:29 +00001498 {
1499 peer->afc_nego[AFI_IP][SAFI_UNICAST] = peer->afc[AFI_IP][SAFI_UNICAST];
1500 peer->afc_nego[AFI_IP][SAFI_MULTICAST] = peer->afc[AFI_IP][SAFI_MULTICAST];
1501 peer->afc_nego[AFI_IP6][SAFI_UNICAST] = peer->afc[AFI_IP6][SAFI_UNICAST];
1502 peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = peer->afc[AFI_IP6][SAFI_MULTICAST];
1503 }
1504
1505 /* Get sockname. */
1506 bgp_getsockname (peer);
1507
1508 BGP_EVENT_ADD (peer, Receive_OPEN_message);
1509
1510 peer->packet_size = 0;
1511 if (peer->ibuf)
1512 stream_reset (peer->ibuf);
1513
1514 return 0;
1515}
1516
1517/* Parse BGP Update packet and make attribute object. */
paul94f2b392005-06-28 12:44:16 +00001518static int
paul718e3742002-12-13 20:15:29 +00001519bgp_update_receive (struct peer *peer, bgp_size_t size)
1520{
1521 int ret;
1522 u_char *end;
1523 struct stream *s;
1524 struct attr attr;
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001525 struct attr_extra extra;
paul718e3742002-12-13 20:15:29 +00001526 bgp_size_t attribute_len;
1527 bgp_size_t update_len;
1528 bgp_size_t withdraw_len;
1529 struct bgp_nlri update;
1530 struct bgp_nlri withdraw;
1531 struct bgp_nlri mp_update;
1532 struct bgp_nlri mp_withdraw;
paul718e3742002-12-13 20:15:29 +00001533
1534 /* Status must be Established. */
1535 if (peer->status != Established)
1536 {
1537 zlog_err ("%s [FSM] Update packet received under status %s",
1538 peer->host, LOOKUP (bgp_status_msg, peer->status));
1539 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
1540 return -1;
1541 }
1542
1543 /* Set initial values. */
1544 memset (&attr, 0, sizeof (struct attr));
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001545 memset (&extra, 0, sizeof (struct attr_extra));
paul718e3742002-12-13 20:15:29 +00001546 memset (&update, 0, sizeof (struct bgp_nlri));
1547 memset (&withdraw, 0, sizeof (struct bgp_nlri));
1548 memset (&mp_update, 0, sizeof (struct bgp_nlri));
1549 memset (&mp_withdraw, 0, sizeof (struct bgp_nlri));
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001550 attr.extra = &extra;
paul718e3742002-12-13 20:15:29 +00001551
1552 s = peer->ibuf;
1553 end = stream_pnt (s) + size;
1554
1555 /* RFC1771 6.3 If the Unfeasible Routes Length or Total Attribute
1556 Length is too large (i.e., if Unfeasible Routes Length + Total
1557 Attribute Length + 23 exceeds the message Length), then the Error
1558 Subcode is set to Malformed Attribute List. */
1559 if (stream_pnt (s) + 2 > end)
1560 {
1561 zlog_err ("%s [Error] Update packet error"
1562 " (packet length is short for unfeasible length)",
1563 peer->host);
1564 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1565 BGP_NOTIFY_UPDATE_MAL_ATTR);
1566 return -1;
1567 }
1568
1569 /* Unfeasible Route Length. */
1570 withdraw_len = stream_getw (s);
1571
1572 /* Unfeasible Route Length check. */
1573 if (stream_pnt (s) + withdraw_len > end)
1574 {
1575 zlog_err ("%s [Error] Update packet error"
1576 " (packet unfeasible length overflow %d)",
1577 peer->host, withdraw_len);
1578 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1579 BGP_NOTIFY_UPDATE_MAL_ATTR);
1580 return -1;
1581 }
1582
1583 /* Unfeasible Route packet format check. */
1584 if (withdraw_len > 0)
1585 {
1586 ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), withdraw_len);
1587 if (ret < 0)
1588 return -1;
1589
1590 if (BGP_DEBUG (packet, PACKET_RECV))
ajs6b514742004-12-08 21:03:23 +00001591 zlog_debug ("%s [Update:RECV] Unfeasible NLRI received", peer->host);
paul718e3742002-12-13 20:15:29 +00001592
1593 withdraw.afi = AFI_IP;
1594 withdraw.safi = SAFI_UNICAST;
1595 withdraw.nlri = stream_pnt (s);
1596 withdraw.length = withdraw_len;
paul9985f832005-02-09 15:51:56 +00001597 stream_forward_getp (s, withdraw_len);
paul718e3742002-12-13 20:15:29 +00001598 }
1599
1600 /* Attribute total length check. */
1601 if (stream_pnt (s) + 2 > end)
1602 {
1603 zlog_warn ("%s [Error] Packet Error"
1604 " (update packet is short for attribute length)",
1605 peer->host);
1606 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1607 BGP_NOTIFY_UPDATE_MAL_ATTR);
1608 return -1;
1609 }
1610
1611 /* Fetch attribute total length. */
1612 attribute_len = stream_getw (s);
1613
1614 /* Attribute length check. */
1615 if (stream_pnt (s) + attribute_len > end)
1616 {
1617 zlog_warn ("%s [Error] Packet Error"
1618 " (update packet attribute length overflow %d)",
1619 peer->host, attribute_len);
1620 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
1621 BGP_NOTIFY_UPDATE_MAL_ATTR);
1622 return -1;
1623 }
Paul Jakmab881c702010-11-23 16:35:42 +00001624
1625 /* Certain attribute parsing errors should not be considered bad enough
1626 * to reset the session for, most particularly any partial/optional
1627 * attributes that have 'tunneled' over speakers that don't understand
1628 * them. Instead we withdraw only the prefix concerned.
1629 *
1630 * Complicates the flow a little though..
1631 */
1632 bgp_attr_parse_ret_t attr_parse_ret = BGP_ATTR_PARSE_PROCEED;
1633 /* This define morphs the update case into a withdraw when lower levels
1634 * have signalled an error condition where this is best.
1635 */
1636#define NLRI_ATTR_ARG (attr_parse_ret != BGP_ATTR_PARSE_WITHDRAW ? &attr : NULL)
paul718e3742002-12-13 20:15:29 +00001637
1638 /* Parse attribute when it exists. */
1639 if (attribute_len)
1640 {
Paul Jakmab881c702010-11-23 16:35:42 +00001641 attr_parse_ret = bgp_attr_parse (peer, &attr, attribute_len,
paul718e3742002-12-13 20:15:29 +00001642 &mp_update, &mp_withdraw);
Paul Jakmab881c702010-11-23 16:35:42 +00001643 if (attr_parse_ret == BGP_ATTR_PARSE_ERROR)
paul718e3742002-12-13 20:15:29 +00001644 return -1;
1645 }
Paul Jakmab881c702010-11-23 16:35:42 +00001646
paul718e3742002-12-13 20:15:29 +00001647 /* Logging the attribute. */
Paul Jakmab881c702010-11-23 16:35:42 +00001648 if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW
1649 || BGP_DEBUG (update, UPDATE_IN))
paul718e3742002-12-13 20:15:29 +00001650 {
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +00001651 char attrstr[BUFSIZ];
1652 attrstr[0] = '\0';
1653
paule01f9cb2004-07-09 17:48:53 +00001654 ret= bgp_dump_attr (peer, &attr, attrstr, BUFSIZ);
Paul Jakmab881c702010-11-23 16:35:42 +00001655 int lvl = (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
1656 ? LOG_ERR : LOG_DEBUG;
1657
1658 if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
1659 zlog (peer->log, LOG_ERR,
1660 "%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.",
1661 peer->host);
paule01f9cb2004-07-09 17:48:53 +00001662
1663 if (ret)
Paul Jakmab881c702010-11-23 16:35:42 +00001664 zlog (peer->log, lvl, "%s rcvd UPDATE w/ attr: %s",
paule01f9cb2004-07-09 17:48:53 +00001665 peer->host, attrstr);
paul718e3742002-12-13 20:15:29 +00001666 }
Paul Jakmab881c702010-11-23 16:35:42 +00001667
paul718e3742002-12-13 20:15:29 +00001668 /* Network Layer Reachability Information. */
1669 update_len = end - stream_pnt (s);
1670
1671 if (update_len)
1672 {
1673 /* Check NLRI packet format and prefix length. */
1674 ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), update_len);
1675 if (ret < 0)
Paul Jakmab881c702010-11-23 16:35:42 +00001676 {
1677 bgp_attr_unintern_sub (&attr);
Paul Jakmab881c702010-11-23 16:35:42 +00001678 return -1;
1679 }
paul718e3742002-12-13 20:15:29 +00001680
1681 /* Set NLRI portion to structure. */
1682 update.afi = AFI_IP;
1683 update.safi = SAFI_UNICAST;
1684 update.nlri = stream_pnt (s);
1685 update.length = update_len;
paul9985f832005-02-09 15:51:56 +00001686 stream_forward_getp (s, update_len);
paul718e3742002-12-13 20:15:29 +00001687 }
1688
1689 /* NLRI is processed only when the peer is configured specific
1690 Address Family and Subsequent Address Family. */
1691 if (peer->afc[AFI_IP][SAFI_UNICAST])
1692 {
1693 if (withdraw.length)
1694 bgp_nlri_parse (peer, NULL, &withdraw);
1695
1696 if (update.length)
1697 {
1698 /* We check well-known attribute only for IPv4 unicast
1699 update. */
1700 ret = bgp_attr_check (peer, &attr);
1701 if (ret < 0)
Paul Jakmab881c702010-11-23 16:35:42 +00001702 {
1703 bgp_attr_unintern_sub (&attr);
Paul Jakmab881c702010-11-23 16:35:42 +00001704 return -1;
1705 }
paul718e3742002-12-13 20:15:29 +00001706
Paul Jakmab881c702010-11-23 16:35:42 +00001707 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &update);
paul718e3742002-12-13 20:15:29 +00001708 }
paule01f9cb2004-07-09 17:48:53 +00001709
hassof4184462005-02-01 20:13:16 +00001710 if (mp_update.length
1711 && mp_update.afi == AFI_IP
1712 && mp_update.safi == SAFI_UNICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001713 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
hassof4184462005-02-01 20:13:16 +00001714
1715 if (mp_withdraw.length
1716 && mp_withdraw.afi == AFI_IP
1717 && mp_withdraw.safi == SAFI_UNICAST)
1718 bgp_nlri_parse (peer, NULL, &mp_withdraw);
1719
paule01f9cb2004-07-09 17:48:53 +00001720 if (! attribute_len && ! withdraw_len)
1721 {
1722 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001723 SET_FLAG (peer->af_sflags[AFI_IP][SAFI_UNICAST],
1724 PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001725
hasso93406d82005-02-02 14:40:33 +00001726 /* NSF delete stale route */
1727 if (peer->nsf[AFI_IP][SAFI_UNICAST])
1728 bgp_clear_stale_route (peer, AFI_IP, SAFI_UNICAST);
1729
1730 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001731 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001732 peer->host);
1733 }
paul718e3742002-12-13 20:15:29 +00001734 }
1735 if (peer->afc[AFI_IP][SAFI_MULTICAST])
1736 {
1737 if (mp_update.length
1738 && mp_update.afi == AFI_IP
1739 && mp_update.safi == SAFI_MULTICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001740 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001741
1742 if (mp_withdraw.length
1743 && mp_withdraw.afi == AFI_IP
1744 && mp_withdraw.safi == SAFI_MULTICAST)
1745 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001746
hasso93406d82005-02-02 14:40:33 +00001747 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001748 && mp_withdraw.afi == AFI_IP
1749 && mp_withdraw.safi == SAFI_MULTICAST
1750 && mp_withdraw.length == 0)
1751 {
1752 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001753 SET_FLAG (peer->af_sflags[AFI_IP][SAFI_MULTICAST],
1754 PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001755
hasso93406d82005-02-02 14:40:33 +00001756 /* NSF delete stale route */
1757 if (peer->nsf[AFI_IP][SAFI_MULTICAST])
1758 bgp_clear_stale_route (peer, AFI_IP, SAFI_MULTICAST);
1759
1760 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001761 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Multicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001762 peer->host);
1763 }
paul718e3742002-12-13 20:15:29 +00001764 }
1765 if (peer->afc[AFI_IP6][SAFI_UNICAST])
1766 {
1767 if (mp_update.length
1768 && mp_update.afi == AFI_IP6
1769 && mp_update.safi == SAFI_UNICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001770 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001771
1772 if (mp_withdraw.length
1773 && mp_withdraw.afi == AFI_IP6
1774 && mp_withdraw.safi == SAFI_UNICAST)
1775 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001776
hasso93406d82005-02-02 14:40:33 +00001777 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001778 && mp_withdraw.afi == AFI_IP6
1779 && mp_withdraw.safi == SAFI_UNICAST
1780 && mp_withdraw.length == 0)
1781 {
1782 /* End-of-RIB received */
hasso93406d82005-02-02 14:40:33 +00001783 SET_FLAG (peer->af_sflags[AFI_IP6][SAFI_UNICAST], PEER_STATUS_EOR_RECEIVED);
paule01f9cb2004-07-09 17:48:53 +00001784
hasso93406d82005-02-02 14:40:33 +00001785 /* NSF delete stale route */
1786 if (peer->nsf[AFI_IP6][SAFI_UNICAST])
1787 bgp_clear_stale_route (peer, AFI_IP6, SAFI_UNICAST);
1788
1789 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001790 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001791 peer->host);
1792 }
paul718e3742002-12-13 20:15:29 +00001793 }
1794 if (peer->afc[AFI_IP6][SAFI_MULTICAST])
1795 {
1796 if (mp_update.length
1797 && mp_update.afi == AFI_IP6
1798 && mp_update.safi == SAFI_MULTICAST)
Paul Jakmab881c702010-11-23 16:35:42 +00001799 bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001800
1801 if (mp_withdraw.length
1802 && mp_withdraw.afi == AFI_IP6
1803 && mp_withdraw.safi == SAFI_MULTICAST)
1804 bgp_nlri_parse (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001805
hasso93406d82005-02-02 14:40:33 +00001806 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001807 && mp_withdraw.afi == AFI_IP6
1808 && mp_withdraw.safi == SAFI_MULTICAST
1809 && mp_withdraw.length == 0)
1810 {
1811 /* End-of-RIB received */
1812
hasso93406d82005-02-02 14:40:33 +00001813 /* NSF delete stale route */
1814 if (peer->nsf[AFI_IP6][SAFI_MULTICAST])
1815 bgp_clear_stale_route (peer, AFI_IP6, SAFI_MULTICAST);
1816
paule01f9cb2004-07-09 17:48:53 +00001817 if (BGP_DEBUG (update, UPDATE_IN))
ajs6b514742004-12-08 21:03:23 +00001818 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Multicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001819 peer->host);
1820 }
paul718e3742002-12-13 20:15:29 +00001821 }
1822 if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
1823 {
1824 if (mp_update.length
1825 && mp_update.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001826 && mp_update.safi == SAFI_MPLS_LABELED_VPN)
Paul Jakmab881c702010-11-23 16:35:42 +00001827 bgp_nlri_parse_vpnv4 (peer, NLRI_ATTR_ARG, &mp_update);
paul718e3742002-12-13 20:15:29 +00001828
1829 if (mp_withdraw.length
1830 && mp_withdraw.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001831 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00001832 bgp_nlri_parse_vpnv4 (peer, NULL, &mp_withdraw);
paule01f9cb2004-07-09 17:48:53 +00001833
hasso93406d82005-02-02 14:40:33 +00001834 if (! withdraw_len
paule01f9cb2004-07-09 17:48:53 +00001835 && mp_withdraw.afi == AFI_IP
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001836 && mp_withdraw.safi == SAFI_MPLS_LABELED_VPN
paule01f9cb2004-07-09 17:48:53 +00001837 && mp_withdraw.length == 0)
1838 {
1839 /* End-of-RIB received */
1840
1841 if (BGP_DEBUG (update, UPDATE_IN))
ajs6b514742004-12-08 21:03:23 +00001842 zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for VPNv4 Unicast from %s",
paule01f9cb2004-07-09 17:48:53 +00001843 peer->host);
1844 }
paul718e3742002-12-13 20:15:29 +00001845 }
1846
1847 /* Everything is done. We unintern temporary structures which
1848 interned in bgp_attr_parse(). */
Paul Jakmab881c702010-11-23 16:35:42 +00001849 bgp_attr_unintern_sub (&attr);
Jorge Boncompte [DTI2]489d0052012-05-07 16:53:03 +00001850
paul718e3742002-12-13 20:15:29 +00001851 /* If peering is stopped due to some reason, do not generate BGP
1852 event. */
1853 if (peer->status != Established)
1854 return 0;
1855
1856 /* Increment packet counter. */
1857 peer->update_in++;
Stephen Hemminger65957882010-01-15 16:22:10 +03001858 peer->update_time = bgp_clock ();
paul718e3742002-12-13 20:15:29 +00001859
Jorge Boncompte [DTI2]e2c38e62012-06-20 17:45:50 +02001860 /* Rearm holdtime timer */
Jorge Boncompte [DTI2]6a4677b2012-05-07 16:53:07 +00001861 BGP_TIMER_OFF (peer->t_holdtime);
Jorge Boncompte [DTI2]e2c38e62012-06-20 17:45:50 +02001862 bgp_timer_set (peer);
paul718e3742002-12-13 20:15:29 +00001863
1864 return 0;
1865}
1866
1867/* Notify message treatment function. */
paul94f2b392005-06-28 12:44:16 +00001868static void
paul718e3742002-12-13 20:15:29 +00001869bgp_notify_receive (struct peer *peer, bgp_size_t size)
1870{
1871 struct bgp_notify bgp_notify;
1872
1873 if (peer->notify.data)
1874 {
1875 XFREE (MTYPE_TMP, peer->notify.data);
1876 peer->notify.data = NULL;
1877 peer->notify.length = 0;
1878 }
1879
1880 bgp_notify.code = stream_getc (peer->ibuf);
1881 bgp_notify.subcode = stream_getc (peer->ibuf);
1882 bgp_notify.length = size - 2;
1883 bgp_notify.data = NULL;
1884
1885 /* Preserv notify code and sub code. */
1886 peer->notify.code = bgp_notify.code;
1887 peer->notify.subcode = bgp_notify.subcode;
1888 /* For further diagnostic record returned Data. */
1889 if (bgp_notify.length)
1890 {
1891 peer->notify.length = size - 2;
1892 peer->notify.data = XMALLOC (MTYPE_TMP, size - 2);
1893 memcpy (peer->notify.data, stream_pnt (peer->ibuf), size - 2);
1894 }
1895
1896 /* For debug */
1897 {
1898 int i;
1899 int first = 0;
1900 char c[4];
1901
1902 if (bgp_notify.length)
1903 {
1904 bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
1905 for (i = 0; i < bgp_notify.length; i++)
1906 if (first)
1907 {
1908 sprintf (c, " %02x", stream_getc (peer->ibuf));
1909 strcat (bgp_notify.data, c);
1910 }
1911 else
1912 {
1913 first = 1;
1914 sprintf (c, "%02x", stream_getc (peer->ibuf));
1915 strcpy (bgp_notify.data, c);
1916 }
1917 }
1918
1919 bgp_notify_print(peer, &bgp_notify, "received");
1920 if (bgp_notify.data)
1921 XFREE (MTYPE_TMP, bgp_notify.data);
1922 }
1923
1924 /* peer count update */
1925 peer->notify_in++;
1926
hassoe0701b72004-05-20 09:19:34 +00001927 if (peer->status == Established)
1928 peer->last_reset = PEER_DOWN_NOTIFY_RECEIVED;
1929
paul718e3742002-12-13 20:15:29 +00001930 /* We have to check for Notify with Unsupported Optional Parameter.
1931 in that case we fallback to open without the capability option.
1932 But this done in bgp_stop. We just mark it here to avoid changing
1933 the fsm tables. */
1934 if (bgp_notify.code == BGP_NOTIFY_OPEN_ERR &&
1935 bgp_notify.subcode == BGP_NOTIFY_OPEN_UNSUP_PARAM )
1936 UNSET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
1937
paul718e3742002-12-13 20:15:29 +00001938 BGP_EVENT_ADD (peer, Receive_NOTIFICATION_message);
1939}
1940
1941/* Keepalive treatment function -- get keepalive send keepalive */
paul94f2b392005-06-28 12:44:16 +00001942static void
paul718e3742002-12-13 20:15:29 +00001943bgp_keepalive_receive (struct peer *peer, bgp_size_t size)
1944{
1945 if (BGP_DEBUG (keepalive, KEEPALIVE))
ajs6b514742004-12-08 21:03:23 +00001946 zlog_debug ("%s KEEPALIVE rcvd", peer->host);
paul718e3742002-12-13 20:15:29 +00001947
1948 BGP_EVENT_ADD (peer, Receive_KEEPALIVE_message);
1949}
1950
1951/* Route refresh message is received. */
paul94f2b392005-06-28 12:44:16 +00001952static void
paul718e3742002-12-13 20:15:29 +00001953bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
1954{
1955 afi_t afi;
1956 safi_t safi;
1957 u_char reserved;
1958 struct stream *s;
1959
1960 /* If peer does not have the capability, send notification. */
1961 if (! CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_ADV))
1962 {
1963 plog_err (peer->log, "%s [Error] BGP route refresh is not enabled",
1964 peer->host);
1965 bgp_notify_send (peer,
1966 BGP_NOTIFY_HEADER_ERR,
1967 BGP_NOTIFY_HEADER_BAD_MESTYPE);
1968 return;
1969 }
1970
1971 /* Status must be Established. */
1972 if (peer->status != Established)
1973 {
1974 plog_err (peer->log,
1975 "%s [Error] Route refresh packet received under status %s",
1976 peer->host, LOOKUP (bgp_status_msg, peer->status));
1977 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
1978 return;
1979 }
1980
1981 s = peer->ibuf;
1982
1983 /* Parse packet. */
1984 afi = stream_getw (s);
1985 reserved = stream_getc (s);
1986 safi = stream_getc (s);
1987
1988 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00001989 zlog_debug ("%s rcvd REFRESH_REQ for afi/safi: %d/%d",
paul718e3742002-12-13 20:15:29 +00001990 peer->host, afi, safi);
1991
1992 /* Check AFI and SAFI. */
1993 if ((afi != AFI_IP && afi != AFI_IP6)
1994 || (safi != SAFI_UNICAST && safi != SAFI_MULTICAST
Denis Ovsienko42e6d742011-07-14 12:36:19 +04001995 && safi != SAFI_MPLS_LABELED_VPN))
paul718e3742002-12-13 20:15:29 +00001996 {
1997 if (BGP_DEBUG (normal, NORMAL))
1998 {
ajs6b514742004-12-08 21:03:23 +00001999 zlog_debug ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored",
paul718e3742002-12-13 20:15:29 +00002000 peer->host, afi, safi);
2001 }
2002 return;
2003 }
2004
2005 /* Adjust safi code. */
Denis Ovsienko42e6d742011-07-14 12:36:19 +04002006 if (safi == SAFI_MPLS_LABELED_VPN)
paul718e3742002-12-13 20:15:29 +00002007 safi = SAFI_MPLS_VPN;
2008
2009 if (size != BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE)
2010 {
2011 u_char *end;
2012 u_char when_to_refresh;
2013 u_char orf_type;
2014 u_int16_t orf_len;
2015
2016 if (size - (BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE) < 5)
2017 {
2018 zlog_info ("%s ORF route refresh length error", peer->host);
2019 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2020 return;
2021 }
2022
2023 when_to_refresh = stream_getc (s);
2024 end = stream_pnt (s) + (size - 5);
2025
Paul Jakma370b64a2007-12-22 16:49:52 +00002026 while ((stream_pnt (s) + 2) < end)
paul718e3742002-12-13 20:15:29 +00002027 {
2028 orf_type = stream_getc (s);
2029 orf_len = stream_getw (s);
Paul Jakma370b64a2007-12-22 16:49:52 +00002030
2031 /* orf_len in bounds? */
2032 if ((stream_pnt (s) + orf_len) > end)
2033 break; /* XXX: Notify instead?? */
paul718e3742002-12-13 20:15:29 +00002034 if (orf_type == ORF_TYPE_PREFIX
2035 || orf_type == ORF_TYPE_PREFIX_OLD)
2036 {
2037 u_char *p_pnt = stream_pnt (s);
2038 u_char *p_end = stream_pnt (s) + orf_len;
2039 struct orf_prefix orfp;
2040 u_char common = 0;
2041 u_int32_t seq;
2042 int psize;
2043 char name[BUFSIZ];
paul718e3742002-12-13 20:15:29 +00002044 int ret;
2045
2046 if (BGP_DEBUG (normal, NORMAL))
2047 {
ajs6b514742004-12-08 21:03:23 +00002048 zlog_debug ("%s rcvd Prefixlist ORF(%d) length %d",
paul718e3742002-12-13 20:15:29 +00002049 peer->host, orf_type, orf_len);
2050 }
2051
Paul Jakma370b64a2007-12-22 16:49:52 +00002052 /* we're going to read at least 1 byte of common ORF header,
2053 * and 7 bytes of ORF Address-filter entry from the stream
2054 */
2055 if (orf_len < 7)
2056 break;
2057
paul718e3742002-12-13 20:15:29 +00002058 /* ORF prefix-list name */
2059 sprintf (name, "%s.%d.%d", peer->host, afi, safi);
2060
2061 while (p_pnt < p_end)
2062 {
Chris Halld64379e2010-05-14 16:38:39 +04002063 /* If the ORF entry is malformed, want to read as much of it
2064 * as possible without going beyond the bounds of the entry,
2065 * to maximise debug information.
2066 */
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002067 int ok;
paul718e3742002-12-13 20:15:29 +00002068 memset (&orfp, 0, sizeof (struct orf_prefix));
2069 common = *p_pnt++;
Chris Halld64379e2010-05-14 16:38:39 +04002070 /* after ++: p_pnt <= p_end */
paul718e3742002-12-13 20:15:29 +00002071 if (common & ORF_COMMON_PART_REMOVE_ALL)
2072 {
2073 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002074 zlog_debug ("%s rcvd Remove-All pfxlist ORF request", peer->host);
paul718e3742002-12-13 20:15:29 +00002075 prefix_bgp_orf_remove_all (name);
2076 break;
2077 }
Chris Halld64379e2010-05-14 16:38:39 +04002078 ok = ((p_end - p_pnt) >= sizeof(u_int32_t)) ;
Denis Ovsienkobb915f52011-12-13 21:11:39 +04002079 if (ok)
Chris Halld64379e2010-05-14 16:38:39 +04002080 {
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002081 memcpy (&seq, p_pnt, sizeof (u_int32_t));
2082 p_pnt += sizeof (u_int32_t);
2083 orfp.seq = ntohl (seq);
Chris Halld64379e2010-05-14 16:38:39 +04002084 }
2085 else
2086 p_pnt = p_end ;
2087
2088 if ((ok = (p_pnt < p_end)))
2089 orfp.ge = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */
2090 if ((ok = (p_pnt < p_end)))
2091 orfp.le = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */
2092 if ((ok = (p_pnt < p_end)))
2093 orfp.p.prefixlen = *p_pnt++ ;
2094 orfp.p.family = afi2family (afi); /* afi checked already */
2095
2096 psize = PSIZE (orfp.p.prefixlen); /* 0 if not ok */
2097 if (psize > prefix_blen(&orfp.p)) /* valid for family ? */
2098 {
2099 ok = 0 ;
2100 psize = prefix_blen(&orfp.p) ;
2101 }
2102 if (psize > (p_end - p_pnt)) /* valid for packet ? */
2103 {
2104 ok = 0 ;
2105 psize = p_end - p_pnt ;
2106 }
2107
2108 if (psize > 0)
2109 memcpy (&orfp.p.u.prefix, p_pnt, psize);
paul718e3742002-12-13 20:15:29 +00002110 p_pnt += psize;
2111
2112 if (BGP_DEBUG (normal, NORMAL))
Jorge Boncompte [DTI2]14542f32012-05-07 16:52:53 +00002113 {
2114 char buf[INET6_BUFSIZ];
2115
2116 zlog_debug ("%s rcvd %s %s seq %u %s/%d ge %d le %d%s",
2117 peer->host,
2118 (common & ORF_COMMON_PART_REMOVE ? "Remove" : "Add"),
2119 (common & ORF_COMMON_PART_DENY ? "deny" : "permit"),
2120 orfp.seq,
2121 inet_ntop (orfp.p.family, &orfp.p.u.prefix, buf, INET6_BUFSIZ),
2122 orfp.p.prefixlen, orfp.ge, orfp.le,
2123 ok ? "" : " MALFORMED");
2124 }
2125
Chris Halld64379e2010-05-14 16:38:39 +04002126 if (ok)
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002127 ret = prefix_bgp_orf_set (name, afi, &orfp,
2128 (common & ORF_COMMON_PART_DENY ? 0 : 1 ),
2129 (common & ORF_COMMON_PART_REMOVE ? 0 : 1));
paul718e3742002-12-13 20:15:29 +00002130
Chris Halld64379e2010-05-14 16:38:39 +04002131 if (!ok || (ret != CMD_SUCCESS))
paul718e3742002-12-13 20:15:29 +00002132 {
2133 if (BGP_DEBUG (normal, NORMAL))
Paul Jakmafdbc8e72011-04-11 16:31:43 +01002134 zlog_debug ("%s Received misformatted prefixlist ORF."
2135 " Remove All pfxlist", peer->host);
paul718e3742002-12-13 20:15:29 +00002136 prefix_bgp_orf_remove_all (name);
2137 break;
2138 }
2139 }
2140 peer->orf_plist[afi][safi] =
2141 prefix_list_lookup (AFI_ORF_PREFIX, name);
2142 }
paul9985f832005-02-09 15:51:56 +00002143 stream_forward_getp (s, orf_len);
paul718e3742002-12-13 20:15:29 +00002144 }
2145 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002146 zlog_debug ("%s rcvd Refresh %s ORF request", peer->host,
paul718e3742002-12-13 20:15:29 +00002147 when_to_refresh == REFRESH_DEFER ? "Defer" : "Immediate");
2148 if (when_to_refresh == REFRESH_DEFER)
2149 return;
2150 }
2151
2152 /* First update is deferred until ORF or ROUTE-REFRESH is received */
2153 if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH))
2154 UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
2155
2156 /* Perform route refreshment to the peer */
2157 bgp_announce_route (peer, afi, safi);
2158}
2159
paul94f2b392005-06-28 12:44:16 +00002160static int
paul718e3742002-12-13 20:15:29 +00002161bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
2162{
2163 u_char *end;
Paul Jakma6d582722007-08-06 15:21:45 +00002164 struct capability_mp_data mpc;
2165 struct capability_header *hdr;
paul718e3742002-12-13 20:15:29 +00002166 u_char action;
2167 struct bgp *bgp;
2168 afi_t afi;
2169 safi_t safi;
2170
2171 bgp = peer->bgp;
2172 end = pnt + length;
2173
2174 while (pnt < end)
Paul Jakma6d582722007-08-06 15:21:45 +00002175 {
paul718e3742002-12-13 20:15:29 +00002176 /* We need at least action, capability code and capability length. */
2177 if (pnt + 3 > end)
2178 {
2179 zlog_info ("%s Capability length error", peer->host);
2180 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2181 return -1;
2182 }
paul718e3742002-12-13 20:15:29 +00002183 action = *pnt;
Paul Jakma6d582722007-08-06 15:21:45 +00002184 hdr = (struct capability_header *)(pnt + 1);
2185
paul718e3742002-12-13 20:15:29 +00002186 /* Action value check. */
2187 if (action != CAPABILITY_ACTION_SET
2188 && action != CAPABILITY_ACTION_UNSET)
2189 {
2190 zlog_info ("%s Capability Action Value error %d",
2191 peer->host, action);
2192 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2193 return -1;
2194 }
2195
2196 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002197 zlog_debug ("%s CAPABILITY has action: %d, code: %u, length %u",
Paul Jakma6d582722007-08-06 15:21:45 +00002198 peer->host, action, hdr->code, hdr->length);
paul718e3742002-12-13 20:15:29 +00002199
2200 /* Capability length check. */
Paul Jakma6d582722007-08-06 15:21:45 +00002201 if ((pnt + hdr->length + 3) > end)
paul718e3742002-12-13 20:15:29 +00002202 {
2203 zlog_info ("%s Capability length error", peer->host);
2204 bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
2205 return -1;
2206 }
2207
Paul Jakma6d582722007-08-06 15:21:45 +00002208 /* Fetch structure to the byte stream. */
2209 memcpy (&mpc, pnt + 3, sizeof (struct capability_mp_data));
2210
paul718e3742002-12-13 20:15:29 +00002211 /* We know MP Capability Code. */
Paul Jakma6d582722007-08-06 15:21:45 +00002212 if (hdr->code == CAPABILITY_CODE_MP)
paul718e3742002-12-13 20:15:29 +00002213 {
Paul Jakma6d582722007-08-06 15:21:45 +00002214 afi = ntohs (mpc.afi);
2215 safi = mpc.safi;
paul718e3742002-12-13 20:15:29 +00002216
2217 /* Ignore capability when override-capability is set. */
2218 if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
2219 continue;
Paul Jakma6d582722007-08-06 15:21:45 +00002220
2221 if (!bgp_afi_safi_valid_indices (afi, &safi))
2222 {
2223 if (BGP_DEBUG (normal, NORMAL))
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002224 zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid "
2225 "(%u/%u)", peer->host, afi, safi);
Paul Jakma6d582722007-08-06 15:21:45 +00002226 continue;
2227 }
2228
paul718e3742002-12-13 20:15:29 +00002229 /* Address family check. */
Paul Jakma6d582722007-08-06 15:21:45 +00002230 if (BGP_DEBUG (normal, NORMAL))
2231 zlog_debug ("%s CAPABILITY has %s MP_EXT CAP for afi/safi: %u/%u",
2232 peer->host,
2233 action == CAPABILITY_ACTION_SET
2234 ? "Advertising" : "Removing",
2235 ntohs(mpc.afi) , mpc.safi);
2236
2237 if (action == CAPABILITY_ACTION_SET)
2238 {
2239 peer->afc_recv[afi][safi] = 1;
2240 if (peer->afc[afi][safi])
2241 {
2242 peer->afc_nego[afi][safi] = 1;
2243 bgp_announce_route (peer, afi, safi);
2244 }
2245 }
2246 else
2247 {
2248 peer->afc_recv[afi][safi] = 0;
2249 peer->afc_nego[afi][safi] = 0;
paul718e3742002-12-13 20:15:29 +00002250
Paul Jakma6d582722007-08-06 15:21:45 +00002251 if (peer_active_nego (peer))
Chris Caputo228da422009-07-18 05:44:03 +00002252 bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
Paul Jakma6d582722007-08-06 15:21:45 +00002253 else
2254 BGP_EVENT_ADD (peer, BGP_Stop);
2255 }
paul718e3742002-12-13 20:15:29 +00002256 }
paul718e3742002-12-13 20:15:29 +00002257 else
2258 {
2259 zlog_warn ("%s unrecognized capability code: %d - ignored",
Paul Jakma6d582722007-08-06 15:21:45 +00002260 peer->host, hdr->code);
paul718e3742002-12-13 20:15:29 +00002261 }
Paul Jakma6d582722007-08-06 15:21:45 +00002262 pnt += hdr->length + 3;
paul718e3742002-12-13 20:15:29 +00002263 }
2264 return 0;
2265}
2266
Paul Jakma01b7ce22009-06-18 12:34:43 +01002267/* Dynamic Capability is received.
2268 *
2269 * This is exported for unit-test purposes
2270 */
Paul Jakma6d582722007-08-06 15:21:45 +00002271int
paul718e3742002-12-13 20:15:29 +00002272bgp_capability_receive (struct peer *peer, bgp_size_t size)
2273{
2274 u_char *pnt;
paul718e3742002-12-13 20:15:29 +00002275
2276 /* Fetch pointer. */
2277 pnt = stream_pnt (peer->ibuf);
2278
2279 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002280 zlog_debug ("%s rcv CAPABILITY", peer->host);
paul718e3742002-12-13 20:15:29 +00002281
2282 /* If peer does not have the capability, send notification. */
2283 if (! CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV))
2284 {
2285 plog_err (peer->log, "%s [Error] BGP dynamic capability is not enabled",
2286 peer->host);
2287 bgp_notify_send (peer,
2288 BGP_NOTIFY_HEADER_ERR,
2289 BGP_NOTIFY_HEADER_BAD_MESTYPE);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002290 return -1;
paul718e3742002-12-13 20:15:29 +00002291 }
2292
2293 /* Status must be Established. */
2294 if (peer->status != Established)
2295 {
2296 plog_err (peer->log,
2297 "%s [Error] Dynamic capability packet received under status %s", peer->host, LOOKUP (bgp_status_msg, peer->status));
2298 bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
Paul Jakma0b2aa3a2007-10-14 22:32:21 +00002299 return -1;
paul718e3742002-12-13 20:15:29 +00002300 }
2301
2302 /* Parse packet. */
Paul Jakma6d582722007-08-06 15:21:45 +00002303 return bgp_capability_msg_parse (peer, pnt, size);
paul718e3742002-12-13 20:15:29 +00002304}
2305
2306/* BGP read utility function. */
paul94f2b392005-06-28 12:44:16 +00002307static int
paul718e3742002-12-13 20:15:29 +00002308bgp_read_packet (struct peer *peer)
2309{
2310 int nbytes;
2311 int readsize;
2312
paul9985f832005-02-09 15:51:56 +00002313 readsize = peer->packet_size - stream_get_endp (peer->ibuf);
paul718e3742002-12-13 20:15:29 +00002314
2315 /* If size is zero then return. */
2316 if (! readsize)
2317 return 0;
2318
2319 /* Read packet from fd. */
Stephen Hemminger35398582010-08-05 10:26:23 -07002320 nbytes = stream_read_try (peer->ibuf, peer->fd, readsize);
paul718e3742002-12-13 20:15:29 +00002321
2322 /* If read byte is smaller than zero then error occured. */
2323 if (nbytes < 0)
2324 {
Stephen Hemminger35398582010-08-05 10:26:23 -07002325 /* Transient error should retry */
2326 if (nbytes == -2)
paul718e3742002-12-13 20:15:29 +00002327 return -1;
2328
2329 plog_err (peer->log, "%s [Error] bgp_read_packet error: %s",
ajs6099b3b2004-11-20 02:06:59 +00002330 peer->host, safe_strerror (errno));
hasso93406d82005-02-02 14:40:33 +00002331
2332 if (peer->status == Established)
2333 {
2334 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
2335 {
2336 peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
2337 SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
2338 }
2339 else
2340 peer->last_reset = PEER_DOWN_CLOSE_SESSION;
2341 }
2342
paul718e3742002-12-13 20:15:29 +00002343 BGP_EVENT_ADD (peer, TCP_fatal_error);
2344 return -1;
2345 }
2346
2347 /* When read byte is zero : clear bgp peer and return */
2348 if (nbytes == 0)
2349 {
2350 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +00002351 plog_debug (peer->log, "%s [Event] BGP connection closed fd %d",
pauleb821182004-05-01 08:44:08 +00002352 peer->host, peer->fd);
hassoe0701b72004-05-20 09:19:34 +00002353
2354 if (peer->status == Established)
hasso93406d82005-02-02 14:40:33 +00002355 {
2356 if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
2357 {
2358 peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
2359 SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
2360 }
2361 else
2362 peer->last_reset = PEER_DOWN_CLOSE_SESSION;
2363 }
hassoe0701b72004-05-20 09:19:34 +00002364
paul718e3742002-12-13 20:15:29 +00002365 BGP_EVENT_ADD (peer, TCP_connection_closed);
2366 return -1;
2367 }
2368
2369 /* We read partial packet. */
paul9985f832005-02-09 15:51:56 +00002370 if (stream_get_endp (peer->ibuf) != peer->packet_size)
paul718e3742002-12-13 20:15:29 +00002371 return -1;
2372
2373 return 0;
2374}
2375
2376/* Marker check. */
paul94f2b392005-06-28 12:44:16 +00002377static int
paul718e3742002-12-13 20:15:29 +00002378bgp_marker_all_one (struct stream *s, int length)
2379{
2380 int i;
2381
2382 for (i = 0; i < length; i++)
2383 if (s->data[i] != 0xff)
2384 return 0;
2385
2386 return 1;
2387}
2388
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002389/* Recent thread time.
2390 On same clock base as bgp_clock (MONOTONIC)
2391 but can be time of last context switch to bgp_read thread. */
2392static time_t
2393bgp_recent_clock (void)
2394{
2395 return recent_relative_time().tv_sec;
2396}
2397
paul718e3742002-12-13 20:15:29 +00002398/* Starting point of packet process function. */
2399int
2400bgp_read (struct thread *thread)
2401{
2402 int ret;
2403 u_char type = 0;
2404 struct peer *peer;
2405 bgp_size_t size;
2406 char notify_data_length[2];
2407
2408 /* Yes first of all get peer pointer. */
2409 peer = THREAD_ARG (thread);
2410 peer->t_read = NULL;
2411
2412 /* For non-blocking IO check. */
2413 if (peer->status == Connect)
2414 {
2415 bgp_connect_check (peer);
2416 goto done;
2417 }
2418 else
2419 {
pauleb821182004-05-01 08:44:08 +00002420 if (peer->fd < 0)
paul718e3742002-12-13 20:15:29 +00002421 {
pauleb821182004-05-01 08:44:08 +00002422 zlog_err ("bgp_read peer's fd is negative value %d", peer->fd);
paul718e3742002-12-13 20:15:29 +00002423 return -1;
2424 }
pauleb821182004-05-01 08:44:08 +00002425 BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
paul718e3742002-12-13 20:15:29 +00002426 }
2427
2428 /* Read packet header to determine type of the packet */
2429 if (peer->packet_size == 0)
2430 peer->packet_size = BGP_HEADER_SIZE;
2431
paul9985f832005-02-09 15:51:56 +00002432 if (stream_get_endp (peer->ibuf) < BGP_HEADER_SIZE)
paul718e3742002-12-13 20:15:29 +00002433 {
2434 ret = bgp_read_packet (peer);
2435
2436 /* Header read error or partial read packet. */
2437 if (ret < 0)
2438 goto done;
2439
2440 /* Get size and type. */
paul9985f832005-02-09 15:51:56 +00002441 stream_forward_getp (peer->ibuf, BGP_MARKER_SIZE);
paul718e3742002-12-13 20:15:29 +00002442 memcpy (notify_data_length, stream_pnt (peer->ibuf), 2);
2443 size = stream_getw (peer->ibuf);
2444 type = stream_getc (peer->ibuf);
2445
2446 if (BGP_DEBUG (normal, NORMAL) && type != 2 && type != 0)
ajs6b514742004-12-08 21:03:23 +00002447 zlog_debug ("%s rcv message type %d, length (excl. header) %d",
paul718e3742002-12-13 20:15:29 +00002448 peer->host, type, size - BGP_HEADER_SIZE);
2449
2450 /* Marker check */
paulf5ba3872004-07-09 12:11:31 +00002451 if (((type == BGP_MSG_OPEN) || (type == BGP_MSG_KEEPALIVE))
paul718e3742002-12-13 20:15:29 +00002452 && ! bgp_marker_all_one (peer->ibuf, BGP_MARKER_SIZE))
2453 {
2454 bgp_notify_send (peer,
2455 BGP_NOTIFY_HEADER_ERR,
2456 BGP_NOTIFY_HEADER_NOT_SYNC);
2457 goto done;
2458 }
2459
2460 /* BGP type check. */
2461 if (type != BGP_MSG_OPEN && type != BGP_MSG_UPDATE
2462 && type != BGP_MSG_NOTIFY && type != BGP_MSG_KEEPALIVE
2463 && type != BGP_MSG_ROUTE_REFRESH_NEW
2464 && type != BGP_MSG_ROUTE_REFRESH_OLD
2465 && type != BGP_MSG_CAPABILITY)
2466 {
2467 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002468 plog_debug (peer->log,
paul718e3742002-12-13 20:15:29 +00002469 "%s unknown message type 0x%02x",
2470 peer->host, type);
2471 bgp_notify_send_with_data (peer,
2472 BGP_NOTIFY_HEADER_ERR,
2473 BGP_NOTIFY_HEADER_BAD_MESTYPE,
2474 &type, 1);
2475 goto done;
2476 }
2477 /* Mimimum packet length check. */
2478 if ((size < BGP_HEADER_SIZE)
2479 || (size > BGP_MAX_PACKET_SIZE)
2480 || (type == BGP_MSG_OPEN && size < BGP_MSG_OPEN_MIN_SIZE)
2481 || (type == BGP_MSG_UPDATE && size < BGP_MSG_UPDATE_MIN_SIZE)
2482 || (type == BGP_MSG_NOTIFY && size < BGP_MSG_NOTIFY_MIN_SIZE)
2483 || (type == BGP_MSG_KEEPALIVE && size != BGP_MSG_KEEPALIVE_MIN_SIZE)
2484 || (type == BGP_MSG_ROUTE_REFRESH_NEW && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
2485 || (type == BGP_MSG_ROUTE_REFRESH_OLD && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
2486 || (type == BGP_MSG_CAPABILITY && size < BGP_MSG_CAPABILITY_MIN_SIZE))
2487 {
2488 if (BGP_DEBUG (normal, NORMAL))
ajs6b514742004-12-08 21:03:23 +00002489 plog_debug (peer->log,
paul718e3742002-12-13 20:15:29 +00002490 "%s bad message length - %d for %s",
2491 peer->host, size,
2492 type == 128 ? "ROUTE-REFRESH" :
2493 bgp_type_str[(int) type]);
2494 bgp_notify_send_with_data (peer,
2495 BGP_NOTIFY_HEADER_ERR,
2496 BGP_NOTIFY_HEADER_BAD_MESLEN,
hassoc9e52be2004-09-26 16:09:34 +00002497 (u_char *) notify_data_length, 2);
paul718e3742002-12-13 20:15:29 +00002498 goto done;
2499 }
2500
2501 /* Adjust size to message length. */
2502 peer->packet_size = size;
2503 }
2504
2505 ret = bgp_read_packet (peer);
2506 if (ret < 0)
2507 goto done;
2508
2509 /* Get size and type again. */
2510 size = stream_getw_from (peer->ibuf, BGP_MARKER_SIZE);
2511 type = stream_getc_from (peer->ibuf, BGP_MARKER_SIZE + 2);
2512
2513 /* BGP packet dump function. */
2514 bgp_dump_packet (peer, type, peer->ibuf);
2515
2516 size = (peer->packet_size - BGP_HEADER_SIZE);
2517
2518 /* Read rest of the packet and call each sort of packet routine */
2519 switch (type)
2520 {
2521 case BGP_MSG_OPEN:
2522 peer->open_in++;
paulf5ba3872004-07-09 12:11:31 +00002523 bgp_open_receive (peer, size); /* XXX return value ignored! */
paul718e3742002-12-13 20:15:29 +00002524 break;
2525 case BGP_MSG_UPDATE:
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002526 peer->readtime = bgp_recent_clock ();
paul718e3742002-12-13 20:15:29 +00002527 bgp_update_receive (peer, size);
2528 break;
2529 case BGP_MSG_NOTIFY:
2530 bgp_notify_receive (peer, size);
2531 break;
2532 case BGP_MSG_KEEPALIVE:
Stephen Hemmingerd61c1bb2013-01-04 22:29:23 +00002533 peer->readtime = bgp_recent_clock ();
paul718e3742002-12-13 20:15:29 +00002534 bgp_keepalive_receive (peer, size);
2535 break;
2536 case BGP_MSG_ROUTE_REFRESH_NEW:
2537 case BGP_MSG_ROUTE_REFRESH_OLD:
2538 peer->refresh_in++;
2539 bgp_route_refresh_receive (peer, size);
2540 break;
2541 case BGP_MSG_CAPABILITY:
2542 peer->dynamic_cap_in++;
2543 bgp_capability_receive (peer, size);
2544 break;
2545 }
2546
2547 /* Clear input buffer. */
2548 peer->packet_size = 0;
2549 if (peer->ibuf)
2550 stream_reset (peer->ibuf);
2551
2552 done:
2553 if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
2554 {
2555 if (BGP_DEBUG (events, EVENTS))
ajs6b514742004-12-08 21:03:23 +00002556 zlog_debug ("%s [Event] Accepting BGP peer delete", peer->host);
paul718e3742002-12-13 20:15:29 +00002557 peer_delete (peer);
paul718e3742002-12-13 20:15:29 +00002558 }
2559 return 0;
2560}