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

📄 bgp_util.c

📁 同时支持IPv4和IPv6的BGP协议实现
💻 C
📖 第 1 页 / 共 3 页
字号:
voidbgp_disable_rte_by_igp(rte)	struct rt_entry *rte;{	struct rpcb *bnp;	struct rt_entry *brte;	struct bgpcblist *bgpcb, *bgpcb_head;	extern byte bgpyes;	if (!bgpyes)		return;	switch(rte->rt_proto.rtp_type) {	case RTPROTO_RIP:	case RTPROTO_IF:#ifdef notyet	case RTPROTO_OSPF:#endif 		bgpcb_head = make_bgpcb_list();		for (bgpcb = bgpcb_head; bgpcb; bgpcb = bgpcb->next) {			bnp = bgpcb->bnp;			/*			 * XXX: bnp might be closed or even freed during the loop,			 * so the validity check is necessary.			 */			if (!bgp_rpcb_isvalid(bnp))				continue;			brte = bnp->rp_adj_ribs_in;			while(brte) {				if (brte->rt_gwsrc_type ==				    rte->rt_proto.rtp_type && /* sanity? */				    brte->rt_gwsrc_entry == rte &&				    (brte->rt_flags & (RTF_UP|RTF_INSTALLED)) ==				    (RTF_UP|RTF_INSTALLED)) {					struct rt_entry crte;					IFLOG(LOG_BGPROUTE)						syslog(LOG_DEBUG,						       "<%s>: BGP route(%s/%d) was disabled",						       __FUNCTION__,						       ip6str(&brte->rt_ripinfo.rip6_dest, 0),						       brte->rt_ripinfo.rip6_plen);					bgp_disable_rte(brte);					/* flush gateway information */					brte->rt_gwsrc_type = RTPROTO_NONE;					brte->rt_gwsrc_entry = NULL;					memset(&brte->rt_gw, 0,					       sizeof(struct in6_addr));					brte->rt_gwif = NULL;					/* withdraw this route */					crte = *brte;					crte.rt_next = crte.rt_prev = &crte;					propagate(&crte);					/* XXX: propagate might invalidate bnp */					if (!bgp_rpcb_isvalid(bnp)) {						syslog(LOG_NOTICE,						       "<%s>: rpcb %p was "						       "invalidated during a "						       "propagation",						       __FUNCTION__, bnp);						break;					}				}				if ((brte = brte->rt_next) == bnp->rp_adj_ribs_in)					break;			}		}		free_bgpcb_list(bgpcb_head);		break;	default:		fatalx("<bgp_disable_rte_by_igp>: rt_proto.rtp_type corrupted");		/* NOTREACHED */	}}struct rpcb *find_epeer_by_rpcb(bnp)	struct rpcb *bnp;{	struct rpcb *ebnp = NULL;	if (bnp == NULL)		return(NULL);	if (bnp->rp_state == BGPSTATE_ESTABLISHED)		return(bnp);	if (bnp->rp_mode & BGPO_IGP) { /* IBGP */		ebnp = find_epeer_by_id(bnp->rp_id);		if (ebnp == NULL)			ebnp = find_epeer_by_addr(&bnp->rp_gaddr);		if (ebnp == NULL) /* last resort */			ebnp = find_epeer_by_addr(&bnp->rp_laddr);	}	else {			/* EBGP */		ebnp = find_epeer_by_as(bnp->rp_as);	}	return(ebnp);}struct rpcb *find_epeer_by_addr(addr)	struct in6_addr *addr;{	struct rpcb *bnp;	struct in6_addr lladdr;	extern struct rpcb *bgb;	if (IN6_IS_ADDR_UNSPECIFIED(addr))		return(NULL);	bnp = bgb;	while(bnp) {		lladdr = bnp->rp_laddr;		if (bnp->rp_ife)			SET_IN6_LINKLOCAL_IFINDEX(&lladdr,						  bnp->rp_ife->ifi_ifn->if_index);		if (bnp->rp_state == BGPSTATE_ESTABLISHED &&		    (IN6_ARE_ADDR_EQUAL(&bnp->rp_gaddr, addr) ||		     (!IN6_IS_ADDR_UNSPECIFIED(&lladdr) &&		      IN6_ARE_ADDR_EQUAL(&lladdr, addr))))			return(bnp);		if ((bnp = bnp->rp_next) == bgb)			break;	}	return NULL;}/* *    find_peer_by_as() */struct rpcb *find_peer_by_as(u_int16_t asnum) {  struct rpcb *bnp;    extern struct rpcb *bgb;  bnp = bgb;  while(bnp) {    if (bnp->rp_as == asnum)      return bnp;    if ((bnp = bnp->rp_next) == bgb)      break;  }  return NULL;}/* *    find_epeer_by_as() *       DESCRIPTION: find ESTABLISHED peer by ASnumber */struct rpcb *find_epeer_by_as(u_int16_t asnum) {  struct rpcb *bnp;    extern struct rpcb *bgb;  bnp = bgb;  while(bnp) {    if (bnp->rp_as    == asnum &&	bnp->rp_state == BGPSTATE_ESTABLISHED)      return bnp;    if ((bnp = bnp->rp_next) == bgb)      break;  }  return NULL;}/* *    find_ppeer_by_as() *       DESCRIPTION: find PASSIVEly connected peer by ASnumber */struct rpcb *find_ppeer_by_as(u_int16_t asnum) {  struct rpcb *bnp;    extern struct rpcb *bgb;  bnp = bgb;  while(bnp) {    if ((bnp->rp_as == asnum) &&	(bnp->rp_mode & BGPO_PASSIVE))      return bnp;    if ((bnp = bnp->rp_next) == bgb)      break;  }  return NULL;}/* *    find_epeer_by_id() *      RETURN VALUES:   a Pointer:  found *                       NULL     : not found */struct rpcb *find_epeer_by_id(u_int32_t id) {  struct rpcb *bnp;    extern struct rpcb *bgb;  if (id == 0)    return NULL;  bnp = bgb;  while(bnp) {    if (bnp->rp_id    == id &&	bnp->rp_state == BGPSTATE_ESTABLISHED)      return bnp;    if ((bnp = bnp->rp_next) == bgb)      break;  }  return NULL;}/* *    find_ppeer_by_id() */struct rpcb *find_ppeer_by_id(u_int32_t id) {  struct rpcb *bnp;    extern struct rpcb *bgb;  bnp = bgb;  while(bnp) {    if (bnp->rp_id    == id &&	(bnp->rp_mode & BGPO_PASSIVE))      return bnp;    if ((bnp = bnp->rp_next) == bgb)      break;  }  return NULL;}struct rpcb *find_active_peer(key)	struct rpcb *key;{	struct rpcb *bnp;	extern struct rpcb *bgb;	/*	 * If state of the KEY rpcb is unspecified(because of, for example,	 * not fully connected yet), there is no rpcb that matches it.	 */	if (key->rp_id == 0 && key->rp_as == 0)		return(NULL);	bnp = bgb;	while(bnp) {		if ((key->rp_mode & BGPO_IGP) &&		    (bnp->rp_mode & BGPO_IGP) &&		    bnp->rp_state >= BGPSTATE_CONNECT &&		    ((bnp->rp_id && bnp->rp_id == key->rp_id) ||		     IN6_ARE_ADDR_EQUAL(&key->rp_gaddr, &bnp->rp_gaddr) ||		     (!IN6_IS_ADDR_UNSPECIFIED(&key->rp_laddr) &&		      IN6_ARE_ADDR_EQUAL(&key->rp_laddr, &bnp->rp_laddr))))			return(bnp);		if (!(key->rp_mode & BGPO_IGP) &&		    !(bnp->rp_mode & BGPO_IGP) &&		    bnp->rp_as == key->rp_as &&		    bnp->rp_state >= BGPSTATE_CONNECT)			return(bnp);		if ((bnp = bnp->rp_next) == bgb)			break;	}	return(NULL);}/* search for an actively opened peer */struct rpcb *find_aopen_peer(key)	struct rpcb *key;{	struct rpcb *bnp = NULL;	if ((key->rp_mode & BGPO_PASSIVE) == 0)		return(key);	if ((bnp = find_apeer_by_addr(&key->rp_gaddr)) == NULL)		bnp = find_apeer_by_addr(&key->rp_laddr);	if (bnp == NULL) {		/*		 * This case could occur when receiving a connection		 * request from an unkown router.		 * We can't call bgp_peerstr here, since it causes an		 * infinite loop.		 */#if 0				/* disabled since this would be noisy */		syslog(LOG_DEBUG,		       "<%s>: can't find an actively opened peer for %x",		       __FUNCTION__, key);#endif	}	return(bnp);}struct rpcb *find_idle_peer(key)	struct rpcb *key;{	struct rpcb *bnp;	extern struct rpcb *bgb;	/*	 * If state of the KEY rpcb is unspecified(because of, for example,	 * not fully connected yet), there is no rpcb that matches it.	 */	if (key->rp_id == 0 && key->rp_as == 0)		return(NULL);	bnp = bgb;	while(bnp) {		if ((key->rp_mode & BGPO_IGP) &&		    (bnp->rp_mode & BGPO_IGP) &&		    bnp->rp_state == BGPSTATE_IDLE &&		    ((bnp->rp_id && bnp->rp_id == key->rp_id) ||		     IN6_ARE_ADDR_EQUAL(&key->rp_gaddr, &bnp->rp_gaddr) ||		     (!IN6_IS_ADDR_UNSPECIFIED(&key->rp_laddr) &&		      IN6_ARE_ADDR_EQUAL(&key->rp_laddr, &bnp->rp_laddr))))			return(bnp);		if (!(key->rp_mode & BGPO_IGP) &&		    !(bnp->rp_mode & BGPO_IGP) &&		    bnp->rp_as == key->rp_as &&		    bnp->rp_state == BGPSTATE_IDLE)			return(bnp);		if ((bnp = bnp->rp_next) == bgb)			break;	}	return(NULL);}/* *    find_apeer_by_addr() *     DESCRIPTION: in the case of LinkLocal-address,  *                   we need I/F information. (e.g. LLADDRHACK) */struct rpcb *find_apeer_by_addr(struct in6_addr *addr){  struct rpcb        *bnp;  struct in6_addr     llhackaddr;  extern struct rpcb *bgb;  if (IN6_IS_ADDR_UNSPECIFIED(addr))    return NULL;  bnp = bgb;  while(bnp) {    llhackaddr = bnp->rp_laddr;    if (!IN6_IS_ADDR_UNSPECIFIED(&llhackaddr)) {      if (bnp->rp_ife)	SET_IN6_LINKLOCAL_IFINDEX(&llhackaddr,				  bnp->rp_ife->ifi_ifn->if_index);      else if (IN6_IS_ADDR_LINKLOCAL(&bnp->rp_addr.sin6_addr) &&	       bnp->rp_addr.sin6_scope_id) {	SET_IN6_LINKLOCAL_IFINDEX(&llhackaddr, bnp->rp_addr.sin6_scope_id);      }    }    if (!(bnp->rp_mode & BGPO_PASSIVE) &&	(IN6_ARE_ADDR_EQUAL(&bnp->rp_gaddr, addr) ||	 (!IN6_IS_ADDR_UNSPECIFIED(&llhackaddr) &&	  IN6_ARE_ADDR_EQUAL(&llhackaddr,    addr))))      return bnp;    if ((bnp = bnp->rp_next) == bgb)      break;  }  return NULL;}/* * Check if a given pointer is actually in the peer list and if * the connection to the peer is ESTABLISHUED. * We need this function since we sometimes encounter a situation where * the connection associated with the pointer is closed or even the pointer * is freed during some operations such as update or withdrawing. * This means that we must not the content of BNP, the argument. * We can only refer the address of the pointer. */intbgp_rpcb_isvalid(bnp)	struct rpcb *bnp;{	extern struct rpcb *bgb;	struct rpcb *b;	b = bgb;	while(b) {		if (b == bnp &&	b->rp_state == BGPSTATE_ESTABLISHED)			return(1);		if ((b = b->rp_next) == bgb)			break;	}	return(0);}/* *   ibgpconfig() * *       Route Reflector [rfc1966]. */voidibgpconfig(){  struct rpcb   *ibnp, *bnp;#if 0  struct ifinfo *ife;  struct ripif  *ripif;#endif  extern byte             IamRR;#if 0  extern byte             ripyes;#endif  extern u_int32_t        clusterId, bgpIdentifier;  extern struct rpcb     *bgb;#if 0  extern struct ifinfo   *ifentry;  extern struct ripif    *ripifs;#endif  if (IamRR)    if (clusterId == 0)      clusterId = bgpIdentifier;  /* ad-hoc */  /*   *  1) A Route from a Non-Client peer   *   *     Reflect to all other Clients.   */  if (IamRR) {    ibnp = bgb;    while (ibnp) {      if (ibnp->rp_mode & BGPO_RRCLIENT) {	bnp = bgb;	while (bnp) {	  if ( (bnp->rp_mode & BGPO_IGP) &&	      !(bnp->rp_mode & BGPO_RRCLIENT) &&	      ibnp != bnp ) {	    struct rtproto *rtp;	  	    MALLOC(rtp, struct rtproto);	  	    rtp->rtp_type = RTPROTO_BGP;	    rtp->rtp_bgp  = bnp;	    if (ibnp->rp_adj_ribs_out)	      insque(rtp, ibnp->rp_adj_ribs_out);	    else {	      rtp->rtp_next = rtp;	      rtp->rtp_prev = rtp;	      ibnp->rp_adj_ribs_out = rtp;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -