blob: 1de435a494255fa757d5bb6aeb3532c7e2dce394 [file] [log] [blame]
/*
* Kernel routing readup by /proc filesystem
* Copyright (C) 1997 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 "rib.h"
#include "zebra/zserv.h"
#include "zebra/rt.h"
/* Proc file system to read IPv4 routing table. */
#ifndef _PATH_PROCNET_ROUTE
#define _PATH_PROCNET_ROUTE "/proc/net/route"
#endif /* _PATH_PROCNET_ROUTE */
/* Proc file system to read IPv6 routing table. */
#ifndef _PATH_PROCNET_ROUTE6
#define _PATH_PROCNET_ROUTE6 "/proc/net/ipv6_route"
#endif /* _PATH_PROCNET_ROUTE6 */
/* To read interface's name */
#define INTERFACE_NAMSIZ 20
/* Reading buffer for one routing entry. */
#define RT_BUFSIZ 1024
/* Kernel routing table read up by /proc filesystem. */
static int
proc_route_read (void)
{
FILE *fp;
char buf[RT_BUFSIZ];
char iface[INTERFACE_NAMSIZ], dest[9], gate[9], mask[9];
int flags, refcnt, use, metric, mtu, window, rtt;
/* Open /proc filesystem */
fp = fopen (_PATH_PROCNET_ROUTE, "r");
if (fp == NULL)
{
zlog_warn ("Can't open %s : %s\n", _PATH_PROCNET_ROUTE, safe_strerror (errno));
return -1;
}
/* Drop first label line. */
fgets (buf, RT_BUFSIZ, fp);
while (fgets (buf, RT_BUFSIZ, fp) != NULL)
{
int n;
struct prefix_ipv4 p;
struct in_addr tmpmask;
struct in_addr gateway;
u_char zebra_flags = 0;
n = sscanf (buf, "%s %s %s %x %d %d %d %s %d %d %d",
iface, dest, gate, &flags, &refcnt, &use, &metric,
mask, &mtu, &window, &rtt);
if (n != 11)
{
zlog_warn ("can't read all of routing information\n");
continue;
}
if (! (flags & RTF_UP))
continue;
if (! (flags & RTF_GATEWAY))
continue;
if (flags & RTF_DYNAMIC)
zebra_flags |= ZEBRA_FLAG_SELFROUTE;
p.family = AF_INET;
sscanf (dest, "%lX", (unsigned long *)&p.prefix);
sscanf (mask, "%lX", (unsigned long *)&tmpmask);
p.prefixlen = ip_masklen (tmpmask);
sscanf (gate, "%lX", (unsigned long *)&gateway);
rib_add_ipv4 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gateway, NULL, 0, 0, 0, 0);
}
fclose (fp);
return 0;
}
#ifdef HAVE_IPV6
static int
proc_ipv6_route_read ()
{
FILE *fp;
char buf [RT_BUFSIZ];
/* Open /proc filesystem */
fp = fopen (_PATH_PROCNET_ROUTE6, "r");
if (fp == NULL)
{
zlog_warn ("Can't open %s : %s", _PATH_PROCNET_ROUTE6,
safe_strerror (errno));
return -1;
}
/* There is no title line, so we don't drop first line. */
while (fgets (buf, RT_BUFSIZ, fp) != NULL)
{
int n;
char dest[33], src[33], gate[33];
char iface[INTERFACE_NAMSIZ];
int dest_plen, src_plen;
int metric, use, refcnt, flags;
struct prefix_ipv6 p;
struct in6_addr gateway;
u_char zebra_flags = 0;
/* Linux 2.1.x write this information at net/ipv6/route.c
rt6_info_node () */
n = sscanf (buf, "%32s %02x %32s %02x %32s %08x %08x %08x %08x %s",
dest, &dest_plen, src, &src_plen, gate,
&metric, &use, &refcnt, &flags, iface);
if (n != 10)
{
/* zlog_warn ("can't read all of routing information %d\n%s\n", n, buf); */
continue;
}
if (! (flags & RTF_UP))
continue;
if (! (flags & RTF_GATEWAY))
continue;
if (flags & RTF_DYNAMIC)
zebra_flags |= ZEBRA_FLAG_SELFROUTE;
p.family = AF_INET6;
str2in6_addr (dest, &p.prefix);
str2in6_addr (gate, &gateway);
p.prefixlen = dest_plen;
rib_add_ipv6 (ZEBRA_ROUTE_KERNEL, zebra_flags, &p, &gateway, 0, 0,
metric, 0);
}
fclose (fp);
return 0;
}
#endif /* HAVE_IPV6 */
void
route_read (void)
{
proc_route_read ();
#ifdef HAVE_IPV6
proc_ipv6_route_read ();
#endif /* HAVE_IPV6 */
}