krt-scan.c 3.72 KB
Newer Older
1 2 3
/*
 *	BIRD -- Linux Routing Table Scanning
 *
4
 *	(c) 1998--2000 Martin Mares <mj@ucw.cz>
5 6 7 8
 *
 *	Can be freely distributed and used under the terms of the GNU GPL.
 */

9
#include <stdio.h>
10
#include <ctype.h>
11 12 13
#include <fcntl.h>
#include <unistd.h>
#include <net/route.h>
14

15
#undef LOCAL_DEBUG
16 17 18 19

#include "nest/bird.h"
#include "nest/route.h"
#include "nest/protocol.h"
20
#include "nest/iface.h"
21 22 23
#include "lib/timer.h"
#include "lib/unix.h"
#include "lib/krt.h"
24
#include "lib/string.h"
25

26 27
static int krt_scan_fd = -1;

28
struct iface *
29
krt_temp_iface(struct krt_proto *p, char *name)
30 31 32
{
  struct iface *i;

33
  WALK_LIST(i, p->scan.temp_ifs)
34 35
    if (!strcmp(i->name, name))
      return i;
36
  i = mb_allocz(p->p.pool, sizeof(struct iface));
37
  strcpy(i->name, name);
38
  add_tail(&p->scan.temp_ifs, &i->n);
39 40 41
  return i;
}

42
static void
43
krt_parse_entry(byte *ent, struct krt_proto *p)
44 45 46
{
  u32 dest0, gw0, mask0;
  ip_addr dest, gw, mask;
47
  unsigned int flags;
48 49
  int masklen;
  net *net;
50
  byte *iface = ent;
51
  rte *e;
52

53
  if (sscanf(ent, "%*s\t%x\t%x\t%x\t%*d\t%*d\t%*d\t%x\t", &dest0, &gw0, &flags, &mask0) != 4)
54
    {
55
      log(L_ERR "krt read: unable to parse `%s'", ent);
56 57
      return;
    }
58 59 60
  while (*ent != '\t')
    ent++;
  *ent = 0;
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75

  dest = ipa_from_u32(dest0);
  ipa_ntoh(dest);
  gw = ipa_from_u32(gw0);
  ipa_ntoh(gw);
  mask = ipa_from_u32(mask0);
  ipa_ntoh(mask);
  if ((masklen = ipa_mklen(mask)) < 0)
    {
      log(L_ERR "krt read: invalid netmask %08x", mask0);
      return;
    }
  DBG("Got %I/%d via %I flags %x\n", dest, masklen, gw, flags);

  if (!(flags & RTF_UP))
76 77 78 79
    {
      DBG("Down.\n");
      return;
    }
80 81 82 83 84 85 86
  if (flags & RTF_HOST)
    masklen = 32;
  if (flags & (RTF_DYNAMIC | RTF_MODIFIED)) /* Redirect route */
    {
      log(L_WARN "krt: Ignoring redirect to %I/%d via %I", dest, masklen, gw);
      return;
    }
87

88
  net = net_get(p->p.table, dest, masklen);
89

90 91 92 93 94 95
  rta a = {
    .proto = &p->p,
    .source = RTS_INHERIT,
    .scope = SCOPE_UNIVERSE,
    .cast = RTC_UNICAST
  };
96 97

  if (flags & RTF_GATEWAY)
98
    {
99
      neighbor *ng = neigh_find(&p->p, &gw, 0);
100
      if (ng && ng->scope)
101 102
	a.iface = ng->iface;
      else
103
	{
104
	  log(L_WARN "Kernel told us to use non-neighbor %I for %I/%d", gw, net->n.prefix, net->n.pxlen);
105 106
	  return;
	}
107 108 109 110 111 112 113
      a.dest = RTD_ROUTER;
      a.gw = gw;
    }
  else if (flags & RTF_REJECT)
    {
      a.dest = RTD_UNREACHABLE;
      a.gw = IPA_NONE;
114
    }
115 116 117 118
  else if (isalpha(iface[0]))
    {
      a.dest = RTD_DEVICE;
      a.gw = IPA_NONE;
119
      a.iface = krt_temp_iface(p, iface);
120
    }
121 122
  else
    {
123
      log(L_WARN "Kernel reporting unknown route type to %I/%d", net->n.prefix, net->n.pxlen);
124 125 126 127 128
      return;
    }

  e = rte_get_temp(&a);
  e->net = net;
129
  e->u.krt.src = KRT_SRC_UNKNOWN;
130
  krt_got_route(p, e);
131 132
}

133 134
void
krt_scan_fire(struct krt_proto *p)
135 136 137 138 139 140 141 142 143 144 145 146 147
{
  byte buf[32768];
  int l, seen_hdr;

  if (krt_scan_fd < 0)
    {
      krt_scan_fd = open("/proc/net/route", O_RDONLY);
      if (krt_scan_fd < 0)
	die("/proc/net/route: %m");
    }
  else if (lseek(krt_scan_fd, 0, SEEK_SET) < 0)
    {
      log(L_ERR "krt seek: %m");
148
      return;
149 150 151 152 153 154 155 156
    }
  seen_hdr = 0;
  while ((l = read(krt_scan_fd, buf, sizeof(buf))) > 0)
    {
      byte *z = buf;
      if (l & 127)
	{
	  log(L_ERR "krt read: misaligned entry: l=%d", l);
157
	  return;
158 159 160 161
	}
      while (l >= 128)
	{
	  if (seen_hdr++)
162
	    krt_parse_entry(z, p);
163 164 165 166 167 168 169
	  z += 128;
	  l -= 128;
	}
    }
  if (l < 0)
    {
      log(L_ERR "krt read: %m");
170
      return;
171 172
    }
  DBG("KRT scan done, seen %d lines\n", seen_hdr);
173 174 175
}

void
176
krt_scan_construct(struct krt_config *c)
177 178 179 180
{
}

void
181 182 183 184 185 186 187 188 189 190 191
krt_scan_preconfig(struct config *c)
{
}

void
krt_scan_postconfig(struct krt_config *c)
{
}

void
krt_scan_start(struct krt_proto *x, int first)
192
{
193
  init_list(&x->scan.temp_ifs);
194 195 196
}

void
197
krt_scan_shutdown(struct krt_proto *x, int last)
198 199
{
}