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

📄 rip_interface.c

📁 大名鼎鼎的路由器源码。程序分ZEBRA、OSPFRIP等3个包。程序框架采用一个路由协议一个进程的方式
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Interface related function for RIP. * Copyright (C) 1997, 98 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 "command.h"#include "if.h"#include "sockunion.h"#include "prefix.h"#include "memory.h"#include "network.h"#include "table.h"#include "log.h"#include "stream.h"#include "thread.h"#include "zclient.h"#include "filter.h"#include "sockopt.h"#include "zebra/connected.h"#include "ripd/ripd.h"#include "ripd/rip_debug.h"void rip_enable_apply (struct interface *);void rip_passive_interface_apply (struct interface *);int rip_if_down(struct interface *ifp);struct message ri_version_msg[] = {  {RI_RIP_VERSION_1,       "1"},  {RI_RIP_VERSION_2,       "2"},  {RI_RIP_VERSION_1_AND_2, "1 2"},  {0,                      NULL}};/* RIP enabled network vector. */vector rip_enable_interface;/* RIP enabled interface table. */struct route_table *rip_enable_network;/* Vector to store passive-interface name. */vector Vrip_passive_interface;/* Join to the RIP version 2 multicast group. */intipv4_multicast_join (int sock, 		     struct in_addr group, 		     struct in_addr ifa,		     unsigned int ifindex){  int ret;  ret = setsockopt_multicast_ipv4 (sock, 				   IP_ADD_MEMBERSHIP, 				   ifa, 				   group.s_addr, 				   ifindex);   if (ret < 0)     zlog (NULL, LOG_INFO, "can't setsockopt IP_ADD_MEMBERSHIP %s",	  strerror (errno));  return ret;}/* Leave from the RIP version 2 multicast group. */intipv4_multicast_leave (int sock, 		      struct in_addr group, 		      struct in_addr ifa,		      unsigned int ifindex){  int ret;  ret = setsockopt_multicast_ipv4 (sock, 				   IP_DROP_MEMBERSHIP, 				   ifa, 				   group.s_addr, 				   ifindex);  if (ret < 0)     zlog (NULL, LOG_INFO, "can't setsockopt IP_DROP_MEMBERSHIP");  return ret;}/* Allocate new RIP's interface configuration. */struct rip_interface *rip_interface_new (){  struct rip_interface *ri;  ri = XMALLOC (MTYPE_RIP_INTERFACE, sizeof (struct rip_interface));  memset (ri, 0, sizeof (struct rip_interface));  /* Default authentication type is simple password for Cisco     compatibility. */  /* ri->auth_type = RIP_NO_AUTH; */  ri->auth_type = RIP_AUTH_SIMPLE_PASSWORD;  /* Set default split-horizon behavior.  If the interface is Frame     Relay or SMDS is enabled, the default value for split-horizon is     off.  But currently Zebra does detect Frame Relay or SMDS     interface.  So all interface is set to split horizon.  */  ri->split_horizon_default = 1;  ri->split_horizon = ri->split_horizon_default;  return ri;}voidrip_interface_multicast_set (int sock, struct interface *ifp){  int ret;  listnode node;  struct servent *sp;  struct sockaddr_in from;  for (node = listhead (ifp->connected); node; nextnode (node))    {      struct prefix_ipv4 *p;      struct connected *connected;      struct in_addr addr;      connected = getdata (node);      p = (struct prefix_ipv4 *) connected->address;      if (p->family == AF_INET)	{	  addr = p->prefix;	  if (setsockopt_multicast_ipv4 (sock, IP_MULTICAST_IF,					 addr, 0, ifp->ifindex) < 0) 	    {	      zlog_warn ("Can't setsockopt IP_MULTICAST_IF to fd %d", sock);	      return;	    }	  /* Bind myself. */	  memset (&from, 0, sizeof (struct sockaddr_in));	  /* Set RIP port. */	  sp = getservbyname ("router", "udp");	  if (sp) 	    from.sin_port = sp->s_port;	  else 	    from.sin_port = htons (RIP_PORT_DEFAULT);	  /* Address shoud be any address. */	  from.sin_family = AF_INET;	  from.sin_addr = addr;#ifdef HAVE_SIN_LEN	  from.sin_len = sizeof (struct sockaddr_in);#endif /* HAVE_SIN_LEN */	  ret = bind (sock, (struct sockaddr *) & from, 		      sizeof (struct sockaddr_in));	  if (ret < 0)	    {	      zlog_warn ("Can't bind socket: %s", strerror (errno));	      return;	    }	  return;	}    }}/* Send RIP request packet to specified interface. */voidrip_request_interface_send (struct interface *ifp, u_char version){  struct sockaddr_in to;  /* RIPv2 support multicast. */  if (version == RIPv2 && if_is_multicast (ifp))    {            if (IS_RIP_DEBUG_EVENT)	zlog_info ("multicast request on %s", ifp->name);      rip_request_send (NULL, ifp, version);      return;    }  /* RIPv1 and non multicast interface. */  if (if_is_pointopoint (ifp) || if_is_broadcast (ifp))    {      listnode cnode;      if (IS_RIP_DEBUG_EVENT)	zlog_info ("broadcast request to %s", ifp->name);      for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))	{	  struct prefix_ipv4 *p;	  struct connected *connected;	  connected = getdata (cnode);	  p = (struct prefix_ipv4 *) connected->destination;	  if (p->family == AF_INET)	    {	      memset (&to, 0, sizeof (struct sockaddr_in));	      to.sin_port = htons (RIP_PORT_DEFAULT);	      to.sin_addr = p->prefix;#if 0	      if (IS_RIP_DEBUG_EVENT)		zlog_info ("SEND request to %s", inet_ntoa (to.sin_addr));#endif /* 0 */	      	      rip_request_send (&to, ifp, version);	    }	}    }}/* This will be executed when interface goes up. */voidrip_request_interface (struct interface *ifp){  struct rip_interface *ri;  /* In default ripd doesn't send RIP_REQUEST to the loopback interface. */  if (if_is_loopback (ifp))    return;  /* If interface is down, don't send RIP packet. */  if (! if_is_up (ifp))    return;  /* Fetch RIP interface information. */  ri = ifp->info;  /* 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_request_interface_send (ifp, RIPv1);      else	rip_request_interface_send (ifp, RIPv2);    }  /* If interface has RIP version configuration use it. */  else    {      if (ri->ri_send & RIPv1)	rip_request_interface_send (ifp, RIPv1);      if (ri->ri_send & RIPv2)	rip_request_interface_send (ifp, RIPv2);    }}/* Send RIP request to the neighbor. */voidrip_request_neighbor (struct in_addr addr){  struct sockaddr_in to;  memset (&to, 0, sizeof (struct sockaddr_in));  to.sin_port = htons (RIP_PORT_DEFAULT);  to.sin_addr = addr;  rip_request_send (&to, NULL, rip->version);}/* Request routes at all interfaces. */voidrip_request_neighbor_all (){  struct route_node *rp;  if (! rip)    return;  if (IS_RIP_DEBUG_EVENT)    zlog_info ("request to the all neighbor");  /* Send request to all neighbor. */  for (rp = route_top (rip->neighbor); rp; rp = route_next (rp))    if (rp->info)      rip_request_neighbor (rp->p.u.prefix4);}/* Multicast packet receive socket. */intrip_multicast_join (struct interface *ifp, int sock){  listnode cnode;  if (if_is_up (ifp) && if_is_multicast (ifp))    {      if (IS_RIP_DEBUG_EVENT)	zlog_info ("multicast join at %s", ifp->name);      for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))	{	  struct prefix_ipv4 *p;	  struct connected *connected;	  struct in_addr group;	      	  connected = getdata (cnode);	  p = (struct prefix_ipv4 *) connected->address;      	  if (p->family != AF_INET)	    continue;      	  group.s_addr = htonl (INADDR_RIP_GROUP);	  if (ipv4_multicast_join (sock, group, p->prefix, ifp->ifindex) < 0)	    return -1;	  else	    return 0;	}    }  return 0;}/* Leave from multicast group. */voidrip_multicast_leave (struct interface *ifp, int sock){  listnode cnode;  if (if_is_up (ifp) && if_is_multicast (ifp))    {      if (IS_RIP_DEBUG_EVENT)	zlog_info ("multicast leave from %s", ifp->name);      for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))	{	  struct prefix_ipv4 *p;	  struct connected *connected;	  struct in_addr group;	      	  connected = getdata (cnode);	  p = (struct prefix_ipv4 *) connected->address;      	  if (p->family != AF_INET)	    continue;      	  group.s_addr = htonl (INADDR_RIP_GROUP);          if (ipv4_multicast_leave (sock, group, p->prefix, ifp->ifindex) == 0)	    return;        }    }}/* Is there and address on interface that I could use ? */intrip_if_ipv4_address_check (struct interface *ifp){  struct listnode *nn;  struct connected *connected;  int count = 0;  for (nn = listhead (ifp->connected); nn; nextnode (nn))    if ((connected = getdata (nn)) != NULL)      {	struct prefix *p;	p = connected->address;	if (p->family == AF_INET)          {	    count++;	  }      }						  return count;}																		/* Does this address belongs to me ? */intif_check_address (struct in_addr addr){  listnode node;  for (node = listhead (iflist); node; nextnode (node))    {      listnode cnode;      struct interface *ifp;      ifp = getdata (node);      for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))	{	  struct connected *connected;	  struct prefix_ipv4 *p;	  connected = getdata (cnode);	  p = (struct prefix_ipv4 *) connected->address;	  if (p->family != AF_INET)	    continue;	  if (IPV4_ADDR_CMP (&p->prefix, &addr) == 0)	    return 1;	}    }  return 0;}/* is this address from a valid neighbor? (RFC2453 - Sec. 3.9.2) */intif_valid_neighbor (struct in_addr addr){  listnode node;  struct connected *connected = NULL;  struct prefix_ipv4 *p;  for (node = listhead (iflist); node; nextnode (node))    {      listnode cnode;      struct interface *ifp;      ifp = getdata (node);      for (cnode = listhead (ifp->connected); cnode; nextnode (cnode))	{	  struct prefix *pxn = NULL; /* Prefix of the neighbor */	  struct prefix *pxc = NULL; /* Prefix of the connected network */	  connected = getdata (cnode);	  if (if_is_pointopoint (ifp))	    {	      p = (struct prefix_ipv4 *) connected->address;	      if (p && p->family == AF_INET)		{		  if (IPV4_ADDR_SAME (&p->prefix, &addr))		    return 1;		  p = (struct prefix_ipv4 *) connected->destination;		  if (p && IPV4_ADDR_SAME (&p->prefix, &addr))		    return 1;		}	    }	  else	    {	      p = (struct prefix_ipv4 *) connected->address;	      if (p->family != AF_INET)		continue;	      pxn = prefix_new();	      pxn->family = AF_INET;	      pxn->prefixlen = 32;	      pxn->u.prefix4 = addr;	      	      pxc = prefix_new();	      prefix_copy(pxc, (struct prefix *) p);	      apply_mask(pxc);	  	      if (prefix_match (pxc, pxn)) 		{		  prefix_free (pxn);		  prefix_free (pxc);		  return 1;		}	      prefix_free(pxc);	      prefix_free(pxn);	    }	}    }  return 0;}/* Inteface link down message processing. */intrip_interface_down (int command, struct zclient *zclient, zebra_size_t length){  struct interface *ifp;  struct stream *s;  s = zclient->ibuf;    /* zebra_interface_state_read() updates interface structure in     iflist. */  ifp = zebra_interface_state_read(s);  if (ifp == NULL)    return 0;  rip_if_down(ifp);   if (IS_RIP_DEBUG_ZEBRA)    zlog_info ("interface %s index %d flags %ld metric %d mtu %d is down",	       ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);  return 0;}/* Inteface link up message processing */intrip_interface_up (int command, struct zclient *zclient, zebra_size_t length){  struct interface *ifp;  /* zebra_interface_state_read () updates interface structure in     iflist. */  ifp = zebra_interface_state_read (zclient->ibuf);  if (ifp == NULL)    return 0;  if (IS_RIP_DEBUG_ZEBRA)    zlog_info ("interface %s index %d flags %ld metric %d mtu %d is up",	       ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);  /* Check if this interface is RIP enabled or not.*/  rip_enable_apply (ifp);   /* Check for a passive interface */  rip_passive_interface_apply (ifp);  /* Apply distribute list to the all interface. */  rip_distribute_update_interface (ifp);  return 0;}/* Inteface addition message from zebra. */intrip_interface_add (int command, struct zclient *zclient, zebra_size_t length){  struct interface *ifp;  ifp = zebra_interface_add_read (zclient->ibuf);  if (IS_RIP_DEBUG_ZEBRA)    zlog_info ("interface add %s index %d flags %ld metric %d mtu %d",	       ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);  /* Check if this interface is RIP enabled or not.*/  rip_enable_apply (ifp);  /* Apply distribute list to the all interface. */  rip_distribute_update_interface (ifp);  /* rip_request_neighbor_all (); */  return 0;}intrip_interface_delete (int command, struct zclient *zclient,		      zebra_size_t length){  struct interface *ifp;  struct stream *s;  s = zclient->ibuf;    /* zebra_interface_state_read() updates interface structure in iflist */  ifp = zebra_interface_state_read(s);  if (ifp == NULL)    return 0;  if (if_is_up (ifp)) {    rip_if_down(ifp);  }     zlog_info("interface delete %s index %d flags %ld metric %d mtu %d",	    ifp->name, ifp->ifindex, ifp->flags, ifp->metric, ifp->mtu);      /* To support pseudo interface do not free interface structure.  */  /* if_delete(ifp); */  return 0;}voidrip_interface_clean (){  listnode node;  struct interface *ifp;  struct rip_interface *ri;  for (node = listhead (iflist); node; nextnode (node))    {      ifp = getdata (node);      ri = ifp->info;      ri->enable_network = 0;      ri->enable_interface = 0;      ri->running = 0;      if (ri->t_wakeup)	{	  thread_cancel (ri->t_wakeup);	  ri->t_wakeup = NULL;	}    }}voidrip_interface_reset (){  listnode node;  struct interface *ifp;  struct rip_interface *ri;  for (node = listhead (iflist); node; nextnode (node))    {      ifp = getdata (node);      ri = ifp->info;      ri->enable_network = 0;      ri->enable_interface = 0;      ri->running = 0;      ri->ri_send = RI_RIP_UNSPEC;      ri->ri_receive = RI_RIP_UNSPEC;      /* ri->auth_type = RIP_NO_AUTH; */      ri->auth_type = RIP_AUTH_SIMPLE_PASSWORD;      if (ri->auth_str)	{	  free (ri->auth_str);	  ri->auth_str = NULL;	}      if (ri->key_chain)	{	  free (ri->key_chain);	  ri->key_chain = NULL;	}      ri->split_horizon = 0;      ri->split_horizon_default = 0;      ri->list[RIP_FILTER_IN] = NULL;      ri->list[RIP_FILTER_OUT] = NULL;      ri->prefix[RIP_FILTER_IN] = NULL;      ri->prefix[RIP_FILTER_OUT] = NULL;            if (ri->t_wakeup)	{	  thread_cancel (ri->t_wakeup);

⌨️ 快捷键说明

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