Commit 9b136840 authored by Jan Moskyto Matejka's avatar Jan Moskyto Matejka Committed by Ondrej Zajicek (work)
Browse files

Netlink and BSD: Integrating IPv4 and IPv6

Squashing and minor changes by Ondrej Santiago Zajicek
parent 04ae8dda
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -31,3 +31,4 @@ event.h
checksum.c
checksum.h
alloca.h
net.c
+57 −3
Original line number Diff line number Diff line
@@ -8,9 +8,9 @@ const u16 net_addr_length[] = {
  [NET_IP6] = sizeof(net_addr_ip6),
  [NET_VPN4] = sizeof(net_addr_vpn4),
  [NET_VPN6] = sizeof(net_addr_vpn6)
}
};

char *
int
net_format(const net_addr *N, char *buf, int buflen)
{
  net_addr_union *n = (void *) N;
@@ -27,6 +27,58 @@ net_format(const net_addr *N, char *buf, int buflen)
  case NET_VPN6:
    return bsnprintf(buf, buflen, "%u:%u %I/%d", (u32) (n->vpn6.rd >> 32), (u32) n->vpn6.rd, n->vpn6.prefix, n->vpn6.pxlen);
  }

  return 0;
}


ip_addr
net_pxmask(const net_addr *a)
{
  switch (a->type)
  {
  case NET_IP4:
  case NET_VPN4:
    return ipa_from_ip4(ip4_mkmask(net4_pxlen(a)));

  case NET_IP6:
  case NET_VPN6:
    return ipa_from_ip6(ip6_mkmask(net6_pxlen(a)));

  default:
    return IPA_NONE;
  }
}


static inline int net_validate_ip4(const net_addr_ip4 *n)
{
  return (n->pxlen <= IP4_MAX_PREFIX_LENGTH) &&
    ip4_zero(ip4_and(n->prefix, ip4_not(ip4_mkmask(n->pxlen))));
}

static inline int net_validate_ip6(const net_addr_ip6 *n)
{
  return (n->pxlen <= IP6_MAX_PREFIX_LENGTH) &&
    ip6_zero(ip6_and(n->prefix, ip6_not(ip6_mkmask(n->pxlen))));
}

int
net_validate(const net_addr *N)
{
  switch (a->type)
  {
  case NET_IP4:
  case NET_VPN4:
    return net_validate_ip4((net_addr_ip4 *) N);

  case NET_IP6:
  case NET_VPN6:
    return net_validate_ip6((net_addr_ip6 *) N);

  default:
    return 0;
  }
}

int
@@ -42,6 +94,8 @@ net_classify(const net_addr *N)

  case NET_IP6:
  case NET_VPN6:
    return ip6_zero(n->ip6.prefix) ? (IADDR_HOST | SCOPE_UNIVERSE) : ip6_classify(n->ip6.prefix);
    return ip6_zero(n->ip6.prefix) ? (IADDR_HOST | SCOPE_UNIVERSE) : ip6_classify(&n->ip6.prefix);
  }

  return 0;
}
+4 −1
Original line number Diff line number Diff line
@@ -131,6 +131,8 @@ static inline uint net6_pxlen(const net_addr *a)
static inline uint net_pxlen(const net_addr *a)
{ return a->pxlen; }

ip_addr net_pxmask(const net_addr *a);


static inline int net_equal(const net_addr *a, const net_addr *b)
{ return (a->length == b->length) && !memcmp(a, b, a->length); }
@@ -203,8 +205,9 @@ static inline void net_normalize_ip6(net_addr_ip6 *n)
void net_normalize(net_addr *N);

int net_validate(const net_addr *N);

int net_classify(const net_addr *N);
char * net_format(const net_addr *N, char *buf, int buflen);
int net_format(const net_addr *N, char *buf, int buflen);


