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

📄 ripng.c

📁 同时支持IPv4和IPv6的BGP协议实现
💻 C
📖 第 1 页 / 共 4 页
字号:
	  }	}	if ((obnp = obnp->rp_next) == bgb)	  break;      } /* while(obnp) iBGP */      obnp = bgb;      while(obnp) {	if (!(obnp->rp_mode & BGPO_IGP) &&                  /* eBGP */	    (orte = find_rte(rte, obnp->rp_adj_ribs_in))) {	  if (rte->rt_ripinfo.rip6_tag == 0) {   /* purely internal */	    IFLOG(LOG_RIP)	      syslog(LOG_DEBUG, "<%s>: %s/%d on %s is purely internal, tag=%u.",		     __FUNCTION__, ip6str(&rte->rt_ripinfo.rip6_dest, 0),		     rte->rt_ripinfo.rip6_plen, ifname,		     ntohs(rte->rt_ripinfo.rip6_tag));	    bgp_disable_rte(orte);	  } else {	    if (rte->rt_ripinfo.rip6_tag == orte->rt_ripinfo.rip6_tag) {	      obnp = NULL;   /* I mean "continue to next rte" */	      break;	    } else	      if (srte) { /* tag differ */		if ((ntohl(srte->rt_aspath->asp_localpref) >		     ntohl(orte->rt_aspath->asp_localpref))		    ||		    ((ntohl(srte->rt_aspath->asp_localpref) ==		      ntohl(orte->rt_aspath->asp_localpref))    &&		     ((aspath2cost(srte->rt_aspath) <		       aspath2cost(orte->rt_aspath))     ||		      (ntohl(srte->rt_aspath->asp_med) <		       ntohl(orte->rt_aspath->asp_med))))) {		  IFLOG(LOG_RIP)		    syslog(LOG_DEBUG, "<%s>: tag differ.", __FUNCTION__);		  bgp_disable_rte(orte); /* XXX: do not have to propagate? */		} else {		  /* don't touch srte's RTF_UP. No need. */		  obnp = NULL;   /* I mean "continue to next rte" */		  break;		}	      }	  }	}	if (obnp == NULL ||	    (obnp = obnp->rp_next) == bgb)	  break;      } /* while(obnp) eBGP */      if (obnp == NULL) {	free(rte);	IFLOG(LOG_RIP)	  syslog(LOG_DEBUG, "<%s>: skip", __FUNCTION__);	continue;   /* to next rte */      }    }    /**  check RIPng routes  **/    oripif = ripifs;    while(oripif) {#define ALTER_RTE {  rte->rt_riptime = lifetime;   lifeyes = 1;\		     rip_erase_rte(orte);\		     uprte  = igp_enable_rte(rte);\		     if (uprte) unn++; }      if ((orte = find_rte(rte, oripif->rip_adj_ribs_in))) {	/* If there is an existing route, compare the next hop address to the	   address of the router from which the datagram came. [rfc2080] */	if (ripif->rip_ife->ifi_ifn->if_index ==	    oripif->rip_ife->ifi_ifn->if_index &&	    IN6_ARE_ADDR_EQUAL(&orte->rt_gw, &fsock.sin6_addr)) {	  if (rte->rt_ripinfo.rip6_metric == RIPNG_METRIC_UNREACHABLE) {	    /* Note that the deletion process is started only when the metric	       is first set to infinity.  If the metric was already infinity,	       then a new deletion process is not started. [rfc2080] */	    if (orte->rt_ripinfo.rip6_metric == RIPNG_METRIC_UNREACHABLE) {	      oripif = NULL;  /* I mean "continue to next rte" */	      break;	    } else {	      orte->rt_riptime = garbage;   garbageyes = 1;	      orte->rt_ripinfo.rip6_metric = RIPNG_METRIC_UNREACHABLE;	      dwnrte = rip_disable_rte(orte); /* copied */	      if (dwnrte) {		dnn++;		dwnrte->rt_next = dwnrte->rt_prev = dwnrte;		propagate(dwnrte);		free(dwnrte);		bgp_recover_rte(orte);		oripif = NULL;	      }	      break;	    }	  }	  /* 0 < rte < 16 */	  if (orte->rt_ripinfo.rip6_metric == RIPNG_METRIC_UNREACHABLE) {	    rte->rt_riptime = lifetime;  lifeyes = 1;	    oripif->rip_adj_ribs_in	      = rte_remove(orte, oripif->rip_adj_ribs_in);	    uprte = igp_enable_rte(rte);   /* copied */	    if (uprte) unn++;	    break; /* while(oripif) */	  }	  /* 0 < orte < 16 */	  if (rte->rt_ripinfo.rip6_metric == orte->rt_ripinfo.rip6_metric) {	    /* If the new metric is the same as the old one, 	       it is simplest to do nothing further	       (beyond reinitializing the timeout...)   [rfc2080] */	 	    orte->rt_riptime = lifetime;  lifeyes = 1;	    oripif = NULL;  /* I mean "continue to next rte" */	    break; /* while(oripif) */	  }	  if (rte->rt_ripinfo.rip6_metric != orte->rt_ripinfo.rip6_metric) {	    /**  Metric Change  **/	    IFLOG(LOG_RIP)	      syslog(LOG_DEBUG,		     "<%s>: metric for %s/%d on %s changes from %d to %d",		     __FUNCTION__, ip6str(&rte->rt_ripinfo.rip6_dest, 0),		     rte->rt_ripinfo.rip6_plen, ifname,		     orte->rt_ripinfo.rip6_metric,		     rte->rt_ripinfo.rip6_metric);	    ALTER_RTE;	    break; /* while(oripif) */	  }	} else {  /* nexthop differ (maybe came from another router) */#if 0     /* there is a heuristic which could be applied.  Normally,	it is senseless to replace a route if the new route has the same	metric as the existing route; this would cause the route to bounce	back and forth, which would generate an intolerable number of	triggered updates.  However, if the existing route is showing signs	of timing out, it may be better to switch to an equally-good	alternative route immediately, rather than waiting for the timeout to	happen.  Therefore, if the new metric is the same as the old one,	examine the timeout for the existing route.  If it is at least	halfway to the expiration point, switch to the new route.  This	heuristic is optional, but highly recommended. [rfc2080.txt]     */#endif	  if (rte->rt_ripinfo.rip6_metric == RIPNG_METRIC_UNREACHABLE ||	      orte->rt_ripinfo.rip6_metric <= rte->rt_ripinfo.rip6_metric) {	    oripif = NULL;  /* I mean "continue to next rte" */	    break; /* while(oripif) */	  } else {	    IFLOG(LOG_RIP)	      syslog(LOG_DEBUG, "<%s>: nexthop for %s/%d changes "		     "from %s to %s on %s",		     __FUNCTION__,		     ip6str(&rte->rt_ripinfo.rip6_dest, 0),		     rte->rt_ripinfo.rip6_plen,		     ip6str(&orte->rt_gw, oripif->rip_ife->ifi_ifn->if_index),		     ip6str(&rte->rt_gw, ripif->rip_ife->ifi_ifn->if_index),		     ifname);	    ALTER_RTE;	    break;	  }	} /*   (nexthop differ)   */      } else {	/* couldn't find the same RTE */      }      if ((oripif = oripif->rip_next) == ripifs)	break;#undef ALTER_RTE    } /*  while(oripif)  */    if (oripif == NULL) {      free(rte);      IFLOG(LOG_RIP)	syslog(LOG_DEBUG, "<%s>: skip", __FUNCTION__);      continue;   /* to next rte */    }    if (!(uprte)) {  /*  Nothing matched in rp_adj_ribs_in  */      if (rte->rt_ripinfo.rip6_metric == RIPNG_METRIC_UNREACHABLE) {	free(rte);	continue;   /* to next rte */      }      rte->rt_riptime = lifetime;  lifeyes = 1;      uprte = igp_enable_rte(rte);  /* copied */      if (uprte) unn++;    }    if (srte) {       struct rt_entry crte;      bgp_enable_rte(srte);      crte = *srte;      crte.rt_next = crte.rt_prev = &crte;      redistribute(&crte);   /* newly synchronized iBGP rte */    }    if (uprte) {      if (uprtehead) {	insque(uprte, uprtehead);      } else {	uprte->rt_next = uprte;	uprte->rt_prev = uprte;	uprtehead = uprte;      }    }  }   /* for (i<nn) */  /* triggerd update Go. */  if (uprtehead) {    redistribute(uprtehead);    while(uprtehead) {      uprtehead	= rte_remove(uprtehead, uprtehead);          }  }  if (lifeyes) {    lifetime->tsk_rip             = ripif;    lifetime->tsk_timename        = RIP_LIFE_TIMER;    lifetime->tsk_timefull.tv_sec = RIP_T_LIFE;    insque(lifetime, taskhead);        /* assume taskhead exists. */    task_timer_update(lifetime);  } else {    free(lifetime);  }  if (garbageyes) {    garbage->tsk_rip             = ripif;    garbage->tsk_timename        = RIP_GARBAGE_TIMER;    garbage->tsk_timefull.tv_sec = RIP_T_GARBAGE;    insque(garbage, taskhead);         /* assume taskhead exists. */    task_timer_update(garbage);  } else {    free(garbage);  }  IFLOG(LOG_RIP)    syslog(LOG_DEBUG, "<rip_process_response>: done, i=%d", i);  return (unn + dnn);}/* *  rip_sendmsg() *     Actually sendmsg. */intrip_sendmsg(sin, pktinfo, len)     struct sockaddr_in6 *sin;      /* dst addr.port           */     struct in6_pktinfo  *pktinfo;  /* src addr, outgoing I/F  */     int                  len;      /* data                    */{  int                 tlen;   /* sizeof To addr (for Adv. API) */  int                 slen;   /* sent data len                 */  struct msghdr       smsghdr;            /* Adv. API */  struct iovec        smsgiov;            /* Adv. API */  static char *cmsg = NULL;	/* buffer for ancillary data */  int cmsglen;  struct cmsghdr     *ch;                 /* Adv. API */  int                 shoplimit;          /* Adv. API */  char                ifname[IFNAMSIZ];  struct riphdr      *rp;    /* RIPng header   */  cmsglen = CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int));  memset(ifname, 0, IFNAMSIZ);  if (cmsg == NULL && (cmsg = malloc(cmsglen)) == NULL)    fatalx("<rip_sendmsg>: malloc failed");  memset(cmsg, 0, cmsglen);  shoplimit = RIPNG_HOPLIMIT;/***  Adv. API  ***/  tlen = sizeof(struct sockaddr_in6);  smsghdr.msg_name       = (caddr_t)sin;    /* dest addr.port              */  smsghdr.msg_namelen    = tlen;            /* size of address             */  smsgiov.iov_base       = (void *)rippkt;  /* buffer, base should be void */  smsgiov.iov_len        = len;             /* sending data len            */  smsghdr.msg_iov        = &smsgiov;  smsghdr.msg_iovlen     = 1; /* 1 iovec obj. */#ifdef ADVANCEDAPI  smsghdr.msg_control    = (caddr_t)cmsg;   /* buffer for ancillary data   */  smsghdr.msg_controllen = cmsglen;#endif  smsghdr.msg_flags      = 0; /* ? */  ch = CMSG_FIRSTHDR(&smsghdr);#ifdef ADVANCEDAPI  ch->cmsg_level = IPPROTO_IPV6;  ch->cmsg_type  = IPV6_PKTINFO;  ch->cmsg_len   = CMSG_LEN(sizeof(struct in6_pktinfo));  /* source address selection */  memcpy(CMSG_DATA(ch), pktinfo, sizeof(struct in6_pktinfo));  ch = CMSG_NXTHDR(&smsghdr, ch);  ch->cmsg_level = IPPROTO_IPV6;  ch->cmsg_type  = IPV6_HOPLIMIT;    /* may not be supported */  ch->cmsg_len   = CMSG_LEN(sizeof(int));  memcpy(CMSG_DATA(ch), &shoplimit, sizeof(int));#else  /* for hydranger */  if (IN6_IS_ADDR_MULTICAST(&sin->sin6_addr) &&      setsockopt(ripsock, IPPROTO_IPV6, IPV6_MULTICAST_IF,		 &pktinfo->ipi6_ifindex, sizeof(u_int)) < 0) {      fatal("<rip_sendmsg>: IPV6_MULTICAST_IF");  }#endif /* ADVANCEDAPI */  if ((slen = sendmsg(ripsock, &smsghdr, 0)) != len) {    syslog(LOG_ERR,                            /* spoofing or misconfig ? */	   "<rip_sendmsg>: sendmsg on %s (src=%s): %s",	   if_indextoname(pktinfo->ipi6_ifindex, ifname),	   ip6str(&pktinfo->ipi6_addr, 0), strerror(errno));    return(-1);  }  IFLOG(LOG_RIP) {    rp = (struct riphdr *)rippkt;    /* RIPng header   */    syslog(LOG_DEBUG,	   "RIPng SEND cmd %s, length %d", rip_msgstr[rp->riph_cmd], len);    syslog(LOG_DEBUG,	   "RIPng SEND %s+%d -> %s+%d (%s)",	   ip6str(&pktinfo->ipi6_addr, 0), RIPNG_PORT, ip6str2(sin),	   ntohs(sin->sin6_port),	   if_indextoname(pktinfo->ipi6_ifindex, ifname));  }  return(0);  /* End of rip_sendmsg */}/* *  rip_make_dump()  *    DESCRIPTION: make a RIP dump msg. *                 Split horizon applied. *                 Don't send the same I/F's direct route (metric = 0) * *     RETURN VALUES:  the number of RTEs */intrip_make_dump(ripif)        struct ripif *ripif;{  struct ripinfo6 *np;   /* RIPng RTE, nibbing to "ripbuf"  */  struct rtproto  *rtp, artp;  struct rt_entry *rte, *base, *agg;  int nn = 0;  np  = (struct ripinfo6 *)(ripbuf + sizeof(struct riphdr));  if (ripif->rip_mode & IFS_DEFAULTORIGINATE) {    memset(np, 0, sizeof(struct ripinfo6));    np->rip6_metric = 1;    np++;    nn++;    IFLOG(LOG_RIP)      syslog(LOG_DEBUG, "RIPng DUMP\t%d\tdefault(originated) on %s",	     nn,	     ripif->rip_ife->ifi_ifn->if_name);  }  memset(&artp, 0, sizeof(artp));  artp.rtp_type = RTPROTO_IF;  artp.rtp_if   = ripif->rip_ife;  aggr_flush();  rtp = ripif->rip_adj_ribs_out;  while(rtp) {    base = NULL;    switch(rtp->rtp_type) {    case RTPROTO_IF:      base = rtp->rtp_if->ifi_rte;      break;    case RTPROTO_BGP:    {	    struct rpcb *ebnp = find_epeer_by_rpcb(rtp->rtp_bgp);	    if (ebnp)		    base = ebnp->rp_adj_ribs_in;	    break;    }    case RTPROTO_RIP:      if (rtp->rtp_rip != ripif)                 /* split horizon */	base = rtp->rtp_rip->rip_adj_ribs_in;      break;    default:      fatalx("<rip_make_dump>: BUG !");      break;    }    rte = base;    while(rte) {      if ((rte->rt_flags & RTF_UP ||   /* iw97: avoid doublebooking */	   (rtp->rtp_type == RTPROTO_RIP &&	    rte->rt_flags & RTF_IGP_EGP_SYNC))) {	if ((rte->rt_flags & (RTF_BLACKHOLE|RTF_REJECT)) != 0) {	  IFLOG(LOG_RIP)	    syslog(LOG_DEBUG,		   "<%s>: rejected route (%s/%d) not advertised on %s",		   __FUNCTION__,		   ip6str(&rte->rt_ripinfo.rip6_dest, 0),		   rte->rt_ripinfo.rip6_plen,		   ripif->rip_ife->ifi_ifn->if_name);	  goto nextroute;	}	agg = rte->rt_aggr.ag_agg;	if (aggr_advable(agg, &artp) &&	    !rip_output_filter(ripif, &agg->rt_ripinfo)) {	  if ((ripif->rip_mode & IFS_DEFAULTORIGINATE) &&	      IN6_IS_ADDR_UNSPECIFIED(&agg->rt_ripinfo.rip6_dest) &&	      agg->rt_ripinfo.rip6_plen == 0) {	    IFLOG(LOG_RIP)	      syslog(LOG_DEBUG,		     "<%s>: ignore default route when originating",		     __FUNCTION__);		  goto nextroute;	  }	  memcpy(np, &agg->rt_ripinfo, sizeof(struct ripinfo6));	  np->rip6_metric = MIN(np->rip6_metric+1, RIPNG_METRIC_UNREACHABLE);	  IFLOG(LOG_RIP)

⌨️ 快捷键说明

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