Exemple #1
0
static void
dev_ifa_notify(struct proto *p, unsigned c, struct ifa *ad)
{
  struct rt_dev_config *P = (void *) p->cf;

  if (!EMPTY_LIST(P->iface_list) &&
      !iface_patt_find(&P->iface_list, ad->iface, ad->iface->addr))
    /* Empty list is automagically treated as "*" */
    return;

  if (ad->flags & IA_SECONDARY)
    return;

  if (ad->scope <= SCOPE_LINK)
    return;

  if (c & IF_CHANGE_DOWN)
    {
      net *n;

      DBG("dev_if_notify: %s:%I going down\n", ad->iface->name, ad->ip);
      n = net_find(p->table, ad->prefix, ad->pxlen);
      if (!n)
	{
	  DBG("dev_if_notify: device shutdown: prefix not found\n");
	  return;
	}

      /* Use iface ID as local source ID */
      struct rte_src *src = rt_get_source(p, ad->iface->index);
      rte_update2(p->main_ahook, n, NULL, src);
    }
  else if (c & IF_CHANGE_UP)
    {
      rta *a;
      net *n;
      rte *e;

      DBG("dev_if_notify: %s:%I going up\n", ad->iface->name, ad->ip);

      /* Use iface ID as local source ID */
      struct rte_src *src = rt_get_source(p, ad->iface->index);

      rta a0 = {
	.src = src,
	.source = RTS_DEVICE,
	.scope = SCOPE_UNIVERSE,
	.cast = RTC_UNICAST,
	.dest = RTD_DEVICE,
	.iface = ad->iface
      };

      a = rta_lookup(&a0);
      n = net_get(p->table, ad->prefix, ad->pxlen);
      e = rte_get_temp(a);
      e->net = n;
      e->pflags = 0;
      rte_update2(p->main_ahook, n, e, src);
    }
}
Exemple #2
0
static void
krt_parse_entry(byte *ent, struct krt_proto *p)
{
  u32 dest0, gw0, mask0;
  ip_addr dest, gw, mask;
  unsigned int flags;
  int masklen;
  net *net;
  byte *iface = ent;
  rte *e;

  if (sscanf(ent, "%*s\t%x\t%x\t%x\t%*d\t%*d\t%*d\t%x\t", &dest0, &gw0, &flags, &mask0) != 4)
    {
      log(L_ERR "krt read: unable to parse `%s'", ent);
      return;
    }
  while (*ent != '\t')
    ent++;
  *ent = 0;

  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))
    {
      DBG("Down.\n");
      return;
    }
  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;
    }

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

  rta a = {
    .proto = &p->p,
    .source = RTS_INHERIT,
    .scope = SCOPE_UNIVERSE,
    .cast = RTC_UNICAST
  };

  if (flags & RTF_GATEWAY)
    {
      neighbor *ng = neigh_find(&p->p, &gw, 0);
      if (ng && ng->scope)
	a.iface = ng->iface;
      else
	{
	  log(L_WARN "Kernel told us to use non-neighbor %I for %I/%d", gw, net->n.prefix, net->n.pxlen);
	  return;
	}
      a.dest = RTD_ROUTER;
      a.gw = gw;
    }
  else if (flags & RTF_REJECT)
    {
      a.dest = RTD_UNREACHABLE;
      a.gw = IPA_NONE;
    }
  else if (isalpha(iface[0]))
    {
      a.dest = RTD_DEVICE;
      a.gw = IPA_NONE;
      a.iface = krt_temp_iface(p, iface);
    }
  else
    {
      log(L_WARN "Kernel reporting unknown route type to %I/%d", net->n.prefix, net->n.pxlen);
      return;
    }

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

void
krt_scan_fire(struct krt_proto *p)
{
  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");
      return;
    }
  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);
	  return;
	}
      while (l >= 128)
	{
	  if (seen_hdr++)
	    krt_parse_entry(z, p);
	  z += 128;
	  l -= 128;
	}
    }
  if (l < 0)
    {
      log(L_ERR "krt read: %m");
      return;
    }
  DBG("KRT scan done, seen %d lines\n", seen_hdr);
}