Commit 9b136840 authored by Jan Moskyto Matejka's avatar Jan Moskyto Matejka Committed by Ondřej Zajíček

Netlink and BSD: Integrating IPv4 and IPv6

Squashing and minor changes by Ondrej Santiago Zajicek
parent 04ae8dda
......@@ -31,3 +31,4 @@ event.h
checksum.c
checksum.h
alloca.h
net.c
......@@ -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;
}
......@@ -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);
......
......@@ -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;
}
......
......@@ -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;
}
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment