📄 bgp_attr.c
字号:
/* AS path attribute extended length bit check. */ if (aspath->length > 255) { stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN); stream_putc (s, BGP_ATTR_AS_PATH); stream_putw (s, aspath->length); } else { stream_putc (s, BGP_ATTR_FLAG_TRANS); stream_putc(s, BGP_ATTR_AS_PATH); stream_putc (s, aspath->length); } stream_put (s, aspath->data, aspath->length); if (aspath != attr->aspath) aspath_free (aspath); /* Nexthop attribute. */ if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_NEXT_HOP) && afi == AFI_IP) { stream_putc (s, BGP_ATTR_FLAG_TRANS); stream_putc (s, BGP_ATTR_NEXT_HOP); stream_putc (s, 4); if (safi == SAFI_MPLS_VPN) { if (attr->nexthop.s_addr == 0) stream_put_ipv4 (s, peer->nexthop.v4.s_addr); else stream_put_ipv4 (s, attr->nexthop.s_addr); } else stream_put_ipv4 (s, attr->nexthop.s_addr); } /* MED attribute. */ if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) { stream_putc (s, BGP_ATTR_FLAG_OPTIONAL); stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC); stream_putc (s, 4); stream_putl (s, attr->med); } /* Local preference. */ if (peer_sort (peer) == BGP_PEER_IBGP || peer_sort (peer) == BGP_PEER_CONFED) { stream_putc (s, BGP_ATTR_FLAG_TRANS); stream_putc (s, BGP_ATTR_LOCAL_PREF); stream_putc (s, 4); stream_putl (s, attr->local_pref); } /* Atomic aggregate. */ if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE)) { stream_putc (s, BGP_ATTR_FLAG_TRANS); stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE); stream_putc (s, 0); } /* Aggregator. */ if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR)) { stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); stream_putc (s, BGP_ATTR_AGGREGATOR); stream_putc (s, 6); stream_putw (s, attr->aggregator_as); stream_put_ipv4 (s, attr->aggregator_addr.s_addr); } /* Community attribute. */ if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_COMMUNITY) && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES))) { if (attr->community->size * 4 > 255) { stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN); stream_putc (s, BGP_ATTR_COMMUNITIES); stream_putw (s, attr->community->size * 4); } else { stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); stream_putc (s, BGP_ATTR_COMMUNITIES); stream_putc (s, attr->community->size * 4); } stream_put (s, attr->community->val, attr->community->size * 4); } /* Route Reflector. */ if (peer_sort (peer) == BGP_PEER_IBGP && from && peer_sort (from) == BGP_PEER_IBGP) { /* Originator ID. */ stream_putc (s, BGP_ATTR_FLAG_OPTIONAL); stream_putc (s, BGP_ATTR_ORIGINATOR_ID); stream_putc (s, 4); if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_ORIGINATOR_ID)) stream_put_in_addr (s, &attr->originator_id); else { if (from) stream_put_in_addr (s, &from->remote_id); else stream_put_in_addr (s, &attr->originator_id); } /* Cluster list. */ stream_putc (s, BGP_ATTR_FLAG_OPTIONAL); stream_putc (s, BGP_ATTR_CLUSTER_LIST); if (attr->cluster) { stream_putc (s, attr->cluster->length + 4); /* If this peer configuration's parent BGP has cluster_id. */ if (bgp->config & BGP_CONFIG_CLUSTER_ID) stream_put_in_addr (s, &bgp->cluster_id); else stream_put_in_addr (s, &bgp->router_id); stream_put (s, attr->cluster->list, attr->cluster->length); } else { stream_putc (s, 4); /* If this peer configuration's parent BGP has cluster_id. */ if (bgp->config & BGP_CONFIG_CLUSTER_ID) stream_put_in_addr (s, &bgp->cluster_id); else stream_put_in_addr (s, &bgp->router_id); } }#ifdef HAVE_IPV6 /* If p is IPv6 address put it into attribute. */ if (p->family == AF_INET6) { unsigned long sizep; stream_putc (s, BGP_ATTR_FLAG_OPTIONAL); stream_putc (s, BGP_ATTR_MP_REACH_NLRI); sizep = stream_get_putp (s); stream_putc (s, 0); /* Length of this attribute. */ stream_putw (s, AFI_IP6); /* AFI */ stream_putc (s, safi); /* SAFI */ stream_putc (s, attr->mp_nexthop_len); if (attr->mp_nexthop_len == 16) stream_put (s, &attr->mp_nexthop_global, 16); else if (attr->mp_nexthop_len == 32) { stream_put (s, &attr->mp_nexthop_global, 16); stream_put (s, &attr->mp_nexthop_local, 16); } /* SNPA */ stream_putc (s, 0); /* Prefix write. */ stream_put_prefix (s, p); /* Set MP attribute length. */ stream_putc_at (s, sizep, (stream_get_putp (s) - sizep) - 1); }#endif /* HAVE_IPV6 */ if (p->family == AF_INET && safi == SAFI_MULTICAST) { unsigned long sizep; stream_putc (s, BGP_ATTR_FLAG_OPTIONAL); stream_putc (s, BGP_ATTR_MP_REACH_NLRI); sizep = stream_get_putp (s); stream_putc (s, 0); /* Length of this attribute. */ stream_putw (s, AFI_IP); /* AFI */ stream_putc (s, SAFI_MULTICAST); /* SAFI */ stream_putc (s, 4); stream_put_ipv4 (s, attr->nexthop.s_addr); /* SNPA */ stream_putc (s, 0); /* Prefix write. */ stream_put_prefix (s, p); /* Set MP attribute length. */ stream_putc_at (s, sizep, (stream_get_putp (s) - sizep) - 1); } if (p->family == AF_INET && safi == SAFI_MPLS_VPN) { unsigned long sizep; stream_putc (s, BGP_ATTR_FLAG_OPTIONAL); stream_putc (s, BGP_ATTR_MP_REACH_NLRI); sizep = stream_get_putp (s); stream_putc (s, 0); /* Length of this attribute. */ stream_putw (s, AFI_IP); /* AFI */ stream_putc (s, BGP_SAFI_VPNV4); /* SAFI */ stream_putc (s, 12); stream_putl (s, 0); stream_putl (s, 0); stream_put (s, &attr->mp_nexthop_global_in, 4); /* SNPA */ stream_putc (s, 0); /* Tag, RD, Prefix write. */ stream_putc (s, p->prefixlen + 88); stream_put (s, tag, 3); stream_put (s, prd->val, 8); stream_put (s, &p->u.prefix, PSIZE (p->prefixlen)); /* Set MP attribute length. */ stream_putc_at (s, sizep, (stream_get_putp (s) - sizep) - 1); } /* Extended Communities attribute. */ if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY) && (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_EXT_COMMUNITIES))) { if (peer_sort (peer) == BGP_PEER_IBGP || peer_sort (peer) == BGP_PEER_CONFED) { if (attr->ecommunity->size * 8 > 255) { stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN); stream_putc (s, BGP_ATTR_EXT_COMMUNITIES); stream_putw (s, attr->ecommunity->size * 8); } else { stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); stream_putc (s, BGP_ATTR_EXT_COMMUNITIES); stream_putc (s, attr->ecommunity->size * 8); } stream_put (s, attr->ecommunity->val, attr->ecommunity->size * 8); } else { u_char *pnt; int tbit; int ecom_tr_size = 0; int i; for (i = 0; i < attr->ecommunity->size; i++) { pnt = attr->ecommunity->val + (i * 8); tbit = *pnt; if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE)) continue; ecom_tr_size++; } if (ecom_tr_size) { if (ecom_tr_size * 8 > 255) { stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN); stream_putc (s, BGP_ATTR_EXT_COMMUNITIES); stream_putw (s, ecom_tr_size * 8); } else { stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); stream_putc (s, BGP_ATTR_EXT_COMMUNITIES); stream_putc (s, ecom_tr_size * 8); } for (i = 0; i < attr->ecommunity->size; i++) { pnt = attr->ecommunity->val + (i * 8); tbit = *pnt; if (CHECK_FLAG (tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE)) continue; stream_put (s, pnt, 8); } } } } /* Unknown transit attribute. */ if (attr->transit) stream_put (s, attr->transit->val, attr->transit->length); /* Return total size of attribute. */ return stream_get_putp (s) - cp;}bgp_size_tbgp_packet_withdraw (struct peer *peer, struct stream *s, struct prefix *p, afi_t afi, safi_t safi, struct prefix_rd *prd, u_char *tag){ unsigned long cp; unsigned long attrlen_pnt; bgp_size_t size; cp = stream_get_putp (s); stream_putc (s, BGP_ATTR_FLAG_OPTIONAL); stream_putc (s, BGP_ATTR_MP_UNREACH_NLRI); attrlen_pnt = stream_get_putp (s); stream_putc (s, 0); /* Length of this attribute. */ stream_putw (s, family2afi (p->family)); if (safi == SAFI_MPLS_VPN) { /* SAFI */ stream_putc (s, BGP_SAFI_VPNV4); /* prefix. */ stream_putc (s, p->prefixlen + 88); stream_put (s, tag, 3); stream_put (s, prd->val, 8); stream_put (s, &p->u.prefix, PSIZE (p->prefixlen)); } else { /* SAFI */ stream_putc (s, safi); /* prefix */ stream_put_prefix (s, p); } /* Set MP attribute length. */ size = stream_get_putp (s) - attrlen_pnt - 1; stream_putc_at (s, attrlen_pnt, size); return stream_get_putp (s) - cp;}/* Initialization of attribute. */voidbgp_attr_init (){ void attrhash_init (); aspath_init (); attrhash_init (); community_init (); ecommunity_init (); cluster_init (); transit_init ();}/* Make attribute packet. */voidbgp_dump_routes_attr (struct stream *s, struct attr *attr){ unsigned long cp; unsigned long len; struct aspath *aspath; /* Remember current pointer. */ cp = stream_get_putp (s); /* Place holder of length. */ stream_putw (s, 0); /* Origin attribute. */ stream_putc (s, BGP_ATTR_FLAG_TRANS); stream_putc (s, BGP_ATTR_ORIGIN); stream_putc (s, 1); stream_putc (s, attr->origin); aspath = attr->aspath; if (aspath->length > 255) { stream_putc (s, BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN); stream_putc (s, BGP_ATTR_AS_PATH); stream_putw (s, aspath->length); } else { stream_putc (s, BGP_ATTR_FLAG_TRANS); stream_putc (s, BGP_ATTR_AS_PATH); stream_putc (s, aspath->length); } stream_put (s, aspath->data, aspath->length); /* Nexthop attribute. */ stream_putc (s, BGP_ATTR_FLAG_TRANS); stream_putc (s, BGP_ATTR_NEXT_HOP); stream_putc (s, 4); stream_put_ipv4 (s, attr->nexthop.s_addr); /* MED attribute. */ if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_MULTI_EXIT_DISC)) { stream_putc (s, BGP_ATTR_FLAG_OPTIONAL); stream_putc (s, BGP_ATTR_MULTI_EXIT_DISC); stream_putc (s, 4); stream_putl (s, attr->med); } /* Local preference. */ if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_LOCAL_PREF)) { stream_putc (s, BGP_ATTR_FLAG_TRANS); stream_putc (s, BGP_ATTR_LOCAL_PREF); stream_putc (s, 4); stream_putl (s, attr->local_pref); } /* Atomic aggregate. */ if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_ATOMIC_AGGREGATE)) { stream_putc (s, BGP_ATTR_FLAG_TRANS); stream_putc (s, BGP_ATTR_ATOMIC_AGGREGATE); stream_putc (s, 0); } /* Aggregator. */ if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR)) { stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); stream_putc (s, BGP_ATTR_AGGREGATOR); stream_putc (s, 6); stream_putw (s, attr->aggregator_as); stream_put_ipv4 (s, attr->aggregator_addr.s_addr); } /* Community attribute. */ if (attr->flag & ATTR_FLAG_BIT (BGP_ATTR_COMMUNITIES)) { if (attr->community->size * 4 > 255) { stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS|BGP_ATTR_FLAG_EXTLEN); stream_putc (s, BGP_ATTR_COMMUNITIES); stream_putw (s, attr->community->size * 4); } else { stream_putc (s, BGP_ATTR_FLAG_OPTIONAL|BGP_ATTR_FLAG_TRANS); stream_putc (s, BGP_ATTR_COMMUNITIES); stream_putc (s, attr->community->size * 4); } stream_put (s, attr->community->val, attr->community->size * 4); } /* Return total size of attribute. */ len = stream_get_putp (s) - cp - 2; stream_putw_at (s, cp, len);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -