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

📄 ripd.c

📁 大名鼎鼎的路由器源码。程序分ZEBRA、OSPFRIP等3个包。程序框架采用一个路由协议一个进程的方式
💻 C
📖 第 1 页 / 共 5 页
字号:
	        /* 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 = IPV4_ADDR_SAME (&rinfo->from, &from->sin_addr);      if (same)	rip_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);	  IPV4_ADDR_COPY (&rinfo->from, &from->sin_addr);	  rinfo->ifindex = ifp->ifindex;	  rinfo->distance = rip_distance_apply (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. */	  if (oldmetric == RIP_METRIC_INFINITY &&	      rinfo->metric < RIP_METRIC_INFINITY)	    {	      rinfo->type = ZEBRA_ROUTE_RIP;	      rinfo->sub_type = RIP_ROUTE_RTE;	      RIP_TIMER_OFF (rinfo->t_garbage_collect);	      if (! IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))		IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);	      rip_zebra_ipv4_add (&p, nexthop, rinfo->metric,				  rinfo->distance);	      rinfo->flags |= RIP_RTF_FIB;	    }	  /* Update nexthop and/or metric value.  */	  if (oldmetric != RIP_METRIC_INFINITY)	    {	      rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric);	      rip_zebra_ipv4_add (&p, nexthop, rinfo->metric,				  rinfo->distance);	      rinfo->flags |= RIP_RTF_FIB;	      if (! IPV4_ADDR_SAME (&rinfo->nexthop, nexthop))		IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);	    }	  /* - Set the route change flag and signal the output process	     to trigger an update. */	  rinfo->flags |= RIP_RTF_CHANGED;	  rip_event (RIP_TRIGGERED_UPDATE, 0);	  /* - If the new metric is infinity, start the deletion	     process (described above); */	  if (rinfo->metric == RIP_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 != RIP_METRIC_INFINITY)		{		  /* - The garbage-collection timer is set for 120 seconds. */		  RIP_TIMER_ON (rinfo->t_garbage_collect, 				rip_garbage_collect, rip->garbage_time);		  RIP_TIMER_OFF (rinfo->t_timeout);		  /* - The metric for the route is set to 16		     (infinity).  This causes the route to be removed		     from service.*/		  rip_zebra_ipv4_delete (&p, &rinfo->nexthop, oldmetric);		  rinfo->flags &= ~RIP_RTF_FIB;		  /* - 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. */	      rip_timeout_update (rinfo);	    }	}      /* Unlock tempolary lock of the route. */      route_unlock_node (rp);    }}/* Dump RIP packet */voidrip_packet_dump (struct rip_packet *packet, int size, char *sndrcv){  caddr_t lim;  struct rte *rte;  char *command_str;  char pbuf[BUFSIZ], nbuf[BUFSIZ];  u_char netmask = 0;  u_char *p;  /* Set command string. */  if (packet->command > 0 && packet->command < RIP_COMMAND_MAX)    command_str = lookup (rip_msg, packet->command);  else    command_str = "unknown";  /* Dump packet header. */  zlog_info ("%s %s version %d packet size %d",	     sndrcv, command_str, packet->version, size);  /* Dump each routing table entry. */  rte = packet->rte;    for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)    {      if (packet->version == RIPv2)	{	  netmask = ip_masklen (rte->mask);	  if (ntohs (rte->family) == 0xffff)            {	      if (ntohs (rte->tag) == RIP_AUTH_SIMPLE_PASSWORD)		{		  p = (u_char *)&rte->prefix;		  zlog_info ("  family 0x%X type %d auth string: %s",			     ntohs (rte->family), ntohs (rte->tag), p);		}	      else if (ntohs (rte->tag) == RIP_AUTH_MD5)		{		  struct rip_md5_info *md5;		  md5 = (struct rip_md5_info *) &packet->rte;		  zlog_info ("  family 0x%X type %d (MD5 authentication)",			     ntohs (md5->family), ntohs (md5->type));		  zlog_info ("    RIP-2 packet len %d Key ID %d"			     " Auth Data len %d", ntohs (md5->packet_len),			     md5->keyid, md5->auth_len);		  zlog_info ("    Sequence Number %ld", (u_long)ntohl (md5->sequence));		}	      else if (ntohs (rte->tag) == RIP_AUTH_DATA)		{		  p = (u_char *)&rte->prefix;		  zlog_info ("  family 0x%X type %d (MD5 data)",			     ntohs (rte->family), ntohs (rte->tag));		  zlog_info ("    MD5: %02X%02X%02X%02X%02X%02X%02X%02X"			     "%02X%02X%02X%02X%02X%02X%02X",			     p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],			     p[9],p[10],p[11],p[12],p[13],p[14],p[15]);		}	      else		{		  zlog_info ("  family 0x%X type %d (Unknown auth type)",			     ntohs (rte->family), ntohs (rte->tag));		}            }	  else	    zlog_info ("  %s/%d -> %s family %d tag %d metric %ld",		       inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),netmask,		       inet_ntop (AF_INET, &rte->nexthop, nbuf, BUFSIZ),		       ntohs (rte->family), ntohs (rte->tag), 		       (u_long)ntohl (rte->metric));	}      else	{	  zlog_info ("  %s family %d tag %d metric %ld", 		     inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),		     ntohs (rte->family), ntohs (rte->tag),		     (u_long)ntohl (rte->metric));	}    }}/* Check if the destination address is valid (unicast; not net 0   or 127) (RFC2453 Section 3.9.2 - Page 26).  But we don't   check net 0 because we accept default route. */intrip_destination_check (struct in_addr addr){  u_int32_t destination;  /* Convert to host byte order. */  destination = ntohl (addr.s_addr);  if (IPV4_NET127 (destination))    return 0;  /* Net 0 may match to the default route. */  if (IPV4_NET0 (destination) && destination != 0)    return 0;  /* Unicast address must belong to class A, B, C. */  if (IN_CLASSA (destination))    return 1;  if (IN_CLASSB (destination))    return 1;  if (IN_CLASSC (destination))    return 1;  return 0;}/* RIP version 2 authentication. */intrip_auth_simple_password (struct rte *rte, struct sockaddr_in *from,			  struct interface *ifp){  struct rip_interface *ri;  char *auth_str;  if (IS_RIP_DEBUG_EVENT)    zlog_info ("RIPv2 simple password authentication from %s",	       inet_ntoa (from->sin_addr));  ri = ifp->info;  if (ri->auth_type != RIP_AUTH_SIMPLE_PASSWORD      || ntohs (rte->tag) != RIP_AUTH_SIMPLE_PASSWORD)    return 0;  /* Simple password authentication. */  if (ri->auth_str)    {      auth_str = (char *) &rte->prefix;	        if (strncmp (auth_str, ri->auth_str, 16) == 0)	return 1;    }  if (ri->key_chain)    {      struct keychain *keychain;      struct key *key;      keychain = keychain_lookup (ri->key_chain);      if (keychain == NULL)	return 0;      key = key_match_for_accept (keychain, (char *) &rte->prefix);      if (key)	return 1;    }  return 0;}/* RIP version 2 authentication with MD5. */intrip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from,	      struct interface *ifp){  struct rip_interface *ri;  struct rip_md5_info *md5;  struct rip_md5_data *md5data;  struct keychain *keychain;  struct key *key;  struct md5_ctx ctx;  u_char pdigest[RIP_AUTH_MD5_SIZE];  u_char digest[RIP_AUTH_MD5_SIZE];  u_int16_t packet_len;  char *auth_str = NULL;    if (IS_RIP_DEBUG_EVENT)    zlog_info ("RIPv2 MD5 authentication from %s", inet_ntoa (from->sin_addr));  ri = ifp->info;  md5 = (struct rip_md5_info *) &packet->rte;  /* Check auth type. */  if (ri->auth_type != RIP_AUTH_MD5 || ntohs (md5->type) != RIP_AUTH_MD5)    return 0;  if (md5->auth_len != RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE)    return 0;  if (ri->key_chain)    {      keychain = keychain_lookup (ri->key_chain);      if (keychain == NULL)	return 0;      key = key_lookup_for_accept (keychain, md5->keyid);      if (key == NULL)	return 0;      auth_str = key->string;    }  if (ri->auth_str)    auth_str = ri->auth_str;  if (! auth_str)    return 0;  /* MD5 digest authentication. */  packet_len = ntohs (md5->packet_len);  md5data = (struct rip_md5_data *)(((u_char *) packet) + packet_len);  /* Save digest to pdigest. */  memcpy (pdigest, md5data->digest, RIP_AUTH_MD5_SIZE);  /* Overwrite digest by my secret. */  memset (md5data->digest, 0, RIP_AUTH_MD5_SIZE);  strncpy (md5data->digest, auth_str, RIP_AUTH_MD5_SIZE);  md5_init_ctx (&ctx);  md5_process_bytes (packet, packet_len + md5->auth_len, &ctx);  md5_finish_ctx (&ctx, digest);  if (memcmp (pdigest, digest, RIP_AUTH_MD5_SIZE) == 0)    return packet_len;  else    return 0;}voidrip_auth_md5_set (struct stream *s, struct interface *ifp){  struct rip_interface *ri;  struct keychain *keychain = NULL;  struct key *key = NULL;  unsigned long len;  struct md5_ctx ctx;  unsigned char secret[RIP_AUTH_MD5_SIZE];  unsigned char digest[RIP_AUTH_MD5_SIZE];  char *auth_str = NULL;  ri = ifp->info;  /* Make it sure this interface is configured as MD5     authentication. */  if (ri->auth_type != RIP_AUTH_MD5)    return;  /* Lookup key chain. */  if (ri->key_chain)    {      keychain = keychain_lookup (ri->key_chain);      if (keychain == NULL)	return;      /* Lookup key. */      key = key_lookup_for_send (keychain);      if (key == NULL)	return;      auth_str = key->string;    }  if (ri->auth_str)    auth_str = ri->auth_str;  if (! auth_str)    return;  /* Get packet length. */  len = s->putp;  /* Check packet length. */  if (len < (RIP_HEADER_SIZE + RIP_RTE_SIZE))    {      zlog_err ("rip_auth_md5_set(): packet length %ld is less than minimum length.", len);      return;    }  /* Move RTE. */  memmove (s->data + RIP_HEADER_SIZE + RIP_RTE_SIZE,	   s->data + RIP_HEADER_SIZE,	   len - RIP_HEADER_SIZE);    /* Set pointer to authentication header. */  stream_set_putp (s, RIP_HEADER_SIZE);  len += RIP_RTE_SIZE;  /* MD5 authentication. */  stream_putw (s, 0xffff);  stream_putw (s, RIP_AUTH_MD5);  /* RIP-2 Packet length.  Actual value is filled in     rip_auth_md5_set(). */  stream_putw (s, len);  /* Key ID. */  if (key)    stream_putc (s, key->index % 256);  else    stream_putc (s, 1);  /* Auth Data Len.  Set 16 for MD5 authentication     data. */  stream_putc (s, RIP_AUTH_MD5_SIZE + RIP_HEADER_SIZE);  /* Sequence Number (non-decreasing). */  /* RFC2080: The value used in the sequence number is     arbitrary, but two suggestions are the time of the     message's creation or a simple message counter. */  stream_putl (s, time (NULL));	        /* Reserved field must be zero. */  stream_putl (s, 0);  stream_putl (s, 0);  /* Set pointer to authentication data. */  stream_set_putp (s, len);  /* Set authentication data. */  stream_putw (s, 0xffff);  stream_putw (s, 0x01);  /* Generate a digest for the RIP packet. */  memset (secret, 0, RIP_AUTH_MD5_SIZE);  strncpy (secret, auth_str, RIP_AUTH_MD5_SIZE);  md5_init_ctx (&ctx);  md5_process_bytes (s->data, s->endp, &ctx);  md5_process_bytes (secret, RIP_AUTH_MD5_SIZE, &ctx);  md5_finish_ctx (&ctx, digest);  /* Copy the digest to the packet. */  stream_write (s, digest, RIP_AUTH_MD5_SIZE);}/* RIP routing information. */voidrip_response_process (struct rip_packet *packet, int size, 		      struct sockaddr_in *from, struct interface *ifp){  caddr_t lim;  struct rte *rte;        /* The Response must be ignored if it is not from the RIP     port. (RFC2453 - Sec. 3.9.2)*/  if (ntohs (from->sin_port) != RIP_PORT_DEFAULT)     {      zlog_info ("response doesn't come from RIP port: %d",		 from->sin_port);      rip_peer_bad_packet (from);      return;    }  /* The datagram's IPv4 source address should be checked to see     whether the datagram is from a valid neighbor; the source of the     datagram must be on a directly connected network  */  if (! if_valid_neighbor (from->sin_addr))     {      zlog_info ("This datagram doesn't came from a valid neighbor: %s",		 inet_ntoa (from->sin_addr));      rip_peer_bad_packet (from);      return;    }  /* It is also worth checking to see whether the response is from one     of the router's own addresses. */  ; /* Alredy done in rip_read () */  /* Update RIP peer. */  rip_peer_update (from, packet->version);  /* Set RTE pointer. */  rte = packet->rte;  for (lim = (caddr_t) packet + size; (caddr_t) rte < lim; rte++)    {      /* RIPv2 authentication check. */      /* If the Address Family Identifier of the first (and only the	 first) entry in the message is 0xFFFF, then the remainder of	 the entry contains the authentication. */      /* If the packet gets here it means authentication enabled */      /* Check is done in rip_read(). So, just skipping it */      if (packet->version == RIPv2 &&	  rte == packet->rte &&	  rte->family == 0xffff)	continue;      if (ntohs (rte->family) != AF_INET)	{	  /* Address family check.  RIP only supports AF_INET. */	  zlog_info ("Unsupported family %d from %s.",		     ntohs (rte->family), inet_ntoa (from->sin_addr));	  continue;	}      /* - is the destination address valid (e.g., unicast; not net 0         or 127) */      if (! rip_destination_check (rte->prefix))        {	  zlog_info ("Network is net 0 or net 127 or it is not unicast network");	  rip_peer_bad_route (from);	  continue;	}       /* Convert metric value to host byte order. */      rte->metric = ntohl (rte->metric);

⌨️ 快捷键说明

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