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

📄 ripngd.c

📁 linux 路由软件 可支持RIP OSPF BGP等
💻 C
📖 第 1 页 / 共 5 页
字号:
      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. */intripng_read (struct thread *thread){  int len;  int sock;  struct sockaddr_in6 from;  struct ripng_packet *packet;  unsigned int ifindex;  struct interface *ifp;  int hoplimit = -1;  /* Check ripng is active and alive. */  assert (ripng != NULL);  assert (ripng->sock >= 0);  /* Fetch thread data and set read pointer to empty for event     managing.  `sock' sould be same as ripng->sock. */  sock = THREAD_FD (thread);  ripng->t_read = NULL;  /* Add myself to the next event. */  ripng_event (RIPNG_READ, sock);  /* Read RIPng packet. */  len = ripng_recv_packet (sock, STREAM_DATA (ripng->ibuf), 			   STREAM_SIZE (ripng->ibuf), &from, &ifindex,			   &hoplimit);  if (len < 0)     {      zlog_warn ("RIPng recvfrom failed: %s.", strerror (errno));      return len;    }  /* Check RTE boundary.  RTE size (Packet length - RIPng header size     (4)) must be multiple size of one RTE size (20). */  if (((len - 4) % 20) != 0)    {      zlog_warn ("RIPng invalid packet size %d from %s", len,		 inet6_ntop (&from.sin6_addr));      return 0;    }  packet = (struct ripng_packet *) STREAM_DATA (ripng->ibuf);  ifp = if_lookup_by_index (ifindex);  /* RIPng packet received. */  if (IS_RIPNG_DEBUG_EVENT)    zlog_info ("RIPng packet received from %s port %d on %s",	       inet6_ntop (&from.sin6_addr), ntohs (from.sin6_port), 	       ifp ? ifp->name : "unknown");  /* Logging before packet checking. */  if (IS_RIPNG_DEBUG_RECV)    ripng_packet_dump (packet, len, "RECV");  /* Packet comes from unknown interface. */  if (ifp == NULL)    {      zlog_warn ("RIPng packet comes from unknown interface %d", ifindex);      return 0;    }  /* Packet version mismatch checking. */  if (packet->version != ripng->version)     {      zlog_warn ("RIPng packet version %d doesn't fit to my version %d", 		 packet->version, ripng->version);      return 0;    }  /* Process RIPng packet. */  switch (packet->command)    {    case RIPNG_REQUEST:      ripng_request_process (packet, len, &from, ifp);      break;    case RIPNG_RESPONSE:      ripng_response_process (packet, len, &from, ifp, hoplimit);      break;    default:      zlog_warn ("Invalid RIPng command %d", packet->command);      break;    }  return 0;}/* Walk down the RIPng routing table then clear changed flag. */voidripng_clear_changed_flag (){  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->flags & RIPNG_RTF_CHANGED)	rinfo->flags &= ~RIPNG_RTF_CHANGED;}/* Regular update of RIPng route.  Send all routing formation to RIPng   enabled interface. */intripng_update (struct thread *t){  listnode node;  struct interface *ifp;  struct ripng_interface *ri;  /* Clear update timer thread. */  ripng->t_update = NULL;  /* Logging update event. */  if (IS_RIPNG_DEBUG_EVENT)    zlog_info ("RIPng update timer expired!");  /* Supply routes to each interface. */  for (node = listhead (iflist); node; nextnode (node))    {      ifp = getdata (node);      ri = ifp->info;      if (if_is_loopback (ifp) || ! if_is_up (ifp))	continue;      if (! ri->running)	continue;      /* When passive interface is specified, suppress announce to the         interface. */      if (ri->passive)	continue;#if RIPNG_ADVANCED      if (ri->ri_send == RIPNG_SEND_OFF)	{	  if (IS_RIPNG_DEBUG_EVENT)	    zlog (NULL, LOG_INFO, 		  "[Event] RIPng send to if %d is suppressed by config",		 ifp->ifindex);	  continue;	}#endif /* RIPNG_ADVANCED */      ripng_output_process (ifp, NULL, ripng_all_route, ripng_split_horizon);    }  /* Triggered updates may be suppressed if a regular update is due by     the time the triggered update would be sent. */  if (ripng->t_triggered_interval)    {      thread_cancel (ripng->t_triggered_interval);      ripng->t_triggered_interval = NULL;    }  ripng->trigger = 0;  /* Reset flush event. */  ripng_event (RIPNG_UPDATE_EVENT, 0);  return 0;}/* Triggered update interval timer. */intripng_triggered_interval (struct thread *t){  ripng->t_triggered_interval = NULL;  if (ripng->trigger)    {      ripng->trigger = 0;      ripng_triggered_update (t);    }  return 0;}     /* Execute triggered update. */intripng_triggered_update (struct thread *t){  listnode node;  struct interface *ifp;  struct ripng_interface *ri;  int interval;  ripng->t_triggered_update = NULL;  /* Cancel interval timer. */  if (ripng->t_triggered_interval)    {      thread_cancel (ripng->t_triggered_interval);      ripng->t_triggered_interval = NULL;    }  ripng->trigger = 0;  /* Logging triggered update. */  if (IS_RIPNG_DEBUG_EVENT)    zlog_info ("RIPng triggered update!");  /* Split Horizon processing is done when generating triggered     updates as well as normal updates (see section 2.6). */  for (node = listhead (iflist); node; nextnode (node))    {      ifp = getdata (node);      ri = ifp->info;      if (if_is_loopback (ifp) || ! if_is_up (ifp))	continue;      if (! ri->running)	continue;      /* When passive interface is specified, suppress announce to the         interface. */      if (ri->passive)	continue;      ripng_output_process (ifp, NULL, ripng_changed_route,			    ripng_split_horizon);    }  /* Once all of the triggered updates have been generated, the route     change flags should be cleared. */  ripng_clear_changed_flag ();  /* After a triggered update is sent, a timer should be set for a     random interval between 1 and 5 seconds.  If other changes that     would trigger updates occur before the timer expires, a single     update is triggered when the timer expires. */  interval = (random () % 5) + 1;  ripng->t_triggered_interval =     thread_add_timer (master, ripng_triggered_interval, NULL, interval);  return 0;}/* Write routing table entry to the stream and return next index of   the routing table entry in the stream. */intripng_write_rte (int num, struct stream *s, struct prefix_ipv6 *p,		 u_int16_t tag, u_char metric){  /* RIPng packet header. */  if (num == 0)    {      stream_putc (s, RIPNG_RESPONSE);      stream_putc (s, RIPNG_V1);      stream_putw (s, 0);    }  /* Write routing table entry. */  stream_write (s, (caddr_t) &p->prefix, sizeof (struct in6_addr));  stream_putw (s, tag);  stream_putc (s, p->prefixlen);  stream_putc (s, metric);  return ++num;}/* Send RESPONSE message to specified destination. */voidripng_output_process (struct interface *ifp, struct sockaddr_in6 *to,		      int route_type, int split_horizon){  int ret;  struct stream *s;  struct route_node *rp;  struct ripng_info *rinfo;  struct ripng_interface *ri;  struct ripng_aggregate *aggregate;  struct prefix_ipv6 *p;  int num;  int mtu;  int rtemax;  u_char metric;  u_char metric_set;  if (IS_RIPNG_DEBUG_EVENT)    zlog_info ("RIPng update routes on interface %s", ifp->name);  /* Output stream get from ripng structre.  XXX this should be     interface structure. */  s = ripng->obuf;  /* Reset stream and RTE counter. */  stream_reset (s);  num = 0;  mtu = ifp->mtu;  if (mtu < 0)    mtu = IFMINMTU;  rtemax = (min (mtu, RIPNG_MAX_PACKET_SIZE) -	    IPV6_HDRLEN - 	    sizeof (struct udphdr) -	    sizeof (struct ripng_packet) +	    sizeof (struct rte)) / sizeof (struct rte);#ifdef DEBUG  zlog_info ("DEBUG RIPng: ifmtu is %d", ifp->mtu);  zlog_info ("DEBUG RIPng: rtemax is %d", rtemax);#endif /* DEBUG */    /* Get RIPng interface. */  ri = ifp->info;    for (rp = route_top (ripng->table); rp; rp = route_next (rp))    {      if ((rinfo = rp->info) != NULL && rinfo->suppress == 0)	{	  p = (struct prefix_ipv6 *) &rp->p;	  metric = rinfo->metric;	  /* Changed route only output. */	  if (route_type == ripng_changed_route &&	      (! (rinfo->flags & RIPNG_RTF_CHANGED)))	    continue;	  /* Split horizon. */	  if (split_horizon == ripng_split_horizon &&	      rinfo->ifindex == ifp->ifindex)	    continue;		  /* Apply output filters.*/	  if (ri->list[RIPNG_FILTER_OUT])	    {	      if (access_list_apply (ri->list[RIPNG_FILTER_OUT], 				     (struct prefix *) p) == FILTER_DENY)		{		  if (IS_RIPNG_DEBUG_PACKET)		    zlog_info ("RIPng %s/%d is filtered by distribute out",			       inet6_ntop (&p->prefix), p->prefixlen);		  continue;		}	    }	  if (ri->prefix[RIPNG_FILTER_OUT])	    {	      if (prefix_list_apply (ri->prefix[RIPNG_FILTER_OUT], 				     (struct prefix *) p) == PREFIX_DENY)		{		  if (IS_RIPNG_DEBUG_PACKET)		    zlog_info ("RIPng %s/%d is filtered by prefix-list out",			       inet6_ntop (&p->prefix), p->prefixlen);		  continue;		}	    }	  /* Preparation for route-map. */	  metric_set = 0;	  /* Route-map */	  if (ri->routemap[RIPNG_FILTER_OUT])	    {	      int ret;	      struct ripng_info newinfo;	      memset (&newinfo, 0, sizeof (struct ripng_info));	      newinfo.metric = metric;	      ret = route_map_apply (ri->routemap[RIPNG_FILTER_OUT], 				     (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 out",			       inet6_ntop (&p->prefix), p->prefixlen);		  return;		}	      metric = newinfo.metric;	      metric_set = newinfo.metric_set;	    }	  /* When the interface route-map does not set metric */	  if (! metric_set)	    {	      /* and the redistribute route-map is set. */	      if (ripng->route_map[rinfo->type].name)		{		  int ret;		  struct ripng_info newinfo;		  memset (&newinfo, 0, sizeof (struct ripng_info));		  newinfo.metric = metric;	      		  ret = route_map_apply (ripng->route_map[rinfo->type].map,					 (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",				   inet6_ntop (&p->prefix), p->prefixlen);		      continue;		    }		  metric = newinfo.metric;		  metric_set = newinfo.metric_set;		}	      /* When the redistribute route-map does not set metric. */	      if (! metric_set)		{		  /* If the redistribute metric is set. */		  if (ripng->route_map[rinfo->type].metric_config		      && rinfo->metric != RIPNG_METRIC_INFINITY)		    {		      metric = ripng->route_map[rinfo->type].metric;		    }		  else		    {		      /* If the route is not connected or localy generated			 one, use default-metric value */		      if (rinfo->type != ZEBRA_ROUTE_RIPNG			  && rinfo->type != ZEBRA_ROUTE_CONNECT			  && rinfo->metric != RIPNG_METRIC_INFINITY)			metric = ripng->default_metric;		    }		}	    }	  /* Write RTE to the stream. */	  num = ripng_write_rte (num, s, p, rinfo->tag, metric);	  if (num == rtemax)	    {	      ret = ripng_send_packet (STREAM_DATA (s), stream_get_endp (s),				       to, ifp);	      if (ret >= 0 && IS_RIPNG_DEBUG_SEND)		ripng_packet_dump ((struct ripng_packet *)STREAM_DATA (s),				   stream_get_endp(s), "SEND");	      num = 0;	      stream_reset (s);

⌨️ 快捷键说明

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