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

📄 ripd.c

📁 大名鼎鼎的路由器源码。程序分ZEBRA、OSPFRIP等3个包。程序框架采用一个路由协议一个进程的方式
💻 C
📖 第 1 页 / 共 5 页
字号:
/* RIP version 1 and 2. * Copyright (C) 1997, 98, 99 Kunihiro Ishiguro <kunihiro@zebra.org> * * This file is part of GNU Zebra. * * GNU Zebra is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * GNU Zebra is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Zebra; see the file COPYING.  If not, write to the Free * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA * 02111-1307, USA.   */#include <zebra.h>#include "if.h"#include "command.h"#include "prefix.h"#include "table.h"#include "thread.h"#include "memory.h"#include "log.h"#include "stream.h"#include "filter.h"#include "sockunion.h"#include "routemap.h"#include "plist.h"#include "distribute.h"#include "md5-gnu.h"#include "keychain.h"#include "ripd/ripd.h"#include "ripd/rip_debug.h"/* RIP Structure. */struct rip *rip = NULL;/* RIP neighbor address table. */struct route_table *rip_neighbor_table;/* RIP route changes. */long rip_global_route_changes = 0;/* RIP queries. */long rip_global_queries = 0;/* Prototypes. */void rip_event (enum rip_event, int);void rip_output_process (struct interface *, struct sockaddr_in *, 			 int, u_char);/* RIP output routes type. */enum  {    rip_all_route,    rip_changed_route  };/* RIP command strings. */struct message rip_msg[] =   {    {RIP_REQUEST,    "REQUEST"},    {RIP_RESPONSE,   "RESPONSE"},    {RIP_TRACEON,    "TRACEON"},    {RIP_TRACEOFF,   "TRACEOFF"},    {RIP_POLL,       "POLL"},    {RIP_POLL_ENTRY, "POLL ENTRY"},    {0,              NULL}  };/* Each route type's strings and default preference. */struct{    int key;  char *str;  char *str_long;} route_info[] =  {    { ZEBRA_ROUTE_SYSTEM,  "X", "system"},    { ZEBRA_ROUTE_KERNEL,  "K", "kernel"},    { ZEBRA_ROUTE_CONNECT, "C", "connected"},    { ZEBRA_ROUTE_STATIC,  "S", "static"},    { ZEBRA_ROUTE_RIP,     "R", "rip"},    { ZEBRA_ROUTE_RIPNG,   "R", "ripng"},    { ZEBRA_ROUTE_OSPF,    "O", "ospf"},    { ZEBRA_ROUTE_OSPF6,   "O", "ospf6"},    { ZEBRA_ROUTE_BGP,     "B", "bgp"}  };/* Utility function to set boradcast option to the socket. */intsockopt_broadcast (int sock){  int ret;  int on = 1;  ret = setsockopt (sock, SOL_SOCKET, SO_BROADCAST, (char *) &on, sizeof on);  if (ret < 0)    {      zlog_warn ("can't set sockopt SO_BROADCAST to socket %d", sock);      return -1;    }  return 0;}intrip_route_rte (struct rip_info *rinfo){  return (rinfo->type == ZEBRA_ROUTE_RIP && rinfo->sub_type == RIP_ROUTE_RTE);}struct rip_info *rip_info_new (){  struct rip_info *new;  new = XMALLOC (MTYPE_RIP_INFO, sizeof (struct rip_info));  memset (new, 0, sizeof (struct rip_info));  return new;}voidrip_info_free (struct rip_info *rinfo){  XFREE (MTYPE_RIP_INFO, rinfo);}/* RIP route garbage collect timer. */intrip_garbage_collect (struct thread *t){  struct rip_info *rinfo;  struct route_node *rp;  rinfo = THREAD_ARG (t);  rinfo->t_garbage_collect = NULL;  /* Off timeout timer. */  RIP_TIMER_OFF (rinfo->t_timeout);    /* Get route_node pointer. */  rp = rinfo->rp;  /* Unlock route_node. */  rp->info = NULL;  route_unlock_node (rp);  /* Free RIP routing information. */  rip_info_free (rinfo);  return 0;}/* Timeout RIP routes. */intrip_timeout (struct thread *t){  struct rip_info *rinfo;  struct route_node *rn;  rinfo = THREAD_ARG (t);  rinfo->t_timeout = NULL;  rn = rinfo->rp;  /* - The garbage-collection timer is set for 120 seconds. */  RIP_TIMER_ON (rinfo->t_garbage_collect, rip_garbage_collect, 		rip->garbage_time);  rip_zebra_ipv4_delete ((struct prefix_ipv4 *)&rn->p, &rinfo->nexthop,			 rinfo->metric);  /* - The metric for the route is set to 16 (infinity).  This causes     the route to be removed from service. */  rinfo->metric = RIP_METRIC_INFINITY;  rinfo->flags &= ~RIP_RTF_FIB;  /* - The route change flag is to indicate that this entry has been     changed. */  rinfo->flags |= RIP_RTF_CHANGED;  /* - The output process is signalled to trigger a response. */  rip_event (RIP_TRIGGERED_UPDATE, 0);  return 0;}voidrip_timeout_update (struct rip_info *rinfo){  if (rinfo->metric != RIP_METRIC_INFINITY)    {      RIP_TIMER_OFF (rinfo->t_timeout);      RIP_TIMER_ON (rinfo->t_timeout, rip_timeout, rip->timeout_time);    }}intrip_incoming_filter (struct prefix_ipv4 *p, struct rip_interface *ri){  struct distribute *dist;  struct access_list *alist;  struct prefix_list *plist;  /* Input distribute-list filtering. */  if (ri->list[RIP_FILTER_IN])    {      if (access_list_apply (ri->list[RIP_FILTER_IN], 			     (struct prefix *) p) == FILTER_DENY)	{	  if (IS_RIP_DEBUG_PACKET)	    zlog_info ("%s/%d filtered by distribute in",		       inet_ntoa (p->prefix), p->prefixlen);	  return -1;	}    }  if (ri->prefix[RIP_FILTER_IN])    {      if (prefix_list_apply (ri->prefix[RIP_FILTER_IN], 			     (struct prefix *) p) == PREFIX_DENY)	{	  if (IS_RIP_DEBUG_PACKET)	    zlog_info ("%s/%d filtered by prefix-list in",		       inet_ntoa (p->prefix), p->prefixlen);	  return -1;	}    }  /* All interface filter check. */  dist = distribute_lookup (NULL);  if (dist)    {      if (dist->list[DISTRIBUTE_IN])	{	  alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_IN]);	    	  if (alist)	    {	      if (access_list_apply (alist,				     (struct prefix *) p) == FILTER_DENY)		{		  if (IS_RIP_DEBUG_PACKET)		    zlog_info ("%s/%d filtered by distribute in",			       inet_ntoa (p->prefix), p->prefixlen);		  return -1;		}	    }	}      if (dist->prefix[DISTRIBUTE_IN])	{	  plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_IN]);	  	  if (plist)	    {	      if (prefix_list_apply (plist,				     (struct prefix *) p) == PREFIX_DENY)		{		  if (IS_RIP_DEBUG_PACKET)		    zlog_info ("%s/%d filtered by prefix-list in",			       inet_ntoa (p->prefix), p->prefixlen);		  return -1;		}	    }	}    }  return 0;}intrip_outgoing_filter (struct prefix_ipv4 *p, struct rip_interface *ri){  struct distribute *dist;  struct access_list *alist;  struct prefix_list *plist;  if (ri->list[RIP_FILTER_OUT])    {      if (access_list_apply (ri->list[RIP_FILTER_OUT],			     (struct prefix *) p) == FILTER_DENY)	{	  if (IS_RIP_DEBUG_PACKET)	    zlog_info ("%s/%d is filtered by distribute out",		       inet_ntoa (p->prefix), p->prefixlen);	  return -1;	}    }  if (ri->prefix[RIP_FILTER_OUT])    {      if (prefix_list_apply (ri->prefix[RIP_FILTER_OUT],			     (struct prefix *) p) == PREFIX_DENY)	{	  if (IS_RIP_DEBUG_PACKET)	    zlog_info ("%s/%d is filtered by prefix-list out",		       inet_ntoa (p->prefix), p->prefixlen);	  return -1;	}    }  /* All interface filter check. */  dist = distribute_lookup (NULL);  if (dist)    {      if (dist->list[DISTRIBUTE_OUT])	{	  alist = access_list_lookup (AFI_IP, dist->list[DISTRIBUTE_OUT]);	    	  if (alist)	    {	      if (access_list_apply (alist,				     (struct prefix *) p) == FILTER_DENY)		{		  if (IS_RIP_DEBUG_PACKET)		    zlog_info ("%s/%d filtered by distribute out",			       inet_ntoa (p->prefix), p->prefixlen);		  return -1;		}	    }	}      if (dist->prefix[DISTRIBUTE_OUT])	{	  plist = prefix_list_lookup (AFI_IP, dist->prefix[DISTRIBUTE_OUT]);	  	  if (plist)	    {	      if (prefix_list_apply (plist,				     (struct prefix *) p) == PREFIX_DENY)		{		  if (IS_RIP_DEBUG_PACKET)		    zlog_info ("%s/%d filtered by prefix-list out",			       inet_ntoa (p->prefix), p->prefixlen);		  return -1;		}	    }	}    }  return 0;}/* Check nexthop address validity. */static intrip_nexthop_check (struct in_addr *addr){  listnode node;  listnode cnode;  struct interface *ifp;  struct connected *ifc;  struct prefix *p;  /* If nexthop address matches local configured address then it is     invalid nexthop. */  for (node = listhead (iflist); node; nextnode (node))    {      ifp = getdata (node);      for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))	{	    	  ifc = getdata (cnode);	  p = ifc->address;	  if (p->family == AF_INET	      && IPV4_ADDR_SAME (&p->u.prefix4, addr))	    return -1;	}    }  return 0;}/* RIP add route to routing table. */voidrip_rte_process (struct rte *rte, struct sockaddr_in *from,		 struct interface *ifp){  int ret;  struct prefix_ipv4 p;  struct route_node *rp;  struct rip_info *rinfo;  struct rip_interface *ri;  struct in_addr *nexthop;  u_char oldmetric;  int same = 0;  /* Make prefix structure. */  memset (&p, 0, sizeof (struct prefix_ipv4));  p.family = AF_INET;  p.prefix = rte->prefix;  p.prefixlen = ip_masklen (rte->mask);  /* Make sure mask is applied. */  apply_mask_ipv4 (&p);  /* Apply input filters. */  ri = ifp->info;  ret = rip_incoming_filter (&p, ri);  if (ret < 0)    return;  /* Once the entry has been validated, update the metric by     adding the cost of the network on wich the message     arrived. If the result is greater than infinity, use infinity     (RFC2453 Sec. 3.9.2) */  /* Zebra ripd can handle offset-list in. */  ret = rip_offset_list_apply_in (&p, ifp, &rte->metric);  /* If offset-list does not modify the metric use interface's     metric. */  if (! ret)    rte->metric += ifp->metric;  if (rte->metric > RIP_METRIC_INFINITY)    rte->metric = RIP_METRIC_INFINITY;  /* Set nexthop pointer. */  if (rte->nexthop.s_addr == 0)    nexthop = &from->sin_addr;  else    nexthop = &rte->nexthop;  /* Check nexthop address. */  if (rip_nexthop_check (nexthop) < 0)    {      if (IS_RIP_DEBUG_PACKET)	zlog_info ("Nexthop address %s is invalid", inet_ntoa (*nexthop));      return;    }  /* Get index for the prefix. */  rp = route_node_get (rip->table, (struct prefix *) &p);  /* Check to see whether there is already RIP route on the table. */  rinfo = rp->info;  if (rinfo)    {      /* Redistributed route check. */      if (rinfo->type != ZEBRA_ROUTE_RIP	  && rinfo->metric != RIP_METRIC_INFINITY)	return;      /* Local static route. */      if (rinfo->type == ZEBRA_ROUTE_RIP	  && rinfo->sub_type == RIP_ROUTE_STATIC	  && rinfo->metric != RIP_METRIC_INFINITY)	return;    }    if (! rinfo)    {      /* Now, check to see whether there is already an explicit route	 for the destination prefix.  If there is no such route, add	 this route to the routing table, unless the metric is	 infinity (there is no point in adding a route which	 unusable). */      if (rte->metric != RIP_METRIC_INFINITY)	{	  rinfo = rip_info_new ();	  	  /* - Setting the destination prefix and length to those in	     the RTE. */	  rinfo->rp = rp;	  /* - Setting the metric to the newly calculated metric (as	     described above). */	  rinfo->metric = rte->metric;	  rinfo->tag = ntohs (rte->tag);	  /* - Set the next hop address to be the address of the router	     from which the datagram came or the next hop address	     specified by a next hop RTE. */	  IPV4_ADDR_COPY (&rinfo->nexthop, nexthop);	  IPV4_ADDR_COPY (&rinfo->from, &from->sin_addr);	  rinfo->ifindex = ifp->ifindex;	  /* - Initialize the timeout for the route.  If the	     garbage-collection timer is running for this route, stop it	     (see section 2.3 for a discussion of the timers). */	  rip_timeout_update (rinfo);	  /* - Set the route change flag. */	  rinfo->flags |= RIP_RTF_CHANGED;	  /* - Signal the output process to trigger an update (see section	     2.5). */	  rip_event (RIP_TRIGGERED_UPDATE, 0);	  /* Finally, route goes into the kernel. */	  rinfo->type = ZEBRA_ROUTE_RIP;	  rinfo->sub_type = RIP_ROUTE_RTE;	  /* Set distance value. */	  rinfo->distance = rip_distance_apply (rinfo);	  rp->info = rinfo;	  rip_zebra_ipv4_add (&p, &rinfo->nexthop, rinfo->metric,			      rinfo->distance);	  rinfo->flags |= RIP_RTF_FIB;	}    }  else    {      /* Route is there but we are not sure the route is RIP or not. */      rinfo = rp->info;

⌨️ 快捷键说明

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