📄 bgp.c
字号:
syslog(LOG_NOTICE, "<%s>: Invalid prefix(%s/%d) in NLRI (ignored) from %s", __FUNCTION__, ip6str(&rte->rt_ripinfo.rip6_dest, 0), rte->rt_ripinfo.rip6_plen, bgp_peerstr(bnp)); free(rte); continue; /* to next rte */ } if (bgp_input_filter(bnp, rte)) { if ((logflags & LOG_BGPINPUT)) syslog(LOG_DEBUG, "<%s>: NLRI %s/%d from %s was filtered", __FUNCTION__, ip6str(&rte->rt_ripinfo.rip6_dest, 0), rte->rt_ripinfo.rip6_plen, bgp_peerstr(bnp)); free(rte); continue; /* to next rte */ } if (rte->rt_ripinfo.rip6_plen == 128) { ife = ifentry; while(ife) { /* check global I/F addrs */ if (IN6_ARE_ADDR_EQUAL(&rte->rt_ripinfo.rip6_dest, &ife->ifi_gaddr)) { ife = NULL; break; } if ((ife = ife->ifi_next) == ifentry) break; } if (ife == NULL) { free(rte); continue; /* ignore */ } } /* * XXX: A link-local next hop is sometimes more useful than global one, * but we can't trust that it's really on a link that we connect with, *so we always use a global next hop for safety... */ rte->rt_bgw = gnhaddr; rte->rt_flags = RTF_UP|RTF_GATEWAY; if (rte->rt_ripinfo.rip6_plen == 128) rte->rt_flags |= RTF_HOST; rte->rt_ripinfo.rip6_tag = htons(aspath2tag(asp)); rte->rt_ripinfo.rip6_metric = 0; /* (ad-hoc) */ rte->rt_proto.rtp_type = RTPROTO_BGP; rte->rt_proto.rtp_bgp = bnp; /* for each RTE, each RTP exists. */ rte->rt_aspath = asp; /* AS path field will be filled in later */ /* check I/F routes */ ife = ifentry; while(ife) { if ((orte = find_rte(rte, ife->ifi_rte))) break; if ((ife = ife->ifi_next) == ifentry) break; } if (orte != NULL) { /* I/F direct route (most preferable) */ if ((logflags & LOG_BGPINPUT)) syslog(LOG_DEBUG, "<%s>: I/F direct %s/%d not overwritten", __FUNCTION__, inet_ntop(AF_INET6, &rte->rt_ripinfo.rip6_dest, in6txt, INET6_ADDRSTRLEN), rte->rt_ripinfo.rip6_plen); free(rte); continue; /* to next rte */ } /* check aggregate routes */ if (find_rte(rte, aggregations)) { if ((logflags & LOG_BGPINPUT)) syslog(LOG_DEBUG, "<%s>: aggregate route %s/%d cannot overwritten", __FUNCTION__, ip6str(&rte->rt_ripinfo.rip6_dest, 0), rte->rt_ripinfo.rip6_plen); free(rte); continue; /* to next rte */ } insque(rte, &uprtehead); /* Keep the RTE in the queue for later use */ } /* End of while (NLRI) */ /* If an optional attribute is recognized, then the value of this attribute is checked. If an error is detected, the attribute is discarded, and the Error Subcode is set to Optional Attribute Error. The Data field contains the attribute (type, length and value). */ if (i != k + atrlen) { bgp_notify(bnp, BGP_ERR_UPDATE, BGP_ERRUPD_OPTATTR, atrlen, &bnp->rp_inpkt[k]); goto done; } break; case PA4_TYPE_MPUNREACHNLRI: /* MP_UNREACH_NLRI (Type Code 15) optional non-transitive */ /* An UPDATE message that contains the MP_UNREACH_NLRI is not required to carry any other path attributes. */ PA4_TYPE_CODE_CHECK; PA4_LEN_PARSE; /* T */ if (!(bnp->rp_inpkt[k] & PA_FLAG_OPT) || (bnp->rp_inpkt[k] & PA_FLAG_TRANS) || (bnp->rp_inpkt[k] & PA_FLAG_PARTIAL)) { /* Attribute Flags Error */ bgp_notify(bnp, BGP_ERR_UPDATE, BGP_ERRUPD_FLAGS, atrlen, &bnp->rp_inpkt[k]); goto done; } /* Address Family Identifier (2 octets) */ if (ntohs(*(u_int16_t *)&bnp->rp_inpkt[i]) != AFN_IP6) { syslog(LOG_NOTICE, "<%s>: AFI is not AFN_IP6(%d)", __FUNCTION__, AFN_IP6); i += atrdatalen; break; /* Gently ignore :-) */ } i += 2; /* SAFI */ /* Subsequent Address Family Identifier (1 octet) */ if (bnp->rp_inpkt[i++] != PA4_MP_UCAST) { /* implmntd for UNIcast only */ syslog(LOG_NOTICE, "<%s>: SAFI isn't (%d). I only support unicast", __FUNCTION__, PA4_MP_UCAST); i = k + atrlen; break; /* Quietly ignore :-< */ }#ifdef DRAFT_IETF_00 /* Unfeasible Routes Length (2 Octets) */ nlrilen = ntohs(*(u_short *)&bnp->rp_inpkt[i]); i += 2; if (i + nlrilen != k + atrlen) { bgp_notify(bnp, BGP_ERR_UPDATE, BGP_ERRUPD_LENGTH, atrlen, &bnp->rp_inpkt[k]); goto done; }#endif /*** Withdrawn Routes ( NLRI encoding ) ***/ while (i < k + atrlen) { /* Malform is detected ASAP */ struct rt_entry *rte; int poctets; /* (minimum len in octet bound) */ int first = 1; /* XXX: just for statistics */ if (first) { bgp_update_stat(bnp, BGPS_WITHDRAWRCVD); first = 0; } MALLOC(rte, struct rt_entry); /* Length in bits (1 octet) */ if ((rte->rt_ripinfo.rip6_plen = bnp->rp_inpkt[i++]) > 128) { syslog(LOG_NOTICE, "<%s>: Bad prefix length (=%d) in NLRI", __FUNCTION__, rte->rt_ripinfo.rip6_plen); free(rte); i = k + atrlen; break; /* ignore rest of MP_UNREACH_NLRI */ } poctets = POCTETS(rte->rt_ripinfo.rip6_plen); /* Dest. */ memcpy(rte->rt_ripinfo.rip6_dest.s6_addr, &bnp->rp_inpkt[i], poctets); i += poctets; if ((logflags & LOG_BGPINPUT)) syslog(LOG_DEBUG, "BGP+ RECV\t\t%s/%d", ip6str(&rte->rt_ripinfo.rip6_dest, 0), rte->rt_ripinfo.rip6_plen); if (!IN6_IS_ADDR_ROUTABLE(&rte->rt_ripinfo.rip6_dest)) { if ((logflags & LOG_BGPINPUT)) syslog(LOG_DEBUG, "<%s>: Invalid prefix(%s/%d) in UNLRI (ignored) from %s", __FUNCTION__, ip6str(&rte->rt_ripinfo.rip6_dest, 0), rte->rt_ripinfo.rip6_plen, bgp_peerstr(bnp)); free(rte); continue; /* to next rte */ } if (bgp_input_filter(bnp, rte)) { IFLOG(LOG_BGPINPUT) syslog(LOG_DEBUG, "<%s>: UNLRI %s/%d from %s was filtered", __FUNCTION__, ip6str(&rte->rt_ripinfo.rip6_dest, 0), rte->rt_ripinfo.rip6_plen, bgp_peerstr(bnp)); free(rte); continue; /* to next rte */ } rte->rt_proto.rtp_type = RTPROTO_BGP; rte->rt_proto.rtp_bgp = bnp; /* for each RTE, each RTP exists. */ rte->rt_aspath = asp; /* AS path field will be filled in later */ insque(rte, &wdrtehead);/* Keep the RTE in the queue for later use */ } /* End of while(NLRI) */ break; default: /* XXX: PA propagation not fully implemented. */ PA4_TYPE_CODE_CHECK; PA4_LEN_PARSE; /* T */ /* If any of the mandatory well-known attributes are not recognized, then the Error Subcode is set to Unrecognized Well-known Attribute. The Data field contains the unrecognized attribute (type, length and value). */ if (!(bnp->rp_inpkt[k] & PA_FLAG_OPT)) { bgp_notify(bnp, BGP_ERR_UPDATE, BGP_ERRUPD_UNKNOWN, atrlen, &bnp->rp_inpkt[k]); goto done; } /* * Optional transitive attributes should be passed to other peers * transparently. */ if ((bnp->rp_inpkt[k] & PA_FLAG_OPT) && (bnp->rp_inpkt[k] & PA_FLAG_TRANS)) { IFLOG(LOG_BGPINPUT) syslog(LOG_DEBUG, "<%s>: BGP+ RECV\t\tUnrecognized Attribute: type=%d,len=%d", __FUNCTION__, bnp->rp_inpkt[k + 1], atrdatalen); optatr = add_optatr(optatr, &bnp->rp_inpkt[k], atrlen); } /* optional non-transitive attributes the Partial bit must be set to 0. */ if (!(bnp->rp_inpkt[k] & PA_FLAG_TRANS) && (bnp->rp_inpkt[k] & PA_FLAG_PARTIAL)) { /* Attribute Flags Error */ bgp_notify(bnp, BGP_ERR_UPDATE, BGP_ERRUPD_FLAGS, atrlen, &bnp->rp_inpkt[k]); goto done; } /* Unrecognized non-transitive optional attributes must be quietly ignored and not passed along to other BGP peers. [Page20] */ /* V */ i += atrdatalen; /* quietry ignore */ break; } /* <-- End of Switch path-attrs. */ } if (pa_p + tpalen != i) { /* Malformed Attribute List */ bgp_notify(bnp, BGP_ERR_UPDATE, BGP_ERRUPD_ATTRLIST, 0, NULL); goto done; } /* In IPv4 BGP4, here appears "traditional NLRI", which can be quietry ignored in BGP4+ (for IPv6) */ if ((v4nlrilen = length - i ) > 0) syslog(LOG_NOTICE, "<bgp_process_update>: traditional NLRI appread (ignore)"); { byte missin_attr = 0; /* If any of the mandatory well-known attributes are not present, then the Error Subcode is set to Missing Well-Known Attribute. The Data field contains the Attribute Type Code of the missing well-known attribute. */ if (!(bit_test(parsedflag, PA4_TYPE_ORIGIN))) missin_attr = PA4_TYPE_ORIGIN; if (!(bit_test(parsedflag, PA4_TYPE_ASPATH))) missin_attr = PA4_TYPE_ASPATH; if (!(bit_test(parsedflag, PA4_TYPE_MPREACHNLRI)) && /* bgp4+ */ !(bit_test(parsedflag, PA4_TYPE_NEXTHOP))) missin_attr = PA4_TYPE_NEXTHOP; if ((bnp->rp_mode & BGPO_IGP) && !(bit_test(parsedflag, PA4_TYPE_LOCALPREF))) missin_attr = PA4_TYPE_LOCALPREF; /* An UPDATE message that contains the MP_UNREACH_NLRI is not required to carry any other path attributes. */ if (missin_attr && (v4nlrilen > 0 || !bit_test(parsedflag, PA4_TYPE_MPUNREACHNLRI))) { bgp_notify(bnp, BGP_ERR_UPDATE, BGP_ERRUPD_MISSING, 1, &missin_attr); goto done; } } /* missin_atr */ /* * At this point, the received message is confirmed to be valid. * Now install or redistribute routes according to the message. */ if (asp) { asp->asp_origin = origin; asp->asp_nexthop = gnhaddr; asp->asp_nexthop_local = lnhaddr; /* may be unspecified */ asp->asp_med = med; /* net order */ asp->asp_localpref = localpref; /* net order */ asp->asp_atomagg = aggregated; asp->asp_origid = originatorid; /* net order */ asp->asp_clstr = cll; asp->asp_optatr = optatr; } /*** ***/ /*** Route Selection ***/ /*** ***/ /* XXX: protocol preference ?? */ for (uprte = uprtehead.rt_next; uprte != &uprtehead; uprte = uprte->rt_next) { struct rt_entry *nrte = NULL; if (bgp_selectroute(uprte, bnp)) goto done; if (bgp_enable_rte(uprte) == 0) { IFLOG(LOG_BGPINPUT) syslog(LOG_NOTICE, "<%s>: MP_REACH_NLRI %s/%d: from %s, " "not enabled", __FUNCTION__, ip6str(&uprte->rt_ripinfo.rip6_dest, 0), uprte->rt_ripinfo.rip6_plen, bgp_peerstr(bnp)); nrte = uprte->rt_prev; /* XXX */ remque(uprte); free(uprte); uprte = nrte; continue; } else { /* (1998/06/30) */ /* Copy enable route into adj-ribs-in list */ struct rt_entry *irte; IFLOG(LOG_BGPINPUT) syslog(LOG_DEBUG, "<%s>: MP_REACH_NLRI %s/%d: from %s, " "enabled(%s)", __FUNCTION__, ip6str(&uprte->rt_ripinfo.rip6_dest, 0), uprte->rt_ripinfo.rip6_plen, bgp_peerstr(bnp), (uprte->rt_flags & RTF_UP) ? "installed" : "backup"); MALLOC(irte, struct rt_entry); memcpy(irte, uprte, sizeof(struct rt_entry)); irte->rt_aspath = aspathcpy(uprte->rt_aspath); if (bnp->rp_adj_ribs_in) { insque(irte, bnp->rp_adj_ribs_in); } else { irte->rt_next = irte->rt_prev = irte; bnp->rp_adj_ribs_in = irte; }; } /* a BGP speaker advertise to its peers (other BGP speakers which it communicates with) in neighboring ASs only those routes that it itself uses [BGP4, Page2] */ if ((bnp->rp_mode & BGPO_IGP && uprte->rt_flags & RTF_UP && ((uprte->rt_flags & RTF_IGP_EGP_SYNC) || (bnp->rp_mode & BGPO_NOSYNC))) || (!(bnp->rp_mode & BGPO_IGP) && uprte->rt_flags & RTF_UP)) continue; /* to next RTE */ else { nrte = uprte->rt_prev; /* XXX */ remque(uprte); free(uprte); uprte = nrte; } } /* * withdraw route */ for (wdrte = wdrtehead.rt_next; wdrte != &wdrtehead; wdrte = wdrte->rt_next) { struct rt_entry *drte; if ((drte = find_rte(wdrte, bnp->rp_adj_ribs_in))) { if (drte->rt_flags & RTF_UP) { struct rt_entry rte; IFLOG(LOG_BGPINPUT) syslog(LOG_NOTICE, "<%s>: MP_UNREACH_NLRI %s/%d: from %s " "(deleted)", __FUNCTION__, ip6str(&wdrte->rt_ripinfo.rip6_dest, 0), wdrte->rt_ripinfo.rip6_plen, bgp_peerstr(bnp)); bgp_disable_rte(drte); /* (also copy "back-pointer" ASpath pointer) */ memcpy(&rte, wdrte, sizeof(struct rt_entry)); rte.rt_next = &rte; rte.rt_prev = &rte; propagate(&rte); if (!bgp_rpcb_isvalid(bnp)) { syslog(LOG_NOTICE, "<%s>: rpcb %p was invalidated during " "a propagation", __FUNCTION__, bnp); goto done; } /* remove and free from the imported list */ bnp->rp_adj_ribs_in = rte_remove(drte, bnp->rp_adj_ribs_in); /* try to recovery from backup routes */ bgp_recover_rte(&rte); if (!bgp_rpcb_isvalid(bnp)) { syslog(LOG_NOTICE, "<%s>: rpcb %p was invalidated during " "a route-recovery", __FUNCTION__, bnp); goto done; } } else { /* * when a backup route is withdrawn, * no update msg is advertized. just delete the entry. */#ifdef DEBUG_BGP syslog(LOG_NOTICE, "<%s>: MP_UNREACH_NLRI %s/%d: from %s (~UP)",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -