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

📄 ripd.c

📁 大名鼎鼎的路由器源码。程序分ZEBRA、OSPFRIP等3个包。程序框架采用一个路由协议一个进程的方式
💻 C
📖 第 1 页 / 共 5 页
字号:
      /* - is the metric valid (i.e., between 1 and 16, inclusive) */      if (! (rte->metric >= 1 && rte->metric <= 16))	{	  zlog_info ("Route's metric is not in the 1-16 range.");	  rip_peer_bad_route (from);	  continue;	}      /* RIPv1 does not have nexthop value. */      if (packet->version == RIPv1 && rte->nexthop.s_addr != 0)	{	  zlog_info ("RIPv1 packet with nexthop value %s",		     inet_ntoa (rte->nexthop));	  rip_peer_bad_route (from);	  continue;	}      /* That is, if the provided information is ignored, a possibly	 sub-optimal, but absolutely valid, route may be taken.  If	 the received Next Hop is not directly reachable, it should be	 treated as 0.0.0.0. */      if (packet->version == RIPv2 && rte->nexthop.s_addr != 0)	{	  u_int32_t addrval;	  /* Multicast address check. */	  addrval = ntohl (rte->nexthop.s_addr);	  if (IN_CLASSD (addrval))	    {	      zlog_info ("Nexthop %s is multicast address, skip this rte",			 inet_ntoa (rte->nexthop));	      continue;	    }	  if (! if_lookup_address (rte->nexthop))	    {	      struct route_node *rn;	      struct rip_info *rinfo;	      rn = route_node_match_ipv4 (rip->table, &rte->nexthop);	      if (rn)		{		  rinfo = rn->info;		  if (rinfo->type == ZEBRA_ROUTE_RIP		      && rinfo->sub_type == RIP_ROUTE_RTE)		    {		      if (IS_RIP_DEBUG_EVENT)			zlog_info ("Next hop %s is on RIP network.  Set nexthop to the packet's originator", inet_ntoa (rte->nexthop));		      rte->nexthop = rinfo->from;		    }		  else		    {		      if (IS_RIP_DEBUG_EVENT)			zlog_info ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop));		      rte->nexthop.s_addr = 0;		    }		  route_unlock_node (rn);		}	      else		{		  if (IS_RIP_DEBUG_EVENT)		    zlog_info ("Next hop %s is not directly reachable. Treat it as 0.0.0.0", inet_ntoa (rte->nexthop));		  rte->nexthop.s_addr = 0;		}	    }	}      /* For RIPv1, there won't be a valid netmask.        This is a best guess at the masks.  If everyone was using old      Ciscos before the 'ip subnet zero' option, it would be almost      right too :-)            Cisco summarize ripv1 advertisments to the classful boundary      (/16 for class B's) except when the RIP packet does to inside      the classful network in question.  */      if ((packet->version == RIPv1 && rte->prefix.s_addr != 0) 	  || (packet->version == RIPv2 	      && (rte->prefix.s_addr != 0 && rte->mask.s_addr == 0)))	{	  u_int32_t destination;	  destination = ntohl (rte->prefix.s_addr);	  if (destination & 0xff) 	    {	      masklen2ip (32, &rte->mask);	    }	  else if ((destination & 0xff00) || IN_CLASSC (destination)) 	    {	      masklen2ip (24, &rte->mask);	    }	  else if ((destination & 0xff0000) || IN_CLASSB (destination)) 	    {	      masklen2ip (16, &rte->mask);	    }	  else 	    {	      masklen2ip (8, &rte->mask);	    }	}      /* In case of RIPv2, if prefix in RTE is not netmask applied one         ignore the entry.  */      if ((packet->version == RIPv2) 	  && (rte->mask.s_addr != 0) 	  && ((rte->prefix.s_addr & rte->mask.s_addr) != rte->prefix.s_addr))	{	  zlog_warn ("RIPv2 address %s is not mask /%d applied one",		     inet_ntoa (rte->prefix), ip_masklen (rte->mask));	  rip_peer_bad_route (from);	  continue;	}      /* Default route's netmask is ignored. */      if (packet->version == RIPv2	  && (rte->prefix.s_addr == 0)	  && (rte->mask.s_addr != 0))	{	  if (IS_RIP_DEBUG_EVENT)	    zlog_info ("Default route with non-zero netmask.  Set zero to netmask");	  rte->mask.s_addr = 0;	}	        /* Routing table updates. */      rip_rte_process (rte, from, ifp);    }}/* RIP packet send to destination address. */intrip_send_packet (caddr_t buf, int size, struct sockaddr_in *to, 		 struct interface *ifp){  int ret;  struct sockaddr_in sin;  int sock;  /* Make destination address. */  memset (&sin, 0, sizeof (struct sockaddr_in));  sin.sin_family = AF_INET;#ifdef HAVE_SIN_LEN  sin.sin_len = sizeof (struct sockaddr_in);#endif /* HAVE_SIN_LEN */  /* When destination is specified, use it's port and address. */  if (to)    {      sock = rip->sock;      sin.sin_port = to->sin_port;      sin.sin_addr = to->sin_addr;    }  else    {      sock = socket (AF_INET, SOCK_DGRAM, 0);            sockopt_broadcast (sock);      sockopt_reuseaddr (sock);      sockopt_reuseport (sock);      sin.sin_port = htons (RIP_PORT_DEFAULT);      sin.sin_addr.s_addr = htonl (INADDR_RIP_GROUP);      /* Set multicast interface. */      rip_interface_multicast_set (sock, ifp);    }  ret = sendto (sock, buf, size, 0, (struct sockaddr *)&sin,		sizeof (struct sockaddr_in));  if (IS_RIP_DEBUG_EVENT)    zlog_info ("SEND to socket %d port %d addr %s",	       sock, ntohs (sin.sin_port), inet_ntoa(sin.sin_addr));  if (ret < 0)    zlog_warn ("can't send packet : %s", strerror (errno));  if (! to)    close (sock);  return ret;}/* Add redistributed route to RIP table. */voidrip_redistribute_add (int type, int sub_type, struct prefix_ipv4 *p, 		      unsigned int ifindex, struct in_addr *nexthop){  int ret;  struct route_node *rp;  struct rip_info *rinfo;  /* Redistribute route  */  ret = rip_destination_check (p->prefix);  if (! ret)    return;  rp = route_node_get (rip->table, (struct prefix *) p);  rinfo = rp->info;  if (rinfo)    {      if (rinfo->type == ZEBRA_ROUTE_CONNECT 	  && rinfo->sub_type == RIP_ROUTE_INTERFACE	  && rinfo->metric != RIP_METRIC_INFINITY)	{	  route_unlock_node (rp);	  return;	}      /* Manually configured RIP route check. */      if (rinfo->type == ZEBRA_ROUTE_RIP 	  && rinfo->sub_type == RIP_ROUTE_STATIC)	{	  if (type != ZEBRA_ROUTE_RIP || sub_type != RIP_ROUTE_STATIC)	    {	      route_unlock_node (rp);	      return;	    }	}      RIP_TIMER_OFF (rinfo->t_timeout);      RIP_TIMER_OFF (rinfo->t_garbage_collect);      if (rip_route_rte (rinfo))	rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rp->p, &rinfo->nexthop,			       rinfo->metric);      rp->info = NULL;      rip_info_free (rinfo);            route_unlock_node (rp);          }  rinfo = rip_info_new ();      rinfo->type = type;  rinfo->sub_type = sub_type;  rinfo->ifindex = ifindex;  rinfo->metric = 1;  rinfo->rp = rp;  if (nexthop)    rinfo->nexthop = *nexthop;  rinfo->flags |= RIP_RTF_FIB;  rp->info = rinfo;  rinfo->flags |= RIP_RTF_CHANGED;  rip_event (RIP_TRIGGERED_UPDATE, 0);}/* Delete redistributed route from RIP table. */voidrip_redistribute_delete (int type, int sub_type, struct prefix_ipv4 *p, 			 unsigned int ifindex){  int ret;  struct route_node *rp;  struct rip_info *rinfo;  ret = rip_destination_check (p->prefix);  if (! ret)    return;  rp = route_node_lookup (rip->table, (struct prefix *) p);  if (rp)    {      rinfo = rp->info;      if (rinfo != NULL	  && rinfo->type == type 	  && rinfo->sub_type == sub_type 	  && rinfo->ifindex == ifindex)	{	  /* 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);	}    }}/* Response to request called from rip_read ().*/voidrip_request_process (struct rip_packet *packet, int size, 		     struct sockaddr_in *from, struct interface *ifp){  caddr_t lim;  struct rte *rte;  struct prefix_ipv4 p;  struct route_node *rp;  struct rip_info *rinfo;  struct rip_interface *ri;  ri = ifp->info;  /* When passive interface is specified, suppress responses */  if (ri->passive)    return;  /* RIP peer update. */  rip_peer_update (from, packet->version);  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 an address family identifier of zero and a     metric of infinity (i.e., 16), then this is a request to send the     entire routing table. */  if ((rte->family == 0xFFFF) && (lim == ((caddr_t) (rte + 2)) )) rte++;    if (lim == ((caddr_t) (rte + 1)) &&      ntohs (rte->family) == 0 &&      ntohl (rte->metric) == RIP_METRIC_INFINITY)    {	      /* All route with split horizon */      rip_output_process (ifp, from, rip_all_route, packet->version);    }  else    {      /* 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. */      p.family = AF_INET;      for (; ((caddr_t) rte) < lim; rte++)	{	  p.prefix = rte->prefix;	  p.prefixlen = ip_masklen (rte->mask);	  apply_mask_ipv4 (&p);	  	  rp = route_node_lookup (rip->table, (struct prefix *) &p);	  if (rp)	    {	      rinfo = rp->info;	      rte->metric = htonl (rinfo->metric);	      route_unlock_node (rp);	    }	  else	    rte->metric = htonl (RIP_METRIC_INFINITY);	}      packet->command = RIP_RESPONSE;      rip_send_packet ((caddr_t) packet, size, from, ifp);    }  rip_global_queries++;}#if RIP_RECVMSG/* Set IPv6 packet info to the socket. */static intsetsockopt_pktinfo (int sock){  int ret;  int val = 1;      ret = setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof(val));  if (ret < 0)    zlog_warn ("Can't setsockopt IP_PKTINFO : %s", strerror (errno));  return ret;}/* Read RIP packet by recvmsg function. */intrip_recvmsg (int sock, u_char *buf, int size, struct sockaddr_in *from,	     int *ifindex){  int ret;  struct msghdr msg;  struct iovec iov;  struct cmsghdr *ptr;  char adata[1024];  msg.msg_name = (void *) from;  msg.msg_namelen = sizeof (struct sockaddr_in);  msg.msg_iov = &iov;  msg.msg_iovlen = 1;  msg.msg_control = (void *) adata;  msg.msg_controllen = sizeof adata;  iov.iov_base = buf;  iov.iov_len = size;  ret = recvmsg (sock, &msg, 0);  if (ret < 0)    return ret;  for (ptr = CMSG_FIRSTHDR(&msg); ptr != NULL; ptr = CMSG_NXTHDR(&msg, ptr))    if (ptr->cmsg_level == IPPROTO_IP && ptr->cmsg_type == IP_PKTINFO)       {	struct in_pktinfo *pktinfo;	int i;	pktinfo = (struct in_pktinfo *) CMSG_DATA (ptr);	i = pktinfo->ipi_ifindex;      }  return ret;}/* RIP packet read function. */intrip_read_new (struct thread *t){  int ret;  int sock;  char buf[RIP_PACKET_MAXSIZ];  struct sockaddr_in from;  unsigned int ifindex;    /* Fetch socket then register myself. */  sock = THREAD_FD (t);  rip_event (RIP_READ, sock);  /* Read RIP packet. */  ret = rip_recvmsg (sock, buf, RIP_PACKET_MAXSIZ, &from, (int *)&ifindex);  if (ret < 0)    {      zlog_warn ("Can't read RIP packet: %s", strerror (errno));      return ret;    }  return ret;}#endif /* RIP_RECVMSG *//* First entry point of RIP packet. */intrip_read (struct thread *t){  int sock;  int ret;  int rtenum;  union rip_buf rip_buf;  struct rip_packet *packet;  struct sockaddr_in from;  int fromlen, len;  struct interface *ifp;  struct rip_interface *ri;  /* Fetch socket then register myself. */  sock = THREAD_FD (t);  rip->t_read = NULL;  /* Add myself to tne next event */  rip_event (RIP_READ, sock);  /* RIPd manages only IPv4. */  memset (&from, 0, sizeof (struct sockaddr_in));  fromlen = sizeof (struct sockaddr_in);  len = recvfrom (sock, (char *)&rip_buf.buf, sizeof (rip_buf.buf), 0, 		  (struct sockaddr *) &from, &fromlen);  if (len < 0)     {      zlog_info ("recvfrom failed: %s", strerror (errno));      return len;    }  /* Check is this packet comming from myself? */  if (if_check_address (from.sin_addr))     {      if (IS_RIP_DEBUG_PACKET)	zlog_warn ("ignore packet comes from myself");      return -1;    }  /* Which interface is this packet comes from. */  ifp = if_lookup_address (from.sin_addr);  /* RIP packet received */  if (IS_RIP_DEBUG_EVENT)    zlog_info ("RECV packet from %s port %d on %s",	       inet_ntoa (from.sin_addr), ntohs (from.sin_port),	       ifp ? ifp->name : "unknown");  /* If this packet come from unknown interface, ignore it. */  if (ifp == NULL)    {      zlog_info ("packet comes from unknown interface");      return -1;    }  /* Packet length check. */  if (len < RIP_PACKET_MINSIZ)    {      zlog_warn ("packet size %d is smaller than minimum size %d",		 len, RIP_PACKET_MINSIZ);      rip_peer_bad_packet (&from);

⌨️ 快捷键说明

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