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

📄 ripd.c

📁 大名鼎鼎的路由器源码。程序分ZEBRA、OSPFRIP等3个包。程序框架采用一个路由协议一个进程的方式
💻 C
📖 第 1 页 / 共 5 页
字号:
	      {		/* If the route is not connected or localy generated		   one, use default-metric value*/		if (rinfo->type != ZEBRA_ROUTE_RIP 		    && rinfo->type != ZEBRA_ROUTE_CONNECT		    && rinfo->metric != RIP_METRIC_INFINITY)		  rinfo->metric_out = rip->default_metric;	      }	  }	/* Apply offset-list */	if (rinfo->metric != RIP_METRIC_INFINITY)	  rip_offset_list_apply_out (p, ifp, &rinfo->metric_out);	if (rinfo->metric_out > RIP_METRIC_INFINITY)	  rinfo->metric_out = RIP_METRIC_INFINITY;	  	/* Write RTE to the stream. */	num = rip_write_rte (num, s, p, version, rinfo, to ? NULL : ifp);	if (num == rtemax)	  {	    if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)	      rip_auth_md5_set (s, ifp);	    ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s),				   to, ifp);	    if (ret >= 0 && IS_RIP_DEBUG_SEND)	      rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),			       stream_get_endp(s), "SEND");	    num = 0;	    stream_reset (s);	  }      }  /* Flush unwritten RTE. */  if (num != 0)    {      if (version == RIPv2 && ri->auth_type == RIP_AUTH_MD5)	rip_auth_md5_set (s, ifp);      ret = rip_send_packet (STREAM_DATA (s), stream_get_endp (s), to, ifp);      if (ret >= 0 && IS_RIP_DEBUG_SEND)	rip_packet_dump ((struct rip_packet *)STREAM_DATA (s),			 stream_get_endp (s), "SEND");      num = 0;      stream_reset (s);    }  /* Statistics updates. */  ri->sent_updates++;}/* Send RIP packet to the interface. */voidrip_update_interface (struct interface *ifp, u_char version, int route_type){  struct prefix_ipv4 *p;  struct connected *connected;  listnode node;  struct sockaddr_in to;  /* When RIP version is 2 and multicast enable interface. */  if (version == RIPv2 && if_is_multicast (ifp))     {      if (IS_RIP_DEBUG_EVENT)	zlog_info ("multicast announce on %s ", ifp->name);      rip_output_process (ifp, NULL, route_type, version);      return;    }  /* If we can't send multicast packet, send it with unicast. */  if (if_is_broadcast (ifp) || if_is_pointopoint (ifp))    {      for (node = listhead (ifp->connected); node; nextnode (node))	{	    	  connected = getdata (node);	  /* Fetch broadcast address or poin-to-point destination             address . */	  p = (struct prefix_ipv4 *) connected->destination;	  if (p->family == AF_INET)	    {	      /* Destination address and port setting. */	      memset (&to, 0, sizeof (struct sockaddr_in));	      to.sin_addr = p->prefix;	      to.sin_port = htons (RIP_PORT_DEFAULT);	      if (IS_RIP_DEBUG_EVENT)		zlog_info ("%s announce to %s on %s",			   if_is_pointopoint (ifp) ? "unicast" : "broadcast",			   inet_ntoa (to.sin_addr), ifp->name);	      rip_output_process (ifp, &to, route_type, version);	    }	}    }}/* Update send to all interface and neighbor. */voidrip_update_process (int route_type){  listnode node;  struct interface *ifp;  struct rip_interface *ri;  struct route_node *rp;  struct sockaddr_in to;  struct prefix_ipv4 *p;  /* Send RIP update to each interface. */  for (node = listhead (iflist); node; nextnode (node))    {      ifp = getdata (node);      if (if_is_loopback (ifp))	continue;      if (! if_is_up (ifp))	continue;      /* Fetch RIP interface information. */      ri = ifp->info;      /* When passive interface is specified, suppress announce to the         interface. */      if (ri->passive)	continue;      if (ri->running)	{	  if (IS_RIP_DEBUG_EVENT) 	    {	      if (ifp->name) 		zlog_info ("SEND UPDATE to %s ifindex %d",			   ifp->name, ifp->ifindex);	      else		zlog_info ("SEND UPDATE to _unknown_ ifindex %d",			   ifp->ifindex);	    }	  /* If there is no version configuration in the interface,             use rip's version setting. */	  if (ri->ri_send == RI_RIP_UNSPEC)	    {	      if (rip->version == RIPv1)		rip_update_interface (ifp, RIPv1, route_type);	      else		rip_update_interface (ifp, RIPv2, route_type);	    }	  /* If interface has RIP version configuration use it. */	  else	    {	      if (ri->ri_send & RIPv1)		rip_update_interface (ifp, RIPv1, route_type);	      if (ri->ri_send & RIPv2)		rip_update_interface (ifp, RIPv2, route_type);	    }	}    }  /* RIP send updates to each neighbor. */  for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))    if (rp->info != NULL)      {	p = (struct prefix_ipv4 *) &rp->p;	ifp = if_lookup_address (p->prefix);	if (! ifp)	  {	    zlog_warn ("Neighbor %s doesn't exist direct connected network",		       inet_ntoa (p->prefix));	    continue;	  }	/* Set destination address and port */	memset (&to, 0, sizeof (struct sockaddr_in));	to.sin_addr = p->prefix;	to.sin_port = htons (RIP_PORT_DEFAULT);	/* RIP version is rip's configuration. */	rip_output_process (ifp, &to, route_type, rip->version);      }}/* RIP's periodical timer. */intrip_update (struct thread *t){  /* Clear timer pointer. */  rip->t_update = NULL;  if (IS_RIP_DEBUG_EVENT)    zlog_info ("update timer fire!");  /* Process update output. */  rip_update_process (rip_all_route);  /* Triggered updates may be suppressed if a regular update is due by     the time the triggered update would be sent. */  if (rip->t_triggered_interval)    {      thread_cancel (rip->t_triggered_interval);      rip->t_triggered_interval = NULL;    }  rip->trigger = 0;  /* Register myself. */  rip_event (RIP_UPDATE_EVENT, 0);  return 0;}/* Walk down the RIP routing table then clear changed flag. */voidrip_clear_changed_flag (){  struct route_node *rp;  struct rip_info *rinfo;  for (rp = route_top (rip->table); rp; rp = route_next (rp))    if ((rinfo = rp->info) != NULL)      if (rinfo->flags & RIP_RTF_CHANGED)	rinfo->flags &= ~RIP_RTF_CHANGED;}/* Triggered update interval timer. */intrip_triggered_interval (struct thread *t){  int rip_triggered_update (struct thread *);  rip->t_triggered_interval = NULL;  if (rip->trigger)    {      rip->trigger = 0;      rip_triggered_update (t);    }  return 0;}     /* Execute triggered update. */intrip_triggered_update (struct thread *t){  int interval;  /* Clear thred pointer. */  rip->t_triggered_update = NULL;  /* Cancel interval timer. */  if (rip->t_triggered_interval)    {      thread_cancel (rip->t_triggered_interval);      rip->t_triggered_interval = NULL;    }  rip->trigger = 0;  /* Logging triggered update. */  if (IS_RIP_DEBUG_EVENT)    zlog_info ("triggered update!");  /* Split Horizon processing is done when generating triggered     updates as well as normal updates (see section 2.6). */  rip_update_process (rip_changed_route);  /* Once all of the triggered updates have been generated, the route     change flags should be cleared. */  rip_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;  rip->t_triggered_interval =     thread_add_timer (master, rip_triggered_interval, NULL, interval);  return 0;}/* Withdraw redistributed route. */voidrip_redistribute_withdraw (int type){  struct route_node *rp;  struct rip_info *rinfo;  if (!rip)    return;  for (rp = route_top (rip->table); rp; rp = route_next (rp))    if ((rinfo = rp->info) != NULL)      {	if (rinfo->type == type	    && rinfo->sub_type != RIP_ROUTE_INTERFACE)	  {	    /* Perform poisoned reverse. */	    rinfo->metric = RIP_METRIC_INFINITY;	    RIP_TIMER_ON (rinfo->t_garbage_collect, 			  rip_garbage_collect, rip->garbage_time);	    RIP_TIMER_OFF (rinfo->t_timeout);	    rinfo->flags |= RIP_RTF_CHANGED;	    rip_event (RIP_TRIGGERED_UPDATE, 0);	  }      }}/* Create new RIP instance and set it to global variable. */intrip_create (){  rip = XMALLOC (MTYPE_RIP, sizeof (struct rip));  memset (rip, 0, sizeof (struct rip));  /* Set initial value. */  rip->version = RIPv2;  rip->update_time = RIP_UPDATE_TIMER_DEFAULT;  rip->timeout_time = RIP_TIMEOUT_TIMER_DEFAULT;  rip->garbage_time = RIP_GARBAGE_TIMER_DEFAULT;  rip->default_metric = RIP_DEFAULT_METRIC_DEFAULT;  /* Initialize RIP routig table. */  rip->table = route_table_init ();  rip->route = route_table_init ();  rip->neighbor = route_table_init ();  /* Make output stream. */  rip->obuf = stream_new (1500);  /* Make socket. */  rip->sock = rip_create_socket ();  if (rip->sock < 0)    return rip->sock;  /* Create read and timer thread. */  rip_event (RIP_READ, rip->sock);  rip_event (RIP_UPDATE_EVENT, 1);  return 0;}/* Sned RIP request to the destination. */intrip_request_send (struct sockaddr_in *to, struct interface *ifp,		  u_char version){  struct rte *rte;  struct rip_packet rip_packet;  memset (&rip_packet, 0, sizeof (rip_packet));  rip_packet.command = RIP_REQUEST;  rip_packet.version = version;  rte = rip_packet.rte;  rte->metric = htonl (RIP_METRIC_INFINITY);  return rip_send_packet ((caddr_t) &rip_packet, sizeof (rip_packet), to, ifp);}intrip_update_jitter (unsigned long time){  return ((rand () % (time + 1)) - (time / 2));}voidrip_event (enum rip_event event, int sock){  int jitter = 0;  switch (event)    {    case RIP_READ:      rip->t_read = thread_add_read (master, rip_read, NULL, sock);      break;    case RIP_UPDATE_EVENT:      if (rip->t_update)	{	  thread_cancel (rip->t_update);	  rip->t_update = NULL;	}      jitter = rip_update_jitter (rip->update_time);      rip->t_update = 	thread_add_timer (master, rip_update, NULL, 			  sock ? 2 : rip->update_time + jitter);      break;    case RIP_TRIGGERED_UPDATE:      if (rip->t_triggered_interval)	rip->trigger = 1;      else if (! rip->t_triggered_update)	rip->t_triggered_update = 	  thread_add_event (master, rip_triggered_update, NULL, 0);      break;    default:      break;    }}DEFUN (router_rip,       router_rip_cmd,       "router rip",       "Enable a routing process\n"       "Routing Information Protocol (RIP)\n"){  int ret;  /* If rip is not enabled before. */  if (! rip)    {      ret = rip_create ();      if (ret < 0)	{	  zlog_info ("Can't create RIP");	  return CMD_WARNING;	}    }  vty->node = RIP_NODE;  vty->index = rip;  return CMD_SUCCESS;}DEFUN (no_router_rip,       no_router_rip_cmd,       "no router rip",       NO_STR       "Enable a routing process\n"       "Routing Information Protocol (RIP)\n"){  if (rip)    rip_clean ();  return CMD_SUCCESS;}DEFUN (rip_version,       rip_version_cmd,       "version <1-2>",       "Set routing protocol version\n"       "version\n"){  int version;  version = atoi (argv[0]);  if (version != RIPv1 && version != RIPv2)    {      vty_out (vty, "invalid rip version %d%s", version,	       VTY_NEWLINE);      return CMD_WARNING;    }  rip->version = version;  return CMD_SUCCESS;} DEFUN (no_rip_version,       no_rip_version_cmd,       "no version",       NO_STR       "Set routing protocol version\n"){  /* Set RIP version to the default. */  rip->version = RIPv2;  return CMD_SUCCESS;} ALIAS (no_rip_version,       no_rip_version_val_cmd,       "no version <1-2>",       NO_STR       "Set routing protocol version\n"       "version\n");DEFUN (rip_route,       rip_route_cmd,       "route A.B.C.D/M",       "RIP static route configuration\n"       "IP prefix <network>/<length>\n"){  int ret;  struct prefix_ipv4 p;  struct route_node *node;  ret = str2prefix_ipv4 (argv[0], &p);  if (ret < 0)    {      vty_out (vty, "Malformed address%s", VTY_NEWLINE);      return CMD_WARNING;    }  apply_mask_ipv4 (&p);  /* For router rip configuration. */  node = route_node_get (rip->route, (struct prefix *) &p);  if (node->info)    {      vty_out (vty, "There is already same static route.%s", VTY_NEWLINE);      route_unlock_node (node);      return CMD_WARNING;    }  node->info = "static";  rip_redistribute_add (ZEBRA_ROUTE_RIP, RIP_ROUTE_STATI

⌨️ 快捷键说明

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