📄 bgp.c
字号:
goto done; } /* V */ switch (bnp->rp_inpkt[i]) { case PATH_ORG_IGP: case PATH_ORG_EGP: case PATH_ORG_XX: if ((logflags & LOG_BGPINPUT)) syslog(LOG_DEBUG, "BGP+ RECV\t\t%s", origin_str[bnp->rp_inpkt[i]]); origin = bnp->rp_inpkt[i++]; break; default: /* If the ORIGIN attribute has an undefined value, then the Error Subcode is set to Invalid Origin Attribute. The Data field contains the unrecognized attribute (type, length and value). */ bgp_notify(bnp, BGP_ERR_UPDATE, BGP_ERRUPD_ORIGIN, atrlen, &bnp->rp_inpkt[k]); goto done; break; } break; case PA4_TYPE_ASPATH: /* ASPATH (Type Code 2) well-known mandatory */ 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; } /* V */ /* construct AS_PATH */ if ((asp = msg2aspath(bnp, i, atrdatalen, &error)) == NULL) { switch (error) { case EINVAL: bgp_notify(bnp, BGP_ERR_UPDATE, BGP_ERRUPD_ASPATH, 0, NULL); goto done; default: /* AS path loop detected. this msg is to be ignore. */ goto done; /* iw97 */ } } i += atrdatalen; break; case PA4_TYPE_NEXTHOP: /* NEXT_HOP (Type Code 3) well-known mandatory */ /* check syntax only. */ 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; } /* IPv4 specific */ if (atrdatalen != PA_LEN_NEXTHOP) { /* Attribute Length Error */ bgp_notify(bnp, BGP_ERR_UPDATE, BGP_ERRUPD_LENGTH, atrlen, &bnp->rp_inpkt[k]); goto done; } /* V */ i += sizeof(struct in_addr); break; case PA4_TYPE_METRIC: /* MULTI_EXIT_DISC (Type Code 4) optional non-transitive */ PA4_TYPE_CODE_CHECK; PA4_LEN_PARSE; /* T */ /* optional non-transitive attributes the Partial bit must be set to 0. */ 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; } if (atrdatalen != PA4_LEN_METRIC) { /* Attribute Length Error */ bgp_notify(bnp, BGP_ERR_UPDATE, BGP_ERRUPD_LENGTH, atrlen, &bnp->rp_inpkt[k]); goto done; } /* V */ if ((logflags & LOG_BGPINPUT)) syslog(LOG_DEBUG, "BGP+ RECV\t\t%d", ntohl(*(u_int32_t *)&bnp->rp_inpkt[i])); med = *(u_int32_t *)&bnp->rp_inpkt[i]; /* net-order */ i += atrdatalen; break; case PA4_TYPE_LOCALPREF: /* LOCAL_PREF (Type Code 5) well-known mandatory */ /* If it is received from an external peer, */ /* then this attribute MUST be ignored. [BGP4+ 5.1.5] */ PA4_TYPE_CODE_CHECK; PA4_LEN_PARSE; if (bnp->rp_mode & BGPO_IGP) { /* 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; } if (atrdatalen != PA4_LEN_LOCALPREF) { /* Attribute Length Error */ bgp_notify(bnp, BGP_ERR_UPDATE, BGP_ERRUPD_LENGTH, atrlen,&bnp->rp_inpkt[k]); goto done; } /* V */ if ((logflags & LOG_BGPINPUT)) syslog(LOG_DEBUG, "BGP+ RECV\t\t%d", ntohl(*(u_int32_t *)&bnp->rp_inpkt[i])); if (bnp->rp_mode & BGPO_IGP) localpref = *(u_int32_t *)&bnp->rp_inpkt[i]; /* net-order */ } i += atrdatalen; break; case PA4_TYPE_ATOMICAGG: /* ATOMIC_AGGREGATE (Type Code 6) well-known discretinary */ 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; } if (atrdatalen != PA4_LEN_ATOMICAGG) { /* Attribute Length Error */ bgp_notify(bnp, BGP_ERR_UPDATE, BGP_ERRUPD_LENGTH, atrlen, &bnp->rp_inpkt[k]); goto done; } /* V */ aggregated = PATH_FLAG_ATOMIC_AGG; i += PA4_LEN_ATOMICAGG; /* this has no data */ break; case PA4_TYPE_AGGREGATOR: /* AGGREGATOR (Type Code 7) optional transitive */ /* this is used for debugging (furthermore, for IPv4 only) */ PA4_TYPE_CODE_CHECK; PA4_LEN_PARSE; /* T */ if (!(bnp->rp_inpkt[k] & PA_FLAG_OPT) || !(bnp->rp_inpkt[k] & PA_FLAG_TRANS)) { /* Attribute Flags Error */ bgp_notify(bnp, BGP_ERR_UPDATE, BGP_ERRUPD_FLAGS, atrlen, &bnp->rp_inpkt[k]); goto done; } if (atrdatalen != PA4_LEN_AGGREGATOR) { /* Attribute Length Error */ bgp_notify(bnp, BGP_ERR_UPDATE, BGP_ERRUPD_LENGTH, atrlen, &bnp->rp_inpkt[k]); goto done; } /* V */ i += PA4_LEN_AGGREGATOR; /* specific for IPv4, so ignored. */ break;#ifdef notyet case PA4_TYPE_COMMUNITY: /* COMMUNITY (Type Code 8) optional transitive */ PA4_TYPE_CODE_CHECK; PA4_LEN_PARSE; /* T */ if (!(bnp->rp_inpkt[k] & PA_FLAG_OPT) || !(bnp->rp_inpkt[k] & PA_FLAG_TRANS)) { /* Attribute Flags Error */ bgp_notify(bnp, BGP_ERR_UPDATE, BGP_ERRUPD_FLAGS, atrlen, &bnp->rp_inpkt[k]); goto done; } if (atrdatalen != 0) { if ((coml = msg2communitylist(bnp, i, atrdatalen)) == NULL) goto done; } i += atrdatalen; break;#endif /* notyet */ case PA4_TYPE_ORIGINATOR: /* ORIGINATOR_ID (Type Code 9) optional non-transitive */ PA4_TYPE_CODE_CHECK; PA4_LEN_PARSE; /* T */ /* optional non-transitive attributes the Partial bit must be set to 0. */ 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; } if (atrdatalen != PA4_LEN_ORIGINATOR) { /* Attribute Length Error */ bgp_notify(bnp, BGP_ERR_UPDATE, BGP_ERRUPD_LENGTH, atrlen, &bnp->rp_inpkt[k]); goto done; } /* V */ /* This attribute is 4 bytes long and it will be created by a RR. [rfc1966] */ if ((logflags & LOG_BGPINPUT)) syslog(LOG_DEBUG, "BGP+ RECV\t\t%s", /* ntohl(*(u_int32_t *)&bnp->rp_inpkt[i])); */ inet_ntoa(*(struct in_addr *)&bnp->rp_inpkt[i])); if ( (bnp->rp_mode & BGPO_IGP) && !(bnp->rp_mode & BGPO_RRCLIENT)) originatorid = *(u_int32_t *)&bnp->rp_inpkt[i]; i += atrdatalen; break; case PA4_TYPE_CLUSTERLIST: /* CLUSTER_LIST (Type Code 10) optional non-transitive */ PA4_TYPE_CODE_CHECK; PA4_LEN_PARSE; /* T */ /* optional non-transitive attributes the Partial bit must be set to 0. */ 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; } /* V */ /* construct CLUSTER_LIST */ /* If the local CLUSTER_ID is found in the cluster-list, the advertisement will be ignored. [rfc1966] */ if (atrdatalen != 0 && (bnp->rp_mode & BGPO_IGP)) { if ((cll = msg2clstrlist(bnp, i, atrdatalen)) == NULL) goto done; } i += atrdatalen; break; case PA4_TYPE_MPREACHNLRI: /* MP_REACH_NLRI (Type Code 14) optional non-transitive */ 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 :-< */ } /* Length of Next Hop Network Address (1 octet) */ nhnalen = bnp->rp_inpkt[i++]; if (!((nhnalen == sizeof(struct in6_addr)) || (nhnalen == sizeof(struct in6_addr) * 2))) { syslog(LOG_NOTICE, "<%s>: nexthop address length (%d) cannot accepted.", __FUNCTION__, (int)nhnalen); i = k + atrlen; break; /* this attribute */ } /* Network Address of Next Hop (variable) */ gnhaddr = *(struct in6_addr *)&bnp->rp_inpkt[i]; /* (normally) */ if ((logflags & LOG_BGPINPUT)) { syslog(LOG_DEBUG, "BGP+ RECV\t\tNextHop"); syslog(LOG_DEBUG, "BGP+ RECV\t\t%s", ip6str(&gnhaddr, 0)); } /* * A BGP speaker shall advertise to its peer in the Network Address of * Next Hop field the global IPv6 address of the next hop, potentially * followed by the link-local IPv6 address of the next hop. * [RFC 2545, Section 3] */ if (IN6_IS_ADDR_LINKLOCAL(&gnhaddr)) { /* consider site-local as well? */ syslog(LOG_NOTICE, "<%s>: 1st next hop(%s) from %s is not global", __FUNCTION__, ip6str(&gnhaddr, 0), bgp_peerstr(bnp)); break; /* go to next attribute */ } IFLOG(LOG_BGPINPUT) { if (!(IN6_IS_ADDR_UNSPECIFIED(&bnp->rp_gaddr)) && /* global */ !(IN6_ARE_ADDR_EQUAL(&bnp->rp_gaddr, &gnhaddr))) syslog(LOG_DEBUG, "<%s>: Third Party NextHop %s from %s", __FUNCTION__, ip6str(&gnhaddr, 0), bgp_peerstr(bnp)); } i += sizeof(struct in6_addr); /* RFC 2283,2545 bellow */ if (nhnalen == sizeof(struct in6_addr) * 2) { if (!IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)&bnp->rp_inpkt[i])) { syslog(LOG_NOTICE, "<%s>: 2nd next hop(%s) from %s is not link-local(ignored)", __FUNCTION__, ip6str((struct in6_addr *)&bnp->rp_inpkt[i], 0), bgp_peerstr(bnp)); } else if ((bnp->rp_mode & BGPO_ONLINK) == 0) { /* * 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. * [RFC 2545, Section 3.] */ syslog(LOG_NOTICE, "<%s>: link-local next hop (%s) from an off-link peer(%s) " "(ignored)", __FUNCTION__, ip6str((struct in6_addr *)&bnp->rp_inpkt[i], 0), bgp_peerstr(bnp)); } else { lnhaddr = *(struct in6_addr *)&bnp->rp_inpkt[i]; IFLOG(LOG_BGPINPUT) { syslog(LOG_DEBUG, "BGP+ RECV\t\t%s", ip6str(&lnhaddr, 0)); if (!(IN6_IS_ADDR_UNSPECIFIED(&bnp->rp_laddr)) && !(IN6_ARE_ADDR_EQUAL(&bnp->rp_laddr, &lnhaddr))) syslog(LOG_DEBUG, "<%s>: Third Party NextHop %s", __FUNCTION__, ip6str(&lnhaddr, 0)); } } i += sizeof(struct in6_addr); } /* Number of SNPAs (1 octet) */ snpanum = bnp->rp_inpkt[i++]; for (j = 0; j < snpanum; j++) { snpalen = bnp->rp_inpkt[i++]; i += ((snpalen % 2) ? snpalen / 2 + 1 : snpalen / 2); }#ifdef DRAFT_IETF_00 /* Network Layer Reachability Information 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 /*** NLRI (4+) ***/ if ((logflags & LOG_BGPINPUT)) syslog(LOG_DEBUG, "BGP+ RECV\t\tNLRI"); while (i < k + atrlen) { /* Malformation is detected ASAP */ struct rt_entry *rte; /* to be installed */ int poctets; /* (minimum len in octet bound) */ struct ifinfo *ife; /* search for */ struct rt_entry *orte; /* which I had */ time_t tloc; MALLOC(rte, struct rt_entry); /* log update time */ (void)time(&tloc); rte->rt_time = tloc; orte = NULL; /* Length (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_REACH_NLRI */ } poctets = POCTETS(rte->rt_ripinfo.rip6_plen); /* Prefix (variable) */ 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(nxthop=%s and %s) from %s", ip6str(&rte->rt_ripinfo.rip6_dest, 0), rte->rt_ripinfo.rip6_plen, ip6str(&gnhaddr, 0), IN6_IS_ADDR_UNSPECIFIED(&lnhaddr) ? "none" : ip6str(&lnhaddr, 0), bgp_peerstr(bnp)); if (!IN6_IS_ADDR_ROUTABLE(&rte->rt_ripinfo.rip6_dest)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -