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

📄 ripng.c

📁 同时支持IPv4和IPv6的BGP协议实现
💻 C
📖 第 1 页 / 共 4 页
字号:
  }  if (ripif->rip_mode & IFS_NORIPIN)    return;             /* discard */    nn = (len - sizeof(struct riphdr)) / sizeof(struct ripinfo6);  if (nn == 0) return;             /* number of RTEs */  rp = (struct riphdr *)ripbuf;    /* RIPng header   */  if (rp->riph_vers !=  RIPNG_VERSION) {    syslog(LOG_ERR, "<rip_input>: Unknown RIPng version %d",	   rp->riph_vers);    return;  }  rp->riph_zero2 = 0;             /* must be ignored, and must be zero */   switch (rp->riph_cmd) {         /* received cmd */  case RIPNGCMD_REQUEST:    ripif->rip_requestrcvd++;    IFLOG(LOG_RIP)	    syslog(LOG_DEBUG, "RIPng RECV cmd=%s, length=%d, nn=%d",		   rip_msgstr[rp->riph_cmd], len, nn);    if (ripif->rip_mode & IFS_NORIPOUT)      return;    ife = ifentry;    while(ife) {  /* from myself ? */      if (ife->ifi_ifn->if_index == rpktinfo->ipi6_ifindex &&	  IN6_ARE_ADDR_EQUAL(&ife->ifi_laddr, &fsock.sin6_addr) &&	  ripsin.sin6_port == fsock.sin6_port) {	return;      }      if ((ife = ife->ifi_next) == ifentry)	break; /* while */    }        nn = rip_process_request(ripif, nn);      if (nn > 0) {      int mm;  /* current */      int done;      done = 0;      if (fsock.sin6_port != ripsin.sin6_port &&        /* RIPNG_PORT */	  !IN6_ARE_ADDR_EQUAL(&rpktinfo->ipi6_addr, &ripsin.sin6_addr) &&	  !IN6_IS_ADDR_UNSPECIFIED(&ripif->rip_ife->ifi_gaddr))	spktinfo.ipi6_addr = ripif->rip_ife->ifi_gaddr; /* copy */      else	spktinfo.ipi6_addr = ripif->rip_ife->ifi_laddr; /* copy */      spktinfo.ipi6_ifindex = rpktinfo->ipi6_ifindex;      while(1) {	mm = MIN(nn - done, RIPNG_MAXRTES);	memcpy(&rippkt[sizeof(struct riphdr)],	       &ripbuf[sizeof(struct riphdr) + done*sizeof(struct ripinfo6)],	       mm * sizeof(struct ripinfo6));	if (rip_sendmsg(&fsock,     /* sender's addr.port  */			&spktinfo,  /* source address, I/F */			sizeof(struct riphdr) + mm * sizeof(struct ripinfo6)))	  ripif->rip_respfail++;	ripif->rip_responsesent++;	done += mm;	if (done == nn) break;      }    }    break;  case RIPNGCMD_RESPONSE:    ripif->rip_responsercvd++;    if (ntohs(fsock.sin6_port) != RIPNG_PORT) {      IFLOG(LOG_RIP)	syslog(LOG_DEBUG,	       "<rip_input>: Response from non RIPng port: %s+%d on %s",	       ip6str2(&fsock), ntohs(fsock.sin6_port),	       if_indextoname(rpktinfo->ipi6_ifindex, ifname));      return; /* The Response must be ignored		 if it is not from the RIPng port. [rfc2080] */    }    if (!IN6_IS_ADDR_LINKLOCAL(&fsock.sin6_addr)) {      IFLOG(LOG_RIP)	syslog(LOG_ERR,	       "<rip_input>: Response from non-linklocal addr: %s on %s",	       ip6str2(&fsock),	       if_indextoname(rpktinfo->ipi6_ifindex, ifname));      return;  /* Ignore response msg from non-link-local address [rfc2080] */    }    /* It is also worth checking to see whether the       response is from one of the router's own addresses [rfc2080] */    ife = ifentry;    while(ife) {      if (ife->ifi_ifn->if_index == rpktinfo->ipi6_ifindex &&	  IN6_ARE_ADDR_EQUAL(&ife->ifi_laddr, &fsock.sin6_addr)) {	return;      }      if ((ife = ife->ifi_next) == ifentry)	break; /* while */    }#ifdef ADVANCEDAPI    /* multicast packets sent from the RIPng port       (i.e. periodic advertisement or triggered update packets) must be       examined to ensure that the hop count is 255. [rfc2080] */    if (rhoplimit != NULL && *rhoplimit != RIPNG_HOPLIMIT &&	rpktinfo != NULL && IN6_IS_ADDR_MULTICAST(&rpktinfo->ipi6_addr)) {      IFLOG(LOG_RIP)	syslog(LOG_ERR,	       "<%s>: Response from non-neighbor: %s on %s, hoplimit=%d",	       __FUNCTION__,	       ip6str2(&fsock), if_indextoname(rpktinfo->ipi6_ifindex, ifname),	       *rhoplimit);      return;    }#endif    IFLOG(LOG_RIP)      syslog(LOG_DEBUG,	     "RIPng RECV cmd=%s, length=%d, nn=%d",	     rip_msgstr[rp->riph_cmd], len, nn);    nn = rip_process_response(ripif, nn);    IFLOG(LOG_RIP)      syslog(LOG_DEBUG,	     "<rip_input>: rip_process_response() returned. (nn=%d)", nn);    break;  default:    syslog(LOG_ERR,	   "<rip_input>: Unknow RIPng command %d", rp->riph_cmd);    break;  }  return; }/* *  rip_process_request() */intrip_process_request(ripif, nn)     struct ripif *ripif;     int           nn;     /* the Number of ripinfo6 */{  int i;  struct ripinfo6 *np;     /* RIPng RTE              */  struct rt_entry  key;  struct rt_entry *base, *rte;  struct rtproto  *rtp;  struct riphdr   *rp;  rp = (struct riphdr *)rippkt;    /* outgoing RIPng header  */  rp->riph_cmd   = RIPNGCMD_RESPONSE;  rp->riph_vers  = RIPNG_VERSION;  rp->riph_zero2 = 0;  np  = (struct ripinfo6 *)(ripbuf + sizeof(struct riphdr));  /* DUMP request */  if (nn == 1 &&      IN6_IS_ADDR_UNSPECIFIED(&np->rip6_dest) &&      np->rip6_plen   == 0 &&      np->rip6_metric == RIPNG_METRIC_UNREACHABLE) {    nn = rip_make_dump(ripif);    return nn;  }  /* If the request is for specific entries, they are looked up in the     routing table and the information is returned as is;     no Split Horizon processing is done.              [rfc2080  2.4.1] */  for (i = 0 ; i < nn ; i++, np++ ) {    rte = NULL;    memset(&key, 0, sizeof(key));    key.rt_ripinfo.rip6_dest = np->rip6_dest;    key.rt_ripinfo.rip6_plen = np->rip6_plen;      rtp = ripif->rip_adj_ribs_out;    while(rtp) {      switch(rtp->rtp_type) {      case RTPROTO_IF:	base = rtp->rtp_if->ifi_rte;	break;      case RTPROTO_BGP:	base = rtp->rtp_bgp->rp_adj_ribs_in;	break;      case RTPROTO_RIP:	base = rtp->rtp_rip->rip_adj_ribs_in;	break;      default:	fatalx("<rip_process_request>: BUG !");	base = NULL;	/*pacify gcc*/	break;			/* NOTREACHED */      }      rte = find_rte(&key, base);      if (rte) break;  /* while */      if ((rtp = rtp->rtp_next) ==  ripif->rip_adj_ribs_out)	break;         /* while */    }    if (rte) {  /* advertizing via RIP */      np->rip6_metric = MIN(rte->rt_ripinfo.rip6_metric + 1, 			    RIPNG_METRIC_UNREACHABLE);      np->rip6_tag    = rte->rt_ripinfo.rip6_tag; /* AS number (net byte) */    } else {      np->rip6_metric = RIPNG_METRIC_UNREACHABLE;      np->rip6_tag    = 0;                        /* no info              */    }  } /* for */  return nn;  /* End of rip_process_request() */}/* * *  rip_process_response() *     DESCRIPTION:   install RTE. and redistribute, if needed. *     RETURN VALUES: the number of "triggered updated" RTEs. (ad-hoc) */intrip_process_response(ripif, nn)     struct ripif *ripif;     int           nn;     /* the Number of ripinfo6 */{  int i;  int unn, dnn;                               /*  return. (no use)    */  struct ripinfo6 *np;                        /*  nibbing             */  struct in6_addr *nhaddr;                    /* "nexthop" address    */  struct ripif    *oripif;  struct rt_entry *uprtehead,  *uprte; /* copied object by igp_enable_rte()  */  struct rt_entry              *dwnrte;/* copied object by rip_disable_rte() */  task            *lifetime,  *garbage;       /*  may be registered          */  byte             lifeyes,    garbageyes;  char *ifname = ripif->rip_ife->ifi_ifn->if_name; /* for debugging use */  extern struct ifinfo    *ifentry;  extern task             *taskhead;  extern byte              bgpyes;  extern struct rt_entry  *aggregations;  IFLOG(LOG_RIP)    syslog(LOG_DEBUG, "<rip_process_response>: invoked, nn=%d", nn);  uprtehead = NULL;  unn = dnn = 0;  MALLOC(lifetime, task);    lifeyes    = 0;  MALLOC(garbage,  task);    garbageyes = 0;    nhaddr = &fsock.sin6_addr;          /*  sender's address (normally) */  np  = (struct ripinfo6 *)&(ripbuf[sizeof(struct riphdr)]);  for (i = 0 ; i < nn ; i++, np++ ) {    struct rt_entry *rte;           /* to be installed    */    struct rt_entry *srte = NULL;   /* newly synchronized */    struct ifinfo   *ife;           /* search for         */    struct rt_entry *orte = NULL;   /* old RTE            */    uprte = NULL;    IFLOG(LOG_RIP)      syslog(LOG_DEBUG, "RIPng RECV\t%d\t%s/%d (%d) on %s",	     i, ip6str(&np->rip6_dest, 0),	     np->rip6_plen, np->rip6_metric, ifname);    if (np->rip6_metric == RIPNG_METRIC_NEXTHOP) { /* "nexthop" address */      if (IN6_IS_ADDR_LINKLOCAL(&np->rip6_dest))	nhaddr = &np->rip6_dest;       else	nhaddr = &fsock.sin6_addr;   /* sender's */      continue;    }    if (!IN6_IS_ADDR_ROUTABLE(&np->rip6_dest)) {	    syslog(LOG_NOTICE,		   "<%s>: non-routable address(%s/%d) on %s",		   __FUNCTION__, ip6str(&np->rip6_dest, 0), np->rip6_plen,		   ripif->rip_ife->ifi_ifn->if_name);	    continue;  /* ignore */    }    /*     * Check route filter and restriction.     */    if (input_filter_check(&ripif->rip_filterset, rip_use_sitelocal, np)) {      IFLOG(LOG_RIP)	syslog(LOG_DEBUG,	       "<%s>: incoming route %s/%d on %s was filtered",	       __FUNCTION__, ip6str(&np->rip6_dest, 0), np->rip6_plen,	       ripif->rip_ife->ifi_ifn->if_name);	      continue;    }    if (np->rip6_metric == 0 ||	np->rip6_metric > RIPNG_METRIC_UNREACHABLE) { 	    syslog(LOG_NOTICE,		   "<%s>: invaid metric(%d) for %s/%d on %s", __FUNCTION__,		   np->rip6_metric, ip6str(&np->rip6_dest, 0), np->rip6_plen,		   ripif->rip_ife->ifi_ifn->if_name);	    continue;  /* ignore */    }    else {	    /* incoming metric addition(if specified) */	    if (ripif->rip_metricin) {		    np->rip6_metric += ripif->rip_metricin;		    if (np->rip6_metric > RIPNG_METRIC_UNREACHABLE)			    np->rip6_metric = RIPNG_METRIC_UNREACHABLE;		    IFLOG(LOG_RIP)		      syslog(LOG_DEBUG,			     "RIPng METRIC ADD\t%d\t%s/%d (%d) on %s",			     i, ip6str(&np->rip6_dest, 0),			     np->rip6_plen, np->rip6_metric, ifname);	    }    }    if (np->rip6_plen > 128) {      syslog(LOG_ERR, 	     "<rip_process_response>: invaid plefix length(%d)", np->rip6_plen);      continue;  /* ignore */    }    if (np->rip6_plen == 128) {      ife = ifentry;      while(ife) {	/*  check I/F addrs  */	if (IN6_ARE_ADDR_EQUAL(&np->rip6_dest, &ife->ifi_gaddr)) {	  ife = NULL;	  break;	}	if ((ife = ife->ifi_next) == ifentry)	  break;      }      if (ife == NULL) {	continue;  /* ignore */	      }    }    MALLOC(rte, struct rt_entry);    rte->rt_gw                  = *nhaddr;    /* copy                       */    rte->rt_flags               = RTF_UP|RTF_GATEWAY;    rte->rt_ripinfo             = *np;  /* tag must be preserved and readvd */    mask_nclear(&rte->rt_ripinfo.rip6_dest, rte->rt_ripinfo.rip6_plen);    if (rte->rt_ripinfo.rip6_plen == 128)      rte->rt_flags |= RTF_HOST;    rte->rt_proto.rtp_type      = RTPROTO_RIP;    rte->rt_proto.rtp_rip       = ripif; /* for each RTE, each RTP exists.  */    rte->rt_riptime             = NULL;    rte->rt_aspath              = NULL;/*  rte->rt_aggr                = 0;    */    /**  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) */      IFLOG(LOG_RIP)	syslog(LOG_DEBUG,	       "<%s>: I/F direct route(%s/%d on %s) cannot overwritten",	       __FUNCTION__,	       ip6str(&orte->rt_ripinfo.rip6_dest, 0),	       orte->rt_ripinfo.rip6_plen, ifname);      free(rte);      continue;  /* to next rte */    }    /**  check aggregate routes  **/    if (find_rte(rte, aggregations)) {      IFLOG(LOG_RIP)	syslog(LOG_DEBUG,	       "<%s>: aggregate route %s/%d on %s cannot overwritten",	       __FUNCTION__, ip6str(&rte->rt_ripinfo.rip6_dest, 0),	       rte->rt_ripinfo.rip6_plen, ifname);      free(rte);      continue;  /* to next rte */    }    /**  check BGP routes              **/    /**    exclude Poisoned Reverse    **/    if (bgpyes &&                       	rte->rt_ripinfo.rip6_metric != RIPNG_METRIC_UNREACHABLE) {      struct rpcb        *obnp;      extern struct rpcb *bgb;      obnp = bgb;      while(obnp) {	if (obnp->rp_mode & BGPO_IGP &&	    (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.",		     __FUNCTION__, ip6str(&rte->rt_ripinfo.rip6_dest, 0),		     rte->rt_ripinfo.rip6_plen, ifname);	    bgp_disable_rte(orte); /* XXX: do not have to propagate? */	  }	  else {	    /**   route synchronization  (1998/06/27)  **/	    if (rte->rt_ripinfo.rip6_tag == orte->rt_ripinfo.rip6_tag) {	      rte->rt_flags  |=   RTF_IGP_EGP_SYNC;	      rte->rt_flags  &=  ~RTF_UP;	      if (!(orte->rt_flags & RTF_IGP_EGP_SYNC)) {		IFLOG(LOG_RIP)		  syslog(LOG_DEBUG, "<%s>: synchronized...%s/%d on %s, tag=%u",			 __FUNCTION__, ip6str(&rte->rt_ripinfo.rip6_dest, 0),			 rte->rt_ripinfo.rip6_plen, ifname,			 ntohs(rte->rt_ripinfo.rip6_tag));		orte->rt_flags |=   RTF_IGP_EGP_SYNC;		/* don't touch RTF_UP, for backup-route */		srte = orte;	      }	    }

⌨️ 快捷键说明

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