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

📄 rt_ioctl.c

📁 大名鼎鼎的路由器源码。程序分ZEBRA、OSPFRIP等3个包。程序框架采用一个路由协议一个进程的方式
💻 C
字号:
/* * kernel routing table update by ioctl(). * Copyright (C) 1997, 98 Kunihiro Ishiguro * * 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 "prefix.h"#include "log.h"#include "if.h"#include "zebra/rib.h"#include "zebra/debug.h"/* Initialize of kernel interface.  There is no kernel communication   support under ioctl().  So this is dummy stub function. */voidkernel_init (){  return;}/* Dummy function of routing socket. */voidkernel_read (int sock){  return;}#if 0/* Initialization prototype of struct sockaddr_in. */static struct sockaddr_in sin_proto ={#ifdef HAVE_SIN_LEN  sizeof (struct sockaddr_in), #endif /* HAVE_SIN_LEN */  AF_INET, 0, {0}, {0}};#endif /* 0 *//* Solaris has ortentry. */#ifdef HAVE_OLD_RTENTRY#define rtentry ortentry#endif /* HAVE_OLD_RTENTRY *//* Interface to ioctl route message. */intkernel_add_route (struct prefix_ipv4 *dest, struct in_addr *gate,		  int index, int flags){  int ret;  int sock;  struct rtentry rtentry;  struct sockaddr_in sin_dest, sin_mask, sin_gate;  memset (&rtentry, 0, sizeof (struct rtentry));  /* Make destination. */  memset (&sin_dest, 0, sizeof (struct sockaddr_in));  sin_dest.sin_family = AF_INET;#ifdef HAVE_SIN_LEN  sin_dest.sin_len = sizeof (struct sockaddr_in);#endif /* HAVE_SIN_LEN */  sin_dest.sin_addr = dest->prefix;  /* Make gateway. */  if (gate)    {      memset (&sin_gate, 0, sizeof (struct sockaddr_in));      sin_gate.sin_family = AF_INET;#ifdef HAVE_SIN_LEN      sin_gate.sin_len = sizeof (struct sockaddr_in);#endif /* HAVE_SIN_LEN */      sin_gate.sin_addr = *gate;    }  memset (&sin_mask, 0, sizeof (struct sockaddr_in));  sin_mask.sin_family = AF_INET;#ifdef HAVE_SIN_LEN      sin_gate.sin_len = sizeof (struct sockaddr_in);#endif /* HAVE_SIN_LEN */  masklen2ip (dest->prefixlen, &sin_mask.sin_addr);  /* Set destination address, mask and gateway.*/  memcpy (&rtentry.rt_dst, &sin_dest, sizeof (struct sockaddr_in));  if (gate)    memcpy (&rtentry.rt_gateway, &sin_gate, sizeof (struct sockaddr_in));#ifndef SUNOS_5  memcpy (&rtentry.rt_genmask, &sin_mask, sizeof (struct sockaddr_in));#endif /* SUNOS_5 */  /* Routing entry flag set. */  if (dest->prefixlen == 32)    rtentry.rt_flags |= RTF_HOST;  if (gate && gate->s_addr != INADDR_ANY)    rtentry.rt_flags |= RTF_GATEWAY;  rtentry.rt_flags |= RTF_UP;  /* Additional flags */  rtentry.rt_flags |= flags;  /* For tagging route. */  /* rtentry.rt_flags |= RTF_DYNAMIC; */  /* Open socket for ioctl. */  sock = socket (AF_INET, SOCK_DGRAM, 0);  if (sock < 0)    {      zlog_warn ("can't make socket\n");      return -1;    }  /* Send message by ioctl(). */  ret = ioctl (sock, SIOCADDRT, &rtentry);  if (ret < 0)    {      switch (errno) 	{	case EEXIST:	  close (sock);	  return ZEBRA_ERR_RTEXIST;	  break;	case ENETUNREACH:	  close (sock);	  return ZEBRA_ERR_RTUNREACH;	  break;	case EPERM:	  close (sock);	  return ZEBRA_ERR_EPERM;	  break;	}      close (sock);      zlog_warn ("write : %s (%d)", strerror (errno), errno);      return 1;    }  close (sock);  return ret;}/* Interface to ioctl route message. */intkernel_ioctl_ipv4 (u_long cmd, struct prefix *p, struct rib *rib, int family){  int ret;  int sock;  struct rtentry rtentry;  struct sockaddr_in sin_dest, sin_mask, sin_gate;  struct nexthop *nexthop;  int nexthop_num = 0;  struct interface *ifp;  memset (&rtentry, 0, sizeof (struct rtentry));  /* Make destination. */  memset (&sin_dest, 0, sizeof (struct sockaddr_in));  sin_dest.sin_family = AF_INET;#ifdef HAVE_SIN_LEN  sin_dest.sin_len = sizeof (struct sockaddr_in);#endif /* HAVE_SIN_LEN */  sin_dest.sin_addr = p->u.prefix4;  if (CHECK_FLAG (rib->flags, ZEBRA_FLAG_BLACKHOLE))    {      SET_FLAG (rtentry.rt_flags, RTF_REJECT);      if (cmd == SIOCADDRT)	for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)	  SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);      goto skip;    }  memset (&sin_gate, 0, sizeof (struct sockaddr_in));  /* Make gateway. */  for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)    {      if ((cmd == SIOCADDRT 	   && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))	  || (cmd == SIOCDELRT	      && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))	{	  if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))	    {	      if (nexthop->rtype == NEXTHOP_TYPE_IPV4 ||		  nexthop->rtype == NEXTHOP_TYPE_IPV4_IFINDEX)		{		  sin_gate.sin_family = AF_INET;#ifdef HAVE_SIN_LEN		  sin_gate.sin_len = sizeof (struct sockaddr_in);#endif /* HAVE_SIN_LEN */		  sin_gate.sin_addr = nexthop->rgate.ipv4;		  rtentry.rt_flags |= RTF_GATEWAY;		}	      if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX		  || nexthop->rtype == NEXTHOP_TYPE_IFNAME)		{		  ifp = if_lookup_by_index (nexthop->rifindex);		  if (ifp)		    rtentry.rt_dev = ifp->name;		  else		    return -1;		}	    }	  else	    {	      if (nexthop->type == NEXTHOP_TYPE_IPV4 ||		  nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)		{		  sin_gate.sin_family = AF_INET;#ifdef HAVE_SIN_LEN		  sin_gate.sin_len = sizeof (struct sockaddr_in);#endif /* HAVE_SIN_LEN */		  sin_gate.sin_addr = nexthop->gate.ipv4;		  rtentry.rt_flags |= RTF_GATEWAY;		}	      if (nexthop->type == NEXTHOP_TYPE_IFINDEX		  || nexthop->type == NEXTHOP_TYPE_IFNAME)		{		  ifp = if_lookup_by_index (nexthop->ifindex);		  if (ifp)		    rtentry.rt_dev = ifp->name;		  else		    return -1;		}	    }	  if (cmd == SIOCADDRT)	    SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);	  nexthop_num++;	  break;	}    }  /* If there is no useful nexthop then return. */  if (nexthop_num == 0)    {      if (IS_ZEBRA_DEBUG_KERNEL)	zlog_info ("netlink_route_multipath(): No useful nexthop.");      return 0;    } skip:  memset (&sin_mask, 0, sizeof (struct sockaddr_in));  sin_mask.sin_family = AF_INET;#ifdef HAVE_SIN_LEN  sin_mask.sin_len = sizeof (struct sockaddr_in);#endif /* HAVE_SIN_LEN */  masklen2ip (p->prefixlen, &sin_mask.sin_addr);  /* Set destination address, mask and gateway.*/  memcpy (&rtentry.rt_dst, &sin_dest, sizeof (struct sockaddr_in));  if (rtentry.rt_flags & RTF_GATEWAY)    memcpy (&rtentry.rt_gateway, &sin_gate, sizeof (struct sockaddr_in));#ifndef SUNOS_5  memcpy (&rtentry.rt_genmask, &sin_mask, sizeof (struct sockaddr_in));#endif /* SUNOS_5 */  /* Metric.  It seems metric minus one value is installed... */  rtentry.rt_metric = rib->metric;  /* Routing entry flag set. */  if (p->prefixlen == 32)    rtentry.rt_flags |= RTF_HOST;  rtentry.rt_flags |= RTF_UP;  /* Additional flags */  /* rtentry.rt_flags |= flags; */  /* For tagging route. */  /* rtentry.rt_flags |= RTF_DYNAMIC; */  /* Open socket for ioctl. */  sock = socket (AF_INET, SOCK_DGRAM, 0);  if (sock < 0)    {      zlog_warn ("can't make socket\n");      return -1;    }  /* Send message by ioctl(). */  ret = ioctl (sock, cmd, &rtentry);  if (ret < 0)    {      switch (errno) 	{	case EEXIST:	  close (sock);	  return ZEBRA_ERR_RTEXIST;	  break;	case ENETUNREACH:	  close (sock);	  return ZEBRA_ERR_RTUNREACH;	  break;	case EPERM:	  close (sock);	  return ZEBRA_ERR_EPERM;	  break;	}      close (sock);      zlog_warn ("write : %s (%d)", strerror (errno), errno);      return ret;    }  close (sock);  return ret;}intkernel_add_ipv4 (struct prefix *p, struct rib *rib){  return kernel_ioctl_ipv4 (SIOCADDRT, p, rib, AF_INET);}intkernel_delete_ipv4 (struct prefix *p, struct rib *rib){  return kernel_ioctl_ipv4 (SIOCDELRT, p, rib, AF_INET);}#ifdef HAVE_IPV6/* Below is hack for GNU libc definition and Linux 2.1.X header. */#undef RTF_DEFAULT#undef RTF_ADDRCONF#include <asm/types.h>#if defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1/* struct in6_rtmsg will be declared in net/route.h. */#else#include <linux/ipv6_route.h>#endifintkernel_ioctl_ipv6 (u_long type, struct prefix_ipv6 *dest, struct in6_addr *gate,		   int index, int flags){  int ret;  int sock;  struct in6_rtmsg rtm;      memset (&rtm, 0, sizeof (struct in6_rtmsg));  rtm.rtmsg_flags |= RTF_UP;  rtm.rtmsg_metric = 1;  memcpy (&rtm.rtmsg_dst, &dest->prefix, sizeof (struct in6_addr));  rtm.rtmsg_dst_len = dest->prefixlen;  /* We need link local index. But this should be done caller...  if (IN6_IS_ADDR_LINKLOCAL(&rtm.rtmsg_gateway))    {      index = if_index_address (&rtm.rtmsg_gateway);      rtm.rtmsg_ifindex = index;    }  else    rtm.rtmsg_ifindex = 0;  */  rtm.rtmsg_flags |= RTF_GATEWAY;  /* For tagging route. */  /* rtm.rtmsg_flags |= RTF_DYNAMIC; */  memcpy (&rtm.rtmsg_gateway, gate, sizeof (struct in6_addr));  if (index)    rtm.rtmsg_ifindex = index;  else    rtm.rtmsg_ifindex = 0;  rtm.rtmsg_metric = 1;    sock = socket (AF_INET6, SOCK_DGRAM, 0);  if (sock < 0)    {      zlog_warn ("can't make socket\n");      return -1;    }  /* Send message via ioctl. */  ret = ioctl (sock, type, &rtm);  if (ret < 0)    {      zlog_warn ("can't %s ipv6 route: %s\n", type == SIOCADDRT ? "add" : "delete", 	   strerror(errno));      ret = errno;      close (sock);      return ret;    }  close (sock);  return ret;}intkernel_ioctl_ipv6_multipath (u_long cmd, struct prefix *p, struct rib *rib,			     int family){  int ret;  int sock;  struct in6_rtmsg rtm;  struct nexthop *nexthop;  int nexthop_num = 0;      memset (&rtm, 0, sizeof (struct in6_rtmsg));  rtm.rtmsg_flags |= RTF_UP;  rtm.rtmsg_metric = rib->metric;  memcpy (&rtm.rtmsg_dst, &p->u.prefix, sizeof (struct in6_addr));  rtm.rtmsg_dst_len = p->prefixlen;  /* We need link local index. But this should be done caller...  if (IN6_IS_ADDR_LINKLOCAL(&rtm.rtmsg_gateway))    {      index = if_index_address (&rtm.rtmsg_gateway);      rtm.rtmsg_ifindex = index;    }  else    rtm.rtmsg_ifindex = 0;  */  rtm.rtmsg_flags |= RTF_GATEWAY;  /* For tagging route. */  /* rtm.rtmsg_flags |= RTF_DYNAMIC; */  /* Make gateway. */  for (nexthop = rib->nexthop; nexthop; nexthop = nexthop->next)    {      if ((cmd == SIOCADDRT 	   && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))	  || (cmd == SIOCDELRT	      && CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))	{	  if (CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_RECURSIVE))	    {	      if (nexthop->rtype == NEXTHOP_TYPE_IPV6		  || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME		  || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX)		{		  memcpy (&rtm.rtmsg_gateway, &nexthop->rgate.ipv6,			  sizeof (struct in6_addr));		}	      if (nexthop->rtype == NEXTHOP_TYPE_IFINDEX		  || nexthop->rtype == NEXTHOP_TYPE_IFNAME		  || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFNAME		  || nexthop->rtype == NEXTHOP_TYPE_IPV6_IFINDEX)		rtm.rtmsg_ifindex = nexthop->rifindex;	      else		rtm.rtmsg_ifindex = 0;	      	    }	  else	    {	      if (nexthop->type == NEXTHOP_TYPE_IPV6		  || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME		  || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)		{		  memcpy (&rtm.rtmsg_gateway, &nexthop->gate.ipv6,			  sizeof (struct in6_addr));		}	      if (nexthop->type == NEXTHOP_TYPE_IFINDEX		  || nexthop->type == NEXTHOP_TYPE_IFNAME		  || nexthop->type == NEXTHOP_TYPE_IPV6_IFNAME		  || nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX)		rtm.rtmsg_ifindex = nexthop->ifindex;	      else		rtm.rtmsg_ifindex = 0;	    }	  if (cmd == SIOCADDRT)	    SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);	  nexthop_num++;	  break;	}    }  /* If there is no useful nexthop then return. */  if (nexthop_num == 0)    {      if (IS_ZEBRA_DEBUG_KERNEL)	zlog_info ("netlink_route_multipath(): No useful nexthop.");      return 0;    }  sock = socket (AF_INET6, SOCK_DGRAM, 0);  if (sock < 0)    {      zlog_warn ("can't make socket\n");      return -1;    }  /* Send message via ioctl. */  ret = ioctl (sock, cmd, &rtm);  if (ret < 0)    {      zlog_warn ("can't %s ipv6 route: %s\n",		 cmd == SIOCADDRT ? "add" : "delete", 	   strerror(errno));      ret = errno;      close (sock);      return ret;    }  close (sock);  return ret;}intkernel_add_ipv6 (struct prefix *p, struct rib *rib){  return kernel_ioctl_ipv6_multipath (SIOCADDRT, p, rib, AF_INET6);}intkernel_delete_ipv6 (struct prefix *p, struct rib *rib){  return kernel_ioctl_ipv6_multipath (SIOCDELRT, p, rib, AF_INET6);}/* Delete IPv6 route from the kernel. */intkernel_delete_ipv6_old (struct prefix_ipv6 *dest, struct in6_addr *gate,		    int index, int flags, int table){  return kernel_ioctl_ipv6 (SIOCDELRT, dest, gate, index, flags);}#endif /* HAVE_IPV6 */

⌨️ 快捷键说明

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