mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-05-02 18:56:53 +00:00
zebra: remove rt_ioctl kernel interface
None of the BSDs uses ioctls to set routes anymore. Signed-off-by: David Lamparter <equinox@opensourcerouting.org> Acked-by: Greg Troxel <gdt@ir.bbn.com> Acked-by: Feng Lu <lu.feng@6wind.com> Acked-by: Paul Jakma <paul@jakma.org>
This commit is contained in:
parent
f9a3a26046
commit
8df1db88df
420
zebra/rt_ioctl.c
420
zebra/rt_ioctl.c
@ -1,420 +0,0 @@
|
||||
/*
|
||||
* 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/zserv.h"
|
||||
#include "zebra/rib.h"
|
||||
#include "zebra/debug.h"
|
||||
#include "zebra/rt.h"
|
||||
|
||||
/* Initialize of kernel interface. There is no kernel communication
|
||||
support under ioctl(). So this is dummy stub function. */
|
||||
void
|
||||
kernel_init (void)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Dummy function of routing socket. */
|
||||
static void
|
||||
kernel_read (int sock)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Solaris has ortentry. */
|
||||
#ifdef HAVE_OLD_RTENTRY
|
||||
#define rtentry ortentry
|
||||
#endif /* HAVE_OLD_RTENTRY */
|
||||
|
||||
/* Interface to ioctl route message. */
|
||||
static int
|
||||
kernel_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, *tnexthop;
|
||||
int recursing;
|
||||
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_STRUCT_SOCKADDR_IN_SIN_LEN
|
||||
sin_dest.sin_len = sizeof (struct sockaddr_in);
|
||||
#endif /* HAVE_STRUCT_SOCKADDR_IN_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 (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
|
||||
{
|
||||
/* We shouldn't encounter recursive nexthops on discard routes,
|
||||
* but it is probably better to handle that case correctly anyway.
|
||||
*/
|
||||
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
|
||||
continue;
|
||||
SET_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB);
|
||||
}
|
||||
goto skip;
|
||||
}
|
||||
|
||||
memset (&sin_gate, 0, sizeof (struct sockaddr_in));
|
||||
|
||||
/* Make gateway. */
|
||||
for (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
|
||||
{
|
||||
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
|
||||
continue;
|
||||
|
||||
if ((cmd == SIOCADDRT
|
||||
&& CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
|
||||
|| (cmd == SIOCDELRT
|
||||
&& CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
|
||||
{
|
||||
if (nexthop->type == NEXTHOP_TYPE_IPV4 ||
|
||||
nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX)
|
||||
{
|
||||
sin_gate.sin_family = AF_INET;
|
||||
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
|
||||
sin_gate.sin_len = sizeof (struct sockaddr_in);
|
||||
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */
|
||||
sin_gate.sin_addr = nexthop->gate.ipv4;
|
||||
rtentry.rt_flags |= RTF_GATEWAY;
|
||||
}
|
||||
if (nexthop->type == NEXTHOP_TYPE_IFINDEX)
|
||||
{
|
||||
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_debug ("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_STRUCT_SOCKADDR_IN_SIN_LEN
|
||||
sin_mask.sin_len = sizeof (struct sockaddr_in);
|
||||
#endif /* HAVE_STRUCT_SOCKADDR_IN_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)", safe_strerror (errno), errno);
|
||||
return ret;
|
||||
}
|
||||
close (sock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
kernel_add_ipv4 (struct prefix *p, struct rib *rib)
|
||||
{
|
||||
return kernel_ioctl_ipv4 (SIOCADDRT, p, rib, AF_INET);
|
||||
}
|
||||
|
||||
int
|
||||
kernel_update_ipv4 (struct prefix *p, struct rib *rib)
|
||||
{
|
||||
kernel_ioctl_ipv4 (SIOCDELRT, p, rib, AF_INET);
|
||||
return kernel_ioctl_ipv4 (SIOCADDRT, p, rib, AF_INET);
|
||||
}
|
||||
|
||||
int
|
||||
kernel_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>
|
||||
#endif
|
||||
|
||||
static int
|
||||
kernel_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",
|
||||
safe_strerror(errno));
|
||||
ret = errno;
|
||||
close (sock);
|
||||
return ret;
|
||||
}
|
||||
close (sock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
kernel_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, *tnexthop;
|
||||
int recursing;
|
||||
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 (ALL_NEXTHOPS_RO(rib->nexthop, nexthop, tnexthop, recursing))
|
||||
{
|
||||
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
|
||||
continue;
|
||||
|
||||
if ((cmd == SIOCADDRT
|
||||
&& CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_ACTIVE))
|
||||
|| (cmd == SIOCDELRT
|
||||
&& CHECK_FLAG (nexthop->flags, NEXTHOP_FLAG_FIB)))
|
||||
{
|
||||
if (nexthop->type == NEXTHOP_TYPE_IPV6
|
||||
|| 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_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_debug ("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",
|
||||
safe_strerror(errno));
|
||||
ret = errno;
|
||||
close (sock);
|
||||
return ret;
|
||||
}
|
||||
close (sock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
kernel_add_ipv6 (struct prefix *p, struct rib *rib)
|
||||
{
|
||||
return kernel_ioctl_ipv6_multipath (SIOCADDRT, p, rib, AF_INET6);
|
||||
}
|
||||
|
||||
int
|
||||
kernel_update_ipv6 (struct prefix *p, struct rib *rib)
|
||||
{
|
||||
kernel_ioctl_ipv6_multipath (SIOCDELRT, p, rib, AF_INET6);
|
||||
return kernel_ioctl_ipv6_multipath(SIOCADDRT, p, rib, AF_INET6);
|
||||
}
|
||||
|
||||
int
|
||||
kernel_delete_ipv6 (struct prefix *p, struct rib *rib)
|
||||
{
|
||||
return kernel_ioctl_ipv6_multipath (SIOCDELRT, p, rib, AF_INET6);
|
||||
}
|
||||
#endif /* HAVE_IPV6 */
|
Loading…
Reference in New Issue
Block a user