int ipa_in_netX(const ip_addr A, const net_addr *N);
+4 −4
Original line number Diff line number Diff line
@@ -81,15 +81,15 @@ if_connected(ip_addr *a, struct iface *i, struct ifa **ap)
	{
	  if (ipa_in_netX(*a, &b->prefix))
	    {
#ifndef IPV6
	      if ((b->pxlen < (BITS_PER_IP_ADDRESS - 1)) &&
		  (ipa_equal(*a, b->prefix) ||	/* Network address */
	      /* Do not allow IPv4 network and broadcast addresses */
	      if (ipa_is_ip4(*a) &&
		  (net_pxlen(&b->prefix) < (BITS_PER_IP_ADDRESS - 1)) &&
		  (ipa_equal(*a, net_prefix(&b->prefix)) ||	/* Network address */
		   ipa_equal(*a, b->brd)))	/* Broadcast */
	      {
		*ap = NULL;
		return -1;
	      }
#endif

	      return b->scope;
	    }
+36 −16
Original line number Diff line number Diff line
@@ -207,7 +207,7 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
  msg.rtm.rtm_addrs = RTA_DST;
  msg.rtm.rtm_flags = RTF_UP | RTF_PROTO1;

  if (net->n.pxlen == MAX_PREFIX_LENGTH)
  if (net_prefix(net->n.addr) == MAX_PREFIX_LENGTH)
    msg.rtm.rtm_flags |= RTF_HOST;
  else
    msg.rtm.rtm_addrs |= RTA_NETMASK;
@@ -251,9 +251,24 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
    _I0(gw) = 0xfe800000 | (i->index & 0x0000ffff);
#endif

  sockaddr_fill(&dst,  BIRD_AF, net->n.prefix, NULL, 0);
  sockaddr_fill(&mask, BIRD_AF, ipa_mkmask(net->n.pxlen), NULL, 0);
  sockaddr_fill(&gate, BIRD_AF, gw, NULL, 0);
  int af = AF_UNSPEC;

  switch (net->n.addr->type) {
    case NET_IP4:
      af = AF_INET;
      break;
    case NET_IP6:
      af = AF_INET6;
      break;
    default:
      log(L_ERR "KRT: Not sending VPN route %N to kernel", net->n.addr);
      return -1;
  }


  sockaddr_fill(&dst,  af, net_prefix(net->n.addr), NULL, 0);
  sockaddr_fill(&mask, af, net_pxmask(net->n.addr), NULL, 0);
  sockaddr_fill(&gate, af, gw, NULL, 0);

  switch (a->dest)
  {
@@ -299,7 +314,7 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
  msg.rtm.rtm_msglen = l;

  if ((l = write(p->sys.sk->fd, (char *)&msg, l)) < 0) {
    log(L_ERR "KRT: Error sending route %I/%d to kernel: %m", net->n.prefix, net->n.pxlen);
    log(L_ERR "KRT: Error sending route %N to kernel: %m", net->n.addr);
    return -1;
  }

@@ -335,6 +350,7 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
  net *net;
  sockaddr dst, gate, mask;
  ip_addr idst, igate, imask;
  net_addr ndst;
  void *body = (char *)msg->buf;
  int new = (msg->rtm.rtm_type != RTM_DELETE);
  char *errmsg = "KRT: Invalid route received";
@@ -386,8 +402,11 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
  if (pxlen < 0)
    { log(L_ERR "%s (%I) - netmask %I", errmsg, idst, imask); return; }

  /* XXXX */
  net_fill_ipa(&ndst, idst, pxlen);

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

  u32 self_mask = RTF_PROTO1;
  u32 alien_mask = RTF_STATIC | RTF_PROTO1 | RTF_GATEWAY;
@@ -426,7 +445,7 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
  else
    src = KRT_SRC_KERNEL;

  net = net_get(p->p.table, idst, pxlen);
  net = net_get(p->p.table, &ndst);

  rta a = {
    .src = p->p.main_source,
@@ -455,8 +474,8 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
  a.iface = if_find_by_index(msg->rtm.rtm_index);
  if (!a.iface)
    {
      log(L_ERR "KRT: Received route %I/%d with unknown ifindex %u",
	  net->n.prefix, net->n.pxlen, msg->rtm.rtm_index);
      log(L_ERR "KRT: Received route %N with unknown ifindex %u",
	  net->n.addr, msg->rtm.rtm_index);
      return;
    }

@@ -480,8 +499,8 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
        if (ipa_classify(a.gw) == (IADDR_HOST | SCOPE_HOST))
          return;

	log(L_ERR "KRT: Received route %I/%d with strange next-hop %I",
	    net->n.prefix, net->n.pxlen, a.gw);
	log(L_ERR "KRT: Received route %N with strange next-hop %I",
	    net->n.addr, a.gw);
	return;
      }
  }
@@ -652,7 +671,7 @@ krt_read_addr(struct ks_msg *msg, int scan)
  imask = ipa_from_sa(&mask);
  ibrd  = ipa_from_sa(&brd);


  /* XXXX */
  if ((masklen = ipa_masklen(imask)) < 0)
  {
    log(L_ERR "KIF: Invalid masklen %I for %s", imask, iface->name);
@@ -673,7 +692,6 @@ krt_read_addr(struct ks_msg *msg, int scan)
  bzero(&ifa, sizeof(ifa));
  ifa.iface = iface;
  ifa.ip = iaddr;
  ifa.pxlen = masklen;

  scope = ipa_classify(ifa.ip);
  if (scope < 0)
@@ -685,7 +703,8 @@ krt_read_addr(struct ks_msg *msg, int scan)

  if (masklen < BITS_PER_IP_ADDRESS)
  {
    ifa.prefix = ipa_and(ifa.ip, ipa_mkmask(masklen));
    net_fill_ipa(&ifa.prefix, ifa.ip, masklen);
    net_normalize(&ifa.prefix);

    if (masklen == (BITS_PER_IP_ADDRESS - 1))
      ifa.opposite = ipa_opposite_m1(ifa.ip);
@@ -703,12 +722,13 @@ krt_read_addr(struct ks_msg *msg, int scan)
  }
  else if (!(iface->flags & IF_MULTIACCESS) && ipa_nonzero(ibrd))
  {
    ifa.prefix = ifa.opposite = ibrd;
    net_fill_ipa(&ifa.prefix, ibrd, BITS_PER_IP_ADDRESS);
    ifa.opposite = ibrd;
    ifa.flags |= IA_PEER;
  }
  else
  {
    ifa.prefix = ifa.ip;
    net_fill_ipa(&ifa.prefix, ifa.ip, BITS_PER_IP_ADDRESS);
    ifa.flags |= IA_HOST;
  }

Loading