Commit 3f358161 authored by Jan Moskyto Matejka's avatar Jan Moskyto Matejka
Browse files

BSD: Explicitly dropping routes with mismatched AF's.

parent 0e965f69
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -183,6 +183,8 @@ fib_rehash(struct fib *f, int step)
static u32
fib_hash(struct fib *f, const net_addr *a)
{
  ASSERT(f->addr_type == a->type);

  switch (f->addr_type)
  {
  case NET_IP4: return FIB_HASH(f, a, ip4);
@@ -232,6 +234,8 @@ fib_find(struct fib *f, const net_addr *a)
static void
fib_insert(struct fib *f, const net_addr *a, struct fib_node *e)
{
  ASSERT(f->addr_type == a->type);

  switch (f->addr_type)
  {
  case NET_IP4: FIB_INSERT(f, a, e, ip4); return;
+20 −8
Original line number Diff line number Diff line
@@ -344,6 +344,7 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
{
  /* p is NULL iff KRT_SHARED_SOCKET and !scan */

  int ipv6;
  rte *e;
  net *net;
  sockaddr dst, gate, mask;
@@ -372,15 +373,19 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)

  switch (dst.sa.sa_family) {
    case AF_INET:
      ipv6 = 0;
      break;
    case AF_INET6:
      /* We do not test family for RTA_NETMASK, because BSD sends us
	 some strange values, but interpreting them as IPv4/IPv6 works */
      mask.sa.sa_family = dst.sa.sa_family;
      ipv6 = 1;
      break;
    default:
      SKIP("invalid DST");
  }

  /* We do not test family for RTA_NETMASK, because BSD sends us
     some strange values, but interpreting them as IPv4/IPv6 works */
  mask.sa.sa_family = dst.sa.sa_family;

  idst  = ipa_from_sa(&dst);
  imask = ipa_from_sa(&mask);
  igate = (gate.sa.sa_family == dst.sa.sa_family) ? ipa_from_sa(&gate) : IPA_NONE;
@@ -389,27 +394,34 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
  if (!scan)
  {
    int table_id = msg->rtm.rtm_tableid;
    p = (table_id < KRT_MAX_TABLES) ? krt_table_map[table_id][!ipa_is_ip4(idst)] : NULL;
    p = (table_id < KRT_MAX_TABLES) ? krt_table_map[table_id][ipv6] : NULL;

    if (!p)
      SKIP("unknown table id %d\n", table_id);
  }
#endif
  if ((!ipv6) && (p->p.table->addr_type != NET_IP4))
    SKIP("reading only IPv4 routes");
  if (  ipv6  && (p->p.table->addr_type != NET_IP6))
    SKIP("reading only IPv6 routes");

  int c = ipa_classify_net(idst);
  if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
    SKIP("strange class/scope\n");

  int pxlen;
  if (ipa_is_ip4(imask))
    pxlen = (flags & RTF_HOST) ? IP4_MAX_PREFIX_LENGTH : ip4_masklen(ipa_to_ip4(imask));
  else
  if (ipv6)
    pxlen = (flags & RTF_HOST) ? IP6_MAX_PREFIX_LENGTH : ip6_masklen(&ipa_to_ip6(imask));
  else
    pxlen = (flags & RTF_HOST) ? IP4_MAX_PREFIX_LENGTH : ip4_masklen(ipa_to_ip4(imask));

  if (pxlen < 0)
    { log(L_ERR "%s (%I) - netmask %I", errmsg, idst, imask); return; }

  net_fill_ipa(&ndst, idst, pxlen);
  if (ipv6)
    net_fill_ip6(&ndst, ipa_to_ip6(idst), pxlen);
  else
    net_fill_ip4(&ndst, ipa_to_ip4(idst), pxlen);

  if ((flags & RTF_GATEWAY) && ipa_zero(igate))
    { log(L_ERR "%s (%N) - missing gateway", errmsg, ndst); return; }