1/* BGP attributes management routines. 2 Copyright (C) 1996, 97, 98, 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 "linklist.h" 24#include "prefix.h" 25#include "memory.h" 26#include "vector.h" 27#include "vty.h" 28#include "stream.h" 29#include "log.h" 30#include "hash.h" 31#include "jhash.h" 32 33#include "bgpd/bgpd.h" 34#include "bgpd/bgp_attr.h" 35#include "bgpd/bgp_route.h" 36#include "bgpd/bgp_aspath.h" 37#include "bgpd/bgp_community.h" 38#include "bgpd/bgp_debug.h" 39#include "bgpd/bgp_packet.h" 40#include "bgpd/bgp_ecommunity.h" 41 42/* Attribute strings for logging. */ 43static const struct message attr_str [] = 44{ 45 { BGP_ATTR_ORIGIN, "ORIGIN" }, 46 { BGP_ATTR_AS_PATH, "AS_PATH" }, 47 { BGP_ATTR_NEXT_HOP, "NEXT_HOP" }, 48 { BGP_ATTR_MULTI_EXIT_DISC, "MULTI_EXIT_DISC" }, 49 { BGP_ATTR_LOCAL_PREF, "LOCAL_PREF" }, 50 { BGP_ATTR_ATOMIC_AGGREGATE, "ATOMIC_AGGREGATE" }, 51 { BGP_ATTR_AGGREGATOR, "AGGREGATOR" }, 52 { BGP_ATTR_COMMUNITIES, "COMMUNITY" }, 53 { BGP_ATTR_ORIGINATOR_ID, "ORIGINATOR_ID" }, 54 { BGP_ATTR_CLUSTER_LIST, "CLUSTER_LIST" }, 55 { BGP_ATTR_DPA, "DPA" }, 56 { BGP_ATTR_ADVERTISER, "ADVERTISER"} , 57 { BGP_ATTR_RCID_PATH, "RCID_PATH" }, 58 { BGP_ATTR_MP_REACH_NLRI, "MP_REACH_NLRI" }, 59 { BGP_ATTR_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" }, 60 { BGP_ATTR_EXT_COMMUNITIES, "EXT_COMMUNITIES" }, 61 { BGP_ATTR_AS4_PATH, "AS4_PATH" }, 62 { BGP_ATTR_AS4_AGGREGATOR, "AS4_AGGREGATOR" }, 63 { BGP_ATTR_AS_PATHLIMIT, "AS_PATHLIMIT" }, 64}; 65static const int attr_str_max = array_size(attr_str); 66 67static const struct message attr_flag_str[] = 68{ 69 { BGP_ATTR_FLAG_OPTIONAL, "Optional" }, 70 { BGP_ATTR_FLAG_TRANS, "Transitive" }, 71 { BGP_ATTR_FLAG_PARTIAL, "Partial" }, 72 /* bgp_attr_flags_diagnose() relies on this bit being last in this list */ 73 { BGP_ATTR_FLAG_EXTLEN, "Extended Length" }, 74}; 75static const size_t attr_flag_str_max = array_size(attr_flag_str); 76 77static struct hash *cluster_hash; 78 79static void * 80cluster_hash_alloc (void *p) 81{ 82 struct cluster_list * val = (struct cluster_list *) p; 83 struct cluster_list *cluster; 84 85 cluster = XMALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list)); 86 cluster->length = val->length; 87 88 if (cluster->length) 89 { 90 cluster->list = XMALLOC (MTYPE_CLUSTER_VAL, val->length); 91 memcpy (cluster->list, val->list, val->length); 92 } 93 else 94 cluster->list = NULL; 95 96 cluster->refcnt = 0; 97 98 return cluster; 99} 100 101/* Cluster list related functions. */ 102static struct cluster_list * 103cluster_parse (struct in_addr * pnt, int length) 104{ 105 struct cluster_list tmp; 106 struct cluster_list *cluster; 107 108 tmp.length = length; 109 tmp.list = pnt; 110 111 cluster = hash_get (cluster_hash, &tmp, cluster_hash_alloc); 112 cluster->refcnt++; 113 return cluster; 114} 115 116int 117cluster_loop_check (struct cluster_list *cluster, struct in_addr originator) 118{ 119 int i; 120 121 for (i = 0; i < cluster->length / 4; i++) 122 if (cluster->list[i].s_addr == originator.s_addr) 123 return 1; 124 return 0; 125} 126 127static unsigned int 128cluster_hash_key_make (void *p) 129{ 130 const struct cluster_list *cluster = p; 131 132 return jhash(cluster->list, cluster->length, 0); 133} 134 135static int 136cluster_hash_cmp (const void *p1, const void *p2) 137{ 138 const struct cluster_list * cluster1 = p1; 139 const struct cluster_list * cluster2 = p2; 140 141 return (cluster1->length == cluster2->length && 142 memcmp (cluster1->list, cluster2->list, cluster1->length) == 0); 143} 144 145static void 146cluster_free (struct cluster_list *cluster) 147{ 148 if (cluster->list) 149 XFREE (MTYPE_CLUSTER_VAL, cluster->list); 150 XFREE (MTYPE_CLUSTER, cluster); 151} 152 153#if 0 154static struct cluster_list * 155cluster_dup (struct cluster_list *cluster) 156{ 157 struct cluster_list *new; 158 159 new = XCALLOC (MTYPE_CLUSTER, sizeof (struct cluster_list)); 160 new->length = cluster->length; 161 162 if (cluster->length) 163 { 164 new->list = XMALLOC (MTYPE_CLUSTER_VAL, cluster->length); 165 memcpy (new->list, cluster->list, cluster->length); 166 } 167 else 168 new->list = NULL; 169 170 return new; 171} 172#endif 173 174static struct cluster_list * 175cluster_intern (struct cluster_list *cluster) 176{ 177 struct cluster_list *find; 178 179 find = hash_get (cluster_hash, cluster, cluster_hash_alloc); 180 find->refcnt++; 181 182 return find; 183} 184 185void 186cluster_unintern (struct cluster_list *cluster) 187{ 188 if (cluster->refcnt) 189 cluster->refcnt--; 190 191 if (cluster->refcnt == 0) 192 { 193 hash_release (cluster_hash, cluster); 194 cluster_free (cluster); 195 } 196} 197 198static void 199cluster_init (void) 200{ 201 cluster_hash = hash_create (cluster_hash_key_make, cluster_hash_cmp); 202} 203 204static void 205cluster_finish (void) 206{ 207 hash_free (cluster_hash); 208 cluster_hash = NULL; 209} 210 211/* Unknown transit attribute. */ 212static struct hash *transit_hash; 213 214static void 215transit_free (struct transit *transit) 216{ 217 if (transit->val) 218 XFREE (MTYPE_TRANSIT_VAL, transit->val); 219 XFREE (MTYPE_TRANSIT, transit); 220} 221 222 223static void * 224transit_hash_alloc (void *p) 225{ 226 /* Transit structure is already allocated. */ 227 return p; 228} 229 230static struct transit * 231transit_intern (struct transit *transit) 232{ 233 struct transit *find; 234 235 find = hash_get (transit_hash, transit, transit_hash_alloc); 236 if (find != transit) 237 transit_free (transit); 238 find->refcnt++; 239 240 return find; 241} 242 243void 244transit_unintern (struct transit *transit) 245{ 246 if (transit->refcnt) 247 transit->refcnt--; 248 249 if (transit->refcnt == 0) 250 { 251 hash_release (transit_hash, transit); 252 transit_free (transit); 253 } 254} 255 256static unsigned int 257transit_hash_key_make (void *p) 258{ 259 const struct transit * transit = p; 260 261 return jhash(transit->val, transit->length, 0); 262} 263 264static int 265transit_hash_cmp (const void *p1, const void *p2) 266{ 267 const struct transit * transit1 = p1; 268 const struct transit * transit2 = p2; 269 270 return (transit1->length == transit2->length && 271 memcmp (transit1->val, transit2->val, transit1->length) == 0); 272} 273 274static void 275transit_init (void) 276{ 277 transit_hash = hash_create (transit_hash_key_make, transit_hash_cmp); 278} 279 280static void 281transit_finish (void) 282{ 283 hash_free (transit_hash); 284 transit_hash = NULL; 285} 286 287/* Attribute hash routines. */ 288static struct hash *attrhash; 289 290static struct attr_extra * 291bgp_attr_extra_new (void) 292{ 293 return XCALLOC (MTYPE_ATTR_EXTRA, sizeof (struct attr_extra)); 294} 295 296void 297bgp_attr_extra_free (struct attr *attr) 298{ 299 if (attr->extra) 300 { 301 XFREE (MTYPE_ATTR_EXTRA, attr->extra); 302 attr->extra = NULL; 303 } 304} 305 306struct attr_extra * 307bgp_attr_extra_get (struct attr *attr) 308{ 309 if (!attr->extra) 310 attr->extra = bgp_attr_extra_new(); 311 return attr->extra; 312} 313 314/* Shallow copy of an attribute 315 * Though, not so shallow that it doesn't copy the contents 316 * of the attr_extra pointed to by 'extra' 317 */ 318void 319bgp_attr_dup (struct attr *new, struct attr *orig) 320{ 321 struct attr_extra *extra = new->extra; 322 323 *new = *orig; 324 /* if caller provided attr_extra space, use it in any case. 325 * 326 * This is neccesary even if orig->extra equals NULL, because otherwise 327 * memory may be later allocated on the heap by bgp_attr_extra_get. 328 * 329 * That memory would eventually be leaked, because the caller must not 330 * call bgp_attr_extra_free if he provided attr_extra on the stack. 331 */ 332 if (extra) 333 { 334 new->extra = extra; 335 memset(new->extra, 0, sizeof(struct attr_extra)); 336 if (orig->extra) 337 *new->extra = *orig->extra; 338 } 339 else if (orig->extra) 340 { 341 new->extra = bgp_attr_extra_new(); 342 *new->extra = *orig->extra; 343 } 344} 345 346unsigned long int 347attr_count (void) 348{ 349 return attrhash->count; 350} 351 352unsigned long int 353attr_unknown_count (void) 354{ 355 return transit_hash->count; 356} 357 358unsigned int 359attrhash_key_make (void *p) 360{ 361 const struct attr *attr = (struct attr *) p; 362 const struct attr_extra *extra = attr->extra; 363 uint32_t key = 0; 364#define MIX(val) key = jhash_1word(val, key) 365 366 MIX(attr->origin); 367 MIX(attr->nexthop.s_addr); 368 MIX(attr->med); 369 MIX(attr->local_pref); 370 371 key += attr->origin; 372 key += attr->nexthop.s_addr; 373 key += attr->med; 374 key += attr->local_pref; 375 376 if (extra) 377 { 378 MIX(extra->aggregator_as); 379 MIX(extra->aggregator_addr.s_addr); 380 MIX(extra->weight); 381 MIX(extra->mp_nexthop_global_in.s_addr); 382 MIX(extra->originator_id.s_addr); 383 } 384 385 if (attr->aspath) 386 MIX(aspath_key_make (attr->aspath)); 387 if (attr->community) 388 MIX(community_hash_make (attr->community)); 389 390 if (extra) 391 { 392 if (extra->ecommunity) 393 MIX(ecommunity_hash_make (extra->ecommunity)); 394 if (extra->cluster) 395 MIX(cluster_hash_key_make (extra->cluster)); 396 if (extra->transit) 397 MIX(transit_hash_key_make (extra->transit)); 398 399#ifdef HAVE_IPV6 400 MIX(extra->mp_nexthop_len); 401 key = jhash(extra->mp_nexthop_global.s6_addr, 16, key); 402 key = jhash(extra->mp_nexthop_local.s6_addr, 16, key); 403#endif /* HAVE_IPV6 */ 404 } 405 406 return key; 407} 408 409int 410attrhash_cmp (const void *p1, const void *p2) 411{ 412 const struct attr * attr1 = p1; 413 const struct attr * attr2 = p2; 414 415 if (attr1->flag == attr2->flag 416 && attr1->origin == attr2->origin 417 && attr1->nexthop.s_addr == attr2->nexthop.s_addr 418 && attr1->aspath == attr2->aspath 419 && attr1->community == attr2->community 420 && attr1->med == attr2->med 421 && attr1->local_pref == attr2->local_pref) 422 { 423 const struct attr_extra *ae1 = attr1->extra; 424 const struct attr_extra *ae2 = attr2->extra; 425 426 if (ae1 && ae2 427 && ae1->aggregator_as == ae2->aggregator_as 428 && ae1->aggregator_addr.s_addr == ae2->aggregator_addr.s_addr 429 && ae1->weight == ae2->weight 430#ifdef HAVE_IPV6 431 && ae1->mp_nexthop_len == ae2->mp_nexthop_len 432 && IPV6_ADDR_SAME (&ae1->mp_nexthop_global, &ae2->mp_nexthop_global) 433 && IPV6_ADDR_SAME (&ae1->mp_nexthop_local, &ae2->mp_nexthop_local) 434#endif /* HAVE_IPV6 */ 435 && IPV4_ADDR_SAME (&ae1->mp_nexthop_global_in, &ae2->mp_nexthop_global_in) 436 && ae1->ecommunity == ae2->ecommunity 437 && ae1->cluster == ae2->cluster 438 && ae1->transit == ae2->transit 439 && IPV4_ADDR_SAME (&ae1->originator_id, &ae2->originator_id)) 440 return 1; 441 else if (ae1 || ae2) 442 return 0; 443 /* neither attribute has extra attributes, so they're same */ 444 return 1; 445 } 446 else 447 return 0; 448} 449 450static void 451attrhash_init (void) 452{ 453 attrhash = hash_create (attrhash_key_make, attrhash_cmp); 454} 455 456static void 457attrhash_finish (void) 458{ 459 hash_free (attrhash); 460 attrhash = NULL; 461} 462 463static void 464attr_show_all_iterator (struct hash_backet *backet, struct vty *vty) 465{ 466 struct attr *attr = backet->data; 467 468 vty_out (vty, "attr[%ld] nexthop %s%s", attr->refcnt, 469 inet_ntoa (attr->nexthop), VTY_NEWLINE); 470} 471 472void 473attr_show_all (struct vty *vty) 474{ 475 hash_iterate (attrhash, 476 (void (*)(struct hash_backet *, void *)) 477 attr_show_all_iterator, 478 vty); 479} 480 481static void * 482bgp_attr_hash_alloc (void *p) 483{ 484 struct attr * val = (struct attr *) p; 485 struct attr *attr; 486 487 attr = XMALLOC (MTYPE_ATTR, sizeof (struct attr)); 488 *attr = *val; 489 if (val->extra) 490 { 491 attr->extra = bgp_attr_extra_new (); 492 *attr->extra = *val->extra; 493 } 494 attr->refcnt = 0; 495 return attr; 496} 497 498/* Internet argument attribute. */ 499struct attr * 500bgp_attr_intern (struct attr *attr) 501{ 502 struct attr *find; 503 504 /* Intern referenced strucutre. */ 505 if (attr->aspath) 506 { 507 if (! attr->aspath->refcnt) 508 attr->aspath = aspath_intern (attr->aspath); 509 else 510 attr->aspath->refcnt++; 511 } 512 if (attr->community) 513 { 514 if (! attr->community->refcnt) 515 attr->community = community_intern (attr->community); 516 else 517 attr->community->refcnt++; 518 } 519 if (attr->extra) 520 { 521 struct attr_extra *attre = attr->extra; 522 523 if (attre->ecommunity) 524 { 525 if (! attre->ecommunity->refcnt) 526 attre->ecommunity = ecommunity_intern (attre->ecommunity); 527 else 528 attre->ecommunity->refcnt++; 529 530 } 531 if (attre->cluster) 532 { 533 if (! attre->cluster->refcnt) 534 attre->cluster = cluster_intern (attre->cluster); 535 else 536 attre->cluster->refcnt++; 537 } 538 if (attre->transit) 539 { 540 if (! attre->transit->refcnt) 541 attre->transit = transit_intern (attre->transit); 542 else 543 attre->transit->refcnt++; 544 } 545 } 546 547 find = (struct attr *) hash_get (attrhash, attr, bgp_attr_hash_alloc); 548 find->refcnt++; 549 550 return find; 551} 552 553 554/* Make network statement's attribute. */ 555struct attr * 556bgp_attr_default_set (struct attr *attr, u_char origin) 557{ 558 memset (attr, 0, sizeof (struct attr)); 559 bgp_attr_extra_get (attr); 560 561 attr->origin = origin; 562 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN); 563 attr->aspath = aspath_empty (); 564 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH); 565 attr->extra->weight = BGP_ATTR_DEFAULT_WEIGHT; 566 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP); 567#ifdef HAVE_IPV6 568 attr->extra->mp_nexthop_len = IPV6_MAX_BYTELEN; 569#endif 570 571 return attr; 572} 573 574 575/* Make network statement's attribute. */ 576struct attr * 577bgp_attr_default_intern (u_char origin) 578{ 579 struct attr attr; 580 struct attr *new; 581 582 bgp_attr_default_set(&attr, origin); 583 584 new = bgp_attr_intern (&attr); 585 bgp_attr_extra_free (&attr); 586 587 aspath_unintern (&new->aspath); 588 return new; 589} 590 591struct attr * 592bgp_attr_aggregate_intern (struct bgp *bgp, u_char origin, 593 struct aspath *aspath, 594 struct community *community, int as_set) 595{ 596 struct attr attr; 597 struct attr *new; 598 struct attr_extra attre; 599 600 memset (&attr, 0, sizeof (struct attr)); 601 memset (&attre, 0, sizeof (struct attr_extra)); 602 attr.extra = &attre; 603 604 /* Origin attribute. */ 605 attr.origin = origin; 606 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN); 607 608 /* AS path attribute. */ 609 if (aspath) 610 attr.aspath = aspath_intern (aspath); 611 else 612 attr.aspath = aspath_empty (); 613 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH); 614 615 /* Next hop attribute. */ 616 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP); 617 618 if (community) 619 { 620 attr.community = community; 621 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES); 622 } 623 624 attre.weight = BGP_ATTR_DEFAULT_WEIGHT; 625#ifdef HAVE_IPV6 626 attre.mp_nexthop_len = IPV6_MAX_BYTELEN; 627#endif 628 if (! as_set) 629 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE); 630 attr.flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR); 631 if (CHECK_FLAG (bgp->config, BGP_CONFIG_CONFEDERATION)) 632 attre.aggregator_as = bgp->confed_id; 633 else 634 attre.aggregator_as = bgp->as; 635 attre.aggregator_addr = bgp->router_id; 636 637 new = bgp_attr_intern (&attr); 638 639 aspath_unintern (&new->aspath); 640 return new; 641} 642 643/* Unintern just the sub-components of the attr, but not the attr */ 644void 645bgp_attr_unintern_sub (struct attr *attr) 646{ 647 /* aspath refcount shoud be decrement. */ 648 if (attr->aspath) 649 aspath_unintern (&attr->aspath); 650 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)); 651 652 if (attr->community) 653 community_unintern (&attr->community); 654 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)); 655 656 if (attr->extra) 657 { 658 if (attr->extra->ecommunity) 659 ecommunity_unintern (&attr->extra->ecommunity); 660 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES)); 661 662 if (attr->extra->cluster) 663 cluster_unintern (attr->extra->cluster); 664 UNSET_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST)); 665 666 if (attr->extra->transit) 667 transit_unintern (attr->extra->transit); 668 } 669} 670 671/* Free bgp attribute and aspath. */ 672void 673bgp_attr_unintern (struct attr **pattr) 674{ 675 struct attr *attr = *pattr; 676 struct attr *ret; 677 struct attr tmp; 678 struct attr_extra tmp_extra; 679 680 /* Decrement attribute reference. */ 681 attr->refcnt--; 682 683 tmp = *attr; 684 685 if (attr->extra) 686 { 687 tmp.extra = &tmp_extra; 688 memcpy (tmp.extra, attr->extra, sizeof (struct attr_extra)); 689 } 690 691 /* If reference becomes zero then free attribute object. */ 692 if (attr->refcnt == 0) 693 { 694 ret = hash_release (attrhash, attr); 695 assert (ret != NULL); 696 bgp_attr_extra_free (attr); 697 XFREE (MTYPE_ATTR, attr); 698 *pattr = NULL; 699 } 700 701 bgp_attr_unintern_sub (&tmp); 702} 703 704void 705bgp_attr_flush (struct attr *attr) 706{ 707 if (attr->aspath && ! attr->aspath->refcnt) 708 aspath_free (attr->aspath); 709 if (attr->community && ! attr->community->refcnt) 710 community_free (attr->community); 711 if (attr->extra) 712 { 713 struct attr_extra *attre = attr->extra; 714 715 if (attre->ecommunity && ! attre->ecommunity->refcnt) 716 ecommunity_free (&attre->ecommunity); 717 if (attre->cluster && ! attre->cluster->refcnt) 718 cluster_free (attre->cluster); 719 if (attre->transit && ! attre->transit->refcnt) 720 transit_free (attre->transit); 721 } 722} 723 724/* Implement draft-scudder-idr-optional-transitive behaviour and 725 * avoid resetting sessions for malformed attributes which are 726 * are partial/optional and hence where the error likely was not 727 * introduced by the sending neighbour. 728 */ 729static bgp_attr_parse_ret_t 730bgp_attr_malformed (struct bgp_attr_parser_args *args, u_char subcode, 731 bgp_size_t length) 732{ 733 struct peer *const peer = args->peer; 734 const u_int8_t flags = args->flags; 735 /* startp and length must be special-cased, as whether or not to 736 * send the attribute data with the NOTIFY depends on the error, 737 * the caller therefore signals this with the seperate length argument 738 */ 739 u_char *notify_datap = (length > 0 ? args->startp : NULL); 740 741 /* Only relax error handling for eBGP peers */ 742 if (peer->sort != BGP_PEER_EBGP) 743 { 744 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode, 745 notify_datap, length); 746 return BGP_ATTR_PARSE_ERROR; 747 748 } 749 750 /* Adjust the stream getp to the end of the attribute, in case we can 751 * still proceed but the caller hasn't read all the attribute. 752 */ 753 stream_set_getp (BGP_INPUT (peer), 754 (args->startp - STREAM_DATA (BGP_INPUT (peer))) 755 + args->total); 756 757 switch (args->type) { 758 /* where an attribute is relatively inconsequential, e.g. it does not 759 * affect route selection, and can be safely ignored, then any such 760 * attributes which are malformed should just be ignored and the route 761 * processed as normal. 762 */ 763 case BGP_ATTR_AS4_AGGREGATOR: 764 case BGP_ATTR_AGGREGATOR: 765 case BGP_ATTR_ATOMIC_AGGREGATE: 766 return BGP_ATTR_PARSE_PROCEED; 767 768 /* Core attributes, particularly ones which may influence route 769 * selection, should always cause session resets 770 */ 771 case BGP_ATTR_ORIGIN: 772 case BGP_ATTR_AS_PATH: 773 case BGP_ATTR_NEXT_HOP: 774 case BGP_ATTR_MULTI_EXIT_DISC: 775 case BGP_ATTR_LOCAL_PREF: 776 case BGP_ATTR_COMMUNITIES: 777 case BGP_ATTR_ORIGINATOR_ID: 778 case BGP_ATTR_CLUSTER_LIST: 779 case BGP_ATTR_MP_REACH_NLRI: 780 case BGP_ATTR_MP_UNREACH_NLRI: 781 case BGP_ATTR_EXT_COMMUNITIES: 782 bgp_notify_send_with_data (peer, BGP_NOTIFY_UPDATE_ERR, subcode, 783 notify_datap, length); 784 return BGP_ATTR_PARSE_ERROR; 785 } 786 787 /* Partial optional attributes that are malformed should not cause 788 * the whole session to be reset. Instead treat it as a withdrawal 789 * of the routes, if possible. 790 */ 791 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS) 792 && CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL) 793 && CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL)) 794 return BGP_ATTR_PARSE_WITHDRAW; 795 796 /* default to reset */ 797 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; 798} 799 800/* Find out what is wrong with the path attribute flag bits and log the error. 801 "Flag bits" here stand for Optional, Transitive and Partial, but not for 802 Extended Length. Checking O/T/P bits at once implies, that the attribute 803 being diagnosed is defined by RFC as either a "well-known" or an "optional, 804 non-transitive" attribute. */ 805static void 806bgp_attr_flags_diagnose (struct bgp_attr_parser_args *args, 807 u_int8_t desired_flags /* how RFC says it must be */ 808) 809{ 810 u_char seen = 0, i; 811 u_char real_flags = args->flags; 812 const u_int8_t attr_code = args->type; 813 814 desired_flags &= ~BGP_ATTR_FLAG_EXTLEN; 815 real_flags &= ~BGP_ATTR_FLAG_EXTLEN; 816 for (i = 0; i <= 2; i++) /* O,T,P, but not E */ 817 if 818 ( 819 CHECK_FLAG (desired_flags, attr_flag_str[i].key) != 820 CHECK_FLAG (real_flags, attr_flag_str[i].key) 821 ) 822 { 823 zlog (args->peer->log, LOG_ERR, "%s attribute must%s be flagged as \"%s\"", 824 LOOKUP (attr_str, attr_code), 825 CHECK_FLAG (desired_flags, attr_flag_str[i].key) ? "" : " not", 826 attr_flag_str[i].str); 827 seen = 1; 828 } 829 if (!seen) 830 { 831 zlog (args->peer->log, LOG_DEBUG, 832 "Strange, %s called for attr %s, but no problem found with flags" 833 " (real flags 0x%x, desired 0x%x)", 834 __func__, LOOKUP (attr_str, attr_code), 835 real_flags, desired_flags); 836 } 837} 838 839/* Required flags for attributes. EXTLEN will be masked off when testing, 840 * as will PARTIAL for optional+transitive attributes. 841 */ 842const u_int8_t attr_flags_values [] = { 843 [BGP_ATTR_ORIGIN] = BGP_ATTR_FLAG_TRANS, 844 [BGP_ATTR_AS_PATH] = BGP_ATTR_FLAG_TRANS, 845 [BGP_ATTR_NEXT_HOP] = BGP_ATTR_FLAG_TRANS, 846 [BGP_ATTR_MULTI_EXIT_DISC] = BGP_ATTR_FLAG_OPTIONAL, 847 [BGP_ATTR_LOCAL_PREF] = BGP_ATTR_FLAG_TRANS, 848 [BGP_ATTR_ATOMIC_AGGREGATE] = BGP_ATTR_FLAG_TRANS, 849 [BGP_ATTR_AGGREGATOR] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL, 850 [BGP_ATTR_COMMUNITIES] = BGP_ATTR_FLAG_TRANS | BGP_ATTR_FLAG_OPTIONAL, 851 [BGP_ATTR_ORIGINATOR_ID] = BGP_ATTR_FLAG_OPTIONAL, 852 [BGP_ATTR_CLUSTER_LIST] = BGP_ATTR_FLAG_OPTIONAL, 853 [BGP_ATTR_MP_REACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL, 854 [BGP_ATTR_MP_UNREACH_NLRI] = BGP_ATTR_FLAG_OPTIONAL, 855 [BGP_ATTR_EXT_COMMUNITIES] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, 856 [BGP_ATTR_AS4_PATH] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, 857 [BGP_ATTR_AS4_AGGREGATOR] = BGP_ATTR_FLAG_OPTIONAL | BGP_ATTR_FLAG_TRANS, 858}; 859static const size_t attr_flags_values_max = 860 sizeof (attr_flags_values) / sizeof (attr_flags_values[0]); 861 862static int 863bgp_attr_flag_invalid (struct bgp_attr_parser_args *args) 864{ 865 u_int8_t mask = BGP_ATTR_FLAG_EXTLEN; 866 const u_int8_t flags = args->flags; 867 const u_int8_t attr_code = args->type; 868 struct peer *const peer = args->peer; 869 870 /* there may be attributes we don't know about */ 871 if (attr_code > attr_flags_values_max) 872 return 0; 873 if (attr_flags_values[attr_code] == 0) 874 return 0; 875 876 /* RFC4271, "For well-known attributes, the Transitive bit MUST be set to 877 * 1." 878 */ 879 if (!CHECK_FLAG (BGP_ATTR_FLAG_OPTIONAL, flags) 880 && !CHECK_FLAG (BGP_ATTR_FLAG_TRANS, flags)) 881 { 882 zlog (peer->log, LOG_ERR, 883 "%s well-known attributes must have transitive flag set (%x)", 884 LOOKUP (attr_str, attr_code), flags); 885 return 1; 886 } 887 888 /* "For well-known attributes and for optional non-transitive attributes, 889 * the Partial bit MUST be set to 0." 890 */ 891 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_PARTIAL)) 892 { 893 if (!CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL)) 894 { 895 zlog (peer->log, LOG_ERR, 896 "%s well-known attribute " 897 "must NOT have the partial flag set (%x)", 898 LOOKUP (attr_str, attr_code), flags); 899 return 1; 900 } 901 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL) 902 && !CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS)) 903 { 904 zlog (peer->log, LOG_ERR, 905 "%s optional + transitive attribute " 906 "must NOT have the partial flag set (%x)", 907 LOOKUP (attr_str, attr_code), flags); 908 return 1; 909 } 910 } 911 912 /* Optional transitive attributes may go through speakers that don't 913 * reocgnise them and set the Partial bit. 914 */ 915 if (CHECK_FLAG (flags, BGP_ATTR_FLAG_OPTIONAL) 916 && CHECK_FLAG (flags, BGP_ATTR_FLAG_TRANS)) 917 SET_FLAG (mask, BGP_ATTR_FLAG_PARTIAL); 918 919 if ((flags & ~mask) 920 == attr_flags_values[attr_code]) 921 return 0; 922 923 bgp_attr_flags_diagnose (args, attr_flags_values[attr_code]); 924 return 1; 925} 926 927/* Get origin attribute of the update message. */ 928static bgp_attr_parse_ret_t 929bgp_attr_origin (struct bgp_attr_parser_args *args) 930{ 931 struct peer *const peer = args->peer; 932 struct attr *const attr = args->attr; 933 const bgp_size_t length = args->length; 934 935 /* If any recognized attribute has Attribute Length that conflicts 936 with the expected length (based on the attribute type code), then 937 the Error Subcode is set to Attribute Length Error. The Data 938 field contains the erroneous attribute (type, length and 939 value). */ 940 if (length != 1) 941 { 942 zlog (peer->log, LOG_ERR, "Origin attribute length is not one %d", 943 length); 944 return bgp_attr_malformed (args, 945 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, 946 args->total); 947 } 948 949 /* Fetch origin attribute. */ 950 attr->origin = stream_getc (BGP_INPUT (peer)); 951 952 /* If the ORIGIN attribute has an undefined value, then the Error 953 Subcode is set to Invalid Origin Attribute. The Data field 954 contains the unrecognized attribute (type, length and value). */ 955 if ((attr->origin != BGP_ORIGIN_IGP) 956 && (attr->origin != BGP_ORIGIN_EGP) 957 && (attr->origin != BGP_ORIGIN_INCOMPLETE)) 958 { 959 zlog (peer->log, LOG_ERR, "Origin attribute value is invalid %d", 960 attr->origin); 961 return bgp_attr_malformed (args, 962 BGP_NOTIFY_UPDATE_INVAL_ORIGIN, 963 args->total); 964 } 965 966 /* Set oring attribute flag. */ 967 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGIN); 968 969 return 0; 970} 971 972/* Parse AS path information. This function is wrapper of 973 aspath_parse. */ 974static int 975bgp_attr_aspath (struct bgp_attr_parser_args *args) 976{ 977 struct attr *const attr = args->attr; 978 struct peer *const peer = args->peer; 979 const bgp_size_t length = args->length; 980 981 /* 982 * peer with AS4 => will get 4Byte ASnums 983 * otherwise, will get 16 Bit 984 */ 985 attr->aspath = aspath_parse (peer->ibuf, length, 986 CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)); 987 988 /* In case of IBGP, length will be zero. */ 989 if (! attr->aspath) 990 { 991 zlog (peer->log, LOG_ERR, 992 "Malformed AS path from %s, length is %d", 993 peer->host, length); 994 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_MAL_AS_PATH, 0); 995 } 996 997 /* Set aspath attribute flag. */ 998 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS_PATH); 999 1000 return BGP_ATTR_PARSE_PROCEED; 1001} 1002 1003static bgp_attr_parse_ret_t 1004bgp_attr_aspath_check (struct peer *const peer, struct attr *const attr) 1005{ 1006 /* These checks were part of bgp_attr_aspath, but with 1007 * as4 we should to check aspath things when 1008 * aspath synthesizing with as4_path has already taken place. 1009 * Otherwise we check ASPATH and use the synthesized thing, and that is 1010 * not right. 1011 * So do the checks later, i.e. here 1012 */ 1013 struct bgp *bgp = peer->bgp; 1014 struct aspath *aspath; 1015 1016 /* Confederation sanity check. */ 1017 if ((peer->sort == BGP_PEER_CONFED && ! aspath_left_confed_check (attr->aspath)) || 1018 (peer->sort == BGP_PEER_EBGP && aspath_confed_check (attr->aspath))) 1019 { 1020 zlog (peer->log, LOG_ERR, "Malformed AS path from %s", peer->host); 1021 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, 1022 BGP_NOTIFY_UPDATE_MAL_AS_PATH); 1023 return BGP_ATTR_PARSE_ERROR; 1024 } 1025 1026 /* First AS check for EBGP. */ 1027 if (bgp != NULL && bgp_flag_check (bgp, BGP_FLAG_ENFORCE_FIRST_AS)) 1028 { 1029 if (peer->sort == BGP_PEER_EBGP 1030 && ! aspath_firstas_check (attr->aspath, peer->as)) 1031 { 1032 zlog (peer->log, LOG_ERR, 1033 "%s incorrect first AS (must be %u)", peer->host, peer->as); 1034 bgp_notify_send (peer, BGP_NOTIFY_UPDATE_ERR, 1035 BGP_NOTIFY_UPDATE_MAL_AS_PATH); 1036 return BGP_ATTR_PARSE_ERROR; 1037 } 1038 } 1039 1040 /* local-as prepend */ 1041 if (peer->change_local_as && 1042 ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND)) 1043 { 1044 aspath = aspath_dup (attr->aspath); 1045 aspath = aspath_add_seq (aspath, peer->change_local_as); 1046 aspath_unintern (&attr->aspath); 1047 attr->aspath = aspath_intern (aspath); 1048 } 1049 1050 return BGP_ATTR_PARSE_PROCEED; 1051} 1052 1053/* Parse AS4 path information. This function is another wrapper of 1054 aspath_parse. */ 1055static int 1056bgp_attr_as4_path (struct bgp_attr_parser_args *args, struct aspath **as4_path) 1057{ 1058 struct peer *const peer = args->peer; 1059 struct attr *const attr = args->attr; 1060 const bgp_size_t length = args->length; 1061 1062 *as4_path = aspath_parse (peer->ibuf, length, 1); 1063 1064 /* In case of IBGP, length will be zero. */ 1065 if (!*as4_path) 1066 { 1067 zlog (peer->log, LOG_ERR, 1068 "Malformed AS4 path from %s, length is %d", 1069 peer->host, length); 1070 return bgp_attr_malformed (args, 1071 BGP_NOTIFY_UPDATE_MAL_AS_PATH, 1072 0); 1073 } 1074 1075 /* Set aspath attribute flag. */ 1076 if (as4_path) 1077 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH); 1078 1079 return BGP_ATTR_PARSE_PROCEED; 1080} 1081 1082/* Nexthop attribute. */ 1083static bgp_attr_parse_ret_t 1084bgp_attr_nexthop (struct bgp_attr_parser_args *args) 1085{ 1086 struct peer *const peer = args->peer; 1087 struct attr *const attr = args->attr; 1088 const bgp_size_t length = args->length; 1089 1090 in_addr_t nexthop_h, nexthop_n; 1091 1092 /* Check nexthop attribute length. */ 1093 if (length != 4) 1094 { 1095 zlog (peer->log, LOG_ERR, "Nexthop attribute length isn't four [%d]", 1096 length); 1097 1098 return bgp_attr_malformed (args, 1099 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, 1100 args->total); 1101 } 1102 1103 /* According to section 6.3 of RFC4271, syntactically incorrect NEXT_HOP 1104 attribute must result in a NOTIFICATION message (this is implemented below). 1105 At the same time, semantically incorrect NEXT_HOP is more likely to be just 1106 logged locally (this is implemented somewhere else). The UPDATE message 1107 gets ignored in any of these cases. */ 1108 nexthop_n = stream_get_ipv4 (peer->ibuf); 1109 nexthop_h = ntohl (nexthop_n); 1110 if (IPV4_NET0 (nexthop_h) || IPV4_NET127 (nexthop_h) || IPV4_CLASS_DE (nexthop_h)) 1111 { 1112 char buf[INET_ADDRSTRLEN]; 1113 inet_ntop (AF_INET, &nexthop_n, buf, INET_ADDRSTRLEN); 1114 zlog (peer->log, LOG_ERR, "Martian nexthop %s", buf); 1115 return bgp_attr_malformed (args, 1116 BGP_NOTIFY_UPDATE_INVAL_NEXT_HOP, 1117 args->total); 1118 } 1119 1120 attr->nexthop.s_addr = nexthop_n; 1121 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP); 1122 1123 return BGP_ATTR_PARSE_PROCEED; 1124} 1125 1126/* MED atrribute. */ 1127static bgp_attr_parse_ret_t 1128bgp_attr_med (struct bgp_attr_parser_args *args) 1129{ 1130 struct peer *const peer = args->peer; 1131 struct attr *const attr = args->attr; 1132 const bgp_size_t length = args->length; 1133 1134 /* Length check. */ 1135 if (length != 4) 1136 { 1137 zlog (peer->log, LOG_ERR, 1138 "MED attribute length isn't four [%d]", length); 1139 1140 return bgp_attr_malformed (args, 1141 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, 1142 args->total); 1143 } 1144 1145 attr->med = stream_getl (peer->ibuf); 1146 1147 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC); 1148 1149 return BGP_ATTR_PARSE_PROCEED; 1150} 1151 1152/* Local preference attribute. */ 1153static bgp_attr_parse_ret_t 1154bgp_attr_local_pref (struct bgp_attr_parser_args *args) 1155{ 1156 struct peer *const peer = args->peer; 1157 struct attr *const attr = args->attr; 1158 const bgp_size_t length = args->length; 1159 1160 /* Length check. */ 1161 if (length != 4) 1162 { 1163 zlog (peer->log, LOG_ERR, "LOCAL_PREF attribute length isn't 4 [%u]", 1164 length); 1165 return bgp_attr_malformed (args, 1166 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, 1167 args->total); 1168 } 1169 1170 /* If it is contained in an UPDATE message that is received from an 1171 external peer, then this attribute MUST be ignored by the 1172 receiving speaker. */ 1173 if (peer->sort == BGP_PEER_EBGP) 1174 { 1175 stream_forward_getp (peer->ibuf, length); 1176 return BGP_ATTR_PARSE_PROCEED; 1177 } 1178 1179 attr->local_pref = stream_getl (peer->ibuf); 1180 1181 /* Set atomic aggregate flag. */ 1182 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF); 1183 1184 return BGP_ATTR_PARSE_PROCEED; 1185} 1186 1187/* Atomic aggregate. */ 1188static int 1189bgp_attr_atomic (struct bgp_attr_parser_args *args) 1190{ 1191 struct peer *const peer = args->peer; 1192 struct attr *const attr = args->attr; 1193 const bgp_size_t length = args->length; 1194 1195 /* Length check. */ 1196 if (length != 0) 1197 { 1198 zlog (peer->log, LOG_ERR, "ATOMIC_AGGREGATE attribute length isn't 0 [%u]", 1199 length); 1200 return bgp_attr_malformed (args, 1201 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, 1202 args->total); 1203 } 1204 1205 /* Set atomic aggregate flag. */ 1206 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE); 1207 1208 return BGP_ATTR_PARSE_PROCEED; 1209} 1210 1211/* Aggregator attribute */ 1212static int 1213bgp_attr_aggregator (struct bgp_attr_parser_args *args) 1214{ 1215 struct peer *const peer = args->peer; 1216 struct attr *const attr = args->attr; 1217 const bgp_size_t length = args->length; 1218 1219 int wantedlen = 6; 1220 struct attr_extra *attre = bgp_attr_extra_get (attr); 1221 1222 /* peer with AS4 will send 4 Byte AS, peer without will send 2 Byte */ 1223 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) 1224 wantedlen = 8; 1225 1226 if (length != wantedlen) 1227 { 1228 zlog (peer->log, LOG_ERR, "AGGREGATOR attribute length isn't %u [%u]", 1229 wantedlen, length); 1230 return bgp_attr_malformed (args, 1231 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, 1232 args->total); 1233 } 1234 1235 if ( CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV ) ) 1236 attre->aggregator_as = stream_getl (peer->ibuf); 1237 else 1238 attre->aggregator_as = stream_getw (peer->ibuf); 1239 attre->aggregator_addr.s_addr = stream_get_ipv4 (peer->ibuf); 1240 1241 /* Set atomic aggregate flag. */ 1242 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR); 1243 1244 return BGP_ATTR_PARSE_PROCEED; 1245} 1246 1247/* New Aggregator attribute */ 1248static bgp_attr_parse_ret_t 1249bgp_attr_as4_aggregator (struct bgp_attr_parser_args *args, 1250 as_t *as4_aggregator_as, 1251 struct in_addr *as4_aggregator_addr) 1252{ 1253 struct peer *const peer = args->peer; 1254 struct attr *const attr = args->attr; 1255 const bgp_size_t length = args->length; 1256 1257 if (length != 8) 1258 { 1259 zlog (peer->log, LOG_ERR, "New Aggregator length is not 8 [%d]", 1260 length); 1261 return bgp_attr_malformed (args, 1262 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, 1263 0); 1264 } 1265 1266 *as4_aggregator_as = stream_getl (peer->ibuf); 1267 as4_aggregator_addr->s_addr = stream_get_ipv4 (peer->ibuf); 1268 1269 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR); 1270 1271 return BGP_ATTR_PARSE_PROCEED; 1272} 1273 1274/* Munge Aggregator and New-Aggregator, AS_PATH and NEW_AS_PATH. 1275 */ 1276static bgp_attr_parse_ret_t 1277bgp_attr_munge_as4_attrs (struct peer *const peer, 1278 struct attr *const attr, 1279 struct aspath *as4_path, as_t as4_aggregator, 1280 struct in_addr *as4_aggregator_addr) 1281{ 1282 int ignore_as4_path = 0; 1283 struct aspath *newpath; 1284 struct attr_extra *attre = attr->extra; 1285 1286 if (!attr->aspath) 1287 { 1288 /* NULL aspath shouldn't be possible as bgp_attr_parse should have 1289 * checked that all well-known, mandatory attributes were present. 1290 * 1291 * Can only be a problem with peer itself - hard error 1292 */ 1293 return BGP_ATTR_PARSE_ERROR; 1294 } 1295 1296 if (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) 1297 { 1298 /* peer can do AS4, so we ignore AS4_PATH and AS4_AGGREGATOR 1299 * if given. 1300 * It is worth a warning though, because the peer really 1301 * should not send them 1302 */ 1303 if (BGP_DEBUG(as4, AS4)) 1304 { 1305 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH))) 1306 zlog_debug ("[AS4] %s %s AS4_PATH", 1307 peer->host, "AS4 capable peer, yet it sent"); 1308 1309 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS4_AGGREGATOR))) 1310 zlog_debug ("[AS4] %s %s AS4_AGGREGATOR", 1311 peer->host, "AS4 capable peer, yet it sent"); 1312 } 1313 1314 return BGP_ATTR_PARSE_PROCEED; 1315 } 1316 1317 /* We have a asn16 peer. First, look for AS4_AGGREGATOR 1318 * because that may override AS4_PATH 1319 */ 1320 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR) ) ) 1321 { 1322 if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) ) 1323 { 1324 assert (attre); 1325 1326 /* received both. 1327 * if the as_number in aggregator is not AS_TRANS, 1328 * then AS4_AGGREGATOR and AS4_PATH shall be ignored 1329 * and the Aggregator shall be taken as 1330 * info on the aggregating node, and the AS_PATH 1331 * shall be taken as the AS_PATH 1332 * otherwise 1333 * the Aggregator shall be ignored and the 1334 * AS4_AGGREGATOR shall be taken as the 1335 * Aggregating node and the AS_PATH is to be 1336 * constructed "as in all other cases" 1337 */ 1338 if (attre->aggregator_as != BGP_AS_TRANS) 1339 { 1340 /* ignore */ 1341 if ( BGP_DEBUG(as4, AS4)) 1342 zlog_debug ("[AS4] %s BGP not AS4 capable peer" 1343 " send AGGREGATOR != AS_TRANS and" 1344 " AS4_AGGREGATOR, so ignore" 1345 " AS4_AGGREGATOR and AS4_PATH", peer->host); 1346 ignore_as4_path = 1; 1347 } 1348 else 1349 { 1350 /* "New_aggregator shall be taken as aggregator" */ 1351 attre->aggregator_as = as4_aggregator; 1352 attre->aggregator_addr.s_addr = as4_aggregator_addr->s_addr; 1353 } 1354 } 1355 else 1356 { 1357 /* We received a AS4_AGGREGATOR but no AGGREGATOR. 1358 * That is bogus - but reading the conditions 1359 * we have to handle AS4_AGGREGATOR as if it were 1360 * AGGREGATOR in that case 1361 */ 1362 if ( BGP_DEBUG(as4, AS4)) 1363 zlog_debug ("[AS4] %s BGP not AS4 capable peer send" 1364 " AS4_AGGREGATOR but no AGGREGATOR, will take" 1365 " it as if AGGREGATOR with AS_TRANS had been there", peer->host); 1366 (attre = bgp_attr_extra_get (attr))->aggregator_as = as4_aggregator; 1367 /* sweep it under the carpet and simulate a "good" AGGREGATOR */ 1368 attr->flag |= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR)); 1369 } 1370 } 1371 1372 /* need to reconcile NEW_AS_PATH and AS_PATH */ 1373 if (!ignore_as4_path && (attr->flag & (ATTR_FLAG_BIT( BGP_ATTR_AS4_PATH)))) 1374 { 1375 newpath = aspath_reconcile_as4 (attr->aspath, as4_path); 1376 aspath_unintern (&attr->aspath); 1377 attr->aspath = aspath_intern (newpath); 1378 } 1379 return BGP_ATTR_PARSE_PROCEED; 1380} 1381 1382/* Community attribute. */ 1383static bgp_attr_parse_ret_t 1384bgp_attr_community (struct bgp_attr_parser_args *args) 1385{ 1386 struct peer *const peer = args->peer; 1387 struct attr *const attr = args->attr; 1388 const bgp_size_t length = args->length; 1389 1390 if (length == 0) 1391 { 1392 attr->community = NULL; 1393 return BGP_ATTR_PARSE_PROCEED; 1394 } 1395 1396 attr->community = 1397 community_parse ((u_int32_t *)stream_pnt (peer->ibuf), length); 1398 1399 /* XXX: fix community_parse to use stream API and remove this */ 1400 stream_forward_getp (peer->ibuf, length); 1401 1402 if (!attr->community) 1403 return bgp_attr_malformed (args, 1404 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, 1405 args->total); 1406 1407 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES); 1408 1409 return BGP_ATTR_PARSE_PROCEED; 1410} 1411 1412/* Originator ID attribute. */ 1413static bgp_attr_parse_ret_t 1414bgp_attr_originator_id (struct bgp_attr_parser_args *args) 1415{ 1416 struct peer *const peer = args->peer; 1417 struct attr *const attr = args->attr; 1418 const bgp_size_t length = args->length; 1419 1420 /* Length check. */ 1421 if (length != 4) 1422 { 1423 zlog (peer->log, LOG_ERR, "Bad originator ID length %d", length); 1424 1425 return bgp_attr_malformed (args, 1426 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, 1427 args->total); 1428 } 1429 1430 (bgp_attr_extra_get (attr))->originator_id.s_addr 1431 = stream_get_ipv4 (peer->ibuf); 1432 1433 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_ORIGINATOR_ID); 1434 1435 return BGP_ATTR_PARSE_PROCEED; 1436} 1437 1438/* Cluster list attribute. */ 1439static bgp_attr_parse_ret_t 1440bgp_attr_cluster_list (struct bgp_attr_parser_args *args) 1441{ 1442 struct peer *const peer = args->peer; 1443 struct attr *const attr = args->attr; 1444 const bgp_size_t length = args->length; 1445 1446 /* Check length. */ 1447 if (length % 4) 1448 { 1449 zlog (peer->log, LOG_ERR, "Bad cluster list length %d", length); 1450 1451 return bgp_attr_malformed (args, BGP_NOTIFY_UPDATE_ATTR_LENG_ERR, 1452 args->total); 1453 } 1454 1455 (bgp_attr_extra_get (attr))->cluster 1456 = cluster_parse ((struct in_addr *)stream_pnt (peer->ibuf), length); 1457 1458 /* XXX: Fix cluster_parse to use stream API and then remove this */ 1459 stream_forward_getp (peer->ibuf, length); 1460 1461 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_CLUSTER_LIST); 1462 1463 return BGP_ATTR_PARSE_PROCEED; 1464} 1465 1466/* Multiprotocol reachability information parse. */ 1467int 1468bgp_mp_reach_parse (struct bgp_attr_parser_args *args, 1469 struct bgp_nlri *mp_update) 1470{ 1471 afi_t afi; 1472 safi_t safi; 1473 bgp_size_t nlri_len; 1474 size_t start; 1475 int ret; 1476 struct stream *s; 1477 struct peer *const peer = args->peer; 1478 struct attr *const attr = args->attr; 1479 const bgp_size_t length = args->length; 1480 struct attr_extra *attre = bgp_attr_extra_get(attr); 1481 1482 /* Set end of packet. */ 1483 s = BGP_INPUT(peer); 1484 start = stream_get_getp(s); 1485 1486 /* safe to read statically sized header? */ 1487#define BGP_MP_REACH_MIN_SIZE 5 1488#define LEN_LEFT (length - (stream_get_getp(s) - start)) 1489 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE)) 1490 { 1491 zlog_info ("%s: %s sent invalid length, %lu", 1492 __func__, peer->host, (unsigned long)length); 1493 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; 1494 } 1495 1496 /* Load AFI, SAFI. */ 1497 afi = stream_getw (s); 1498 safi = stream_getc (s); 1499 1500 /* Get nexthop length. */ 1501 attre->mp_nexthop_len = stream_getc (s); 1502 1503 if (LEN_LEFT < attre->mp_nexthop_len) 1504 { 1505 zlog_info ("%s: %s, MP nexthop length, %u, goes past end of attribute", 1506 __func__, peer->host, attre->mp_nexthop_len); 1507 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; 1508 } 1509 1510 /* Nexthop length check. */ 1511 switch (attre->mp_nexthop_len) 1512 { 1513 case 4: 1514 stream_get (&attre->mp_nexthop_global_in, s, 4); 1515 /* Probably needed for RFC 2283 */ 1516 if (attr->nexthop.s_addr == 0) 1517 memcpy(&attr->nexthop.s_addr, &attre->mp_nexthop_global_in, 4); 1518 break; 1519 case 12: 1520 stream_getl (s); /* RD high */ 1521 stream_getl (s); /* RD low */ 1522 stream_get (&attre->mp_nexthop_global_in, s, 4); 1523 break; 1524#ifdef HAVE_IPV6 1525 case 16: 1526 stream_get (&attre->mp_nexthop_global, s, 16); 1527 break; 1528 case 32: 1529 stream_get (&attre->mp_nexthop_global, s, 16); 1530 stream_get (&attre->mp_nexthop_local, s, 16); 1531 if (! IN6_IS_ADDR_LINKLOCAL (&attre->mp_nexthop_local)) 1532 { 1533 char buf1[INET6_ADDRSTRLEN]; 1534 char buf2[INET6_ADDRSTRLEN]; 1535 1536 if (BGP_DEBUG (update, UPDATE_IN)) 1537 zlog_debug ("%s got two nexthop %s %s but second one is not a link-local nexthop", peer->host, 1538 inet_ntop (AF_INET6, &attre->mp_nexthop_global, 1539 buf1, INET6_ADDRSTRLEN), 1540 inet_ntop (AF_INET6, &attre->mp_nexthop_local, 1541 buf2, INET6_ADDRSTRLEN)); 1542 1543 attre->mp_nexthop_len = 16; 1544 } 1545 break; 1546#endif /* HAVE_IPV6 */ 1547 default: 1548 zlog_info ("%s: (%s) Wrong multiprotocol next hop length: %d", 1549 __func__, peer->host, attre->mp_nexthop_len); 1550 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; 1551 } 1552 1553 if (!LEN_LEFT) 1554 { 1555 zlog_info ("%s: (%s) Failed to read SNPA and NLRI(s)", 1556 __func__, peer->host); 1557 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; 1558 } 1559 1560 { 1561 u_char val; 1562 if ((val = stream_getc (s))) 1563 zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field", 1564 peer->host, val); 1565 } 1566 1567 /* must have nrli_len, what is left of the attribute */ 1568 nlri_len = LEN_LEFT; 1569 if ((!nlri_len) || (nlri_len > STREAM_READABLE(s))) 1570 { 1571 zlog_info ("%s: (%s) Failed to read NLRI", 1572 __func__, peer->host); 1573 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; 1574 } 1575 1576 if (safi != SAFI_MPLS_LABELED_VPN) 1577 { 1578 ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), nlri_len); 1579 if (ret < 0) 1580 { 1581 zlog_info ("%s: (%s) NLRI doesn't pass sanity check", 1582 __func__, peer->host); 1583 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; 1584 } 1585 } 1586 1587 mp_update->afi = afi; 1588 mp_update->safi = safi; 1589 mp_update->nlri = stream_pnt (s); 1590 mp_update->length = nlri_len; 1591 1592 stream_forward_getp (s, nlri_len); 1593 1594 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI); 1595 1596 return BGP_ATTR_PARSE_PROCEED; 1597#undef LEN_LEFT 1598} 1599 1600/* Multiprotocol unreachable parse */ 1601int 1602bgp_mp_unreach_parse (struct bgp_attr_parser_args *args, 1603 struct bgp_nlri *mp_withdraw) 1604{ 1605 struct stream *s; 1606 afi_t afi; 1607 safi_t safi; 1608 u_int16_t withdraw_len; 1609 int ret; 1610 struct peer *const peer = args->peer; 1611 struct attr *const attr = args->attr; 1612 const bgp_size_t length = args->length; 1613 1614 s = peer->ibuf; 1615 1616#define BGP_MP_UNREACH_MIN_SIZE 3 1617 if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE)) 1618 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; 1619 1620 afi = stream_getw (s); 1621 safi = stream_getc (s); 1622 1623 withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE; 1624 1625 if (safi != SAFI_MPLS_LABELED_VPN) 1626 { 1627 ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), withdraw_len); 1628 if (ret < 0) 1629 return BGP_ATTR_PARSE_ERROR_NOTIFYPLS; 1630 } 1631 1632 mp_withdraw->afi = afi; 1633 mp_withdraw->safi = safi; 1634 mp_withdraw->nlri = stream_pnt (s); 1635 mp_withdraw->length = withdraw_len; 1636 1637 stream_forward_getp (s, withdraw_len); 1638 1639 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI); 1640 1641 return BGP_ATTR_PARSE_PROCEED; 1642} 1643 1644/* Extended Community attribute. */ 1645static bgp_attr_parse_ret_t 1646bgp_attr_ext_communities (struct bgp_attr_parser_args *args) 1647{ 1648 struct peer *const peer = args->peer; 1649 struct attr *const attr = args->attr; 1650 const bgp_size_t length = args->length; 1651 1652 if (length == 0) 1653 { 1654 if (attr->extra) 1655 attr->extra->ecommunity = NULL; 1656 /* Empty extcomm doesn't seem to be invalid per se */ 1657 return BGP_ATTR_PARSE_PROCEED; 1658 } 1659 1660 (bgp_attr_extra_get (attr))->ecommunity = 1661 ecommunity_parse ((u_int8_t *)stream_pnt (peer->ibuf), length); 1662 /* XXX: fix ecommunity_parse to use stream API */ 1663 stream_forward_getp (peer->ibuf, length); 1664 1665 if (!attr->extra->ecommunity) 1666 return bgp_attr_malformed (args, 1667 BGP_NOTIFY_UPDATE_OPT_ATTR_ERR, 1668 args->total); 1669 1670 attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES); 1671 1672 return BGP_ATTR_PARSE_PROCEED; 1673} 1674 1675/* BGP unknown attribute treatment. */ 1676static bgp_attr_parse_ret_t 1677bgp_attr_unknown (struct bgp_attr_parser_args *args) 1678{ 1679 bgp_size_t total = args->total; 1680 struct transit *transit; 1681 struct attr_extra *attre; 1682 struct peer *const peer = args->peer; 1683 struct attr *const attr = args->attr; 1684 u_char *const startp = args->startp; 1685 const u_char type = args->type; 1686 const u_char flag = args->flags; 1687 const bgp_size_t length = args->length; 1688 1689 1690 if (BGP_DEBUG (normal, NORMAL)) 1691 zlog_debug ("%s Unknown attribute is received (type %d, length %d)", 1692 peer->host, type, length); 1693 1694 if (BGP_DEBUG (events, EVENTS)) 1695 zlog (peer->log, LOG_DEBUG, 1696 "Unknown attribute type %d length %d is received", type, length); 1697 1698 /* Forward read pointer of input stream. */ 1699 stream_forward_getp (peer->ibuf, length); 1700 1701 /* If any of the mandatory well-known attributes are not recognized, 1702 then the Error Subcode is set to Unrecognized Well-known 1703 Attribute. The Data field contains the unrecognized attribute 1704 (type, length and value). */ 1705 if (!CHECK_FLAG (flag, BGP_ATTR_FLAG_OPTIONAL)) 1706 { 1707 return bgp_attr_malformed (args, 1708 BGP_NOTIFY_UPDATE_UNREC_ATTR, 1709 args->total); 1710 } 1711 1712 /* Unrecognized non-transitive optional attributes must be quietly 1713 ignored and not passed along to other BGP peers. */ 1714 if (! CHECK_FLAG (flag, BGP_ATTR_FLAG_TRANS)) 1715 return BGP_ATTR_PARSE_PROCEED; 1716 1717 /* If a path with recognized transitive optional attribute is 1718 accepted and passed along to other BGP peers and the Partial bit 1719 in the Attribute Flags octet is set to 1 by some previous AS, it 1720 is not set back to 0 by the current AS. */ 1721 SET_FLAG (*startp, BGP_ATTR_FLAG_PARTIAL); 1722 1723 /* Store transitive attribute to the end of attr->transit. */ 1724 if (! ((attre = bgp_attr_extra_get(attr))->transit) ) 1725 attre->transit = XCALLOC (MTYPE_TRANSIT, sizeof (struct transit)); 1726 1727 transit = attre->transit; 1728 1729 if (transit->val) 1730 transit->val = XREALLOC (MTYPE_TRANSIT_VAL, transit->val, 1731 transit->length + total); 1732 else 1733 transit->val = XMALLOC (MTYPE_TRANSIT_VAL, total); 1734 1735 memcpy (transit->val + transit->length, startp, total); 1736 transit->length += total; 1737 1738 return BGP_ATTR_PARSE_PROCEED; 1739} 1740 1741/* Well-known attribute check. */ 1742static int 1743bgp_attr_check (struct peer *peer, struct attr *attr) 1744{ 1745 u_char type = 0; 1746 1747 /* BGP Graceful-Restart End-of-RIB for IPv4 unicast is signaled as an 1748 * empty UPDATE. */ 1749 if (CHECK_FLAG (peer->cap, PEER_CAP_RESTART_RCV) && !attr->flag) 1750 return BGP_ATTR_PARSE_PROCEED; 1751 1752 /* "An UPDATE message that contains the MP_UNREACH_NLRI is not required 1753 to carry any other path attributes.", though if MP_REACH_NLRI or NLRI 1754 are present, it should. Check for any other attribute being present 1755 instead. 1756 */ 1757 if (attr->flag == ATTR_FLAG_BIT (BGP_ATTR_MP_UNREACH_NLRI)) 1758 return BGP_ATTR_PARSE_PROCEED; 1759 1760 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_ORIGIN))) 1761 type = BGP_ATTR_ORIGIN; 1762 1763 if (! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH))) 1764 type = BGP_ATTR_AS_PATH; 1765 1766 /* RFC 2858 makes Next-Hop optional/ignored, if MP_REACH_NLRI is present and 1767 * NLRI is empty. We can't easily check NLRI empty here though. 1768 */ 1769 if (!CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP)) 1770 && !CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_MP_REACH_NLRI))) 1771 type = BGP_ATTR_NEXT_HOP; 1772 1773 if (peer->sort == BGP_PEER_IBGP 1774 && ! CHECK_FLAG (attr->flag, ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF))) 1775 type = BGP_ATTR_LOCAL_PREF; 1776 1777 if (type) 1778 { 1779 zlog (peer->log, LOG_WARNING, 1780 "%s Missing well-known attribute %d / %s", 1781 peer->host, type, LOOKUP (attr_str, type)); 1782 bgp_notify_send_with_data (peer, 1783 BGP_NOTIFY_UPDATE_ERR, 1784 BGP_NOTIFY_UPDATE_MISS_ATTR, 1785 &type, 1); 1786 return BGP_ATTR_PARSE_ERROR; 1787 } 1788 return BGP_ATTR_PARSE_PROCEED; 1789} 1790 1791/* Read attribute of update packet. This function is called from 1792 bgp_update_receive() in bgp_packet.c. */ 1793bgp_attr_parse_ret_t 1794bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size, 1795 struct bgp_nlri *mp_update, struct bgp_nlri *mp_withdraw) 1796{ 1797 int ret; 1798 u_char flag = 0; 1799 u_char type = 0; 1800 bgp_size_t length; 1801 u_char *startp, *endp; 1802 u_char *attr_endp; 1803 u_char seen[BGP_ATTR_BITMAP_SIZE]; 1804 /* we need the as4_path only until we have synthesized the as_path with it */ 1805 /* same goes for as4_aggregator */ 1806 struct aspath *as4_path = NULL; 1807 as_t as4_aggregator = 0; 1808 struct in_addr as4_aggregator_addr = { 0 }; 1809 1810 /* Initialize bitmap. */ 1811 memset (seen, 0, BGP_ATTR_BITMAP_SIZE); 1812 1813 /* End pointer of BGP attribute. */ 1814 endp = BGP_INPUT_PNT (peer) + size; 1815 1816 /* Get attributes to the end of attribute length. */ 1817 while (BGP_INPUT_PNT (peer) < endp) 1818 { 1819 /* Check remaining length check.*/ 1820 if (endp - BGP_INPUT_PNT (peer) < BGP_ATTR_MIN_LEN) 1821 { 1822 /* XXX warning: long int format, int arg (arg 5) */ 1823 zlog (peer->log, LOG_WARNING, 1824 "%s: error BGP attribute length %lu is smaller than min len", 1825 peer->host, 1826 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer)))); 1827 1828 bgp_notify_send (peer, 1829 BGP_NOTIFY_UPDATE_ERR, 1830 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); 1831 return BGP_ATTR_PARSE_ERROR; 1832 } 1833 1834 /* Fetch attribute flag and type. */ 1835 startp = BGP_INPUT_PNT (peer); 1836 /* "The lower-order four bits of the Attribute Flags octet are 1837 unused. They MUST be zero when sent and MUST be ignored when 1838 received." */ 1839 flag = 0xF0 & stream_getc (BGP_INPUT (peer)); 1840 type = stream_getc (BGP_INPUT (peer)); 1841 1842 /* Check whether Extended-Length applies and is in bounds */ 1843 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN) 1844 && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1))) 1845 { 1846 zlog (peer->log, LOG_WARNING, 1847 "%s: Extended length set, but just %lu bytes of attr header", 1848 peer->host, 1849 (unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer)))); 1850 1851 bgp_notify_send (peer, 1852 BGP_NOTIFY_UPDATE_ERR, 1853 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); 1854 return BGP_ATTR_PARSE_ERROR; 1855 } 1856 1857 /* Check extended attribue length bit. */ 1858 if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)) 1859 length = stream_getw (BGP_INPUT (peer)); 1860 else 1861 length = stream_getc (BGP_INPUT (peer)); 1862 1863 /* If any attribute appears more than once in the UPDATE 1864 message, then the Error Subcode is set to Malformed Attribute 1865 List. */ 1866 1867 if (CHECK_BITMAP (seen, type)) 1868 { 1869 zlog (peer->log, LOG_WARNING, 1870 "%s: error BGP attribute type %d appears twice in a message", 1871 peer->host, type); 1872 1873 bgp_notify_send (peer, 1874 BGP_NOTIFY_UPDATE_ERR, 1875 BGP_NOTIFY_UPDATE_MAL_ATTR); 1876 return BGP_ATTR_PARSE_ERROR; 1877 } 1878 1879 /* Set type to bitmap to check duplicate attribute. `type' is 1880 unsigned char so it never overflow bitmap range. */ 1881 1882 SET_BITMAP (seen, type); 1883 1884 /* Overflow check. */ 1885 attr_endp = BGP_INPUT_PNT (peer) + length; 1886 1887 if (attr_endp > endp) 1888 { 1889 zlog (peer->log, LOG_WARNING, 1890 "%s: BGP type %d length %d is too large, attribute total length is %d. attr_endp is %p. endp is %p", peer->host, type, length, size, attr_endp, endp); 1891 bgp_notify_send (peer, 1892 BGP_NOTIFY_UPDATE_ERR, 1893 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); 1894 return BGP_ATTR_PARSE_ERROR; 1895 } 1896 1897 struct bgp_attr_parser_args attr_args = { 1898 .peer = peer, 1899 .length = length, 1900 .attr = attr, 1901 .type = type, 1902 .flags = flag, 1903 .startp = startp, 1904 .total = attr_endp - startp, 1905 }; 1906 1907 1908 /* If any recognized attribute has Attribute Flags that conflict 1909 with the Attribute Type Code, then the Error Subcode is set to 1910 Attribute Flags Error. The Data field contains the erroneous 1911 attribute (type, length and value). */ 1912 if (bgp_attr_flag_invalid (&attr_args)) 1913 { 1914 bgp_attr_parse_ret_t ret; 1915 ret = bgp_attr_malformed (&attr_args, 1916 BGP_NOTIFY_UPDATE_ATTR_FLAG_ERR, 1917 attr_args.total); 1918 if (ret == BGP_ATTR_PARSE_PROCEED) 1919 continue; 1920 return ret; 1921 } 1922 1923 /* OK check attribute and store it's value. */ 1924 switch (type) 1925 { 1926 case BGP_ATTR_ORIGIN: 1927 ret = bgp_attr_origin (&attr_args); 1928 break; 1929 case BGP_ATTR_AS_PATH: 1930 ret = bgp_attr_aspath (&attr_args); 1931 break; 1932 case BGP_ATTR_AS4_PATH: 1933 ret = bgp_attr_as4_path (&attr_args, &as4_path); 1934 break; 1935 case BGP_ATTR_NEXT_HOP: 1936 ret = bgp_attr_nexthop (&attr_args); 1937 break; 1938 case BGP_ATTR_MULTI_EXIT_DISC: 1939 ret = bgp_attr_med (&attr_args); 1940 break; 1941 case BGP_ATTR_LOCAL_PREF: 1942 ret = bgp_attr_local_pref (&attr_args); 1943 break; 1944 case BGP_ATTR_ATOMIC_AGGREGATE: 1945 ret = bgp_attr_atomic (&attr_args); 1946 break; 1947 case BGP_ATTR_AGGREGATOR: 1948 ret = bgp_attr_aggregator (&attr_args); 1949 break; 1950 case BGP_ATTR_AS4_AGGREGATOR: 1951 ret = bgp_attr_as4_aggregator (&attr_args, 1952 &as4_aggregator, 1953 &as4_aggregator_addr); 1954 break; 1955 case BGP_ATTR_COMMUNITIES: 1956 ret = bgp_attr_community (&attr_args); 1957 break; 1958 case BGP_ATTR_ORIGINATOR_ID: 1959 ret = bgp_attr_originator_id (&attr_args); 1960 break; 1961 case BGP_ATTR_CLUSTER_LIST: 1962 ret = bgp_attr_cluster_list (&attr_args); 1963 break; 1964 case BGP_ATTR_MP_REACH_NLRI: 1965 ret = bgp_mp_reach_parse (&attr_args, mp_update); 1966 break; 1967 case BGP_ATTR_MP_UNREACH_NLRI: 1968 ret = bgp_mp_unreach_parse (&attr_args, mp_withdraw); 1969 break; 1970 case BGP_ATTR_EXT_COMMUNITIES: 1971 ret = bgp_attr_ext_communities (&attr_args); 1972 break; 1973 default: 1974 ret = bgp_attr_unknown (&attr_args); 1975 break; 1976 } 1977 1978 if (ret == BGP_ATTR_PARSE_ERROR_NOTIFYPLS) 1979 { 1980 bgp_notify_send (peer, 1981 BGP_NOTIFY_UPDATE_ERR, 1982 BGP_NOTIFY_UPDATE_MAL_ATTR); 1983 ret = BGP_ATTR_PARSE_ERROR; 1984 } 1985 1986 /* If hard error occured immediately return to the caller. */ 1987 if (ret == BGP_ATTR_PARSE_ERROR) 1988 { 1989 zlog (peer->log, LOG_WARNING, 1990 "%s: Attribute %s, parse error", 1991 peer->host, 1992 LOOKUP (attr_str, type)); 1993 if (as4_path) 1994 aspath_unintern (&as4_path); 1995 return ret; 1996 } 1997 if (ret == BGP_ATTR_PARSE_WITHDRAW) 1998 { 1999 2000 zlog (peer->log, LOG_WARNING, 2001 "%s: Attribute %s, parse error - treating as withdrawal", 2002 peer->host, 2003 LOOKUP (attr_str, type)); 2004 if (as4_path) 2005 aspath_unintern (&as4_path); 2006 return ret; 2007 } 2008 2009 /* Check the fetched length. */ 2010 if (BGP_INPUT_PNT (peer) != attr_endp) 2011 { 2012 zlog (peer->log, LOG_WARNING, 2013 "%s: BGP attribute %s, fetch error", 2014 peer->host, LOOKUP (attr_str, type)); 2015 bgp_notify_send (peer, 2016 BGP_NOTIFY_UPDATE_ERR, 2017 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); 2018 if (as4_path) 2019 aspath_unintern (&as4_path); 2020 return BGP_ATTR_PARSE_ERROR; 2021 } 2022 } 2023 /* Check final read pointer is same as end pointer. */ 2024 if (BGP_INPUT_PNT (peer) != endp) 2025 { 2026 zlog (peer->log, LOG_WARNING, 2027 "%s: BGP attribute %s, length mismatch", 2028 peer->host, LOOKUP (attr_str, type)); 2029 bgp_notify_send (peer, 2030 BGP_NOTIFY_UPDATE_ERR, 2031 BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); 2032 if (as4_path) 2033 aspath_unintern (&as4_path); 2034 return BGP_ATTR_PARSE_ERROR; 2035 } 2036 2037 /* Check all mandatory well-known attributes are present */ 2038 { 2039 bgp_attr_parse_ret_t ret; 2040 if ((ret = bgp_attr_check (peer, attr)) < 0) 2041 { 2042 if (as4_path) 2043 aspath_unintern (&as4_path); 2044 return ret; 2045 } 2046 } 2047 2048 /* 2049 * At this place we can see whether we got AS4_PATH and/or 2050 * AS4_AGGREGATOR from a 16Bit peer and act accordingly. 2051 * We can not do this before we've read all attributes because 2052 * the as4 handling does not say whether AS4_PATH has to be sent 2053 * after AS_PATH or not - and when AS4_AGGREGATOR will be send 2054 * in relationship to AGGREGATOR. 2055 * So, to be defensive, we are not relying on any order and read 2056 * all attributes first, including these 32bit ones, and now, 2057 * afterwards, we look what and if something is to be done for as4. 2058 * 2059 * It is possible to not have AS_PATH, e.g. GR EoR and sole 2060 * MP_UNREACH_NLRI. 2061 */ 2062 /* actually... this doesn't ever return failure currently, but 2063 * better safe than sorry */ 2064 if (CHECK_FLAG(attr->flag, ATTR_FLAG_BIT (BGP_ATTR_AS_PATH)) 2065 && bgp_attr_munge_as4_attrs (peer, attr, as4_path, 2066 as4_aggregator, &as4_aggregator_addr)) 2067 { 2068 bgp_notify_send (peer, 2069 BGP_NOTIFY_UPDATE_ERR, 2070 BGP_NOTIFY_UPDATE_MAL_ATTR); 2071 if (as4_path) 2072 aspath_unintern (&as4_path); 2073 return BGP_ATTR_PARSE_ERROR; 2074 } 2075 2076 /* At this stage, we have done all fiddling with as4, and the 2077 * resulting info is in attr->aggregator resp. attr->aspath 2078 * so we can chuck as4_aggregator and as4_path alltogether in 2079 * order to save memory 2080 */ 2081 if (as4_path) 2082 { 2083 aspath_unintern (&as4_path); /* unintern - it is in the hash */ 2084 /* The flag that we got this is still there, but that does not 2085 * do any trouble 2086 */ 2087 } 2088 /* 2089 * The "rest" of the code does nothing with as4_aggregator. 2090 * there is no memory attached specifically which is not part 2091 * of the attr. 2092 * so ignoring just means do nothing. 2093 */ 2094 /* 2095 * Finally do the checks on the aspath we did not do yet 2096 * because we waited for a potentially synthesized aspath. 2097 */ 2098 if (attr->flag & (ATTR_FLAG_BIT(BGP_ATTR_AS_PATH))) 2099 { 2100 ret = bgp_attr_aspath_check (peer, attr); 2101 if (ret != BGP_ATTR_PARSE_PROCEED) 2102 return ret; 2103 } 2104 2105 /* Finally intern unknown attribute. */ 2106 if (attr->extra && attr->extra->transit) 2107 attr->extra->transit = transit_intern (attr->extra->transit); 2108 2109 return BGP_ATTR_PARSE_PROCEED; 2110} 2111 2112int stream_put_prefix (struct stream *, struct prefix *); 2113 2114size_t 2115bgp_packet_mpattr_start (struct stream *s, afi_t afi, safi_t safi, 2116 struct attr *attr) 2117{ 2118 size_t sizep; 2119 2120 /* Set extended bit always to encode the attribute length as 2 bytes */ 2121 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN); 2122 stream_putc (s, BGP_ATTR_MP_REACH_NLRI); 2123 sizep = stream_get_endp (s); 2124 stream_putw (s, 0); /* Marker: Attribute length. */ 2125 stream_putw (s, afi); /* AFI */ 2126 stream_putc (s, safi); /* SAFI */ 2127 2128 /* Nexthop */ 2129 switch (afi) 2130 { 2131 case AFI_IP: 2132 switch (safi) 2133 { 2134 case SAFI_UNICAST: 2135 case SAFI_MULTICAST: 2136 stream_putc (s, 4); 2137 stream_put_ipv4 (s, attr->nexthop.s_addr); 2138 break; 2139 case SAFI_MPLS_VPN: 2140 stream_putc (s, 12); 2141 stream_putl (s, 0); 2142 stream_putl (s, 0); 2143 stream_put (s, &attr->extra->mp_nexthop_global_in, 4); 2144 break; 2145 default: 2146 break; 2147 } 2148 break; 2149#ifdef HAVE_IPV6 2150 case AFI_IP6: 2151 switch (safi) 2152 { 2153 case SAFI_UNICAST: 2154 case SAFI_MULTICAST: 2155 { 2156 struct attr_extra *attre = attr->extra; 2157 2158 assert (attr->extra); 2159 stream_putc (s, attre->mp_nexthop_len); 2160 stream_put (s, &attre->mp_nexthop_global, 16); 2161 if (attre->mp_nexthop_len == 32) 2162 stream_put (s, &attre->mp_nexthop_local, 16); 2163 } 2164 default: 2165 break; 2166 } 2167 break; 2168#endif /*HAVE_IPV6*/ 2169 default: 2170 break; 2171 } 2172 2173 /* SNPA */ 2174 stream_putc (s, 0); 2175 return sizep; 2176} 2177 2178void 2179bgp_packet_mpattr_prefix (struct stream *s, afi_t afi, safi_t safi, 2180 struct prefix *p, struct prefix_rd *prd, 2181 u_char *tag) 2182{ 2183 switch (safi) 2184 { 2185 case SAFI_MPLS_VPN: 2186 /* Tag, RD, Prefix write. */ 2187 stream_putc (s, p->prefixlen + 88); 2188 stream_put (s, tag, 3); 2189 stream_put (s, prd->val, 8); 2190 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen)); 2191 break; 2192 default: 2193 /* Prefix write. */ 2194 stream_put_prefix (s, p); 2195 break; 2196 } 2197} 2198 2199void 2200bgp_packet_mpattr_end (struct stream *s, size_t sizep) 2201{ 2202 /* Set MP attribute length. Don't count the (2) bytes used to encode 2203 the attr length */ 2204 stream_putw_at (s, sizep, (stream_get_endp (s) - sizep) - 2); 2205} 2206 2207/* Make attribute packet. */ 2208bgp_size_t 2209bgp_packet_attribute (struct bgp *bgp, struct peer *peer, 2210 struct stream *s, struct attr *attr, 2211 struct prefix *p, afi_t afi, safi_t safi, 2212 struct peer *from, struct prefix_rd *prd, u_char *tag) 2213{ 2214 size_t cp; 2215 size_t aspath_sizep; 2216 struct aspath *aspath; 2217 int send_as4_path = 0; 2218 int send_as4_aggregator = 0; 2219 int use32bit = (CHECK_FLAG (peer->cap, PEER_CAP_AS4_RCV)) ? 1 : 0; 2220 size_t mpattrlen_pos = 0; 2221 2222 if (! bgp) 2223 bgp = bgp_get_default (); 2224 2225 /* Remember current pointer. */ 2226 cp = stream_get_endp (s); 2227 2228 if (p && !(afi == AFI_IP && safi == SAFI_UNICAST)) 2229 { 2230 mpattrlen_pos = bgp_packet_mpattr_start(s, afi, safi, attr); 2231 bgp_packet_mpattr_prefix(s, afi, safi, p, prd, tag); 2232 bgp_packet_mpattr_end(s, mpattrlen_pos); 2233 } 2234 2235 /* Origin attribute. */ 2236 stream_putc (s, BGP_ATTR_FLAG_TRANS); 2237 stream_putc (s, BGP_ATTR_ORIGIN); 2238 stream_putc (s, 1); 2239 stream_putc (s, attr->origin); 2240 2241 /* AS path attribute. */ 2242 2243 /* If remote-peer is EBGP */ 2244 if (peer->sort == BGP_PEER_EBGP 2245 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_AS_PATH_UNCHANGED) 2246 || attr->aspath->segments == NULL) 2247 && (! CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_RSERVER_CLIENT))) 2248 { 2249 aspath = aspath_dup (attr->aspath); 2250 2251 if (CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) 2252 { 2253 /* Strip the confed info, and then stuff our path CONFED_ID 2254 on the front */ 2255 aspath = aspath_delete_confed_seq (aspath); 2256 aspath = aspath_add_seq (aspath, bgp->confed_id); 2257 } 2258 else 2259 { 2260 if (peer->change_local_as) { 2261 /* If replace-as is specified, we only use the change_local_as when 2262 advertising routes. */ 2263 if( ! CHECK_FLAG (peer->flags, PEER_FLAG_LOCAL_AS_REPLACE_AS) ) { 2264 aspath = aspath_add_seq (aspath, peer->local_as); 2265 } 2266 aspath = aspath_add_seq (aspath, peer->change_local_as); 2267 } else { 2268 aspath = aspath_add_seq (aspath, peer->local_as); 2269 } 2270 } 2271 } 2272 else if (peer->sort == BGP_PEER_CONFED) 2273 { 2274 /* A confed member, so we need to do the AS_CONFED_SEQUENCE thing */ 2275 aspath = aspath_dup (attr->aspath); 2276 aspath = aspath_add_confed_seq (aspath, peer->local_as); 2277 } 2278 else 2279 aspath = attr->aspath; 2280 2281 /* If peer is not AS4 capable, then: 2282 * - send the created AS_PATH out as AS4_PATH (optional, transitive), 2283 * but ensure that no AS_CONFED_SEQUENCE and AS_CONFED_SET path segment 2284 * types are in it (i.e. exclude them if they are there) 2285 * AND do this only if there is at least one asnum > 65535 in the path! 2286 * - send an AS_PATH out, but put 16Bit ASnums in it, not 32bit, and change 2287 * all ASnums > 65535 to BGP_AS_TRANS 2288 */ 2289 2290 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN); 2291 stream_putc (s, BGP_ATTR_AS_PATH); 2292 aspath_sizep = stream_get_endp (s); 2293 stream_putw (s, 0); 2294 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, use32bit)); 2295 2296 /* OLD session may need NEW_AS_PATH sent, if there are 4-byte ASNs 2297 * in the path 2298 */ 2299 if (!use32bit && aspath_has_as4 (aspath)) 2300 send_as4_path = 1; /* we'll do this later, at the correct place */ 2301 2302 /* Nexthop attribute. */ 2303 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP) 2304 { 2305 stream_putc (s, BGP_ATTR_FLAG_TRANS); 2306 stream_putc (s, BGP_ATTR_NEXT_HOP); 2307 stream_putc (s, 4); 2308 if (safi == SAFI_MPLS_VPN) 2309 { 2310 if (attr->nexthop.s_addr == 0) 2311 stream_put_ipv4 (s, peer->nexthop.v4.s_addr); 2312 else 2313 stream_put_ipv4 (s, attr->nexthop.s_addr); 2314 } 2315 else 2316 stream_put_ipv4 (s, attr->nexthop.s_addr); 2317 } 2318 2319 /* MED attribute. */ 2320 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) 2321 { 2322 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL); 2323 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC); 2324 stream_putc (s, 4); 2325 stream_putl (s, attr->med); 2326 } 2327 2328 /* Local preference. */ 2329 if (peer->sort == BGP_PEER_IBGP || 2330 peer->sort == BGP_PEER_CONFED) 2331 { 2332 stream_putc (s, BGP_ATTR_FLAG_TRANS); 2333 stream_putc (s, BGP_ATTR_LOCAL_PREF); 2334 stream_putc (s, 4); 2335 stream_putl (s, attr->local_pref); 2336 } 2337 2338 /* Atomic aggregate. */ 2339 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE)) 2340 { 2341 stream_putc (s, BGP_ATTR_FLAG_TRANS); 2342 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE); 2343 stream_putc (s, 0); 2344 } 2345 2346 /* Aggregator. */ 2347 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR)) 2348 { 2349 assert (attr->extra); 2350 2351 /* Common to BGP_ATTR_AGGREGATOR, regardless of ASN size */ 2352 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); 2353 stream_putc (s, BGP_ATTR_AGGREGATOR); 2354 2355 if (use32bit) 2356 { 2357 /* AS4 capable peer */ 2358 stream_putc (s, 8); 2359 stream_putl (s, attr->extra->aggregator_as); 2360 } 2361 else 2362 { 2363 /* 2-byte AS peer */ 2364 stream_putc (s, 6); 2365 2366 /* Is ASN representable in 2-bytes? Or must AS_TRANS be used? */ 2367 if ( attr->extra->aggregator_as > 65535 ) 2368 { 2369 stream_putw (s, BGP_AS_TRANS); 2370 2371 /* we have to send AS4_AGGREGATOR, too. 2372 * we'll do that later in order to send attributes in ascending 2373 * order. 2374 */ 2375 send_as4_aggregator = 1; 2376 } 2377 else 2378 stream_putw (s, (u_int16_t) attr->extra->aggregator_as); 2379 } 2380 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr); 2381 } 2382 2383 /* Community attribute. */ 2384 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY) 2385 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))) 2386 { 2387 if (attr->community->size * 4 > 255) 2388 { 2389 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN); 2390 stream_putc (s, BGP_ATTR_COMMUNITIES); 2391 stream_putw (s, attr->community->size * 4); 2392 } 2393 else 2394 { 2395 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); 2396 stream_putc (s, BGP_ATTR_COMMUNITIES); 2397 stream_putc (s, attr->community->size * 4); 2398 } 2399 stream_put (s, attr->community->val, attr->community->size * 4); 2400 } 2401 2402 /* Route Reflector. */ 2403 if (peer->sort == BGP_PEER_IBGP 2404 && from 2405 && from->sort == BGP_PEER_IBGP) 2406 { 2407 /* Originator ID. */ 2408 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL); 2409 stream_putc (s, BGP_ATTR_ORIGINATOR_ID); 2410 stream_putc (s, 4); 2411 2412 if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) 2413 stream_put_in_addr (s, &attr->extra->originator_id); 2414 else 2415 stream_put_in_addr (s, &from->remote_id); 2416 2417 /* Cluster list. */ 2418 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL); 2419 stream_putc (s, BGP_ATTR_CLUSTER_LIST); 2420 2421 if (attr->extra && attr->extra->cluster) 2422 { 2423 stream_putc (s, attr->extra->cluster->length + 4); 2424 /* If this peer configuration's parent BGP has cluster_id. */ 2425 if (bgp->config & BGP_CONFIG_CLUSTER_ID) 2426 stream_put_in_addr (s, &bgp->cluster_id); 2427 else 2428 stream_put_in_addr (s, &bgp->router_id); 2429 stream_put (s, attr->extra->cluster->list, 2430 attr->extra->cluster->length); 2431 } 2432 else 2433 { 2434 stream_putc (s, 4); 2435 /* If this peer configuration's parent BGP has cluster_id. */ 2436 if (bgp->config & BGP_CONFIG_CLUSTER_ID) 2437 stream_put_in_addr (s, &bgp->cluster_id); 2438 else 2439 stream_put_in_addr (s, &bgp->router_id); 2440 } 2441 } 2442 2443 /* Extended Communities attribute. */ 2444 if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY) 2445 && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES))) 2446 { 2447 struct attr_extra *attre = attr->extra; 2448 2449 assert (attre); 2450 2451 if (peer->sort == BGP_PEER_IBGP 2452 || peer->sort == BGP_PEER_CONFED) 2453 { 2454 if (attre->ecommunity->size * 8 > 255) 2455 { 2456 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN); 2457 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES); 2458 stream_putw (s, attre->ecommunity->size * 8); 2459 } 2460 else 2461 { 2462 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); 2463 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES); 2464 stream_putc (s, attre->ecommunity->size * 8); 2465 } 2466 stream_put (s, attre->ecommunity->val, attre->ecommunity->size * 8); 2467 } 2468 else 2469 { 2470 u_int8_t *pnt; 2471 int tbit; 2472 int ecom_tr_size = 0; 2473 int i; 2474 2475 for (i = 0; i < attre->ecommunity->size; i++) 2476 { 2477 pnt = attre->ecommunity->val + (i * 8); 2478 tbit = *pnt; 2479 2480 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE)) 2481 continue; 2482 2483 ecom_tr_size++; 2484 } 2485 2486 if (ecom_tr_size) 2487 { 2488 if (ecom_tr_size * 8 > 255) 2489 { 2490 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN); 2491 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES); 2492 stream_putw (s, ecom_tr_size * 8); 2493 } 2494 else 2495 { 2496 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); 2497 stream_putc (s, BGP_ATTR_EXT_COMMUNITIES); 2498 stream_putc (s, ecom_tr_size * 8); 2499 } 2500 2501 for (i = 0; i < attre->ecommunity->size; i++) 2502 { 2503 pnt = attre->ecommunity->val + (i * 8); 2504 tbit = *pnt; 2505 2506 if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE)) 2507 continue; 2508 2509 stream_put (s, pnt, 8); 2510 } 2511 } 2512 } 2513 } 2514 2515 if ( send_as4_path ) 2516 { 2517 /* If the peer is NOT As4 capable, AND */ 2518 /* there are ASnums > 65535 in path THEN 2519 * give out AS4_PATH */ 2520 2521 /* Get rid of all AS_CONFED_SEQUENCE and AS_CONFED_SET 2522 * path segments! 2523 * Hm, I wonder... confederation things *should* only be at 2524 * the beginning of an aspath, right? Then we should use 2525 * aspath_delete_confed_seq for this, because it is already 2526 * there! (JK) 2527 * Folks, talk to me: what is reasonable here!? 2528 */ 2529 aspath = aspath_delete_confed_seq (aspath); 2530 2531 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN); 2532 stream_putc (s, BGP_ATTR_AS4_PATH); 2533 aspath_sizep = stream_get_endp (s); 2534 stream_putw (s, 0); 2535 stream_putw_at (s, aspath_sizep, aspath_put (s, aspath, 1)); 2536 } 2537 2538 if (aspath != attr->aspath) 2539 aspath_free (aspath); 2540 2541 if ( send_as4_aggregator ) 2542 { 2543 assert (attr->extra); 2544 2545 /* send AS4_AGGREGATOR, at this place */ 2546 /* this section of code moved here in order to ensure the correct 2547 * *ascending* order of attributes 2548 */ 2549 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); 2550 stream_putc (s, BGP_ATTR_AS4_AGGREGATOR); 2551 stream_putc (s, 8); 2552 stream_putl (s, attr->extra->aggregator_as); 2553 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr); 2554 } 2555 2556 /* Unknown transit attribute. */ 2557 if (attr->extra && attr->extra->transit) 2558 stream_put (s, attr->extra->transit->val, attr->extra->transit->length); 2559 2560 /* Return total size of attribute. */ 2561 return stream_get_endp (s) - cp; 2562} 2563 2564size_t 2565bgp_packet_mpunreach_start (struct stream *s, afi_t afi, safi_t safi) 2566{ 2567 unsigned long attrlen_pnt; 2568 2569 /* Set extended bit always to encode the attribute length as 2 bytes */ 2570 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_EXTLEN); 2571 stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI); 2572 2573 attrlen_pnt = stream_get_endp (s); 2574 stream_putw (s, 0); /* Length of this attribute. */ 2575 2576 stream_putw (s, afi); 2577 safi = (safi == SAFI_MPLS_VPN) ? SAFI_MPLS_LABELED_VPN : safi; 2578 stream_putc (s, safi); 2579 return attrlen_pnt; 2580} 2581 2582void 2583bgp_packet_mpunreach_prefix (struct stream *s, struct prefix *p, 2584 afi_t afi, safi_t safi, struct prefix_rd *prd, 2585 u_char *tag) 2586{ 2587 if (safi == SAFI_MPLS_VPN) 2588 { 2589 stream_putc (s, p->prefixlen + 88); 2590 stream_put (s, tag, 3); 2591 stream_put (s, prd->val, 8); 2592 stream_put (s, &p->u.prefix, PSIZE (p->prefixlen)); 2593 } 2594 else 2595 stream_put_prefix (s, p); 2596} 2597 2598void 2599bgp_packet_mpunreach_end (struct stream *s, size_t attrlen_pnt) 2600{ 2601 bgp_size_t size; 2602 2603 /* Set MP attribute length. Don't count the (2) bytes used to encode 2604 the attr length */ 2605 size = stream_get_endp (s) - attrlen_pnt - 2; 2606 stream_putw_at (s, attrlen_pnt, size); 2607} 2608 2609/* Initialization of attribute. */ 2610void 2611bgp_attr_init (void) 2612{ 2613 aspath_init (); 2614 attrhash_init (); 2615 community_init (); 2616 ecommunity_init (); 2617 cluster_init (); 2618 transit_init (); 2619} 2620 2621void 2622bgp_attr_finish (void) 2623{ 2624 aspath_finish (); 2625 attrhash_finish (); 2626 community_finish (); 2627 ecommunity_finish (); 2628 cluster_finish (); 2629 transit_finish (); 2630} 2631 2632/* Make attribute packet. */ 2633void 2634bgp_dump_routes_attr (struct stream *s, struct attr *attr, 2635 struct prefix *prefix) 2636{ 2637 unsigned long cp; 2638 unsigned long len; 2639 size_t aspath_lenp; 2640 struct aspath *aspath; 2641 2642 /* Remember current pointer. */ 2643 cp = stream_get_endp (s); 2644 2645 /* Place holder of length. */ 2646 stream_putw (s, 0); 2647 2648 /* Origin attribute. */ 2649 stream_putc (s, BGP_ATTR_FLAG_TRANS); 2650 stream_putc (s, BGP_ATTR_ORIGIN); 2651 stream_putc (s, 1); 2652 stream_putc (s, attr->origin); 2653 2654 aspath = attr->aspath; 2655 2656 stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN); 2657 stream_putc (s, BGP_ATTR_AS_PATH); 2658 aspath_lenp = stream_get_endp (s); 2659 stream_putw (s, 0); 2660 2661 stream_putw_at (s, aspath_lenp, aspath_put (s, aspath, 1)); 2662 2663 /* Nexthop attribute. */ 2664 /* If it's an IPv6 prefix, don't dump the IPv4 nexthop to save space */ 2665 if(prefix != NULL 2666#ifdef HAVE_IPV6 2667 && prefix->family != AF_INET6 2668#endif /* HAVE_IPV6 */ 2669 ) 2670 { 2671 stream_putc (s, BGP_ATTR_FLAG_TRANS); 2672 stream_putc (s, BGP_ATTR_NEXT_HOP); 2673 stream_putc (s, 4); 2674 stream_put_ipv4 (s, attr->nexthop.s_addr); 2675 } 2676 2677 /* MED attribute. */ 2678 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) 2679 { 2680 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL); 2681 stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC); 2682 stream_putc (s, 4); 2683 stream_putl (s, attr->med); 2684 } 2685 2686 /* Local preference. */ 2687 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)) 2688 { 2689 stream_putc (s, BGP_ATTR_FLAG_TRANS); 2690 stream_putc (s, BGP_ATTR_LOCAL_PREF); 2691 stream_putc (s, 4); 2692 stream_putl (s, attr->local_pref); 2693 } 2694 2695 /* Atomic aggregate. */ 2696 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE)) 2697 { 2698 stream_putc (s, BGP_ATTR_FLAG_TRANS); 2699 stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE); 2700 stream_putc (s, 0); 2701 } 2702 2703 /* Aggregator. */ 2704 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR)) 2705 { 2706 assert (attr->extra); 2707 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); 2708 stream_putc (s, BGP_ATTR_AGGREGATOR); 2709 stream_putc (s, 8); 2710 stream_putl (s, attr->extra->aggregator_as); 2711 stream_put_ipv4 (s, attr->extra->aggregator_addr.s_addr); 2712 } 2713 2714 /* Community attribute. */ 2715 if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)) 2716 { 2717 if (attr->community->size * 4 > 255) 2718 { 2719 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN); 2720 stream_putc (s, BGP_ATTR_COMMUNITIES); 2721 stream_putw (s, attr->community->size * 4); 2722 } 2723 else 2724 { 2725 stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); 2726 stream_putc (s, BGP_ATTR_COMMUNITIES); 2727 stream_putc (s, attr->community->size * 4); 2728 } 2729 stream_put (s, attr->community->val, attr->community->size * 4); 2730 } 2731 2732#ifdef HAVE_IPV6 2733 /* Add a MP_NLRI attribute to dump the IPv6 next hop */ 2734 if (prefix != NULL && prefix->family == AF_INET6 && attr->extra && 2735 (attr->extra->mp_nexthop_len == 16 || attr->extra->mp_nexthop_len == 32) ) 2736 { 2737 int sizep; 2738 struct attr_extra *attre = attr->extra; 2739 2740 stream_putc(s, BGP_ATTR_FLAG_OPTIONAL); 2741 stream_putc(s, BGP_ATTR_MP_REACH_NLRI); 2742 sizep = stream_get_endp (s); 2743 2744 /* MP header */ 2745 stream_putc (s, 0); /* Marker: Attribute length. */ 2746 stream_putw(s, AFI_IP6); /* AFI */ 2747 stream_putc(s, SAFI_UNICAST); /* SAFI */ 2748 2749 /* Next hop */ 2750 stream_putc(s, attre->mp_nexthop_len); 2751 stream_put(s, &attre->mp_nexthop_global, 16); 2752 if (attre->mp_nexthop_len == 32) 2753 stream_put(s, &attre->mp_nexthop_local, 16); 2754 2755 /* SNPA */ 2756 stream_putc(s, 0); 2757 2758 /* Prefix */ 2759 stream_put_prefix(s, prefix); 2760 2761 /* Set MP attribute length. */ 2762 stream_putc_at (s, sizep, (stream_get_endp (s) - sizep) - 1); 2763 } 2764#endif /* HAVE_IPV6 */ 2765 2766 /* Return total size of attribute. */ 2767 len = stream_get_endp (s) - cp - 2; 2768 stream_putw_at (s, cp, len); 2769} 2770