summaryrefslogtreecommitdiff
path: root/sysdep/bsd/krt-sock.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdep/bsd/krt-sock.c')
-rw-r--r--sysdep/bsd/krt-sock.c192
1 files changed, 119 insertions, 73 deletions
diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c
index f2ae81c3..3440ed63 100644
--- a/sysdep/bsd/krt-sock.c
+++ b/sysdep/bsd/krt-sock.c
@@ -28,9 +28,9 @@
#include "nest/route.h"
#include "nest/protocol.h"
#include "nest/iface.h"
-#include "lib/timer.h"
-#include "lib/unix.h"
-#include "lib/krt.h"
+#include "sysdep/unix/timer.h"
+#include "sysdep/unix/unix.h"
+#include "sysdep/unix/krt.h"
#include "lib/string.h"
#include "lib/socket.h"
@@ -72,7 +72,6 @@
#endif
-
/* Dynamic max number of tables */
int krt_max_tables;
@@ -136,7 +135,7 @@ extern int setfib(int fib);
/* table_id -> krt_proto map */
#ifdef KRT_SHARED_SOCKET
-static struct krt_proto *krt_table_map[KRT_MAX_TABLES];
+static struct krt_proto *krt_table_map[KRT_MAX_TABLES][2];
#endif
@@ -207,7 +206,8 @@ 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)
+ /* XXXX */
+ if (net_pxlen(net->n.addr) == net_max_prefix_length[net->n.addr->type])
msg.rtm.rtm_flags |= RTF_HOST;
else
msg.rtm.rtm_addrs |= RTA_NETMASK;
@@ -245,15 +245,28 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
gw = a->gw;
-#ifdef IPV6
/* Embed interface ID to link-local address */
if (ipa_is_link_local(gw))
_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)
{
@@ -281,7 +294,7 @@ krt_send_route(struct krt_proto *p, int cmd, rte *e)
return -1;
}
- sockaddr_fill(&gate, BIRD_AF, i->addr->ip, NULL, 0);
+ sockaddr_fill(&gate, ipa_is_ip4(i->addr->ip) ? AF_INET : AF_INET6, i->addr->ip, NULL, 0);
msg.rtm.rtm_addrs |= RTA_GATEWAY;
}
break;
@@ -299,7 +312,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;
}
@@ -331,10 +344,12 @@ 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;
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";
@@ -352,42 +367,64 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
if (flags & RTF_LLINFO)
SKIP("link-local\n");
-#ifdef KRT_SHARED_SOCKET
- if (!scan)
- {
- int table_id = msg->rtm.rtm_tableid;
- p = (table_id < KRT_MAX_TABLES) ? krt_table_map[table_id] : NULL;
-
- if (!p)
- SKIP("unknown table id %d\n", table_id);
- }
-#endif
-
GETADDR(&dst, RTA_DST);
GETADDR(&gate, RTA_GATEWAY);
GETADDR(&mask, RTA_NETMASK);
- if (dst.sa.sa_family != BIRD_AF)
- SKIP("invalid DST");
+ switch (dst.sa.sa_family) {
+ case AF_INET:
+ ipv6 = 0;
+ break;
+ case AF_INET6:
+ 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 == BIRD_AF) ? ipa_from_sa(&gate) : IPA_NONE;
+ igate = (gate.sa.sa_family == dst.sa.sa_family) ? ipa_from_sa(&gate) : IPA_NONE;
- /* We do not test family for RTA_NETMASK, because BSD sends us
- some strange values, but interpreting them as IPv4/IPv6 works */
+#ifdef KRT_SHARED_SOCKET
+ if (!scan)
+ {
+ int table_id = msg->rtm.rtm_tableid;
+ 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.main_channel->table->addr_type != NET_IP4))
+ SKIP("reading only IPv4 routes");
+ if ( ipv6 && (p->p.main_channel->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 = (flags & RTF_HOST) ? MAX_PREFIX_LENGTH : ipa_masklen(imask);
+ int pxlen;
+ 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; }
+ 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 (%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 +463,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.main_channel->table, &ndst);
rta a = {
.src = p->p.main_source,
@@ -455,8 +492,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;
}
@@ -466,11 +503,9 @@ krt_read_route(struct ks_msg *msg, struct krt_proto *p, int scan)
a.dest = RTD_ROUTER;
a.gw = igate;
-#ifdef IPV6
/* Clean up embedded interface ID returned in link-local address */
if (ipa_is_link_local(a.gw))
_I0(a.gw) = 0xfe800000;
-#endif
ng = neigh_find2(&p->p, &a.gw, a.iface, 0);
if (!ng || (ng->scope == SCOPE_HOST))
@@ -480,8 +515,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;
}
}
@@ -643,22 +678,24 @@ krt_read_addr(struct ks_msg *msg, int scan)
GETADDR (&null, RTA_AUTHOR);
GETADDR (&brd, RTA_BRD);
- /* Some other family address */
- if (addr.sa.sa_family != BIRD_AF)
- return;
+ /* Is addr family IP4 or IP6? */
+ int ipv6;
+ switch (addr.sa.sa_family) {
+ case AF_INET: ipv6 = 0; break;
+ case AF_INET6: ipv6 = 1; break;
+ default: return;
+ }
iaddr = ipa_from_sa(&addr);
imask = ipa_from_sa(&mask);
ibrd = ipa_from_sa(&brd);
-
- if ((masklen = ipa_masklen(imask)) < 0)
+ if ((ipv6 ? (masklen = ip6_masklen(&ipa_to_ip6(imask))) : (masklen = ip4_masklen(ipa_to_ip4(imask)))) < 0)
{
- log(L_ERR "KIF: Invalid masklen %I for %s", imask, iface->name);
+ log(L_ERR "KIF: Invalid mask %I for %s", imask, iface->name);
return;
}
-#ifdef IPV6
/* Clean up embedded interface ID returned in link-local address */
if (ipa_is_link_local(iaddr))
@@ -666,13 +703,11 @@ krt_read_addr(struct ks_msg *msg, int scan)
if (ipa_is_link_local(ibrd))
_I0(ibrd) = 0xfe800000;
-#endif
bzero(&ifa, sizeof(ifa));
ifa.iface = iface;
ifa.ip = iaddr;
- ifa.pxlen = masklen;
scope = ipa_classify(ifa.ip);
if (scope < 0)
@@ -682,17 +717,16 @@ krt_read_addr(struct ks_msg *msg, int scan)
}
ifa.scope = scope & IADDR_SCOPE_MASK;
- if (masklen < BITS_PER_IP_ADDRESS)
+ if (masklen < (ipv6 ? IP6_MAX_PREFIX_LENGTH : IP4_MAX_PREFIX_LENGTH))
{
- 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))
+ if (masklen == ((ipv6 ? IP6_MAX_PREFIX_LENGTH : IP4_MAX_PREFIX_LENGTH) - 1))
ifa.opposite = ipa_opposite_m1(ifa.ip);
-#ifndef IPV6
- if (masklen == (BITS_PER_IP_ADDRESS - 2))
+ if ((!ipv6) && (masklen == IP4_MAX_PREFIX_LENGTH - 2))
ifa.opposite = ipa_opposite_m2(ifa.ip);
-#endif
if (iface->flags & IF_BROADCAST)
ifa.brd = ibrd;
@@ -702,12 +736,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, (ipv6 ? IP6_MAX_PREFIX_LENGTH : IP4_MAX_PREFIX_LENGTH));
+ ifa.opposite = ibrd;
ifa.flags |= IA_PEER;
}
else
{
- ifa.prefix = ifa.ip;
+ net_fill_ipa(&ifa.prefix, ifa.ip, (ipv6 ? IP6_MAX_PREFIX_LENGTH : IP4_MAX_PREFIX_LENGTH));
ifa.flags |= IA_HOST;
}
@@ -804,7 +839,7 @@ krt_sysctl_scan(struct proto *p, int cmd, int table_id)
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
- mib[3] = BIRD_AF;
+ mib[3] = 0; // Set AF to 0 for all available families
mib[4] = cmd;
mib[5] = 0;
mcnt = 6;
@@ -948,6 +983,7 @@ krt_sock_open(pool *pool, void *data, int table_id)
return sk;
}
+static u32 krt_table_cf[(KRT_MAX_TABLES+31) / 32][2];
#ifdef KRT_SHARED_SOCKET
@@ -979,7 +1015,17 @@ krt_sock_close_shared(void)
int
krt_sys_start(struct krt_proto *p)
{
- krt_table_map[KRT_CF->sys.table_id] = p;
+ int id = KRT_CF->sys.table_id;
+
+ if (krt_table_cf[id/32][!!(p->af == AF_INET6)] & (1 << (id%32)))
+ {
+ log(L_ERR "%s: Multiple kernel syncers defined for table #%d", p->p.name, id);
+ return 0;
+ }
+
+ krt_table_cf[id/32][!!(p->af == AF_INET6)] |= (1 << (id%32));
+
+ krt_table_map[KRT_CF->sys.table_id][!!(p->af == AF_INET6)] = p;
krt_sock_open_shared();
p->sys.sk = krt_sock;
@@ -990,10 +1036,12 @@ krt_sys_start(struct krt_proto *p)
void
krt_sys_shutdown(struct krt_proto *p)
{
+ krt_table_cf[(KRT_CF->sys.table_id)/32][!!(p->af == AF_INET6)] &= ~(1 << ((KRT_CF->sys.table_id)%32));
+
krt_sock_close_shared();
p->sys.sk = NULL;
- krt_table_map[KRT_CF->sys.table_id] = NULL;
+ krt_table_map[KRT_CF->sys.table_id][!!(p->af == AF_INET6)] = NULL;
krt_buffer_release(&p->p);
}
@@ -1003,6 +1051,16 @@ krt_sys_shutdown(struct krt_proto *p)
int
krt_sys_start(struct krt_proto *p)
{
+ int id = KRT_CF->sys.table_id;
+
+ if (krt_table_cf[id/32][!!(p->af == AF_INET6)] & (1 << (id%32)))
+ {
+ log(L_ERR "%s: Multiple kernel syncers defined for table #%d", p->p.name, id);
+ return 0;
+ }
+
+ krt_table_cf[id/32][!!(p->af == AF_INET6)] |= (1 << (id%32));
+
p->sys.sk = krt_sock_open(p->p.pool, p, KRT_CF->sys.table_id);
return 1;
}
@@ -1010,6 +1068,8 @@ krt_sys_start(struct krt_proto *p)
void
krt_sys_shutdown(struct krt_proto *p)
{
+ krt_table_cf[(KRT_CF->sys.table_id)/32][!!(p->af == AF_INET6)] &= ~(1 << ((KRT_CF->sys.table_id)%32));
+
rfree(p->sys.sk);
p->sys.sk = NULL;
@@ -1021,8 +1081,6 @@ krt_sys_shutdown(struct krt_proto *p)
/* KRT configuration callbacks */
-static u32 krt_table_cf[(KRT_MAX_TABLES+31) / 32];
-
int
krt_sys_reconfigure(struct krt_proto *p UNUSED, struct krt_config *n, struct krt_config *o)
{
@@ -1036,18 +1094,6 @@ krt_sys_preconfig(struct config *c UNUSED)
bzero(&krt_table_cf, sizeof(krt_table_cf));
}
-void
-krt_sys_postconfig(struct krt_config *x)
-{
- u32 *tbl = krt_table_cf;
- int id = x->sys.table_id;
-
- if (tbl[id/32] & (1 << (id%32)))
- cf_error("Multiple kernel syncers defined for table #%d", id);
-
- tbl[id/32] |= (1 << (id%32));
-}
-
void krt_sys_init_config(struct krt_config *c)
{
c->sys.table_id = 0; /* Default table */
@@ -1076,7 +1122,7 @@ kif_sys_shutdown(struct kif_proto *p)
struct ifa *
kif_get_primary_ip(struct iface *i)
{
-#ifndef IPV6
+#if 0
static int fd = -1;
if (fd < 0)