📄 bgp_output.c
字号:
case RTPROTO_IF: case RTPROTO_RIP: origin = PATH_ORG_IGP; break; case RTPROTO_BGP: if (rtp->rtp_bgp->rp_mode & BGPO_IGP) { if (rte->rt_aspath) origin = rte->rt_aspath->asp_origin; else origin = PATH_ORG_IGP; /* I originate. */ } else { origin = PATH_ORG_EGP; } break; case RTPROTO_AGGR: origin = PATH_ORG_IGP; /* no case */ break; default: fatalx("BUG ! Invalid origin protocol"); origin = 0; /*pacify gcc*/ /*NOTREACHED*/ } switch (origin) { case PATH_ORG_IGP: case PATH_ORG_EGP: case PATH_ORG_XX: outpkt[i] = origin; IFLOG(LOG_BGPOUTPUT) syslog(LOG_DEBUG, "BGP+ SEND\t\t%s", origin_str[origin]); break; default: fatalx("BUG ! Invalid ORIGIN attribute"); break; } i += PA4_LEN_ORIGIN; /** AS_PATH (Type Code 2) **/ /* well-known mandatory */ outpkt[i++] |= PA_FLAG_TRANS; /* well-known mandatory */ outpkt[i++] = PA4_TYPE_ASPATH; /* T */ BGP_LOG_ATTR; i++; /* L */ /* later re-written */ /* V */ if (bnp->rp_mode & BGPO_IGP) asp = rte->rt_aspath; else { asp = prepend_aspath(my_as_number, rte->rt_aspath, 1); /* mallocated */ if (bnp->rp_ebgp_as_prepends) { int i; for (i = 0; i < bnp->rp_ebgp_as_prepends; i++) asp = prepend_aspath(my_as_number, asp, 0); } } aspathlen = aspath2msg(asp ,i); /* AS path is identical to the */ /* head of RTEs (i.e. argument) */ /* L */ if (aspathlen <= 0xff) { outpkt[i-1] = aspathlen; i += aspathlen; } else { netaspathlen = htons(aspathlen); memcpy(&outpkt[i-1], &netaspathlen, sizeof(netaspathlen)); outpkt[i-3] |= PA_FLAG_EXTLEN; i += 1; aspath2msg(asp ,i); /* overwrite (...slow) */ } if (!(bnp->rp_mode & BGPO_IGP)) { /* mallocated */ free_aspath(asp); asp = NULL; } /** NEXT_HOP (Type Code 3) **/ /* This is only allowed IPv4 address, so it's "no sense" for us. */ outpkt[i++] |= PA_FLAG_TRANS; /* well-known mandatory */ outpkt[i++] = PA4_TYPE_NEXTHOP; /* T */ BGP_LOG_ATTR; outpkt[i++] = sizeof(struct in_addr); /* L (IPv4 specific) */ /* V */ /* added by jinmei to interoperate with CISCO */ memcpy(&outpkt[i], (void *)&bgpIdentifier, PA_LEN_NEXTHOP); i += PA_LEN_NEXTHOP; /* IPv4 address makes "no sense" */ /** MULTI_EXIT_DISC (Type Code 4) optional non-transitive **/ /* which received from a neighboring AS [BGP4+ 5.1.4] */ /* MUST NOT be propagated to other neighboring ASs */ if ((bnp->rp_mode & BGPO_IGP) && rte->rt_aspath && rte->rt_aspath->asp_med != 0) /* net-order */ { outpkt[i++] |= PA_FLAG_OPT; outpkt[i++] = PA4_TYPE_METRIC; /* T */ BGP_LOG_ATTR; outpkt[i++] = PA4_LEN_METRIC; /* L */ /* V */ memcpy(&outpkt[i], &rte->rt_aspath->asp_med, PA4_LEN_METRIC); i += PA4_LEN_METRIC; } /** LOCAL_PREF (Type Code 5) well-known mandatory **/ /* when it goes to external peer, It MUST NOT be included */ if (bnp->rp_mode & BGPO_IGP) { /* IGP */ u_int32_t netlocalpref; if (rte->rt_aspath) netlocalpref = rte->rt_aspath->asp_localpref; else netlocalpref = bnp->rp_prefer; outpkt[i++] |= PA_FLAG_TRANS; /* well-known mandatory */ outpkt[i++] = PA4_TYPE_LOCALPREF; /* T */ outpkt[i++] = PA4_LEN_LOCALPREF; /* L */ /* V */ memcpy(&outpkt[i], &netlocalpref, PA4_LEN_LOCALPREF); i += PA4_LEN_LOCALPREF; } /** ATOMIC_AGGREGATE (Type Code 6) well-known discretinary */ if ( rte->rt_aspath && (rte->rt_aspath->asp_atomagg & PATH_FLAG_ATOMIC_AGG)) { outpkt[i++] |= PA_FLAG_TRANS; /* well-known discretinary */ outpkt[i++] = PA4_TYPE_ATOMICAGG; /* T */ outpkt[i++] = PA4_LEN_ATOMICAGG; /* L (IPv4 specific) */ /* no data */ } /** ORIGINATOR_ID (Type Code 9) optional non-transitive */ /* * ORIGINATOR_ID is a new optional, non-transitive BGP attribute of Type * code 9. This attribute is 4 bytes long and it will be created by a * RR. This attribute will carry the ROUTER_ID of the originator of the * route in the local AS. A BGP speaker should not create an * ORIGINATOR_ID attribute if one already exists. */ if (IamRR && (bnp->rp_mode & BGPO_IGP)) { /* ~fromEBGP and ~(ORIG_ID exists) */ if (!(rtp->rtp_type == RTPROTO_BGP && /* excluding EBGP */ (!(rtp->rtp_bgp->rp_mode & BGPO_IGP)))) { netorigid = (rte->rt_aspath && (rte->rt_aspath->asp_origid != 0)) ? rte->rt_aspath->asp_origid : rtp->rtp_bgp->rp_id; /* * A route reflector must never send routing information back to the * router specified in ORIGINATOR_ID. */ if (netorigid == bnp->rp_id) { IFLOG(LOG_BGPOUTPUT) syslog(LOG_DEBUG, "<%s>: UPDATE to %s is prevented since it's going to be " "looped (Origin ID: %s)", __FUNCTION__, bgp_peerstr(bnp), inet_ntoa(*(struct in_addr *)&netorigid)); return(NULL); } outpkt[i++] |= PA_FLAG_OPT; outpkt[i++] = PA4_TYPE_ORIGINATOR; /* T */ BGP_LOG_ATTR; outpkt[i++] = PA4_LEN_ORIGINATOR; /* L */ IFLOG(LOG_BGPOUTPUT) syslog(LOG_DEBUG, "BGP+ SEND\t\t%s", inet_ntoa(*(struct in_addr *)&netorigid)); memcpy(&outpkt[i], &netorigid, PA4_LEN_ORIGINATOR); i += PA4_LEN_ORIGINATOR; } } /** CLUSTER_LIST (Type Code 10) optional non-transitive */ /* When a RR reflects a route from its Clients to a Non-Client peer, it must append the local CLUSTER_ID to the CLUSTER_LIST. If the CLUSTER_LIST is empty, it must create a new one. Using this attribute an RR can identify if the routing information is looped back to the same cluster due to mis-configuration. If the local CLUSTER_ID is found in the cluster-list, the advertisement will be ignored. */ if (IamRR && rtp->rtp_type == RTPROTO_BGP && (rtp->rtp_bgp->rp_mode & BGPO_RRCLIENT) && (bnp->rp_mode & BGPO_IGP) && !(bnp->rp_mode & BGPO_RRCLIENT)) { struct clstrlist *cll; int cllen; u_int16_t netcllen; extern u_int32_t clusterId; outpkt[i++] |= PA_FLAG_OPT; outpkt[i++] = PA4_TYPE_CLUSTERLIST; /* T */ BGP_LOG_ATTR; i++; /* L */ /* later re-written */ /* V */ cll = prepend_clstrlist(clusterId, rte->rt_aspath->asp_clstr); cllen = clstrlist2msg(cll, i); /* L */ if (cllen <= 0xff) { outpkt[i-1] = cllen; i += cllen; } else { netcllen = htons(cllen); memcpy(&outpkt[i-1], &netcllen, sizeof(netcllen)); outpkt[i-3] |= PA_FLAG_EXTLEN; i += 1; clstrlist2msg(cll ,i); /* overwrite (...slow) */ } free_clstrlist(cll); } /** **/ /** MP_REACH_NLRI (Type Code 14) (optional non-transitive) **/ /** **/ outpkt[i] |= PA_FLAG_OPT; outpkt[i++] |= PA_FLAG_EXTLEN; /* tmp */ outpkt[i++] = PA4_TYPE_MPREACHNLRI; /* T */ BGP_LOG_ATTR; i += 2; /* Extended length (temporaly) */ /* L */ mp_p = i; /* V */ /* Address Family Identifier (2 octets) */ netafi = htons(AFN_IP6); memcpy(&outpkt[i], &netafi, 2); i += 2; /* Subsequent Address Family Identifier (1 octet) */ outpkt[i++] = PA4_MP_UCAST; /* implmntd for UNIcast only */ /* Length of Next Hop Network Address (1 octet) */ lennh_p = i++; /* Network Address of Next Hop (variable) */ IFLOG(LOG_BGPOUTPUT) syslog(LOG_DEBUG, "BGP+ SEND\t\tNextHop");#define PUT_NEXTHOP(nexthop) \ { outpkt[lennh_p] += (byte)sizeof(struct in6_addr); \ memcpy(&outpkt[i], (nexthop), \ sizeof(struct in6_addr)); \ i += sizeof(struct in6_addr); \ } /* * The link-local address shall be included in the Next Hop field if and * only if the BGP speaker shares a common subnet with the entity * identified by the global IPv6 address carried in the Network Address * of Next Hop field and the peer the route is being advertised to. * * In all other cases a BGP speaker shall advertise to its peer in the * Network Address field only the global IPv6 address of the next hop * (the value of the Length of Network Address of Next Hop field shall * be set to 16). * [RFC 2545, Section 3] */ if (bnp->rp_mode & BGPO_IGP) { /* to IBGP */ if (rte->rt_aspath && !IN6_IS_ADDR_UNSPECIFIED(&rte->rt_aspath->asp_nexthop) && (bnp->rp_mode & BGPO_NEXTHOPSELF) == 0) { PUT_NEXTHOP(&rte->rt_aspath->asp_nexthop); /* must be global */ } } else { /* to EBGP */ if (rte->rt_aspath && !IN6_IS_ADDR_UNSPECIFIED(&rte->rt_aspath->asp_nexthop)) { struct rt_entry *irte; irte = bnp->rp_ife->ifi_rte; while (irte) { if (IN6_ARE_PRFX_EQUAL(&rte->rt_aspath->asp_nexthop, &irte->rt_ripinfo.rip6_dest, irte->rt_ripinfo.rip6_plen)) { PUT_NEXTHOP(&rte->rt_aspath->asp_nexthop); break; } if ((irte = irte->rt_next) == bnp->rp_ife->ifi_rte) break; } } } /* If a global address to be included is not decided, choose one */ if (IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)&outpkt[lennh_p + 1])) { /* put my global */ if (!IN6_IS_ADDR_LINKLOCAL(&bnp->rp_myaddr.sin6_addr)) { PUT_NEXTHOP(&bnp->rp_myaddr.sin6_addr); } else { if (!IN6_IS_ADDR_UNSPECIFIED(&bnp->rp_ife->ifi_gaddr)) PUT_NEXTHOP(&bnp->rp_ife->ifi_gaddr); } } /* * Put my linklocal for an on-link peer * XXX: we suspect if it's really useful...see a comment in * bgp_process_update(). */ if (IN6_IS_ADDR_LINKLOCAL(&bnp->rp_ife->ifi_laddr) && (bnp->rp_mode & BGPO_ONLINK)) { PUT_NEXTHOP(&bnp->rp_ife->ifi_laddr); } IFLOG(LOG_BGPOUTPUT) { if (outpkt[lennh_p] == 0) syslog(LOG_DEBUG, "BGP+ SEND\t\t(I have no Nexthop address)"); if (outpkt[lennh_p] >= 16) syslog(LOG_DEBUG, "BGP+ SEND\t\t%s", ip6str((struct in6_addr *)&outpkt[lennh_p + 1], 0)); if (outpkt[lennh_p] >= 32) syslog(LOG_DEBUG, "BGP+ SEND\t\t%s", ip6str((struct in6_addr *)&outpkt[lennh_p + 1 + 16], 0)); } /* Number of SNPAs (1 octet) */ outpkt[i++] = 0; /* NOT implmntd */ #ifdef DRAFT_IETF_00 /* Network Layer Reachability Information Length (2 Octets) */ i += 2;#endif nlri_p = i; /*** NLRI (4+) ***/ IFLOG(LOG_BGPOUTPUT) syslog(LOG_DEBUG, "BGP+ SEND\t\tNLRI"); rt = rte; /* rte:argument */ while(rt) { int poctets; /* (minimum len in octet bound) */ /* Generally, each AS has its own preferred default router. Therefore, default routes should generally not leave the boundary of an AS. [rfc2080.txt] */ if (!(bnp->rp_mode & BGPO_IGP) && IN6_IS_ADDR_UNSPECIFIED(&rte->rt_ripinfo.rip6_dest)) goto next_rte; /* generic filter */ if (bgp_output_filter(bnp, rt)) goto next_rte; agg = rt->rt_aggr.ag_agg; /* (1998/06/12) */ if (aggr_advable(agg, &artp)) { poctets = POCTETS(agg->rt_ripinfo.rip6_plen); if (i + 1 + poctets > BGPMAXPACKETSIZE ) { /* 4096 octets */ syslog(LOG_NOTICE, "<%s>: Max Size of BGP message", __FUNCTION__); rt = rt->rt_prev; break; /* while(rt) */ } outpkt[i++] = agg->rt_ripinfo.rip6_plen; memcpy(&outpkt[i], agg->rt_ripinfo.rip6_dest.s6_addr, poctets); i += poctets; IFLOG(LOG_BGPOUTPUT) syslog(LOG_DEBUG, "BGP+ SENDING MP_REACH\t\t%s/%d to %s", ip6str(&agg->rt_ripinfo.rip6_dest, 0), agg->rt_ripinfo.rip6_plen, bgp_peerstr(bnp)); agg->rt_aggr.ag_flags |= AGGR_ADVDONE; } if (rt->rt_aggr.ag_flags & AGGR_NOADVD && agg && agg->rt_aggr.ag_flags & AGGR_ADVDONE) goto next_rte; if (rtp->rtp_type == RTPROTO_RIP && (rt->rt_flags & RTF_IGP_EGP_SYNC || !(rt->rt_flags & RTF_UP))) goto next_rte; IFLOG(LOG_BGPOUTPUT) syslog(LOG_DEBUG, "BGP+ SEND\t\t%s/%d", ip6str(&rt->rt_ripinfo.rip6_dest, 0), rt->rt_ripinfo.rip6_plen); if (rtp->rtp_type == RTPROTO_BGP) { if ((rt->rt_flags & (RTF_UP|RTF_INSTALLED)) != (RTF_UP|RTF_INSTALLED)) { IFLOG(LOG_BGPOUTPUT) syslog(LOG_DEBUG, "BGP+ SEND\t\t\t(was skipped since unavaiable)"); goto next_rte;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -