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

📄 ripd.c

📁 大名鼎鼎的路由器源码。程序分ZEBRA、OSPFRIP等3个包。程序框架采用一个路由协议一个进程的方式
💻 C
📖 第 1 页 / 共 5 页
字号:
      return len;    }  if (len > RIP_PACKET_MAXSIZ)    {      zlog_warn ("packet size %d is larger than max size %d",		 len, RIP_PACKET_MAXSIZ);      rip_peer_bad_packet (&from);      return len;    }  /* Packet alignment check. */  if ((len - RIP_PACKET_MINSIZ) % 20)    {      zlog_warn ("packet size %d is wrong for RIP packet alignment", len);      rip_peer_bad_packet (&from);      return len;    }  /* Set RTE number. */  rtenum = ((len - RIP_PACKET_MINSIZ) / 20);  /* For easy to handle. */  packet = &rip_buf.rip_packet;  /* RIP version check. */  if (packet->version == 0)    {      zlog_info ("version 0 with command %d received.", packet->command);      rip_peer_bad_packet (&from);      return -1;    }  /* Dump RIP packet. */  if (IS_RIP_DEBUG_RECV)    rip_packet_dump (packet, len, "RECV");  /* RIP version adjust.  This code should rethink now.  RFC1058 says     that "Version 1 implementations are to ignore this extra data and     process only the fields specified in this document.". So RIPv3     packet should be treated as RIPv1 ignoring must be zero field. */  if (packet->version > RIPv2)    packet->version = RIPv2;  /* Is RIP running or is this RIP neighbor ?*/  ri = ifp->info;  if (! ri->running && ! rip_neighbor_lookup (&from))    {      if (IS_RIP_DEBUG_EVENT)	zlog_info ("RIP is not enabled on interface %s.", ifp->name);      rip_peer_bad_packet (&from);      return -1;    }  /* RIP Version check. */  if (packet->command == RIP_RESPONSE)    {      if (ri->ri_receive == RI_RIP_UNSPEC)	{	  if (packet->version != rip->version) 	    {	      if (IS_RIP_DEBUG_PACKET)		zlog_warn ("  packet's v%d doesn't fit to my version %d", 			   packet->version, rip->version);	      rip_peer_bad_packet (&from);	      return -1;	    }	}      else	{	  if (packet->version == RIPv1)	    if (! (ri->ri_receive & RIPv1))	      {		if (IS_RIP_DEBUG_PACKET)		  zlog_warn ("  packet's v%d doesn't fit to if version spec", 			     packet->version);		rip_peer_bad_packet (&from);		return -1;	      }	  if (packet->version == RIPv2)	    if (! (ri->ri_receive & RIPv2))	      {		if (IS_RIP_DEBUG_PACKET)		  zlog_warn ("  packet's v%d doesn't fit to if version spec", 			     packet->version);		rip_peer_bad_packet (&from);		return -1;	      }	}    }  /* RFC2453 5.2 If the router is not configured to authenticate RIP-2     messages, then RIP-1 and unauthenticated RIP-2 messages will be     accepted; authenticated RIP-2 messages shall be discarded.  */  if ((ri->auth_type == RIP_NO_AUTH)       && rtenum       && (packet->version == RIPv2) && (packet->rte->family == 0xffff))    {      if (IS_RIP_DEBUG_EVENT)	zlog_warn ("packet RIPv%d is dropped because authentication disabled", 		   packet->version);      rip_peer_bad_packet (&from);      return -1;    }  /* If the router is configured to authenticate RIP-2 messages, then     RIP-1 messages and RIP-2 messages which pass authentication     testing shall be accepted; unauthenticated and failed     authentication RIP-2 messages shall be discarded.  For maximum     security, RIP-1 messages should be ignored when authentication is     in use (see section 4.1); otherwise, the routing information from     authenticated messages will be propagated by RIP-1 routers in an     unauthenticated manner. */  if ((ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD        || ri->auth_type == RIP_AUTH_MD5)      && rtenum)    {      /* We follow maximum security. */      if (packet->version == RIPv1 && packet->rte->family == 0xffff)	{	  if (IS_RIP_DEBUG_PACKET)	    zlog_warn ("packet RIPv%d is dropped because authentication enabled", packet->version);	  rip_peer_bad_packet (&from);	  return -1;	}      /* Check RIPv2 authentication. */      if (packet->version == RIPv2)	{	  if (packet->rte->family == 0xffff)	    {	      if (ntohs (packet->rte->tag) == RIP_AUTH_SIMPLE_PASSWORD)                {		  ret = rip_auth_simple_password (packet->rte, &from, ifp);		  if (! ret)		    {		      if (IS_RIP_DEBUG_EVENT)			zlog_warn ("RIPv2 simple password authentication failed");		      rip_peer_bad_packet (&from);		      return -1;		    }		  else		    {		      if (IS_RIP_DEBUG_EVENT)			zlog_info ("RIPv2 simple password authentication success");		    }                }	      else if (ntohs (packet->rte->tag) == RIP_AUTH_MD5)                {		  ret = rip_auth_md5 (packet, &from, ifp);		  if (! ret)		    {		      if (IS_RIP_DEBUG_EVENT)			zlog_warn ("RIPv2 MD5 authentication failed");		      rip_peer_bad_packet (&from);		      return -1;		    }		  else		    {		      if (IS_RIP_DEBUG_EVENT)			zlog_info ("RIPv2 MD5 authentication success");		    }		  /* Reset RIP packet length to trim MD5 data. */		  len = ret;                 }	      else		{		  if (IS_RIP_DEBUG_EVENT)		    zlog_warn ("Unknown authentication type %d",			       ntohs (packet->rte->tag));		  rip_peer_bad_packet (&from);		  return -1;		}	    }	  else	    {	      /* There is no authentication in the packet. */	      if (ri->auth_str || ri->key_chain)		{		  if (IS_RIP_DEBUG_EVENT)		    zlog_warn ("RIPv2 authentication failed: no authentication in packet");		  rip_peer_bad_packet (&from);		  return -1;		}	    }	}    }    /* Process each command. */  switch (packet->command)    {    case RIP_RESPONSE:      rip_response_process (packet, len, &from, ifp);      break;    case RIP_REQUEST:    case RIP_POLL:      rip_request_process (packet, len, &from, ifp);      break;    case RIP_TRACEON:    case RIP_TRACEOFF:      zlog_info ("Obsolete command %s received, please sent it to routed", 		 lookup (rip_msg, packet->command));      rip_peer_bad_packet (&from);      break;    case RIP_POLL_ENTRY:      zlog_info ("Obsolete command %s received", 		 lookup (rip_msg, packet->command));      rip_peer_bad_packet (&from);      break;    default:      zlog_info ("Unknown RIP command %d received", packet->command);      rip_peer_bad_packet (&from);      break;    }  return len;}/* Make socket for RIP protocol. */int rip_create_socket (){  int ret;  int sock;  struct sockaddr_in addr;  struct servent *sp;  memset (&addr, 0, sizeof (struct sockaddr_in));  /* Set RIP port. */  sp = getservbyname ("router", "udp");  if (sp)     addr.sin_port = sp->s_port;  else     addr.sin_port = htons (RIP_PORT_DEFAULT);  /* Address shoud be any address. */  addr.sin_family = AF_INET;  addr.sin_addr.s_addr = INADDR_ANY;  /* Make datagram socket. */  sock = socket (AF_INET, SOCK_DGRAM, 0);  if (sock < 0)     {      perror ("socket");      exit (1);    }  sockopt_broadcast (sock);  sockopt_reuseaddr (sock);  sockopt_reuseport (sock);#ifdef RIP_RECVMSG  setsockopt_pktinfo (sock);#endif /* RIP_RECVMSG */  ret = bind (sock, (struct sockaddr *) & addr, sizeof (addr));  if (ret < 0)    {      perror ("bind");      return ret;    }    return sock;}/* Write routing table entry to the stream and return next index of   the routing table entry in the stream. */intrip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,	       u_char version, struct rip_info *rinfo, struct interface *ifp){  struct in_addr mask;  struct rip_interface *ri;  /* RIP packet header. */  if (num == 0)    {      stream_putc (s, RIP_RESPONSE);      stream_putc (s, version);      stream_putw (s, 0);      /* In case of we need RIPv2 authentication. */      if (version == RIPv2 && ifp)	{	  ri = ifp->info;	      	  if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)	    {	      if (ri->auth_str)		{		  stream_putw (s, 0xffff);		  stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);		  memset ((s->data + s->putp), 0, 16);		  strncpy ((s->data + s->putp), ri->auth_str, 16);		  stream_set_putp (s, s->putp + 16);		  num++;		}	      if (ri->key_chain)		{		  struct keychain *keychain;		  struct key *key;		  keychain = keychain_lookup (ri->key_chain);		  if (keychain)		    {		      key = key_lookup_for_send (keychain);		      		      if (key)			{			  stream_putw (s, 0xffff);			  stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);			  memset ((s->data + s->putp), 0, 16);			  strncpy ((s->data + s->putp), key->string, 16);			  stream_set_putp (s, s->putp + 16);			  num++;			}		    }		}	    }	}    }  /* Write routing table entry. */  if (version == RIPv1)    {      stream_putw (s, AF_INET);      stream_putw (s, 0);      stream_put_ipv4 (s, p->prefix.s_addr);      stream_put_ipv4 (s, 0);      stream_put_ipv4 (s, 0);      stream_putl (s, rinfo->metric_out);    }  else    {      masklen2ip (p->prefixlen, &mask);      stream_putw (s, AF_INET);      stream_putw (s, rinfo->tag);      stream_put_ipv4 (s, p->prefix.s_addr);      stream_put_ipv4 (s, mask.s_addr);      stream_put_ipv4 (s, rinfo->nexthop_out.s_addr);      stream_putl (s, rinfo->metric_out);    }  return ++num;}/* Send update to the ifp or spcified neighbor. */voidrip_output_process (struct interface *ifp, struct sockaddr_in *to,		    int route_type, u_char version){  int ret;  struct stream *s;  struct route_node *rp;  struct rip_info *rinfo;  struct rip_interface *ri;  struct prefix_ipv4 *p;  struct prefix_ipv4 classfull;  int num;  int rtemax;  /* Logging output event. */  if (IS_RIP_DEBUG_EVENT)    {      if (to)	zlog_info ("update routes to neighbor %s", inet_ntoa (to->sin_addr));      else	zlog_info ("update routes on interface %s ifindex %d",		   ifp->name, ifp->ifindex);    }  /* Set output stream. */  s = rip->obuf;  /* Reset stream and RTE counter. */  stream_reset (s);  num = 0;  rtemax = (RIP_PACKET_MAXSIZ - 4) / 20;  /* Get RIP interface. */  ri = ifp->info;      /* If output interface is in simple password authentication mode, we     need space for authentication data.  */  if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)    rtemax -= 1;  /* If output interface is in MD5 authentication mode, we need space     for authentication header and data. */  if (ri->auth_type == RIP_AUTH_MD5)    rtemax -= 2;  /* If output interface is in simple password authentication mode     and string or keychain is specified we need space for auth. data */  if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)    {      if (ri->key_chain)	{	  struct keychain *keychain;	  keychain = keychain_lookup (ri->key_chain);	  if (keychain)	    if (key_lookup_for_send (keychain))	      rtemax -=1;	}      else	if (ri->auth_str)	  rtemax -=1;    }  for (rp = route_top (rip->table); rp; rp = route_next (rp))    if ((rinfo = rp->info) != NULL)      {	/* Some inheritance stuff:                                          */	/* Before we process with ipv4 prefix we should mask it             */	/* with Classful mask if we send RIPv1 packet.That's because        */	/* user could set non-classful mask or we could get it by RIPv2     */	/* or other protocol. checked with Cisco's way of life :)           */		if (version == RIPv1)	  {	    memcpy (&classfull, &rp->p, sizeof (struct prefix_ipv4));	    if (IS_RIP_DEBUG_PACKET)	      zlog_info("%s/%d before RIPv1 mask check ",			inet_ntoa (classfull.prefix), classfull.prefixlen);	    apply_classful_mask_ipv4 (&classfull);	    p = &classfull;	    if (IS_RIP_DEBUG_PACKET)	      zlog_info("%s/%d after RIPv1 mask check",			inet_ntoa (p->prefix), p->prefixlen);	  }	else 	  p = (struct prefix_ipv4 *) &rp->p;	/* Apply output filters. */	ret = rip_outgoing_filter (p, ri);	if (ret < 0)	  continue;	/* Changed route only output. */	if (route_type == rip_changed_route &&	    (! (rinfo->flags & RIP_RTF_CHANGED)))	  continue;	/* Split horizon. */	/* if (split_horizon == rip_split_horizon) */	if (ri->split_horizon)	  {	    /* We perform split horizon for RIP and connected route. */	    if ((rinfo->type == ZEBRA_ROUTE_RIP ||		 rinfo->type == ZEBRA_ROUTE_CONNECT) &&		rinfo->ifindex == ifp->ifindex)	      continue;	  }	/* Preparation for route-map. */	rinfo->metric_set = 0;	rinfo->nexthop_out.s_addr = 0;	rinfo->metric_out = rinfo->metric;	rinfo->ifindex_out = ifp->ifindex;	/* In order to avoid some local loops, if the RIP route has a	   nexthop via this interface, keep the nexthop, otherwise set	   it to 0. The nexthop should not be propagated beyond the	   local broadcast/multicast area in order to avoid an IGP	   multi-level recursive look-up.  For RIP and connected	   route, we don't set next hop value automatically.  For	   settting next hop to those routes, please use	   route-map.  */	if (rinfo->type != ZEBRA_ROUTE_RIP	    && rinfo->type != ZEBRA_ROUTE_CONNECT	    && rinfo->ifindex == ifp->ifindex)	  rinfo->nexthop_out = rinfo->nexthop;           	/* Apply route map - continue, if deny */	if (rip->route_map[rinfo->type].name	    && rinfo->sub_type != RIP_ROUTE_INTERFACE)	  {	    ret = route_map_apply (rip->route_map[rinfo->type].map,				   (struct prefix *)p, RMAP_RIP, rinfo);	    if (ret == RMAP_DENYMATCH) 	      {		if (IS_RIP_DEBUG_PACKET)		  zlog_info ("%s/%d is filtered by route-map",			     inet_ntoa (p->prefix), p->prefixlen);		continue;	      }	  }	/* When route-map does not set metric. */	if (! rinfo->metric_set)	  {	    /* If redistribute metric is set. */	    if (rip->route_map[rinfo->type].metric_config		&& rinfo->metric != RIP_METRIC_INFINITY)	      {		rinfo->metric_out = rip->route_map[rinfo->type].metric;	      }	    else

⌨️ 快捷键说明

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