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

📄 ripngd.c

📁 大名鼎鼎的路由器源码。程序分ZEBRA、OSPFRIP等3个包。程序框架采用一个路由协议一个进程的方式
💻 C
📖 第 1 页 / 共 5 页
字号:
ripng_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);	    }	}      if ((aggregate = rp->aggregate) != NULL && 	  aggregate->count > 0 && 	  aggregate->suppress == 0)	{	  p = (struct prefix_ipv6 *) &rp->p;	  metric = aggregate->metric;	  /* 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;		}	    }	  /* 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;	    }	  /* Changed route only output. */	  if (route_type == ripng_changed_route)	    continue;	  /* Write RTE to the stream. */	  num = ripng_write_rte (num, s, p, aggregate->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)

⌨️ 快捷键说明

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