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

📄 ripngd.c

📁 大名鼎鼎的路由器源码。程序分ZEBRA、OSPFRIP等3个包。程序框架采用一个路由协议一个进程的方式
💻 C
📖 第 1 页 / 共 5 页
字号:
     apply_mask_ipv6. */  apply_mask_ipv6 (&p);  /* Apply input filters. */  ri = ifp->info;  if (ri->list[RIPNG_FILTER_IN])    {      if (access_list_apply (ri->list[RIPNG_FILTER_IN], &p) == FILTER_DENY)	{	  if (IS_RIPNG_DEBUG_PACKET)	    zlog_info ("RIPng %s/%d is filtered by distribute in",		       inet6_ntop (&p.prefix), p.prefixlen);	  return;	}    }  if (ri->prefix[RIPNG_FILTER_IN])    {      if (prefix_list_apply (ri->prefix[RIPNG_FILTER_IN], &p) == PREFIX_DENY)	{	  if (IS_RIPNG_DEBUG_PACKET)	    zlog_info ("RIPng %s/%d is filtered by prefix-list in",		       inet6_ntop (&p.prefix), p.prefixlen);	  return;	}    }  /* Modify entry. */  if (ri->routemap[RIPNG_FILTER_IN])    {      int ret;      struct ripng_info newinfo;      memset (&newinfo, 0, sizeof (struct ripng_info));      newinfo.metric = rte->metric;      ret = route_map_apply (ri->routemap[RIPNG_FILTER_IN], 			     (struct prefix *)&p, RMAP_RIPNG, &newinfo);      if (ret == RMAP_DENYMATCH)	{	  if (IS_RIPNG_DEBUG_PACKET)	    zlog_info ("RIPng %s/%d is filtered by route-map in",		       inet6_ntop (&p.prefix), p.prefixlen);	  return;	}      rte->metric = newinfo.metric;    }  /* Set nexthop pointer. */  if (ripng_nexthop->flag == RIPNG_NEXTHOP_ADDRESS)    nexthop = &ripng_nexthop->address;  else    nexthop = &from->sin6_addr;  /* Lookup RIPng routing table. */  rp = route_node_get (ripng->table, (struct prefix *) &p);  if (rp->info == NULL)    {      /* Now, check to see whether there is already an explicit route	 for the destination prefix.  If there is no such route, add	 this route to the routing table, unless the metric is	 infinity (there is no point in adding a route which	 unusable). */      if (rte->metric != RIPNG_METRIC_INFINITY)	{	  rinfo = ripng_info_new ();	  	  /* - Setting the destination prefix and length to those in	     the RTE. */	  rp->info = rinfo;	  rinfo->rp = rp;	  /* - Setting the metric to the newly calculated metric (as	     described above). */	  rinfo->metric = rte->metric;	  rinfo->tag = ntohs (rte->tag);	  /* - Set the next hop address to be the address of the router	     from which the datagram came or the next hop address	     specified by a next hop RTE. */	  IPV6_ADDR_COPY (&rinfo->nexthop, nexthop);	  IPV6_ADDR_COPY (&rinfo->from, &from->sin6_addr);	  rinfo->ifindex = ifp->ifindex;	  /* - Initialize the timeout for the route.  If the	     garbage-collection timer is running for this route, stop it. */	  ripng_timeout_update (rinfo);	  /* - Set the route change flag. */	  rinfo->flags |= RIPNG_RTF_CHANGED;	  /* - Signal the output process to trigger an update (see section	     2.5). */	  ripng_event (RIPNG_TRIGGERED_UPDATE, 0);	  /* Finally, route goes into the kernel. */	  rinfo->type = ZEBRA_ROUTE_RIPNG;	  rinfo->sub_type = RIPNG_ROUTE_RTE;	  ripng_zebra_ipv6_add (&p, &rinfo->nexthop, rinfo->ifindex);	  rinfo->flags |= RIPNG_RTF_FIB;	  /* Aggregate check. */	  ripng_aggregate_increment (rp, rinfo);	}    }  else    {      rinfo = rp->info;	        /* If there is an existing route, compare the next hop address	 to the address of the router from which the datagram came.	 If this datagram is from the same router as the existing	 route, reinitialize the timeout.  */      same = (IN6_ARE_ADDR_EQUAL (&rinfo->from, &from->sin6_addr) 	      && (rinfo->ifindex == ifp->ifindex));      if (same)	ripng_timeout_update (rinfo);      /* Next, compare the metrics.  If the datagram is from the same	 router as the existing route, and the new metric is different	 than the old one; or, if the new metric is lower than the old	 one; do the following actions: */      if ((same && rinfo->metric != rte->metric) ||	  rte->metric < rinfo->metric)	{	  /* - Adopt the route from the datagram.  That is, put the	     new metric in, and adjust the next hop address (if	     necessary). */	  oldmetric = rinfo->metric;	  rinfo->metric = rte->metric;	  rinfo->tag = ntohs (rte->tag);	  if (! IN6_ARE_ADDR_EQUAL (&rinfo->nexthop, nexthop))	    {	      ripng_zebra_ipv6_delete (&p, &rinfo->nexthop, rinfo->ifindex);	      ripng_zebra_ipv6_add (&p, nexthop, ifp->ifindex);	      rinfo->flags |= RIPNG_RTF_FIB;	      IPV6_ADDR_COPY (&rinfo->nexthop, nexthop);	    }	  IPV6_ADDR_COPY (&rinfo->from, &from->sin6_addr);	  rinfo->ifindex = ifp->ifindex;	  /* - Set the route change flag and signal the output process	     to trigger an update. */	  rinfo->flags |= RIPNG_RTF_CHANGED;	  ripng_event (RIPNG_TRIGGERED_UPDATE, 0);	  /* - If the new metric is infinity, start the deletion	     process (described above); */	  if (rinfo->metric == RIPNG_METRIC_INFINITY)	    {	      /* If the new metric is infinity, the deletion process		 begins for the route, which is no longer used for		 routing packets.  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. */	      if (oldmetric != RIPNG_METRIC_INFINITY)		{		  /* - The garbage-collection timer is set for 120 seconds. */		  RIPNG_TIMER_ON (rinfo->t_garbage_collect, 				  ripng_garbage_collect, ripng->garbage_time);		  RIPNG_TIMER_OFF (rinfo->t_timeout);		  /* - The metric for the route is set to 16		     (infinity).  This causes the route to be removed		     from service.*/		  /* - The route change flag is to indicate that this		     entry has been changed. */		  /* - The output process is signalled to trigger a                     response. */		  ;  /* Above processes are already done previously. */		}	    }	  else	    {	      /* otherwise, re-initialize the timeout. */	      ripng_timeout_update (rinfo);	      /* Should a new route to this network be established		 while the garbage-collection timer is running, the		 new route will replace the one that is about to be		 deleted.  In this case the garbage-collection timer		 must be cleared. */	      RIPNG_TIMER_OFF (rinfo->t_garbage_collect);	    }	}      /* Unlock tempolary lock of the route. */      route_unlock_node (rp);    }}/* Add redistributed route to RIPng table. */voidripng_redistribute_add (int type, int sub_type, struct prefix_ipv6 *p, 			unsigned int ifindex){  struct route_node *rp;  struct ripng_info *rinfo;  /* Redistribute route  */  if (IN6_IS_ADDR_LINKLOCAL (&p->prefix))    return;  if (IN6_IS_ADDR_LOOPBACK (&p->prefix))    return;  rp = route_node_get (ripng->table, (struct prefix *) p);  rinfo = rp->info;  if (rinfo)    {      RIPNG_TIMER_OFF (rinfo->t_timeout);      RIPNG_TIMER_OFF (rinfo->t_garbage_collect);      route_unlock_node (rp);    }  else    {      rinfo = ripng_info_new ();      ripng_aggregate_increment (rp, rinfo);    }  rinfo->type = type;  rinfo->sub_type = sub_type;  rinfo->ifindex = ifindex;  rinfo->metric = 1;  rinfo->flags |= RIPNG_RTF_FIB;  rinfo->rp = rp;  rp->info = rinfo;}/* Delete redistributed route to RIPng table. */voidripng_redistribute_delete (int type, int sub_type, struct prefix_ipv6 *p, 			   unsigned int ifindex){  struct route_node *rp;  struct ripng_info *rinfo;  if (IN6_IS_ADDR_LINKLOCAL (&p->prefix))    return;  if (IN6_IS_ADDR_LOOPBACK (&p->prefix))    return;  rp = route_node_lookup (ripng->table, (struct prefix *) p);  if (rp)    {      rinfo = rp->info;      if (rinfo != NULL	  && rinfo->type == type 	  && rinfo->sub_type == sub_type 	  && rinfo->ifindex == ifindex)	{	  rp->info = NULL;	  RIPNG_TIMER_OFF (rinfo->t_timeout);	  RIPNG_TIMER_OFF (rinfo->t_garbage_collect);	  	  ripng_info_free (rinfo);	  route_unlock_node (rp);	}      /* For unlock route_node_lookup (). */      route_unlock_node (rp);    }}/* Withdraw redistributed route. */voidripng_redistribute_withdraw (int type){  struct route_node *rp;  struct ripng_info *rinfo;  for (rp = route_top (ripng->table); rp; rp = route_next (rp))    if ((rinfo = rp->info) != NULL)      {	if (rinfo->type == type)	  {	    rp->info = NULL;	    RIPNG_TIMER_OFF (rinfo->t_timeout);	    RIPNG_TIMER_OFF (rinfo->t_garbage_collect);	    ripng_info_free (rinfo);	    route_unlock_node (rp);	  }      }}/* RIP routing information. */voidripng_response_process (struct ripng_packet *packet, int size, 			struct sockaddr_in6 *from, struct interface *ifp,			int hoplimit){  caddr_t lim;  struct rte *rte;  struct ripng_nexthop nexthop;  /* RFC2080 2.4.2  Response Messages:   The Response must be ignored if it is not from the RIPng port.  */  if (ntohs (from->sin6_port) != RIPNG_PORT_DEFAULT)    {      zlog_warn ("RIPng packet comes from non RIPng port %d from %s",		 ntohs (from->sin6_port), inet6_ntop (&from->sin6_addr));      return;    }  /* The datagram's IPv6 source address should be checked to see   whether the datagram is from a valid neighbor; the source of the   datagram must be a link-local address.  */  if (! IN6_IS_ADDR_LINKLOCAL(&from->sin6_addr))   {      zlog_warn ("RIPng packet comes from non link local address %s",		 inet6_ntop (&from->sin6_addr));      return;    }  /* It is also worth checking to see whether the response is from one   of the router's own addresses.  Interfaces on broadcast networks   may receive copies of their own multicasts immediately.  If a   router processes its own output as new input, confusion is likely,   and such datagrams must be ignored. */  if (ripng_lladdr_check (ifp, &from->sin6_addr))    {      zlog_warn ("RIPng packet comes from my own link local address %s",		 inet6_ntop (&from->sin6_addr));      return;    }  /* As an additional check, periodic advertisements must have their   hop counts set to 255, and inbound, 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. */  if (hoplimit >= 0 && hoplimit != 255)    {      zlog_warn ("RIPng packet comes with non 255 hop count %d from %s",		 hoplimit, inet6_ntop (&from->sin6_addr));      return;    }  /* Reset nexthop. */  memset (&nexthop, 0, sizeof (struct ripng_nexthop));  nexthop.flag = RIPNG_NEXTHOP_UNSPEC;  /* Set RTE pointer. */  rte = packet->rte;  for (lim = ((caddr_t) packet) + size; (caddr_t) rte < lim; rte++)     {      /* First of all, we have to check this RTE is next hop RTE or         not.  Next hop RTE is completely different with normal RTE so         we need special treatment. */      if (rte->metric == RIPNG_METRIC_NEXTHOP)	{	  ripng_nexthop_rte (rte, from, &nexthop);	  continue;	}      /* RTE information validation. */      /* - is the destination prefix valid (e.g., not a multicast         prefix and not a link-local address) A link-local address         should never be present in an RTE. */      if (IN6_IS_ADDR_MULTICAST (&rte->addr))	{	  zlog_warn ("Destination prefix is a multicast address %s/%d [%d]",		     inet6_ntop (&rte->addr), rte->prefixlen, rte->metric);	  continue;	}      if (IN6_IS_ADDR_LINKLOCAL (&rte->addr))	{	  zlog_warn ("Destination prefix is a link-local address %s/%d [%d]",		     inet6_ntop (&rte->addr), rte->prefixlen, rte->metric);	  continue;	}      if (IN6_IS_ADDR_LOOPBACK (&rte->addr))	{	  zlog_warn ("Destination prefix is a loopback address %s/%d [%d]",		     inet6_ntop (&rte->addr), rte->prefixlen, rte->metric);	  continue;	}      /* - is the prefix length valid (i.e., between 0 and 128,         inclusive) */      if (rte->prefixlen > 128)	{	  zlog_warn ("Invalid prefix length %s/%d from %s%%%s",		     inet6_ntop (&rte->addr), rte->prefixlen,		     inet6_ntop (&from->sin6_addr), ifp->name);	  continue;	}      /* - is the metric valid (i.e., between 1 and 16, inclusive) */      if (! (rte->metric >= 1 && rte->metric <= 16))	{	  zlog_warn ("Invalid metric %d from %s%%%s", rte->metric,		     inet6_ntop (&from->sin6_addr), ifp->name);	  continue;	}      /* Metric calculation. */      rte->metric += ifp->metric;      if (rte->metric > RIPNG_METRIC_INFINITY)	rte->metric = RIPNG_METRIC_INFINITY;      /* Routing table updates. */      ripng_route_process (rte, from, &nexthop, ifp);    }}/* Response to request message. */voidripng_request_process (struct ripng_packet *packet,int size, 		       struct sockaddr_in6 *from, struct interface *ifp){  caddr_t lim;  struct rte *rte;  struct prefix_ipv6 p;  struct route_node *rp;  struct ripng_info *rinfo;  struct ripng_interface *ri;  /* Check RIPng process is enabled on this interface. */  ri = ifp->info;  if (! ri->running)    return;  /* When passive interface is specified, suppress responses */  if (ri->passive)    return;  lim = ((caddr_t) packet) + size;  rte = packet->rte;  /* The Request is processed entry by entry.  If there are no     entries, no response is given. */  if (lim == (caddr_t) rte)    return;  /* There is one special case.  If there is exactly one entry in the     request, and it has a destination prefix of zero, a prefix length     of zero, and a metric of infinity (i.e., 16), then this is a     request to send the entire routing table.  In that case, a call     is made to the output process to send the routing table to the     requesting address/port. */  if (lim == ((caddr_t) (rte + 1)) &&      IN6_IS_ADDR_UNSPECIFIED (&rte->addr) &&      rte->prefixlen == 0 &&      rte->metric == RIPNG_METRIC_INFINITY)    {	      /* All route with split horizon */      ripng_output_process (ifp, from, ripng_all_route, ripng_split_horizon);    }  else    {      /* Except for this special case, processing is quite simple.	 Examine the list of RTEs in the Request one by one.  For each	 entry, look up the destination in the router's routing	 database and, if there is a route, put that route's metric in	 the metric field of the RTE.  If there is no explicit route	 to the specified destination, put infinity in the metric	 field.  Once all the entries have been filled in, change the	 command from Request to Response and send the datagram back	 to the requestor. */      memset (&p, 0, sizeof (struct prefix_ipv6));      p.family = AF_INET6;      for (; ((caddr_t) rte) < lim; rte++)	{	  p.prefix = rte->addr;	  p.prefixlen = rte->prefixlen;	  apply_mask_ipv6 (&p);	  	  rp = route_node_lookup (ripng->table, (struct prefix *) &p);	  if (rp)	    {	      rinfo = rp->info;	      rte->metric = rinfo->metric;	      route_unlock_node (rp);	    }	  else	    rte->metric = RIPNG_METRIC_INFINITY;	}      packet->command = RIPNG_RESPONSE;      ripng_send_packet ((caddr_t) packet, size, from, ifp);    }}/* First entry point of reading RIPng packet. */int

⌨️ 快捷键说明

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