Commit 421838ff authored by Martin Mares's avatar Martin Mares
Browse files

rte_update: Check sanity of incoming entries. Throw out (and log) all routes

to bogus prefixes and non-local routes to host scope addresses.
parent 529c4149
Loading
Loading
Loading
Loading
+40 −6
Original line number Diff line number Diff line
@@ -165,6 +165,38 @@ rt_feed_baby(struct proto *p)
    }
}

static inline int
rte_validate(rte *e)
{
  int c;
  net *n = e->net;

  ASSERT(!ipa_nonzero(ipa_and(n->n.prefix, ipa_not(ipa_mkmask(n->n.pxlen)))));
  if (n->n.pxlen)
    {
      c = ipa_classify(n->n.prefix);
      if (c < 0 || !(c & IADDR_HOST))
	{
	  if (!ipa_nonzero(n->n.prefix) && n->n.pxlen <= 1)
	    return 1;		/* Default route and half-default route is OK */
	  log(L_WARN "Ignoring bogus route %I/%d received from %I via %s",
	      n->n.prefix, n->n.pxlen, e->attrs->from, e->attrs->proto->name);
	  return 0;
	}
      if ((c & IADDR_SCOPE_MASK) == SCOPE_HOST)
	{
	  int s = e->attrs->source;
	  if (s != RTS_STATIC && s != RTS_DEVICE && s != RTS_STATIC_DEVICE)
	    {
	      log(L_WARN "Ignoring host scope route %I/%d received from %I via %s",
		  n->n.prefix, n->n.pxlen, e->attrs->from, e->attrs->proto->name);
	      return 0;
	    }
	}
    }
  return 1;
}

void
rte_free(rte *e)
{
@@ -187,14 +219,16 @@ rte_update(net *net, struct proto *p, rte *new)
  rte *old = NULL;
  rte **k, *r, *s;

  if (new && p->in_filter && f_run(p->in_filter, new, NULL) != F_ACCEPT)
  if (new)
    {
      if (!rte_validate(new) || p->in_filter && f_run(p->in_filter, new, NULL) != F_ACCEPT)
	{
	  rte_free(new);
	  return;
	}

  if (new && !(new->attrs->aflags & RTAF_CACHED)) /* Need to copy attributes */
      if (!(new->attrs->aflags & RTAF_CACHED)) /* Need to copy attributes */
	new->attrs = rta_lookup(new->attrs);
    }

  k = &net->routes;			/* Find and remove original route from the same protocol */
  while (old = *k)