Annotation of embedaddon/quagga/bgpd/bgp_packet.c, revision 1.1
1.1 ! misho 1: /* BGP packet management routine.
! 2: Copyright (C) 1999 Kunihiro Ishiguro
! 3:
! 4: This file is part of GNU Zebra.
! 5:
! 6: GNU Zebra is free software; you can redistribute it and/or modify it
! 7: under the terms of the GNU General Public License as published by the
! 8: Free Software Foundation; either version 2, or (at your option) any
! 9: later version.
! 10:
! 11: GNU Zebra is distributed in the hope that it will be useful, but
! 12: WITHOUT ANY WARRANTY; without even the implied warranty of
! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
! 14: General Public License for more details.
! 15:
! 16: You should have received a copy of the GNU General Public License
! 17: along with GNU Zebra; see the file COPYING. If not, write to the Free
! 18: Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
! 19: 02111-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"
! 49: #include "bgpd/bgp_vty.h"
! 50:
! 51: int stream_put_prefix (struct stream *, struct prefix *);
! 52:
! 53: /* Set up BGP packet marker and packet type. */
! 54: static int
! 55: bgp_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. */
! 70: return stream_get_endp (s);
! 71: }
! 72:
! 73: /* Set BGP packet header size entry. If size is zero then use current
! 74: stream size. */
! 75: static int
! 76: bgp_packet_set_size (struct stream *s)
! 77: {
! 78: int cp;
! 79:
! 80: /* Preserve current pointer. */
! 81: cp = stream_get_endp (s);
! 82: stream_putw_at (s, BGP_MARKER_SIZE, cp);
! 83:
! 84: return cp;
! 85: }
! 86:
! 87: /* Add new packet to the peer. */
! 88: static void
! 89: bgp_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. */
! 96: static void
! 97: bgp_packet_delete (struct peer *peer)
! 98: {
! 99: stream_free (stream_fifo_pop (peer->obuf));
! 100: }
! 101:
! 102: /* Check file descriptor whether connect is established. */
! 103: static void
! 104: bgp_connect_check (struct peer *peer)
! 105: {
! 106: int status;
! 107: socklen_t slen;
! 108: 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);
! 116: ret = getsockopt(peer->fd, SOL_SOCKET, SO_ERROR, (void *) &status, &slen);
! 117:
! 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))
! 134: plog_debug (peer->log, "%s [Event] Connect failed (%s)",
! 135: peer->host, safe_strerror (errno));
! 136: BGP_EVENT_ADD (peer, TCP_connection_open_failed);
! 137: }
! 138: }
! 139:
! 140: /* Make BGP update packet. */
! 141: static struct stream *
! 142: bgp_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;
! 152: char buf[BUFSIZ];
! 153:
! 154: s = peer->work;
! 155: stream_reset (s);
! 156:
! 157: adv = FIFO_HEAD (&peer->sync[afi][safi]->update);
! 158:
! 159: while (adv)
! 160: {
! 161: assert (adv->rn);
! 162: rn = adv->rn;
! 163: adj = adv->adj;
! 164: if (adv->binfo)
! 165: binfo = adv->binfo;
! 166:
! 167: /* When remaining space can't include NLRI and it's length. */
! 168: if (STREAM_REMAIN (s) <= BGP_NLRI_LENGTH + PSIZE (rn->p.prefixlen))
! 169: break;
! 170:
! 171: /* If packet is empty, set attribute. */
! 172: if (stream_empty (s))
! 173: {
! 174: struct prefix_rd *prd = NULL;
! 175: u_char *tag = NULL;
! 176: struct peer *from = NULL;
! 177:
! 178: if (rn->prn)
! 179: prd = (struct prefix_rd *) &rn->prn->p;
! 180: if (binfo)
! 181: {
! 182: from = binfo->peer;
! 183: if (binfo->extra)
! 184: tag = binfo->extra->tag;
! 185: }
! 186:
! 187: bgp_packet_set_marker (s, BGP_MSG_UPDATE);
! 188: stream_putw (s, 0);
! 189: pos = stream_get_endp (s);
! 190: stream_putw (s, 0);
! 191: total_attr_len = bgp_packet_attribute (NULL, peer, s,
! 192: adv->baa->attr,
! 193: &rn->p, afi, safi,
! 194: from, prd, tag);
! 195: stream_putw_at (s, pos, total_attr_len);
! 196: }
! 197:
! 198: if (afi == AFI_IP && safi == SAFI_UNICAST)
! 199: stream_put_prefix (s, &rn->p);
! 200:
! 201: if (BGP_DEBUG (update, UPDATE_OUT))
! 202: zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d",
! 203: peer->host,
! 204: inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, BUFSIZ),
! 205: rn->p.prefixlen);
! 206:
! 207: /* Synchnorize attribute. */
! 208: if (adj->attr)
! 209: bgp_attr_unintern (&adj->attr);
! 210: else
! 211: peer->scount[afi][safi]++;
! 212:
! 213: adj->attr = bgp_attr_intern (adv->baa->attr);
! 214:
! 215: adv = bgp_advertise_clean (peer, adj, afi, safi);
! 216:
! 217: if (! (afi == AFI_IP && safi == SAFI_UNICAST))
! 218: break;
! 219: }
! 220:
! 221: if (! stream_empty (s))
! 222: {
! 223: bgp_packet_set_size (s);
! 224: packet = stream_dup (s);
! 225: bgp_packet_add (peer, packet);
! 226: BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
! 227: stream_reset (s);
! 228: return packet;
! 229: }
! 230: return NULL;
! 231: }
! 232:
! 233: static struct stream *
! 234: bgp_update_packet_eor (struct peer *peer, afi_t afi, safi_t safi)
! 235: {
! 236: struct stream *s;
! 237: struct stream *packet;
! 238:
! 239: if (DISABLE_BGP_ANNOUNCE)
! 240: return NULL;
! 241:
! 242: if (BGP_DEBUG (normal, NORMAL))
! 243: zlog_debug ("send End-of-RIB for %s to %s", afi_safi_print (afi, safi), peer->host);
! 244:
! 245: s = stream_new (BGP_MAX_PACKET_SIZE);
! 246:
! 247: /* Make BGP update packet. */
! 248: bgp_packet_set_marker (s, BGP_MSG_UPDATE);
! 249:
! 250: /* Unfeasible Routes Length */
! 251: stream_putw (s, 0);
! 252:
! 253: if (afi == AFI_IP && safi == SAFI_UNICAST)
! 254: {
! 255: /* Total Path Attribute Length */
! 256: stream_putw (s, 0);
! 257: }
! 258: else
! 259: {
! 260: /* Total Path Attribute Length */
! 261: stream_putw (s, 6);
! 262: stream_putc (s, BGP_ATTR_FLAG_OPTIONAL);
! 263: stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI);
! 264: stream_putc (s, 3);
! 265: stream_putw (s, afi);
! 266: stream_putc (s, safi);
! 267: }
! 268:
! 269: bgp_packet_set_size (s);
! 270: packet = stream_dup (s);
! 271: bgp_packet_add (peer, packet);
! 272: stream_free (s);
! 273: return packet;
! 274: }
! 275:
! 276: /* Make BGP withdraw packet. */
! 277: static struct stream *
! 278: bgp_withdraw_packet (struct peer *peer, afi_t afi, safi_t safi)
! 279: {
! 280: struct stream *s;
! 281: struct stream *packet;
! 282: struct bgp_adj_out *adj;
! 283: struct bgp_advertise *adv;
! 284: struct bgp_node *rn;
! 285: unsigned long pos;
! 286: bgp_size_t unfeasible_len;
! 287: bgp_size_t total_attr_len;
! 288: char buf[BUFSIZ];
! 289:
! 290: s = peer->work;
! 291: stream_reset (s);
! 292:
! 293: while ((adv = FIFO_HEAD (&peer->sync[afi][safi]->withdraw)) != NULL)
! 294: {
! 295: assert (adv->rn);
! 296: adj = adv->adj;
! 297: rn = adv->rn;
! 298:
! 299: if (STREAM_REMAIN (s)
! 300: < (BGP_NLRI_LENGTH + BGP_TOTAL_ATTR_LEN + PSIZE (rn->p.prefixlen)))
! 301: break;
! 302:
! 303: if (stream_empty (s))
! 304: {
! 305: bgp_packet_set_marker (s, BGP_MSG_UPDATE);
! 306: stream_putw (s, 0);
! 307: }
! 308:
! 309: if (afi == AFI_IP && safi == SAFI_UNICAST)
! 310: stream_put_prefix (s, &rn->p);
! 311: else
! 312: {
! 313: struct prefix_rd *prd = NULL;
! 314:
! 315: if (rn->prn)
! 316: prd = (struct prefix_rd *) &rn->prn->p;
! 317: pos = stream_get_endp (s);
! 318: stream_putw (s, 0);
! 319: total_attr_len
! 320: = bgp_packet_withdraw (peer, s, &rn->p, afi, safi, prd, NULL);
! 321:
! 322: /* Set total path attribute length. */
! 323: stream_putw_at (s, pos, total_attr_len);
! 324: }
! 325:
! 326: if (BGP_DEBUG (update, UPDATE_OUT))
! 327: zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d -- unreachable",
! 328: peer->host,
! 329: inet_ntop (rn->p.family, &(rn->p.u.prefix), buf, BUFSIZ),
! 330: rn->p.prefixlen);
! 331:
! 332: peer->scount[afi][safi]--;
! 333:
! 334: bgp_adj_out_remove (rn, adj, peer, afi, safi);
! 335: bgp_unlock_node (rn);
! 336:
! 337: if (! (afi == AFI_IP && safi == SAFI_UNICAST))
! 338: break;
! 339: }
! 340:
! 341: if (! stream_empty (s))
! 342: {
! 343: if (afi == AFI_IP && safi == SAFI_UNICAST)
! 344: {
! 345: unfeasible_len
! 346: = stream_get_endp (s) - BGP_HEADER_SIZE - BGP_UNFEASIBLE_LEN;
! 347: stream_putw_at (s, BGP_HEADER_SIZE, unfeasible_len);
! 348: stream_putw (s, 0);
! 349: }
! 350: bgp_packet_set_size (s);
! 351: packet = stream_dup (s);
! 352: bgp_packet_add (peer, packet);
! 353: stream_reset (s);
! 354: return packet;
! 355: }
! 356:
! 357: return NULL;
! 358: }
! 359:
! 360: void
! 361: bgp_default_update_send (struct peer *peer, struct attr *attr,
! 362: afi_t afi, safi_t safi, struct peer *from)
! 363: {
! 364: struct stream *s;
! 365: struct stream *packet;
! 366: struct prefix p;
! 367: unsigned long pos;
! 368: bgp_size_t total_attr_len;
! 369: char attrstr[BUFSIZ];
! 370: char buf[BUFSIZ];
! 371:
! 372: if (DISABLE_BGP_ANNOUNCE)
! 373: return;
! 374:
! 375: if (afi == AFI_IP)
! 376: str2prefix ("0.0.0.0/0", &p);
! 377: #ifdef HAVE_IPV6
! 378: else
! 379: str2prefix ("::/0", &p);
! 380: #endif /* HAVE_IPV6 */
! 381:
! 382: /* Logging the attribute. */
! 383: if (BGP_DEBUG (update, UPDATE_OUT))
! 384: {
! 385: bgp_dump_attr (peer, attr, attrstr, BUFSIZ);
! 386: zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d %s",
! 387: peer->host, inet_ntop(p.family, &(p.u.prefix), buf, BUFSIZ),
! 388: p.prefixlen, attrstr);
! 389: }
! 390:
! 391: s = stream_new (BGP_MAX_PACKET_SIZE);
! 392:
! 393: /* Make BGP update packet. */
! 394: bgp_packet_set_marker (s, BGP_MSG_UPDATE);
! 395:
! 396: /* Unfeasible Routes Length. */
! 397: stream_putw (s, 0);
! 398:
! 399: /* Make place for total attribute length. */
! 400: pos = stream_get_endp (s);
! 401: stream_putw (s, 0);
! 402: total_attr_len = bgp_packet_attribute (NULL, peer, s, attr, &p, afi, safi, from, NULL, NULL);
! 403:
! 404: /* Set Total Path Attribute Length. */
! 405: stream_putw_at (s, pos, total_attr_len);
! 406:
! 407: /* NLRI set. */
! 408: if (p.family == AF_INET && safi == SAFI_UNICAST)
! 409: stream_put_prefix (s, &p);
! 410:
! 411: /* Set size. */
! 412: bgp_packet_set_size (s);
! 413:
! 414: packet = stream_dup (s);
! 415: stream_free (s);
! 416:
! 417: /* Dump packet if debug option is set. */
! 418: #ifdef DEBUG
! 419: /* bgp_packet_dump (packet); */
! 420: #endif /* DEBUG */
! 421:
! 422: /* Add packet to the peer. */
! 423: bgp_packet_add (peer, packet);
! 424:
! 425: BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
! 426: }
! 427:
! 428: void
! 429: bgp_default_withdraw_send (struct peer *peer, afi_t afi, safi_t safi)
! 430: {
! 431: struct stream *s;
! 432: struct stream *packet;
! 433: struct prefix p;
! 434: unsigned long pos;
! 435: unsigned long cp;
! 436: bgp_size_t unfeasible_len;
! 437: bgp_size_t total_attr_len;
! 438: char buf[BUFSIZ];
! 439:
! 440: if (DISABLE_BGP_ANNOUNCE)
! 441: return;
! 442:
! 443: if (afi == AFI_IP)
! 444: str2prefix ("0.0.0.0/0", &p);
! 445: #ifdef HAVE_IPV6
! 446: else
! 447: str2prefix ("::/0", &p);
! 448: #endif /* HAVE_IPV6 */
! 449:
! 450: total_attr_len = 0;
! 451: pos = 0;
! 452:
! 453: if (BGP_DEBUG (update, UPDATE_OUT))
! 454: zlog (peer->log, LOG_DEBUG, "%s send UPDATE %s/%d -- unreachable",
! 455: peer->host, inet_ntop(p.family, &(p.u.prefix), buf, BUFSIZ),
! 456: p.prefixlen);
! 457:
! 458: s = stream_new (BGP_MAX_PACKET_SIZE);
! 459:
! 460: /* Make BGP update packet. */
! 461: bgp_packet_set_marker (s, BGP_MSG_UPDATE);
! 462:
! 463: /* Unfeasible Routes Length. */;
! 464: cp = stream_get_endp (s);
! 465: stream_putw (s, 0);
! 466:
! 467: /* Withdrawn Routes. */
! 468: if (p.family == AF_INET && safi == SAFI_UNICAST)
! 469: {
! 470: stream_put_prefix (s, &p);
! 471:
! 472: unfeasible_len = stream_get_endp (s) - cp - 2;
! 473:
! 474: /* Set unfeasible len. */
! 475: stream_putw_at (s, cp, unfeasible_len);
! 476:
! 477: /* Set total path attribute length. */
! 478: stream_putw (s, 0);
! 479: }
! 480: else
! 481: {
! 482: pos = stream_get_endp (s);
! 483: stream_putw (s, 0);
! 484: total_attr_len = bgp_packet_withdraw (peer, s, &p, afi, safi, NULL, NULL);
! 485:
! 486: /* Set total path attribute length. */
! 487: stream_putw_at (s, pos, total_attr_len);
! 488: }
! 489:
! 490: bgp_packet_set_size (s);
! 491:
! 492: packet = stream_dup (s);
! 493: stream_free (s);
! 494:
! 495: /* Add packet to the peer. */
! 496: bgp_packet_add (peer, packet);
! 497:
! 498: BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
! 499: }
! 500:
! 501: /* Get next packet to be written. */
! 502: static struct stream *
! 503: bgp_write_packet (struct peer *peer)
! 504: {
! 505: afi_t afi;
! 506: safi_t safi;
! 507: struct stream *s = NULL;
! 508: struct bgp_advertise *adv;
! 509:
! 510: s = stream_fifo_head (peer->obuf);
! 511: if (s)
! 512: return s;
! 513:
! 514: for (afi = AFI_IP; afi < AFI_MAX; afi++)
! 515: for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
! 516: {
! 517: adv = FIFO_HEAD (&peer->sync[afi][safi]->withdraw);
! 518: if (adv)
! 519: {
! 520: s = bgp_withdraw_packet (peer, afi, safi);
! 521: if (s)
! 522: return s;
! 523: }
! 524: }
! 525:
! 526: for (afi = AFI_IP; afi < AFI_MAX; afi++)
! 527: for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
! 528: {
! 529: adv = FIFO_HEAD (&peer->sync[afi][safi]->update);
! 530: if (adv)
! 531: {
! 532: if (adv->binfo && adv->binfo->uptime < peer->synctime)
! 533: {
! 534: if (CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_RCV)
! 535: && CHECK_FLAG (adv->binfo->peer->cap, PEER_CAP_RESTART_ADV)
! 536: && ! CHECK_FLAG (adv->binfo->flags, BGP_INFO_STALE)
! 537: && safi != SAFI_MPLS_VPN)
! 538: {
! 539: if (CHECK_FLAG (adv->binfo->peer->af_sflags[afi][safi],
! 540: PEER_STATUS_EOR_RECEIVED))
! 541: s = bgp_update_packet (peer, afi, safi);
! 542: }
! 543: else
! 544: s = bgp_update_packet (peer, afi, safi);
! 545: }
! 546:
! 547: if (s)
! 548: return s;
! 549: }
! 550:
! 551: if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV))
! 552: {
! 553: if (peer->afc_nego[afi][safi] && peer->synctime
! 554: && ! CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND)
! 555: && safi != SAFI_MPLS_VPN)
! 556: {
! 557: SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_EOR_SEND);
! 558: return bgp_update_packet_eor (peer, afi, safi);
! 559: }
! 560: }
! 561: }
! 562:
! 563: return NULL;
! 564: }
! 565:
! 566: /* Is there partially written packet or updates we can send right
! 567: now. */
! 568: static int
! 569: bgp_write_proceed (struct peer *peer)
! 570: {
! 571: afi_t afi;
! 572: safi_t safi;
! 573: struct bgp_advertise *adv;
! 574:
! 575: if (stream_fifo_head (peer->obuf))
! 576: return 1;
! 577:
! 578: for (afi = AFI_IP; afi < AFI_MAX; afi++)
! 579: for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
! 580: if (FIFO_HEAD (&peer->sync[afi][safi]->withdraw))
! 581: return 1;
! 582:
! 583: for (afi = AFI_IP; afi < AFI_MAX; afi++)
! 584: for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++)
! 585: if ((adv = FIFO_HEAD (&peer->sync[afi][safi]->update)) != NULL)
! 586: if (adv->binfo->uptime < peer->synctime)
! 587: return 1;
! 588:
! 589: return 0;
! 590: }
! 591:
! 592: /* Write packet to the peer. */
! 593: int
! 594: bgp_write (struct thread *thread)
! 595: {
! 596: struct peer *peer;
! 597: u_char type;
! 598: struct stream *s;
! 599: int num;
! 600: unsigned int count = 0;
! 601:
! 602: /* Yes first of all get peer pointer. */
! 603: peer = THREAD_ARG (thread);
! 604: peer->t_write = NULL;
! 605:
! 606: /* For non-blocking IO check. */
! 607: if (peer->status == Connect)
! 608: {
! 609: bgp_connect_check (peer);
! 610: return 0;
! 611: }
! 612:
! 613: s = bgp_write_packet (peer);
! 614: if (!s)
! 615: return 0; /* nothing to send */
! 616:
! 617: sockopt_cork (peer->fd, 1);
! 618:
! 619: /* Nonblocking write until TCP output buffer is full. */
! 620: do
! 621: {
! 622: int writenum;
! 623:
! 624: /* Number of bytes to be sent. */
! 625: writenum = stream_get_endp (s) - stream_get_getp (s);
! 626:
! 627: /* Call write() system call. */
! 628: num = write (peer->fd, STREAM_PNT (s), writenum);
! 629: if (num < 0)
! 630: {
! 631: /* write failed either retry needed or error */
! 632: if (ERRNO_IO_RETRY(errno))
! 633: break;
! 634:
! 635: BGP_EVENT_ADD (peer, TCP_fatal_error);
! 636: return 0;
! 637: }
! 638:
! 639: if (num != writenum)
! 640: {
! 641: /* Partial write */
! 642: stream_forward_getp (s, num);
! 643: break;
! 644: }
! 645:
! 646: /* Retrieve BGP packet type. */
! 647: stream_set_getp (s, BGP_MARKER_SIZE + 2);
! 648: type = stream_getc (s);
! 649:
! 650: switch (type)
! 651: {
! 652: case BGP_MSG_OPEN:
! 653: peer->open_out++;
! 654: break;
! 655: case BGP_MSG_UPDATE:
! 656: peer->update_out++;
! 657: break;
! 658: case BGP_MSG_NOTIFY:
! 659: peer->notify_out++;
! 660: /* Double start timer. */
! 661: peer->v_start *= 2;
! 662:
! 663: /* Overflow check. */
! 664: if (peer->v_start >= (60 * 2))
! 665: peer->v_start = (60 * 2);
! 666:
! 667: /* Flush any existing events */
! 668: BGP_EVENT_ADD (peer, BGP_Stop);
! 669: return 0;
! 670: case BGP_MSG_KEEPALIVE:
! 671: peer->keepalive_out++;
! 672: break;
! 673: case BGP_MSG_ROUTE_REFRESH_NEW:
! 674: case BGP_MSG_ROUTE_REFRESH_OLD:
! 675: peer->refresh_out++;
! 676: break;
! 677: case BGP_MSG_CAPABILITY:
! 678: peer->dynamic_cap_out++;
! 679: break;
! 680: }
! 681:
! 682: /* OK we send packet so delete it. */
! 683: bgp_packet_delete (peer);
! 684: }
! 685: while (++count < BGP_WRITE_PACKET_MAX &&
! 686: (s = bgp_write_packet (peer)) != NULL);
! 687:
! 688: if (bgp_write_proceed (peer))
! 689: BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
! 690: else
! 691: sockopt_cork (peer->fd, 0);
! 692:
! 693: return 0;
! 694: }
! 695:
! 696: /* This is only for sending NOTIFICATION message to neighbor. */
! 697: static int
! 698: bgp_write_notify (struct peer *peer)
! 699: {
! 700: int ret, val;
! 701: u_char type;
! 702: struct stream *s;
! 703:
! 704: /* There should be at least one packet. */
! 705: s = stream_fifo_head (peer->obuf);
! 706: if (!s)
! 707: return 0;
! 708: assert (stream_get_endp (s) >= BGP_HEADER_SIZE);
! 709:
! 710: /* Put socket in blocking mode. */
! 711: val = fcntl (peer->fd, F_GETFL, 0);
! 712: fcntl (peer->fd, F_SETFL, val & ~O_NONBLOCK);
! 713:
! 714: ret = writen (peer->fd, STREAM_DATA (s), stream_get_endp (s));
! 715: if (ret <= 0)
! 716: {
! 717: BGP_EVENT_ADD (peer, TCP_fatal_error);
! 718: return 0;
! 719: }
! 720:
! 721: /* Retrieve BGP packet type. */
! 722: stream_set_getp (s, BGP_MARKER_SIZE + 2);
! 723: type = stream_getc (s);
! 724:
! 725: assert (type == BGP_MSG_NOTIFY);
! 726:
! 727: /* Type should be notify. */
! 728: peer->notify_out++;
! 729:
! 730: /* Double start timer. */
! 731: peer->v_start *= 2;
! 732:
! 733: /* Overflow check. */
! 734: if (peer->v_start >= (60 * 2))
! 735: peer->v_start = (60 * 2);
! 736:
! 737: BGP_EVENT_ADD (peer, BGP_Stop);
! 738:
! 739: return 0;
! 740: }
! 741:
! 742: /* Make keepalive packet and send it to the peer. */
! 743: void
! 744: bgp_keepalive_send (struct peer *peer)
! 745: {
! 746: struct stream *s;
! 747: int length;
! 748:
! 749: s = stream_new (BGP_MAX_PACKET_SIZE);
! 750:
! 751: /* Make keepalive packet. */
! 752: bgp_packet_set_marker (s, BGP_MSG_KEEPALIVE);
! 753:
! 754: /* Set packet size. */
! 755: length = bgp_packet_set_size (s);
! 756:
! 757: /* Dump packet if debug option is set. */
! 758: /* bgp_packet_dump (s); */
! 759:
! 760: if (BGP_DEBUG (keepalive, KEEPALIVE))
! 761: zlog_debug ("%s sending KEEPALIVE", peer->host);
! 762: if (BGP_DEBUG (normal, NORMAL))
! 763: zlog_debug ("%s send message type %d, length (incl. header) %d",
! 764: peer->host, BGP_MSG_KEEPALIVE, length);
! 765:
! 766: /* Add packet to the peer. */
! 767: bgp_packet_add (peer, s);
! 768:
! 769: BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
! 770: }
! 771:
! 772: /* Make open packet and send it to the peer. */
! 773: void
! 774: bgp_open_send (struct peer *peer)
! 775: {
! 776: struct stream *s;
! 777: int length;
! 778: u_int16_t send_holdtime;
! 779: as_t local_as;
! 780:
! 781: if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
! 782: send_holdtime = peer->holdtime;
! 783: else
! 784: send_holdtime = peer->bgp->default_holdtime;
! 785:
! 786: /* local-as Change */
! 787: if (peer->change_local_as)
! 788: local_as = peer->change_local_as;
! 789: else
! 790: local_as = peer->local_as;
! 791:
! 792: s = stream_new (BGP_MAX_PACKET_SIZE);
! 793:
! 794: /* Make open packet. */
! 795: bgp_packet_set_marker (s, BGP_MSG_OPEN);
! 796:
! 797: /* Set open packet values. */
! 798: stream_putc (s, BGP_VERSION_4); /* BGP version */
! 799: stream_putw (s, (local_as <= BGP_AS_MAX) ? (u_int16_t) local_as
! 800: : BGP_AS_TRANS);
! 801: stream_putw (s, send_holdtime); /* Hold Time */
! 802: stream_put_in_addr (s, &peer->local_id); /* BGP Identifier */
! 803:
! 804: /* Set capability code. */
! 805: bgp_open_capability (s, peer);
! 806:
! 807: /* Set BGP packet length. */
! 808: length = bgp_packet_set_size (s);
! 809:
! 810: if (BGP_DEBUG (normal, NORMAL))
! 811: zlog_debug ("%s sending OPEN, version %d, my as %u, holdtime %d, id %s",
! 812: peer->host, BGP_VERSION_4, local_as,
! 813: send_holdtime, inet_ntoa (peer->local_id));
! 814:
! 815: if (BGP_DEBUG (normal, NORMAL))
! 816: zlog_debug ("%s send message type %d, length (incl. header) %d",
! 817: peer->host, BGP_MSG_OPEN, length);
! 818:
! 819: /* Dump packet if debug option is set. */
! 820: /* bgp_packet_dump (s); */
! 821:
! 822: /* Add packet to the peer. */
! 823: bgp_packet_add (peer, s);
! 824:
! 825: BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
! 826: }
! 827:
! 828: /* Send BGP notify packet with data potion. */
! 829: void
! 830: bgp_notify_send_with_data (struct peer *peer, u_char code, u_char sub_code,
! 831: u_char *data, size_t datalen)
! 832: {
! 833: struct stream *s;
! 834: int length;
! 835:
! 836: /* Allocate new stream. */
! 837: s = stream_new (BGP_MAX_PACKET_SIZE);
! 838:
! 839: /* Make nitify packet. */
! 840: bgp_packet_set_marker (s, BGP_MSG_NOTIFY);
! 841:
! 842: /* Set notify packet values. */
! 843: stream_putc (s, code); /* BGP notify code */
! 844: stream_putc (s, sub_code); /* BGP notify sub_code */
! 845:
! 846: /* If notify data is present. */
! 847: if (data)
! 848: stream_write (s, data, datalen);
! 849:
! 850: /* Set BGP packet length. */
! 851: length = bgp_packet_set_size (s);
! 852:
! 853: /* Add packet to the peer. */
! 854: stream_fifo_clean (peer->obuf);
! 855: bgp_packet_add (peer, s);
! 856:
! 857: /* For debug */
! 858: {
! 859: struct bgp_notify bgp_notify;
! 860: int first = 0;
! 861: int i;
! 862: char c[4];
! 863:
! 864: bgp_notify.code = code;
! 865: bgp_notify.subcode = sub_code;
! 866: bgp_notify.data = NULL;
! 867: bgp_notify.length = length - BGP_MSG_NOTIFY_MIN_SIZE;
! 868:
! 869: if (bgp_notify.length)
! 870: {
! 871: bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
! 872: for (i = 0; i < bgp_notify.length; i++)
! 873: if (first)
! 874: {
! 875: sprintf (c, " %02x", data[i]);
! 876: strcat (bgp_notify.data, c);
! 877: }
! 878: else
! 879: {
! 880: first = 1;
! 881: sprintf (c, "%02x", data[i]);
! 882: strcpy (bgp_notify.data, c);
! 883: }
! 884: }
! 885: bgp_notify_print (peer, &bgp_notify, "sending");
! 886: if (bgp_notify.data)
! 887: XFREE (MTYPE_TMP, bgp_notify.data);
! 888: }
! 889:
! 890: if (BGP_DEBUG (normal, NORMAL))
! 891: zlog_debug ("%s send message type %d, length (incl. header) %d",
! 892: peer->host, BGP_MSG_NOTIFY, length);
! 893:
! 894: /* peer reset cause */
! 895: if (sub_code != BGP_NOTIFY_CEASE_CONFIG_CHANGE)
! 896: {
! 897: if (sub_code == BGP_NOTIFY_CEASE_ADMIN_RESET)
! 898: {
! 899: peer->last_reset = PEER_DOWN_USER_RESET;
! 900: zlog_info ("Notification sent to neighbor %s: User reset", peer->host);
! 901: }
! 902: else if (sub_code == BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN)
! 903: {
! 904: peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
! 905: zlog_info ("Notification sent to neighbor %s: shutdown", peer->host);
! 906: }
! 907: else
! 908: {
! 909: peer->last_reset = PEER_DOWN_NOTIFY_SEND;
! 910: zlog_info ("Notification sent to neighbor %s: type %u/%u",
! 911: peer->host, code, sub_code);
! 912: }
! 913: }
! 914: else
! 915: zlog_info ("Notification sent to neighbor %s: configuration change",
! 916: peer->host);
! 917:
! 918: /* Call immediately. */
! 919: BGP_WRITE_OFF (peer->t_write);
! 920:
! 921: bgp_write_notify (peer);
! 922: }
! 923:
! 924: /* Send BGP notify packet. */
! 925: void
! 926: bgp_notify_send (struct peer *peer, u_char code, u_char sub_code)
! 927: {
! 928: bgp_notify_send_with_data (peer, code, sub_code, NULL, 0);
! 929: }
! 930:
! 931: /* Send route refresh message to the peer. */
! 932: void
! 933: bgp_route_refresh_send (struct peer *peer, afi_t afi, safi_t safi,
! 934: u_char orf_type, u_char when_to_refresh, int remove)
! 935: {
! 936: struct stream *s;
! 937: struct stream *packet;
! 938: int length;
! 939: struct bgp_filter *filter;
! 940: int orf_refresh = 0;
! 941:
! 942: if (DISABLE_BGP_ANNOUNCE)
! 943: return;
! 944:
! 945: filter = &peer->filter[afi][safi];
! 946:
! 947: /* Adjust safi code. */
! 948: if (safi == SAFI_MPLS_VPN)
! 949: safi = BGP_SAFI_VPNV4;
! 950:
! 951: s = stream_new (BGP_MAX_PACKET_SIZE);
! 952:
! 953: /* Make BGP update packet. */
! 954: if (CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV))
! 955: bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_NEW);
! 956: else
! 957: bgp_packet_set_marker (s, BGP_MSG_ROUTE_REFRESH_OLD);
! 958:
! 959: /* Encode Route Refresh message. */
! 960: stream_putw (s, afi);
! 961: stream_putc (s, 0);
! 962: stream_putc (s, safi);
! 963:
! 964: if (orf_type == ORF_TYPE_PREFIX
! 965: || orf_type == ORF_TYPE_PREFIX_OLD)
! 966: if (remove || filter->plist[FILTER_IN].plist)
! 967: {
! 968: u_int16_t orf_len;
! 969: unsigned long orfp;
! 970:
! 971: orf_refresh = 1;
! 972: stream_putc (s, when_to_refresh);
! 973: stream_putc (s, orf_type);
! 974: orfp = stream_get_endp (s);
! 975: stream_putw (s, 0);
! 976:
! 977: if (remove)
! 978: {
! 979: UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
! 980: stream_putc (s, ORF_COMMON_PART_REMOVE_ALL);
! 981: if (BGP_DEBUG (normal, NORMAL))
! 982: zlog_debug ("%s sending REFRESH_REQ to remove ORF(%d) (%s) for afi/safi: %d/%d",
! 983: peer->host, orf_type,
! 984: (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
! 985: afi, safi);
! 986: }
! 987: else
! 988: {
! 989: SET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_PREFIX_SEND);
! 990: prefix_bgp_orf_entry (s, filter->plist[FILTER_IN].plist,
! 991: ORF_COMMON_PART_ADD, ORF_COMMON_PART_PERMIT,
! 992: ORF_COMMON_PART_DENY);
! 993: if (BGP_DEBUG (normal, NORMAL))
! 994: zlog_debug ("%s sending REFRESH_REQ with pfxlist ORF(%d) (%s) for afi/safi: %d/%d",
! 995: peer->host, orf_type,
! 996: (when_to_refresh == REFRESH_DEFER ? "defer" : "immediate"),
! 997: afi, safi);
! 998: }
! 999:
! 1000: /* Total ORF Entry Len. */
! 1001: orf_len = stream_get_endp (s) - orfp - 2;
! 1002: stream_putw_at (s, orfp, orf_len);
! 1003: }
! 1004:
! 1005: /* Set packet size. */
! 1006: length = bgp_packet_set_size (s);
! 1007:
! 1008: if (BGP_DEBUG (normal, NORMAL))
! 1009: {
! 1010: if (! orf_refresh)
! 1011: zlog_debug ("%s sending REFRESH_REQ for afi/safi: %d/%d",
! 1012: peer->host, afi, safi);
! 1013: zlog_debug ("%s send message type %d, length (incl. header) %d",
! 1014: peer->host, CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV) ?
! 1015: BGP_MSG_ROUTE_REFRESH_NEW : BGP_MSG_ROUTE_REFRESH_OLD, length);
! 1016: }
! 1017:
! 1018: /* Make real packet. */
! 1019: packet = stream_dup (s);
! 1020: stream_free (s);
! 1021:
! 1022: /* Add packet to the peer. */
! 1023: bgp_packet_add (peer, packet);
! 1024:
! 1025: BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
! 1026: }
! 1027:
! 1028: /* Send capability message to the peer. */
! 1029: void
! 1030: bgp_capability_send (struct peer *peer, afi_t afi, safi_t safi,
! 1031: int capability_code, int action)
! 1032: {
! 1033: struct stream *s;
! 1034: struct stream *packet;
! 1035: int length;
! 1036:
! 1037: /* Adjust safi code. */
! 1038: if (safi == SAFI_MPLS_VPN)
! 1039: safi = BGP_SAFI_VPNV4;
! 1040:
! 1041: s = stream_new (BGP_MAX_PACKET_SIZE);
! 1042:
! 1043: /* Make BGP update packet. */
! 1044: bgp_packet_set_marker (s, BGP_MSG_CAPABILITY);
! 1045:
! 1046: /* Encode MP_EXT capability. */
! 1047: if (capability_code == CAPABILITY_CODE_MP)
! 1048: {
! 1049: stream_putc (s, action);
! 1050: stream_putc (s, CAPABILITY_CODE_MP);
! 1051: stream_putc (s, CAPABILITY_CODE_MP_LEN);
! 1052: stream_putw (s, afi);
! 1053: stream_putc (s, 0);
! 1054: stream_putc (s, safi);
! 1055:
! 1056: if (BGP_DEBUG (normal, NORMAL))
! 1057: zlog_debug ("%s sending CAPABILITY has %s MP_EXT CAP for afi/safi: %d/%d",
! 1058: peer->host, action == CAPABILITY_ACTION_SET ?
! 1059: "Advertising" : "Removing", afi, safi);
! 1060: }
! 1061:
! 1062: /* Set packet size. */
! 1063: length = bgp_packet_set_size (s);
! 1064:
! 1065: /* Make real packet. */
! 1066: packet = stream_dup (s);
! 1067: stream_free (s);
! 1068:
! 1069: /* Add packet to the peer. */
! 1070: bgp_packet_add (peer, packet);
! 1071:
! 1072: if (BGP_DEBUG (normal, NORMAL))
! 1073: zlog_debug ("%s send message type %d, length (incl. header) %d",
! 1074: peer->host, BGP_MSG_CAPABILITY, length);
! 1075:
! 1076: BGP_WRITE_ON (peer->t_write, bgp_write, peer->fd);
! 1077: }
! 1078:
! 1079: /* RFC1771 6.8 Connection collision detection. */
! 1080: static int
! 1081: bgp_collision_detect (struct peer *new, struct in_addr remote_id)
! 1082: {
! 1083: struct peer *peer;
! 1084: struct listnode *node, *nnode;
! 1085: struct bgp *bgp;
! 1086:
! 1087: bgp = bgp_get_default ();
! 1088: if (! bgp)
! 1089: return 0;
! 1090:
! 1091: /* Upon receipt of an OPEN message, the local system must examine
! 1092: all of its connections that are in the OpenConfirm state. A BGP
! 1093: speaker may also examine connections in an OpenSent state if it
! 1094: knows the BGP Identifier of the peer by means outside of the
! 1095: protocol. If among these connections there is a connection to a
! 1096: remote BGP speaker whose BGP Identifier equals the one in the
! 1097: OPEN message, then the local system performs the following
! 1098: collision resolution procedure: */
! 1099:
! 1100: for (ALL_LIST_ELEMENTS (bgp->peer, node, nnode, peer))
! 1101: {
! 1102: /* Under OpenConfirm status, local peer structure already hold
! 1103: remote router ID. */
! 1104:
! 1105: if (peer != new
! 1106: && (peer->status == OpenConfirm || peer->status == OpenSent)
! 1107: && sockunion_same (&peer->su, &new->su))
! 1108: {
! 1109: /* 1. The BGP Identifier of the local system is compared to
! 1110: the BGP Identifier of the remote system (as specified in
! 1111: the OPEN message). */
! 1112:
! 1113: if (ntohl (peer->local_id.s_addr) < ntohl (remote_id.s_addr))
! 1114: {
! 1115: /* 2. If the value of the local BGP Identifier is less
! 1116: than the remote one, the local system closes BGP
! 1117: connection that already exists (the one that is
! 1118: already in the OpenConfirm state), and accepts BGP
! 1119: connection initiated by the remote system. */
! 1120:
! 1121: if (peer->fd >= 0)
! 1122: bgp_notify_send (peer, BGP_NOTIFY_CEASE, BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
! 1123: return 1;
! 1124: }
! 1125: else
! 1126: {
! 1127: /* 3. Otherwise, the local system closes newly created
! 1128: BGP connection (the one associated with the newly
! 1129: received OPEN message), and continues to use the
! 1130: existing one (the one that is already in the
! 1131: OpenConfirm state). */
! 1132:
! 1133: if (new->fd >= 0)
! 1134: bgp_notify_send (new, BGP_NOTIFY_CEASE,
! 1135: BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
! 1136: return -1;
! 1137: }
! 1138: }
! 1139: }
! 1140: return 0;
! 1141: }
! 1142:
! 1143: static int
! 1144: bgp_open_receive (struct peer *peer, bgp_size_t size)
! 1145: {
! 1146: int ret;
! 1147: u_char version;
! 1148: u_char optlen;
! 1149: u_int16_t holdtime;
! 1150: u_int16_t send_holdtime;
! 1151: as_t remote_as;
! 1152: as_t as4 = 0;
! 1153: struct peer *realpeer;
! 1154: struct in_addr remote_id;
! 1155: int capability;
! 1156: u_int8_t notify_data_remote_as[2];
! 1157: u_int8_t notify_data_remote_id[4];
! 1158:
! 1159: realpeer = NULL;
! 1160:
! 1161: /* Parse open packet. */
! 1162: version = stream_getc (peer->ibuf);
! 1163: memcpy (notify_data_remote_as, stream_pnt (peer->ibuf), 2);
! 1164: remote_as = stream_getw (peer->ibuf);
! 1165: holdtime = stream_getw (peer->ibuf);
! 1166: memcpy (notify_data_remote_id, stream_pnt (peer->ibuf), 4);
! 1167: remote_id.s_addr = stream_get_ipv4 (peer->ibuf);
! 1168:
! 1169: /* Receive OPEN message log */
! 1170: if (BGP_DEBUG (normal, NORMAL))
! 1171: zlog_debug ("%s rcv OPEN, version %d, remote-as (in open) %u,"
! 1172: " holdtime %d, id %s",
! 1173: peer->host, version, remote_as, holdtime,
! 1174: inet_ntoa (remote_id));
! 1175:
! 1176: /* BEGIN to read the capability here, but dont do it yet */
! 1177: capability = 0;
! 1178: optlen = stream_getc (peer->ibuf);
! 1179:
! 1180: if (optlen != 0)
! 1181: {
! 1182: /* We need the as4 capability value *right now* because
! 1183: * if it is there, we have not got the remote_as yet, and without
! 1184: * that we do not know which peer is connecting to us now.
! 1185: */
! 1186: as4 = peek_for_as4_capability (peer, optlen);
! 1187: }
! 1188:
! 1189: /* Just in case we have a silly peer who sends AS4 capability set to 0 */
! 1190: if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV) && !as4)
! 1191: {
! 1192: zlog_err ("%s bad OPEN, got AS4 capability, but AS4 set to 0",
! 1193: peer->host);
! 1194: bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
! 1195: BGP_NOTIFY_OPEN_BAD_PEER_AS);
! 1196: return -1;
! 1197: }
! 1198:
! 1199: if (remote_as == BGP_AS_TRANS)
! 1200: {
! 1201: /* Take the AS4 from the capability. We must have received the
! 1202: * capability now! Otherwise we have a asn16 peer who uses
! 1203: * BGP_AS_TRANS, for some unknown reason.
! 1204: */
! 1205: if (as4 == BGP_AS_TRANS)
! 1206: {
! 1207: zlog_err ("%s [AS4] NEW speaker using AS_TRANS for AS4, not allowed",
! 1208: peer->host);
! 1209: bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
! 1210: BGP_NOTIFY_OPEN_BAD_PEER_AS);
! 1211: return -1;
! 1212: }
! 1213:
! 1214: if (!as4 && BGP_DEBUG (as4, AS4))
! 1215: zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but no AS4."
! 1216: " Odd, but proceeding.", peer->host);
! 1217: else if (as4 < BGP_AS_MAX && BGP_DEBUG (as4, AS4))
! 1218: zlog_debug ("%s [AS4] OPEN remote_as is AS_TRANS, but AS4 (%u) fits "
! 1219: "in 2-bytes, very odd peer.", peer->host, as4);
! 1220: if (as4)
! 1221: remote_as = as4;
! 1222: }
! 1223: else
! 1224: {
! 1225: /* We may have a partner with AS4 who has an asno < BGP_AS_MAX */
! 1226: /* If we have got the capability, peer->as4cap must match remote_as */
! 1227: if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)
! 1228: && as4 != remote_as)
! 1229: {
! 1230: /* raise error, log this, close session */
! 1231: zlog_err ("%s bad OPEN, got AS4 capability, but remote_as %u"
! 1232: " mismatch with 16bit 'myasn' %u in open",
! 1233: peer->host, as4, remote_as);
! 1234: bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
! 1235: BGP_NOTIFY_OPEN_BAD_PEER_AS);
! 1236: return -1;
! 1237: }
! 1238: }
! 1239:
! 1240: /* Lookup peer from Open packet. */
! 1241: if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
! 1242: {
! 1243: int as = 0;
! 1244:
! 1245: realpeer = peer_lookup_with_open (&peer->su, remote_as, &remote_id, &as);
! 1246:
! 1247: if (! realpeer)
! 1248: {
! 1249: /* Peer's source IP address is check in bgp_accept(), so this
! 1250: must be AS number mismatch or remote-id configuration
! 1251: mismatch. */
! 1252: if (as)
! 1253: {
! 1254: if (BGP_DEBUG (normal, NORMAL))
! 1255: zlog_debug ("%s bad OPEN, wrong router identifier %s",
! 1256: peer->host, inet_ntoa (remote_id));
! 1257: bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
! 1258: BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
! 1259: notify_data_remote_id, 4);
! 1260: }
! 1261: else
! 1262: {
! 1263: if (BGP_DEBUG (normal, NORMAL))
! 1264: zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
! 1265: peer->host, remote_as, peer->as);
! 1266: bgp_notify_send_with_data (peer, BGP_NOTIFY_OPEN_ERR,
! 1267: BGP_NOTIFY_OPEN_BAD_PEER_AS,
! 1268: notify_data_remote_as, 2);
! 1269: }
! 1270: return -1;
! 1271: }
! 1272: }
! 1273:
! 1274: /* When collision is detected and this peer is closed. Retrun
! 1275: immidiately. */
! 1276: ret = bgp_collision_detect (peer, remote_id);
! 1277: if (ret < 0)
! 1278: return ret;
! 1279:
! 1280: /* Hack part. */
! 1281: if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
! 1282: {
! 1283: if (realpeer->status == Established
! 1284: && CHECK_FLAG (realpeer->sflags, PEER_STATUS_NSF_MODE))
! 1285: {
! 1286: realpeer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
! 1287: SET_FLAG (realpeer->sflags, PEER_STATUS_NSF_WAIT);
! 1288: }
! 1289: else if (ret == 0 && realpeer->status != Active
! 1290: && realpeer->status != OpenSent
! 1291: && realpeer->status != OpenConfirm
! 1292: && realpeer->status != Connect)
! 1293: {
! 1294: /* XXX: This is an awful problem..
! 1295: *
! 1296: * According to the RFC we should just let this connection (of the
! 1297: * accepted 'peer') continue on to Established if the other
! 1298: * connection (the 'realpeer' one) is in state Connect, and deal
! 1299: * with the more larval FSM as/when it gets far enough to receive
! 1300: * an Open. We don't do that though, we instead close the (more
! 1301: * developed) accepted connection.
! 1302: *
! 1303: * This means there's a race, which if hit, can loop:
! 1304: *
! 1305: * FSM for A FSM for B
! 1306: * realpeer accept-peer realpeer accept-peer
! 1307: *
! 1308: * Connect Connect
! 1309: * Active
! 1310: * OpenSent OpenSent
! 1311: * <arrive here,
! 1312: * Notify, delete>
! 1313: * Idle Active
! 1314: * OpenSent OpenSent
! 1315: * <arrive here,
! 1316: * Notify, delete>
! 1317: * Idle
! 1318: * <wait> <wait>
! 1319: * Connect Connect
! 1320: *
! 1321: *
! 1322: * If both sides are Quagga, they're almost certain to wait for
! 1323: * the same amount of time of course (which doesn't preclude other
! 1324: * implementations also waiting for same time). The race is
! 1325: * exacerbated by high-latency (in bgpd and/or the network).
! 1326: *
! 1327: * The reason we do this is because our FSM is tied to our peer
! 1328: * structure, which carries our configuration information, etc.
! 1329: * I.e. we can't let the accepted-peer FSM continue on as it is,
! 1330: * cause it's not associated with any actual peer configuration -
! 1331: * it's just a dummy.
! 1332: *
! 1333: * It's possible we could hack-fix this by just bgp_stop'ing the
! 1334: * realpeer and continueing on with the 'transfer FSM' below.
! 1335: * Ideally, we need to seperate FSMs from struct peer.
! 1336: *
! 1337: * Setting one side to passive avoids the race, as a workaround.
! 1338: */
! 1339: if (BGP_DEBUG (events, EVENTS))
! 1340: zlog_debug ("%s peer status is %s close connection",
! 1341: realpeer->host, LOOKUP (bgp_status_msg,
! 1342: realpeer->status));
! 1343: bgp_notify_send (peer, BGP_NOTIFY_CEASE,
! 1344: BGP_NOTIFY_CEASE_CONNECT_REJECT);
! 1345:
! 1346: return -1;
! 1347: }
! 1348:
! 1349: if (BGP_DEBUG (events, EVENTS))
! 1350: zlog_debug ("%s [Event] Transfer accept BGP peer to real (state %s)",
! 1351: peer->host,
! 1352: LOOKUP (bgp_status_msg, realpeer->status));
! 1353:
! 1354: bgp_stop (realpeer);
! 1355:
! 1356: /* Transfer file descriptor. */
! 1357: realpeer->fd = peer->fd;
! 1358: peer->fd = -1;
! 1359:
! 1360: /* Transfer input buffer. */
! 1361: stream_free (realpeer->ibuf);
! 1362: realpeer->ibuf = peer->ibuf;
! 1363: realpeer->packet_size = peer->packet_size;
! 1364: peer->ibuf = NULL;
! 1365:
! 1366: /* Transfer status. */
! 1367: realpeer->status = peer->status;
! 1368: bgp_stop (peer);
! 1369:
! 1370: /* peer pointer change. Open packet send to neighbor. */
! 1371: peer = realpeer;
! 1372: bgp_open_send (peer);
! 1373: if (peer->fd < 0)
! 1374: {
! 1375: zlog_err ("bgp_open_receive peer's fd is negative value %d",
! 1376: peer->fd);
! 1377: return -1;
! 1378: }
! 1379: BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
! 1380: }
! 1381:
! 1382: /* remote router-id check. */
! 1383: if (remote_id.s_addr == 0
! 1384: || ntohl (remote_id.s_addr) >= 0xe0000000
! 1385: || ntohl (peer->local_id.s_addr) == ntohl (remote_id.s_addr))
! 1386: {
! 1387: if (BGP_DEBUG (normal, NORMAL))
! 1388: zlog_debug ("%s bad OPEN, wrong router identifier %s",
! 1389: peer->host, inet_ntoa (remote_id));
! 1390: bgp_notify_send_with_data (peer,
! 1391: BGP_NOTIFY_OPEN_ERR,
! 1392: BGP_NOTIFY_OPEN_BAD_BGP_IDENT,
! 1393: notify_data_remote_id, 4);
! 1394: return -1;
! 1395: }
! 1396:
! 1397: /* Set remote router-id */
! 1398: peer->remote_id = remote_id;
! 1399:
! 1400: /* Peer BGP version check. */
! 1401: if (version != BGP_VERSION_4)
! 1402: {
! 1403: u_int8_t maxver = BGP_VERSION_4;
! 1404: if (BGP_DEBUG (normal, NORMAL))
! 1405: zlog_debug ("%s bad protocol version, remote requested %d, local request %d",
! 1406: peer->host, version, BGP_VERSION_4);
! 1407: bgp_notify_send_with_data (peer,
! 1408: BGP_NOTIFY_OPEN_ERR,
! 1409: BGP_NOTIFY_OPEN_UNSUP_VERSION,
! 1410: &maxver, 1);
! 1411: return -1;
! 1412: }
! 1413:
! 1414: /* Check neighbor as number. */
! 1415: if (remote_as != peer->as)
! 1416: {
! 1417: if (BGP_DEBUG (normal, NORMAL))
! 1418: zlog_debug ("%s bad OPEN, remote AS is %u, expected %u",
! 1419: peer->host, remote_as, peer->as);
! 1420: bgp_notify_send_with_data (peer,
! 1421: BGP_NOTIFY_OPEN_ERR,
! 1422: BGP_NOTIFY_OPEN_BAD_PEER_AS,
! 1423: notify_data_remote_as, 2);
! 1424: return -1;
! 1425: }
! 1426:
! 1427: /* From the rfc: Upon receipt of an OPEN message, a BGP speaker MUST
! 1428: calculate the value of the Hold Timer by using the smaller of its
! 1429: configured Hold Time and the Hold Time received in the OPEN message.
! 1430: The Hold Time MUST be either zero or at least three seconds. An
! 1431: implementation may reject connections on the basis of the Hold Time. */
! 1432:
! 1433: if (holdtime < 3 && holdtime != 0)
! 1434: {
! 1435: bgp_notify_send (peer,
! 1436: BGP_NOTIFY_OPEN_ERR,
! 1437: BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
! 1438: return -1;
! 1439: }
! 1440:
! 1441: /* From the rfc: A reasonable maximum time between KEEPALIVE messages
! 1442: would be one third of the Hold Time interval. KEEPALIVE messages
! 1443: MUST NOT be sent more frequently than one per second. An
! 1444: implementation MAY adjust the rate at which it sends KEEPALIVE
! 1445: messages as a function of the Hold Time interval. */
! 1446:
! 1447: if (CHECK_FLAG (peer->config, PEER_CONFIG_TIMER))
! 1448: send_holdtime = peer->holdtime;
! 1449: else
! 1450: send_holdtime = peer->bgp->default_holdtime;
! 1451:
! 1452: if (holdtime < send_holdtime)
! 1453: peer->v_holdtime = holdtime;
! 1454: else
! 1455: peer->v_holdtime = send_holdtime;
! 1456:
! 1457: peer->v_keepalive = peer->v_holdtime / 3;
! 1458:
! 1459: /* Open option part parse. */
! 1460: if (optlen != 0)
! 1461: {
! 1462: ret = bgp_open_option_parse (peer, optlen, &capability);
! 1463: if (ret < 0)
! 1464: return ret;
! 1465: }
! 1466: else
! 1467: {
! 1468: if (BGP_DEBUG (normal, NORMAL))
! 1469: zlog_debug ("%s rcvd OPEN w/ OPTION parameter len: 0",
! 1470: peer->host);
! 1471: }
! 1472:
! 1473: /* Override capability. */
! 1474: if (! capability || CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
! 1475: {
! 1476: peer->afc_nego[AFI_IP][SAFI_UNICAST] = peer->afc[AFI_IP][SAFI_UNICAST];
! 1477: peer->afc_nego[AFI_IP][SAFI_MULTICAST] = peer->afc[AFI_IP][SAFI_MULTICAST];
! 1478: peer->afc_nego[AFI_IP6][SAFI_UNICAST] = peer->afc[AFI_IP6][SAFI_UNICAST];
! 1479: peer->afc_nego[AFI_IP6][SAFI_MULTICAST] = peer->afc[AFI_IP6][SAFI_MULTICAST];
! 1480: }
! 1481:
! 1482: /* Get sockname. */
! 1483: bgp_getsockname (peer);
! 1484:
! 1485: BGP_EVENT_ADD (peer, Receive_OPEN_message);
! 1486:
! 1487: peer->packet_size = 0;
! 1488: if (peer->ibuf)
! 1489: stream_reset (peer->ibuf);
! 1490:
! 1491: return 0;
! 1492: }
! 1493:
! 1494: /* Parse BGP Update packet and make attribute object. */
! 1495: static int
! 1496: bgp_update_receive (struct peer *peer, bgp_size_t size)
! 1497: {
! 1498: int ret;
! 1499: u_char *end;
! 1500: struct stream *s;
! 1501: struct attr attr;
! 1502: bgp_size_t attribute_len;
! 1503: bgp_size_t update_len;
! 1504: bgp_size_t withdraw_len;
! 1505: struct bgp_nlri update;
! 1506: struct bgp_nlri withdraw;
! 1507: struct bgp_nlri mp_update;
! 1508: struct bgp_nlri mp_withdraw;
! 1509: char attrstr[BUFSIZ] = "";
! 1510:
! 1511: /* Status must be Established. */
! 1512: if (peer->status != Established)
! 1513: {
! 1514: zlog_err ("%s [FSM] Update packet received under status %s",
! 1515: peer->host, LOOKUP (bgp_status_msg, peer->status));
! 1516: bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
! 1517: return -1;
! 1518: }
! 1519:
! 1520: /* Set initial values. */
! 1521: memset (&attr, 0, sizeof (struct attr));
! 1522: memset (&update, 0, sizeof (struct bgp_nlri));
! 1523: memset (&withdraw, 0, sizeof (struct bgp_nlri));
! 1524: memset (&mp_update, 0, sizeof (struct bgp_nlri));
! 1525: memset (&mp_withdraw, 0, sizeof (struct bgp_nlri));
! 1526:
! 1527: s = peer->ibuf;
! 1528: end = stream_pnt (s) + size;
! 1529:
! 1530: /* RFC1771 6.3 If the Unfeasible Routes Length or Total Attribute
! 1531: Length is too large (i.e., if Unfeasible Routes Length + Total
! 1532: Attribute Length + 23 exceeds the message Length), then the Error
! 1533: Subcode is set to Malformed Attribute List. */
! 1534: if (stream_pnt (s) + 2 > end)
! 1535: {
! 1536: zlog_err ("%s [Error] Update packet error"
! 1537: " (packet length is short for unfeasible length)",
! 1538: peer->host);
! 1539: bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
! 1540: BGP_NOTIFY_UPDATE_MAL_ATTR);
! 1541: return -1;
! 1542: }
! 1543:
! 1544: /* Unfeasible Route Length. */
! 1545: withdraw_len = stream_getw (s);
! 1546:
! 1547: /* Unfeasible Route Length check. */
! 1548: if (stream_pnt (s) + withdraw_len > end)
! 1549: {
! 1550: zlog_err ("%s [Error] Update packet error"
! 1551: " (packet unfeasible length overflow %d)",
! 1552: peer->host, withdraw_len);
! 1553: bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
! 1554: BGP_NOTIFY_UPDATE_MAL_ATTR);
! 1555: return -1;
! 1556: }
! 1557:
! 1558: /* Unfeasible Route packet format check. */
! 1559: if (withdraw_len > 0)
! 1560: {
! 1561: ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), withdraw_len);
! 1562: if (ret < 0)
! 1563: return -1;
! 1564:
! 1565: if (BGP_DEBUG (packet, PACKET_RECV))
! 1566: zlog_debug ("%s [Update:RECV] Unfeasible NLRI received", peer->host);
! 1567:
! 1568: withdraw.afi = AFI_IP;
! 1569: withdraw.safi = SAFI_UNICAST;
! 1570: withdraw.nlri = stream_pnt (s);
! 1571: withdraw.length = withdraw_len;
! 1572: stream_forward_getp (s, withdraw_len);
! 1573: }
! 1574:
! 1575: /* Attribute total length check. */
! 1576: if (stream_pnt (s) + 2 > end)
! 1577: {
! 1578: zlog_warn ("%s [Error] Packet Error"
! 1579: " (update packet is short for attribute length)",
! 1580: peer->host);
! 1581: bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
! 1582: BGP_NOTIFY_UPDATE_MAL_ATTR);
! 1583: return -1;
! 1584: }
! 1585:
! 1586: /* Fetch attribute total length. */
! 1587: attribute_len = stream_getw (s);
! 1588:
! 1589: /* Attribute length check. */
! 1590: if (stream_pnt (s) + attribute_len > end)
! 1591: {
! 1592: zlog_warn ("%s [Error] Packet Error"
! 1593: " (update packet attribute length overflow %d)",
! 1594: peer->host, attribute_len);
! 1595: bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR,
! 1596: BGP_NOTIFY_UPDATE_MAL_ATTR);
! 1597: return -1;
! 1598: }
! 1599:
! 1600: /* Certain attribute parsing errors should not be considered bad enough
! 1601: * to reset the session for, most particularly any partial/optional
! 1602: * attributes that have 'tunneled' over speakers that don't understand
! 1603: * them. Instead we withdraw only the prefix concerned.
! 1604: *
! 1605: * Complicates the flow a little though..
! 1606: */
! 1607: bgp_attr_parse_ret_t attr_parse_ret = BGP_ATTR_PARSE_PROCEED;
! 1608: /* This define morphs the update case into a withdraw when lower levels
! 1609: * have signalled an error condition where this is best.
! 1610: */
! 1611: #define NLRI_ATTR_ARG (attr_parse_ret != BGP_ATTR_PARSE_WITHDRAW ? &attr : NULL)
! 1612:
! 1613: /* Parse attribute when it exists. */
! 1614: if (attribute_len)
! 1615: {
! 1616: attr_parse_ret = bgp_attr_parse (peer, &attr, attribute_len,
! 1617: &mp_update, &mp_withdraw);
! 1618: if (attr_parse_ret == BGP_ATTR_PARSE_ERROR)
! 1619: return -1;
! 1620: }
! 1621:
! 1622: /* Logging the attribute. */
! 1623: if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW
! 1624: || BGP_DEBUG (update, UPDATE_IN))
! 1625: {
! 1626: ret= bgp_dump_attr (peer, &attr, attrstr, BUFSIZ);
! 1627: int lvl = (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
! 1628: ? LOG_ERR : LOG_DEBUG;
! 1629:
! 1630: if (attr_parse_ret == BGP_ATTR_PARSE_WITHDRAW)
! 1631: zlog (peer->log, LOG_ERR,
! 1632: "%s rcvd UPDATE with errors in attr(s)!! Withdrawing route.",
! 1633: peer->host);
! 1634:
! 1635: if (ret)
! 1636: zlog (peer->log, lvl, "%s rcvd UPDATE w/ attr: %s",
! 1637: peer->host, attrstr);
! 1638: }
! 1639:
! 1640: /* Network Layer Reachability Information. */
! 1641: update_len = end - stream_pnt (s);
! 1642:
! 1643: if (update_len)
! 1644: {
! 1645: /* Check NLRI packet format and prefix length. */
! 1646: ret = bgp_nlri_sanity_check (peer, AFI_IP, stream_pnt (s), update_len);
! 1647: if (ret < 0)
! 1648: {
! 1649: bgp_attr_unintern_sub (&attr);
! 1650: if (attr.extra)
! 1651: bgp_attr_extra_free (&attr);
! 1652: return -1;
! 1653: }
! 1654:
! 1655: /* Set NLRI portion to structure. */
! 1656: update.afi = AFI_IP;
! 1657: update.safi = SAFI_UNICAST;
! 1658: update.nlri = stream_pnt (s);
! 1659: update.length = update_len;
! 1660: stream_forward_getp (s, update_len);
! 1661: }
! 1662:
! 1663: /* NLRI is processed only when the peer is configured specific
! 1664: Address Family and Subsequent Address Family. */
! 1665: if (peer->afc[AFI_IP][SAFI_UNICAST])
! 1666: {
! 1667: if (withdraw.length)
! 1668: bgp_nlri_parse (peer, NULL, &withdraw);
! 1669:
! 1670: if (update.length)
! 1671: {
! 1672: /* We check well-known attribute only for IPv4 unicast
! 1673: update. */
! 1674: ret = bgp_attr_check (peer, &attr);
! 1675: if (ret < 0)
! 1676: {
! 1677: bgp_attr_unintern_sub (&attr);
! 1678: if (attr.extra)
! 1679: bgp_attr_extra_free (&attr);
! 1680: return -1;
! 1681: }
! 1682:
! 1683: bgp_nlri_parse (peer, NLRI_ATTR_ARG, &update);
! 1684: }
! 1685:
! 1686: if (mp_update.length
! 1687: && mp_update.afi == AFI_IP
! 1688: && mp_update.safi == SAFI_UNICAST)
! 1689: bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
! 1690:
! 1691: if (mp_withdraw.length
! 1692: && mp_withdraw.afi == AFI_IP
! 1693: && mp_withdraw.safi == SAFI_UNICAST)
! 1694: bgp_nlri_parse (peer, NULL, &mp_withdraw);
! 1695:
! 1696: if (! attribute_len && ! withdraw_len)
! 1697: {
! 1698: /* End-of-RIB received */
! 1699: SET_FLAG (peer->af_sflags[AFI_IP][SAFI_UNICAST],
! 1700: PEER_STATUS_EOR_RECEIVED);
! 1701:
! 1702: /* NSF delete stale route */
! 1703: if (peer->nsf[AFI_IP][SAFI_UNICAST])
! 1704: bgp_clear_stale_route (peer, AFI_IP, SAFI_UNICAST);
! 1705:
! 1706: if (BGP_DEBUG (normal, NORMAL))
! 1707: zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Unicast from %s",
! 1708: peer->host);
! 1709: }
! 1710: }
! 1711: if (peer->afc[AFI_IP][SAFI_MULTICAST])
! 1712: {
! 1713: if (mp_update.length
! 1714: && mp_update.afi == AFI_IP
! 1715: && mp_update.safi == SAFI_MULTICAST)
! 1716: bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
! 1717:
! 1718: if (mp_withdraw.length
! 1719: && mp_withdraw.afi == AFI_IP
! 1720: && mp_withdraw.safi == SAFI_MULTICAST)
! 1721: bgp_nlri_parse (peer, NULL, &mp_withdraw);
! 1722:
! 1723: if (! withdraw_len
! 1724: && mp_withdraw.afi == AFI_IP
! 1725: && mp_withdraw.safi == SAFI_MULTICAST
! 1726: && mp_withdraw.length == 0)
! 1727: {
! 1728: /* End-of-RIB received */
! 1729: SET_FLAG (peer->af_sflags[AFI_IP][SAFI_MULTICAST],
! 1730: PEER_STATUS_EOR_RECEIVED);
! 1731:
! 1732: /* NSF delete stale route */
! 1733: if (peer->nsf[AFI_IP][SAFI_MULTICAST])
! 1734: bgp_clear_stale_route (peer, AFI_IP, SAFI_MULTICAST);
! 1735:
! 1736: if (BGP_DEBUG (normal, NORMAL))
! 1737: zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv4 Multicast from %s",
! 1738: peer->host);
! 1739: }
! 1740: }
! 1741: if (peer->afc[AFI_IP6][SAFI_UNICAST])
! 1742: {
! 1743: if (mp_update.length
! 1744: && mp_update.afi == AFI_IP6
! 1745: && mp_update.safi == SAFI_UNICAST)
! 1746: bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
! 1747:
! 1748: if (mp_withdraw.length
! 1749: && mp_withdraw.afi == AFI_IP6
! 1750: && mp_withdraw.safi == SAFI_UNICAST)
! 1751: bgp_nlri_parse (peer, NULL, &mp_withdraw);
! 1752:
! 1753: if (! withdraw_len
! 1754: && mp_withdraw.afi == AFI_IP6
! 1755: && mp_withdraw.safi == SAFI_UNICAST
! 1756: && mp_withdraw.length == 0)
! 1757: {
! 1758: /* End-of-RIB received */
! 1759: SET_FLAG (peer->af_sflags[AFI_IP6][SAFI_UNICAST], PEER_STATUS_EOR_RECEIVED);
! 1760:
! 1761: /* NSF delete stale route */
! 1762: if (peer->nsf[AFI_IP6][SAFI_UNICAST])
! 1763: bgp_clear_stale_route (peer, AFI_IP6, SAFI_UNICAST);
! 1764:
! 1765: if (BGP_DEBUG (normal, NORMAL))
! 1766: zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Unicast from %s",
! 1767: peer->host);
! 1768: }
! 1769: }
! 1770: if (peer->afc[AFI_IP6][SAFI_MULTICAST])
! 1771: {
! 1772: if (mp_update.length
! 1773: && mp_update.afi == AFI_IP6
! 1774: && mp_update.safi == SAFI_MULTICAST)
! 1775: bgp_nlri_parse (peer, NLRI_ATTR_ARG, &mp_update);
! 1776:
! 1777: if (mp_withdraw.length
! 1778: && mp_withdraw.afi == AFI_IP6
! 1779: && mp_withdraw.safi == SAFI_MULTICAST)
! 1780: bgp_nlri_parse (peer, NULL, &mp_withdraw);
! 1781:
! 1782: if (! withdraw_len
! 1783: && mp_withdraw.afi == AFI_IP6
! 1784: && mp_withdraw.safi == SAFI_MULTICAST
! 1785: && mp_withdraw.length == 0)
! 1786: {
! 1787: /* End-of-RIB received */
! 1788:
! 1789: /* NSF delete stale route */
! 1790: if (peer->nsf[AFI_IP6][SAFI_MULTICAST])
! 1791: bgp_clear_stale_route (peer, AFI_IP6, SAFI_MULTICAST);
! 1792:
! 1793: if (BGP_DEBUG (update, UPDATE_IN))
! 1794: zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for IPv6 Multicast from %s",
! 1795: peer->host);
! 1796: }
! 1797: }
! 1798: if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
! 1799: {
! 1800: if (mp_update.length
! 1801: && mp_update.afi == AFI_IP
! 1802: && mp_update.safi == BGP_SAFI_VPNV4)
! 1803: bgp_nlri_parse_vpnv4 (peer, NLRI_ATTR_ARG, &mp_update);
! 1804:
! 1805: if (mp_withdraw.length
! 1806: && mp_withdraw.afi == AFI_IP
! 1807: && mp_withdraw.safi == BGP_SAFI_VPNV4)
! 1808: bgp_nlri_parse_vpnv4 (peer, NULL, &mp_withdraw);
! 1809:
! 1810: if (! withdraw_len
! 1811: && mp_withdraw.afi == AFI_IP
! 1812: && mp_withdraw.safi == BGP_SAFI_VPNV4
! 1813: && mp_withdraw.length == 0)
! 1814: {
! 1815: /* End-of-RIB received */
! 1816:
! 1817: if (BGP_DEBUG (update, UPDATE_IN))
! 1818: zlog (peer->log, LOG_DEBUG, "rcvd End-of-RIB for VPNv4 Unicast from %s",
! 1819: peer->host);
! 1820: }
! 1821: }
! 1822:
! 1823: /* Everything is done. We unintern temporary structures which
! 1824: interned in bgp_attr_parse(). */
! 1825: bgp_attr_unintern_sub (&attr);
! 1826: if (attr.extra)
! 1827: bgp_attr_extra_free (&attr);
! 1828:
! 1829: /* If peering is stopped due to some reason, do not generate BGP
! 1830: event. */
! 1831: if (peer->status != Established)
! 1832: return 0;
! 1833:
! 1834: /* Increment packet counter. */
! 1835: peer->update_in++;
! 1836: peer->update_time = bgp_clock ();
! 1837:
! 1838: /* Generate BGP event. */
! 1839: BGP_EVENT_ADD (peer, Receive_UPDATE_message);
! 1840:
! 1841: return 0;
! 1842: }
! 1843:
! 1844: /* Notify message treatment function. */
! 1845: static void
! 1846: bgp_notify_receive (struct peer *peer, bgp_size_t size)
! 1847: {
! 1848: struct bgp_notify bgp_notify;
! 1849:
! 1850: if (peer->notify.data)
! 1851: {
! 1852: XFREE (MTYPE_TMP, peer->notify.data);
! 1853: peer->notify.data = NULL;
! 1854: peer->notify.length = 0;
! 1855: }
! 1856:
! 1857: bgp_notify.code = stream_getc (peer->ibuf);
! 1858: bgp_notify.subcode = stream_getc (peer->ibuf);
! 1859: bgp_notify.length = size - 2;
! 1860: bgp_notify.data = NULL;
! 1861:
! 1862: /* Preserv notify code and sub code. */
! 1863: peer->notify.code = bgp_notify.code;
! 1864: peer->notify.subcode = bgp_notify.subcode;
! 1865: /* For further diagnostic record returned Data. */
! 1866: if (bgp_notify.length)
! 1867: {
! 1868: peer->notify.length = size - 2;
! 1869: peer->notify.data = XMALLOC (MTYPE_TMP, size - 2);
! 1870: memcpy (peer->notify.data, stream_pnt (peer->ibuf), size - 2);
! 1871: }
! 1872:
! 1873: /* For debug */
! 1874: {
! 1875: int i;
! 1876: int first = 0;
! 1877: char c[4];
! 1878:
! 1879: if (bgp_notify.length)
! 1880: {
! 1881: bgp_notify.data = XMALLOC (MTYPE_TMP, bgp_notify.length * 3);
! 1882: for (i = 0; i < bgp_notify.length; i++)
! 1883: if (first)
! 1884: {
! 1885: sprintf (c, " %02x", stream_getc (peer->ibuf));
! 1886: strcat (bgp_notify.data, c);
! 1887: }
! 1888: else
! 1889: {
! 1890: first = 1;
! 1891: sprintf (c, "%02x", stream_getc (peer->ibuf));
! 1892: strcpy (bgp_notify.data, c);
! 1893: }
! 1894: }
! 1895:
! 1896: bgp_notify_print(peer, &bgp_notify, "received");
! 1897: if (bgp_notify.data)
! 1898: XFREE (MTYPE_TMP, bgp_notify.data);
! 1899: }
! 1900:
! 1901: /* peer count update */
! 1902: peer->notify_in++;
! 1903:
! 1904: if (peer->status == Established)
! 1905: peer->last_reset = PEER_DOWN_NOTIFY_RECEIVED;
! 1906:
! 1907: /* We have to check for Notify with Unsupported Optional Parameter.
! 1908: in that case we fallback to open without the capability option.
! 1909: But this done in bgp_stop. We just mark it here to avoid changing
! 1910: the fsm tables. */
! 1911: if (bgp_notify.code == BGP_NOTIFY_OPEN_ERR &&
! 1912: bgp_notify.subcode == BGP_NOTIFY_OPEN_UNSUP_PARAM )
! 1913: UNSET_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
! 1914:
! 1915: BGP_EVENT_ADD (peer, Receive_NOTIFICATION_message);
! 1916: }
! 1917:
! 1918: /* Keepalive treatment function -- get keepalive send keepalive */
! 1919: static void
! 1920: bgp_keepalive_receive (struct peer *peer, bgp_size_t size)
! 1921: {
! 1922: if (BGP_DEBUG (keepalive, KEEPALIVE))
! 1923: zlog_debug ("%s KEEPALIVE rcvd", peer->host);
! 1924:
! 1925: BGP_EVENT_ADD (peer, Receive_KEEPALIVE_message);
! 1926: }
! 1927:
! 1928: /* Route refresh message is received. */
! 1929: static void
! 1930: bgp_route_refresh_receive (struct peer *peer, bgp_size_t size)
! 1931: {
! 1932: afi_t afi;
! 1933: safi_t safi;
! 1934: u_char reserved;
! 1935: struct stream *s;
! 1936:
! 1937: /* If peer does not have the capability, send notification. */
! 1938: if (! CHECK_FLAG (peer->cap, PEER_CAP_REFRESH_ADV))
! 1939: {
! 1940: plog_err (peer->log, "%s [Error] BGP route refresh is not enabled",
! 1941: peer->host);
! 1942: bgp_notify_send (peer,
! 1943: BGP_NOTIFY_HEADER_ERR,
! 1944: BGP_NOTIFY_HEADER_BAD_MESTYPE);
! 1945: return;
! 1946: }
! 1947:
! 1948: /* Status must be Established. */
! 1949: if (peer->status != Established)
! 1950: {
! 1951: plog_err (peer->log,
! 1952: "%s [Error] Route refresh packet received under status %s",
! 1953: peer->host, LOOKUP (bgp_status_msg, peer->status));
! 1954: bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
! 1955: return;
! 1956: }
! 1957:
! 1958: s = peer->ibuf;
! 1959:
! 1960: /* Parse packet. */
! 1961: afi = stream_getw (s);
! 1962: reserved = stream_getc (s);
! 1963: safi = stream_getc (s);
! 1964:
! 1965: if (BGP_DEBUG (normal, NORMAL))
! 1966: zlog_debug ("%s rcvd REFRESH_REQ for afi/safi: %d/%d",
! 1967: peer->host, afi, safi);
! 1968:
! 1969: /* Check AFI and SAFI. */
! 1970: if ((afi != AFI_IP && afi != AFI_IP6)
! 1971: || (safi != SAFI_UNICAST && safi != SAFI_MULTICAST
! 1972: && safi != BGP_SAFI_VPNV4))
! 1973: {
! 1974: if (BGP_DEBUG (normal, NORMAL))
! 1975: {
! 1976: zlog_debug ("%s REFRESH_REQ for unrecognized afi/safi: %d/%d - ignored",
! 1977: peer->host, afi, safi);
! 1978: }
! 1979: return;
! 1980: }
! 1981:
! 1982: /* Adjust safi code. */
! 1983: if (safi == BGP_SAFI_VPNV4)
! 1984: safi = SAFI_MPLS_VPN;
! 1985:
! 1986: if (size != BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE)
! 1987: {
! 1988: u_char *end;
! 1989: u_char when_to_refresh;
! 1990: u_char orf_type;
! 1991: u_int16_t orf_len;
! 1992:
! 1993: if (size - (BGP_MSG_ROUTE_REFRESH_MIN_SIZE - BGP_HEADER_SIZE) < 5)
! 1994: {
! 1995: zlog_info ("%s ORF route refresh length error", peer->host);
! 1996: bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
! 1997: return;
! 1998: }
! 1999:
! 2000: when_to_refresh = stream_getc (s);
! 2001: end = stream_pnt (s) + (size - 5);
! 2002:
! 2003: while ((stream_pnt (s) + 2) < end)
! 2004: {
! 2005: orf_type = stream_getc (s);
! 2006: orf_len = stream_getw (s);
! 2007:
! 2008: /* orf_len in bounds? */
! 2009: if ((stream_pnt (s) + orf_len) > end)
! 2010: break; /* XXX: Notify instead?? */
! 2011: if (orf_type == ORF_TYPE_PREFIX
! 2012: || orf_type == ORF_TYPE_PREFIX_OLD)
! 2013: {
! 2014: u_char *p_pnt = stream_pnt (s);
! 2015: u_char *p_end = stream_pnt (s) + orf_len;
! 2016: struct orf_prefix orfp;
! 2017: u_char common = 0;
! 2018: u_int32_t seq;
! 2019: int psize;
! 2020: char name[BUFSIZ];
! 2021: char buf[BUFSIZ];
! 2022: int ret;
! 2023:
! 2024: if (BGP_DEBUG (normal, NORMAL))
! 2025: {
! 2026: zlog_debug ("%s rcvd Prefixlist ORF(%d) length %d",
! 2027: peer->host, orf_type, orf_len);
! 2028: }
! 2029:
! 2030: /* we're going to read at least 1 byte of common ORF header,
! 2031: * and 7 bytes of ORF Address-filter entry from the stream
! 2032: */
! 2033: if (orf_len < 7)
! 2034: break;
! 2035:
! 2036: /* ORF prefix-list name */
! 2037: sprintf (name, "%s.%d.%d", peer->host, afi, safi);
! 2038:
! 2039: while (p_pnt < p_end)
! 2040: {
! 2041: /* If the ORF entry is malformed, want to read as much of it
! 2042: * as possible without going beyond the bounds of the entry,
! 2043: * to maximise debug information.
! 2044: */
! 2045: int ok;
! 2046: memset (&orfp, 0, sizeof (struct orf_prefix));
! 2047: common = *p_pnt++;
! 2048: /* after ++: p_pnt <= p_end */
! 2049: if (common & ORF_COMMON_PART_REMOVE_ALL)
! 2050: {
! 2051: if (BGP_DEBUG (normal, NORMAL))
! 2052: zlog_debug ("%s rcvd Remove-All pfxlist ORF request", peer->host);
! 2053: prefix_bgp_orf_remove_all (name);
! 2054: break;
! 2055: }
! 2056: ok = ((p_end - p_pnt) >= sizeof(u_int32_t)) ;
! 2057: if (!ok)
! 2058: {
! 2059: memcpy (&seq, p_pnt, sizeof (u_int32_t));
! 2060: p_pnt += sizeof (u_int32_t);
! 2061: orfp.seq = ntohl (seq);
! 2062: }
! 2063: else
! 2064: p_pnt = p_end ;
! 2065:
! 2066: if ((ok = (p_pnt < p_end)))
! 2067: orfp.ge = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */
! 2068: if ((ok = (p_pnt < p_end)))
! 2069: orfp.le = *p_pnt++ ; /* value checked in prefix_bgp_orf_set() */
! 2070: if ((ok = (p_pnt < p_end)))
! 2071: orfp.p.prefixlen = *p_pnt++ ;
! 2072: orfp.p.family = afi2family (afi); /* afi checked already */
! 2073:
! 2074: psize = PSIZE (orfp.p.prefixlen); /* 0 if not ok */
! 2075: if (psize > prefix_blen(&orfp.p)) /* valid for family ? */
! 2076: {
! 2077: ok = 0 ;
! 2078: psize = prefix_blen(&orfp.p) ;
! 2079: }
! 2080: if (psize > (p_end - p_pnt)) /* valid for packet ? */
! 2081: {
! 2082: ok = 0 ;
! 2083: psize = p_end - p_pnt ;
! 2084: }
! 2085:
! 2086: if (psize > 0)
! 2087: memcpy (&orfp.p.u.prefix, p_pnt, psize);
! 2088: p_pnt += psize;
! 2089:
! 2090: if (BGP_DEBUG (normal, NORMAL))
! 2091: zlog_debug ("%s rcvd %s %s seq %u %s/%d ge %d le %d%s",
! 2092: peer->host,
! 2093: (common & ORF_COMMON_PART_REMOVE ? "Remove" : "Add"),
! 2094: (common & ORF_COMMON_PART_DENY ? "deny" : "permit"),
! 2095: orfp.seq,
! 2096: inet_ntop (orfp.p.family, &orfp.p.u.prefix, buf, BUFSIZ),
! 2097: orfp.p.prefixlen, orfp.ge, orfp.le,
! 2098: ok ? "" : " MALFORMED");
! 2099:
! 2100: if (ok)
! 2101: ret = prefix_bgp_orf_set (name, afi, &orfp,
! 2102: (common & ORF_COMMON_PART_DENY ? 0 : 1 ),
! 2103: (common & ORF_COMMON_PART_REMOVE ? 0 : 1));
! 2104:
! 2105: if (!ok || (ret != CMD_SUCCESS))
! 2106: {
! 2107: if (BGP_DEBUG (normal, NORMAL))
! 2108: zlog_debug ("%s Received misformatted prefixlist ORF."
! 2109: " Remove All pfxlist", peer->host);
! 2110: prefix_bgp_orf_remove_all (name);
! 2111: break;
! 2112: }
! 2113: }
! 2114: peer->orf_plist[afi][safi] =
! 2115: prefix_list_lookup (AFI_ORF_PREFIX, name);
! 2116: }
! 2117: stream_forward_getp (s, orf_len);
! 2118: }
! 2119: if (BGP_DEBUG (normal, NORMAL))
! 2120: zlog_debug ("%s rcvd Refresh %s ORF request", peer->host,
! 2121: when_to_refresh == REFRESH_DEFER ? "Defer" : "Immediate");
! 2122: if (when_to_refresh == REFRESH_DEFER)
! 2123: return;
! 2124: }
! 2125:
! 2126: /* First update is deferred until ORF or ROUTE-REFRESH is received */
! 2127: if (CHECK_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH))
! 2128: UNSET_FLAG (peer->af_sflags[afi][safi], PEER_STATUS_ORF_WAIT_REFRESH);
! 2129:
! 2130: /* Perform route refreshment to the peer */
! 2131: bgp_announce_route (peer, afi, safi);
! 2132: }
! 2133:
! 2134: static int
! 2135: bgp_capability_msg_parse (struct peer *peer, u_char *pnt, bgp_size_t length)
! 2136: {
! 2137: u_char *end;
! 2138: struct capability_mp_data mpc;
! 2139: struct capability_header *hdr;
! 2140: u_char action;
! 2141: struct bgp *bgp;
! 2142: afi_t afi;
! 2143: safi_t safi;
! 2144:
! 2145: bgp = peer->bgp;
! 2146: end = pnt + length;
! 2147:
! 2148: while (pnt < end)
! 2149: {
! 2150: /* We need at least action, capability code and capability length. */
! 2151: if (pnt + 3 > end)
! 2152: {
! 2153: zlog_info ("%s Capability length error", peer->host);
! 2154: bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
! 2155: return -1;
! 2156: }
! 2157: action = *pnt;
! 2158: hdr = (struct capability_header *)(pnt + 1);
! 2159:
! 2160: /* Action value check. */
! 2161: if (action != CAPABILITY_ACTION_SET
! 2162: && action != CAPABILITY_ACTION_UNSET)
! 2163: {
! 2164: zlog_info ("%s Capability Action Value error %d",
! 2165: peer->host, action);
! 2166: bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
! 2167: return -1;
! 2168: }
! 2169:
! 2170: if (BGP_DEBUG (normal, NORMAL))
! 2171: zlog_debug ("%s CAPABILITY has action: %d, code: %u, length %u",
! 2172: peer->host, action, hdr->code, hdr->length);
! 2173:
! 2174: /* Capability length check. */
! 2175: if ((pnt + hdr->length + 3) > end)
! 2176: {
! 2177: zlog_info ("%s Capability length error", peer->host);
! 2178: bgp_notify_send (peer, BGP_NOTIFY_CEASE, 0);
! 2179: return -1;
! 2180: }
! 2181:
! 2182: /* Fetch structure to the byte stream. */
! 2183: memcpy (&mpc, pnt + 3, sizeof (struct capability_mp_data));
! 2184:
! 2185: /* We know MP Capability Code. */
! 2186: if (hdr->code == CAPABILITY_CODE_MP)
! 2187: {
! 2188: afi = ntohs (mpc.afi);
! 2189: safi = mpc.safi;
! 2190:
! 2191: /* Ignore capability when override-capability is set. */
! 2192: if (CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
! 2193: continue;
! 2194:
! 2195: if (!bgp_afi_safi_valid_indices (afi, &safi))
! 2196: {
! 2197: if (BGP_DEBUG (normal, NORMAL))
! 2198: zlog_debug ("%s Dynamic Capability MP_EXT afi/safi invalid "
! 2199: "(%u/%u)", peer->host, afi, safi);
! 2200: continue;
! 2201: }
! 2202:
! 2203: /* Address family check. */
! 2204: if (BGP_DEBUG (normal, NORMAL))
! 2205: zlog_debug ("%s CAPABILITY has %s MP_EXT CAP for afi/safi: %u/%u",
! 2206: peer->host,
! 2207: action == CAPABILITY_ACTION_SET
! 2208: ? "Advertising" : "Removing",
! 2209: ntohs(mpc.afi) , mpc.safi);
! 2210:
! 2211: if (action == CAPABILITY_ACTION_SET)
! 2212: {
! 2213: peer->afc_recv[afi][safi] = 1;
! 2214: if (peer->afc[afi][safi])
! 2215: {
! 2216: peer->afc_nego[afi][safi] = 1;
! 2217: bgp_announce_route (peer, afi, safi);
! 2218: }
! 2219: }
! 2220: else
! 2221: {
! 2222: peer->afc_recv[afi][safi] = 0;
! 2223: peer->afc_nego[afi][safi] = 0;
! 2224:
! 2225: if (peer_active_nego (peer))
! 2226: bgp_clear_route (peer, afi, safi, BGP_CLEAR_ROUTE_NORMAL);
! 2227: else
! 2228: BGP_EVENT_ADD (peer, BGP_Stop);
! 2229: }
! 2230: }
! 2231: else
! 2232: {
! 2233: zlog_warn ("%s unrecognized capability code: %d - ignored",
! 2234: peer->host, hdr->code);
! 2235: }
! 2236: pnt += hdr->length + 3;
! 2237: }
! 2238: return 0;
! 2239: }
! 2240:
! 2241: /* Dynamic Capability is received.
! 2242: *
! 2243: * This is exported for unit-test purposes
! 2244: */
! 2245: int
! 2246: bgp_capability_receive (struct peer *peer, bgp_size_t size)
! 2247: {
! 2248: u_char *pnt;
! 2249:
! 2250: /* Fetch pointer. */
! 2251: pnt = stream_pnt (peer->ibuf);
! 2252:
! 2253: if (BGP_DEBUG (normal, NORMAL))
! 2254: zlog_debug ("%s rcv CAPABILITY", peer->host);
! 2255:
! 2256: /* If peer does not have the capability, send notification. */
! 2257: if (! CHECK_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV))
! 2258: {
! 2259: plog_err (peer->log, "%s [Error] BGP dynamic capability is not enabled",
! 2260: peer->host);
! 2261: bgp_notify_send (peer,
! 2262: BGP_NOTIFY_HEADER_ERR,
! 2263: BGP_NOTIFY_HEADER_BAD_MESTYPE);
! 2264: return -1;
! 2265: }
! 2266:
! 2267: /* Status must be Established. */
! 2268: if (peer->status != Established)
! 2269: {
! 2270: plog_err (peer->log,
! 2271: "%s [Error] Dynamic capability packet received under status %s", peer->host, LOOKUP (bgp_status_msg, peer->status));
! 2272: bgp_notify_send (peer, BGP_NOTIFY_FSM_ERR, 0);
! 2273: return -1;
! 2274: }
! 2275:
! 2276: /* Parse packet. */
! 2277: return bgp_capability_msg_parse (peer, pnt, size);
! 2278: }
! 2279:
! 2280: /* BGP read utility function. */
! 2281: static int
! 2282: bgp_read_packet (struct peer *peer)
! 2283: {
! 2284: int nbytes;
! 2285: int readsize;
! 2286:
! 2287: readsize = peer->packet_size - stream_get_endp (peer->ibuf);
! 2288:
! 2289: /* If size is zero then return. */
! 2290: if (! readsize)
! 2291: return 0;
! 2292:
! 2293: /* Read packet from fd. */
! 2294: nbytes = stream_read_try (peer->ibuf, peer->fd, readsize);
! 2295:
! 2296: /* If read byte is smaller than zero then error occured. */
! 2297: if (nbytes < 0)
! 2298: {
! 2299: /* Transient error should retry */
! 2300: if (nbytes == -2)
! 2301: return -1;
! 2302:
! 2303: plog_err (peer->log, "%s [Error] bgp_read_packet error: %s",
! 2304: peer->host, safe_strerror (errno));
! 2305:
! 2306: if (peer->status == Established)
! 2307: {
! 2308: if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
! 2309: {
! 2310: peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
! 2311: SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
! 2312: }
! 2313: else
! 2314: peer->last_reset = PEER_DOWN_CLOSE_SESSION;
! 2315: }
! 2316:
! 2317: BGP_EVENT_ADD (peer, TCP_fatal_error);
! 2318: return -1;
! 2319: }
! 2320:
! 2321: /* When read byte is zero : clear bgp peer and return */
! 2322: if (nbytes == 0)
! 2323: {
! 2324: if (BGP_DEBUG (events, EVENTS))
! 2325: plog_debug (peer->log, "%s [Event] BGP connection closed fd %d",
! 2326: peer->host, peer->fd);
! 2327:
! 2328: if (peer->status == Established)
! 2329: {
! 2330: if (CHECK_FLAG (peer->sflags, PEER_STATUS_NSF_MODE))
! 2331: {
! 2332: peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
! 2333: SET_FLAG (peer->sflags, PEER_STATUS_NSF_WAIT);
! 2334: }
! 2335: else
! 2336: peer->last_reset = PEER_DOWN_CLOSE_SESSION;
! 2337: }
! 2338:
! 2339: BGP_EVENT_ADD (peer, TCP_connection_closed);
! 2340: return -1;
! 2341: }
! 2342:
! 2343: /* We read partial packet. */
! 2344: if (stream_get_endp (peer->ibuf) != peer->packet_size)
! 2345: return -1;
! 2346:
! 2347: return 0;
! 2348: }
! 2349:
! 2350: /* Marker check. */
! 2351: static int
! 2352: bgp_marker_all_one (struct stream *s, int length)
! 2353: {
! 2354: int i;
! 2355:
! 2356: for (i = 0; i < length; i++)
! 2357: if (s->data[i] != 0xff)
! 2358: return 0;
! 2359:
! 2360: return 1;
! 2361: }
! 2362:
! 2363: /* Starting point of packet process function. */
! 2364: int
! 2365: bgp_read (struct thread *thread)
! 2366: {
! 2367: int ret;
! 2368: u_char type = 0;
! 2369: struct peer *peer;
! 2370: bgp_size_t size;
! 2371: char notify_data_length[2];
! 2372:
! 2373: /* Yes first of all get peer pointer. */
! 2374: peer = THREAD_ARG (thread);
! 2375: peer->t_read = NULL;
! 2376:
! 2377: /* For non-blocking IO check. */
! 2378: if (peer->status == Connect)
! 2379: {
! 2380: bgp_connect_check (peer);
! 2381: goto done;
! 2382: }
! 2383: else
! 2384: {
! 2385: if (peer->fd < 0)
! 2386: {
! 2387: zlog_err ("bgp_read peer's fd is negative value %d", peer->fd);
! 2388: return -1;
! 2389: }
! 2390: BGP_READ_ON (peer->t_read, bgp_read, peer->fd);
! 2391: }
! 2392:
! 2393: /* Read packet header to determine type of the packet */
! 2394: if (peer->packet_size == 0)
! 2395: peer->packet_size = BGP_HEADER_SIZE;
! 2396:
! 2397: if (stream_get_endp (peer->ibuf) < BGP_HEADER_SIZE)
! 2398: {
! 2399: ret = bgp_read_packet (peer);
! 2400:
! 2401: /* Header read error or partial read packet. */
! 2402: if (ret < 0)
! 2403: goto done;
! 2404:
! 2405: /* Get size and type. */
! 2406: stream_forward_getp (peer->ibuf, BGP_MARKER_SIZE);
! 2407: memcpy (notify_data_length, stream_pnt (peer->ibuf), 2);
! 2408: size = stream_getw (peer->ibuf);
! 2409: type = stream_getc (peer->ibuf);
! 2410:
! 2411: if (BGP_DEBUG (normal, NORMAL) && type != 2 && type != 0)
! 2412: zlog_debug ("%s rcv message type %d, length (excl. header) %d",
! 2413: peer->host, type, size - BGP_HEADER_SIZE);
! 2414:
! 2415: /* Marker check */
! 2416: if (((type == BGP_MSG_OPEN) || (type == BGP_MSG_KEEPALIVE))
! 2417: && ! bgp_marker_all_one (peer->ibuf, BGP_MARKER_SIZE))
! 2418: {
! 2419: bgp_notify_send (peer,
! 2420: BGP_NOTIFY_HEADER_ERR,
! 2421: BGP_NOTIFY_HEADER_NOT_SYNC);
! 2422: goto done;
! 2423: }
! 2424:
! 2425: /* BGP type check. */
! 2426: if (type != BGP_MSG_OPEN && type != BGP_MSG_UPDATE
! 2427: && type != BGP_MSG_NOTIFY && type != BGP_MSG_KEEPALIVE
! 2428: && type != BGP_MSG_ROUTE_REFRESH_NEW
! 2429: && type != BGP_MSG_ROUTE_REFRESH_OLD
! 2430: && type != BGP_MSG_CAPABILITY)
! 2431: {
! 2432: if (BGP_DEBUG (normal, NORMAL))
! 2433: plog_debug (peer->log,
! 2434: "%s unknown message type 0x%02x",
! 2435: peer->host, type);
! 2436: bgp_notify_send_with_data (peer,
! 2437: BGP_NOTIFY_HEADER_ERR,
! 2438: BGP_NOTIFY_HEADER_BAD_MESTYPE,
! 2439: &type, 1);
! 2440: goto done;
! 2441: }
! 2442: /* Mimimum packet length check. */
! 2443: if ((size < BGP_HEADER_SIZE)
! 2444: || (size > BGP_MAX_PACKET_SIZE)
! 2445: || (type == BGP_MSG_OPEN && size < BGP_MSG_OPEN_MIN_SIZE)
! 2446: || (type == BGP_MSG_UPDATE && size < BGP_MSG_UPDATE_MIN_SIZE)
! 2447: || (type == BGP_MSG_NOTIFY && size < BGP_MSG_NOTIFY_MIN_SIZE)
! 2448: || (type == BGP_MSG_KEEPALIVE && size != BGP_MSG_KEEPALIVE_MIN_SIZE)
! 2449: || (type == BGP_MSG_ROUTE_REFRESH_NEW && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
! 2450: || (type == BGP_MSG_ROUTE_REFRESH_OLD && size < BGP_MSG_ROUTE_REFRESH_MIN_SIZE)
! 2451: || (type == BGP_MSG_CAPABILITY && size < BGP_MSG_CAPABILITY_MIN_SIZE))
! 2452: {
! 2453: if (BGP_DEBUG (normal, NORMAL))
! 2454: plog_debug (peer->log,
! 2455: "%s bad message length - %d for %s",
! 2456: peer->host, size,
! 2457: type == 128 ? "ROUTE-REFRESH" :
! 2458: bgp_type_str[(int) type]);
! 2459: bgp_notify_send_with_data (peer,
! 2460: BGP_NOTIFY_HEADER_ERR,
! 2461: BGP_NOTIFY_HEADER_BAD_MESLEN,
! 2462: (u_char *) notify_data_length, 2);
! 2463: goto done;
! 2464: }
! 2465:
! 2466: /* Adjust size to message length. */
! 2467: peer->packet_size = size;
! 2468: }
! 2469:
! 2470: ret = bgp_read_packet (peer);
! 2471: if (ret < 0)
! 2472: goto done;
! 2473:
! 2474: /* Get size and type again. */
! 2475: size = stream_getw_from (peer->ibuf, BGP_MARKER_SIZE);
! 2476: type = stream_getc_from (peer->ibuf, BGP_MARKER_SIZE + 2);
! 2477:
! 2478: /* BGP packet dump function. */
! 2479: bgp_dump_packet (peer, type, peer->ibuf);
! 2480:
! 2481: size = (peer->packet_size - BGP_HEADER_SIZE);
! 2482:
! 2483: /* Read rest of the packet and call each sort of packet routine */
! 2484: switch (type)
! 2485: {
! 2486: case BGP_MSG_OPEN:
! 2487: peer->open_in++;
! 2488: bgp_open_receive (peer, size); /* XXX return value ignored! */
! 2489: break;
! 2490: case BGP_MSG_UPDATE:
! 2491: peer->readtime = time(NULL); /* Last read timer reset */
! 2492: bgp_update_receive (peer, size);
! 2493: break;
! 2494: case BGP_MSG_NOTIFY:
! 2495: bgp_notify_receive (peer, size);
! 2496: break;
! 2497: case BGP_MSG_KEEPALIVE:
! 2498: peer->readtime = time(NULL); /* Last read timer reset */
! 2499: bgp_keepalive_receive (peer, size);
! 2500: break;
! 2501: case BGP_MSG_ROUTE_REFRESH_NEW:
! 2502: case BGP_MSG_ROUTE_REFRESH_OLD:
! 2503: peer->refresh_in++;
! 2504: bgp_route_refresh_receive (peer, size);
! 2505: break;
! 2506: case BGP_MSG_CAPABILITY:
! 2507: peer->dynamic_cap_in++;
! 2508: bgp_capability_receive (peer, size);
! 2509: break;
! 2510: }
! 2511:
! 2512: /* Clear input buffer. */
! 2513: peer->packet_size = 0;
! 2514: if (peer->ibuf)
! 2515: stream_reset (peer->ibuf);
! 2516:
! 2517: done:
! 2518: if (CHECK_FLAG (peer->sflags, PEER_STATUS_ACCEPT_PEER))
! 2519: {
! 2520: if (BGP_DEBUG (events, EVENTS))
! 2521: zlog_debug ("%s [Event] Accepting BGP peer delete", peer->host);
! 2522: peer_delete (peer);
! 2523: }
! 2524: return 0;
! 2525: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>