⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bgp_output.c

📁 同时支持IPv4和IPv6的BGP协议实现
💻 C
📖 第 1 页 / 共 3 页
字号:
  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 + -