summaryrefslogtreecommitdiff
path: root/sysdep
diff options
context:
space:
mode:
Diffstat (limited to 'sysdep')
-rw-r--r--sysdep/bsd/Makefile5
-rw-r--r--sysdep/bsd/Modules5
-rw-r--r--sysdep/bsd/krt-sock.c192
-rw-r--r--sysdep/bsd/krt-sys.h4
-rw-r--r--sysdep/cf/bsd-v6.h22
-rw-r--r--sysdep/cf/bsd.h3
-rw-r--r--sysdep/cf/linux-v6.h21
-rw-r--r--sysdep/cf/linux.h5
-rw-r--r--sysdep/linux/Makefile4
-rw-r--r--sysdep/linux/Modules5
-rw-r--r--sysdep/linux/netlink.c433
-rw-r--r--sysdep/linux/sysio.h2
-rw-r--r--sysdep/unix/Makefile5
-rw-r--r--sysdep/unix/Modules12
-rw-r--r--sysdep/unix/config.Y3
-rw-r--r--sysdep/unix/io.c43
-rw-r--r--sysdep/unix/krt.Y35
-rw-r--r--sysdep/unix/krt.c169
-rw-r--r--sysdep/unix/krt.h10
-rw-r--r--sysdep/unix/log.c2
-rw-r--r--sysdep/unix/main.c8
-rw-r--r--sysdep/unix/unix.h31
22 files changed, 576 insertions, 443 deletions
diff --git a/sysdep/bsd/Makefile b/sysdep/bsd/Makefile
new file mode 100644
index 00000000..ddc87239
--- /dev/null
+++ b/sysdep/bsd/Makefile
@@ -0,0 +1,5 @@
+src := krt-sock.c
+obj := $(src-o-files)
+$(all-daemon)
+$(conf-y-targets): $(s)krt-sock.Y
+
diff --git a/sysdep/bsd/Modules b/sysdep/bsd/Modules
deleted file mode 100644
index 39db88e9..00000000
--- a/sysdep/bsd/Modules
+++ /dev/null
@@ -1,5 +0,0 @@
-krt-sock.c
-krt-sock.Y
-krt-sys.h
-sysio.h
-setkey.h
diff --git a/sysdep/bsd/krt-sock.c b/sysdep/bsd/krt-sock.c
index 6ff3b2b7..56026bdd 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;
@@ -941,6 +976,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
@@ -972,7 +1008,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;
@@ -983,10 +1029,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);
}
@@ -996,6 +1044,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;
}
@@ -1003,6 +1061,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;
@@ -1014,8 +1074,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)
{
@@ -1029,18 +1087,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 */
@@ -1069,7 +1115,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)
diff --git a/sysdep/bsd/krt-sys.h b/sysdep/bsd/krt-sys.h
index a63f8caf..870cdf2c 100644
--- a/sysdep/bsd/krt-sys.h
+++ b/sysdep/bsd/krt-sys.h
@@ -44,8 +44,8 @@ struct krt_state {
static inline void krt_sys_io_init(void) { }
static inline void krt_sys_init(struct krt_proto *p UNUSED) { }
+static inline void krt_sys_postconfig(struct krt_config *x UNUSED) { }
-static inline int krt_sys_get_attr(eattr *a UNUSED, byte *buf UNUSED, int buflen UNUSED) { }
-
+static inline int krt_sys_get_attr(eattr *a UNUSED, byte *buf UNUSED, int buflen UNUSED) { return GA_UNKNOWN; }
#endif
diff --git a/sysdep/cf/bsd-v6.h b/sysdep/cf/bsd-v6.h
deleted file mode 100644
index 745dfba3..00000000
--- a/sysdep/cf/bsd-v6.h
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Configuration for *BSD based systems (tested on FreeBSD and NetBSD)
- *
- * (c) 2004 Ondrej Filip <feela@network.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-#define IPV6
-
-#define CONFIG_AUTO_ROUTES
-#define CONFIG_SELF_CONSCIOUS
-#define CONFIG_MULTIPLE_TABLES
-#define CONFIG_SINGLE_ROUTE
-
-#define CONFIG_SKIP_MC_BIND
-#define CONFIG_NO_IFACE_BIND
-
-/*
-Link: sysdep/unix
-Link: sysdep/bsd
- */
diff --git a/sysdep/cf/bsd.h b/sysdep/cf/bsd.h
index 51beb42b..22c54277 100644
--- a/sysdep/cf/bsd.h
+++ b/sysdep/cf/bsd.h
@@ -15,6 +15,9 @@
#define CONFIG_NO_IFACE_BIND
#define CONFIG_USE_HDRINCL
+#define CONFIG_INCLUDE_SYSIO_H "sysdep/bsd/sysio.h"
+#define CONFIG_INCLUDE_KRTSYS_H "sysdep/bsd/krt-sys.h"
+
/*
Link: sysdep/unix
Link: sysdep/bsd
diff --git a/sysdep/cf/linux-v6.h b/sysdep/cf/linux-v6.h
deleted file mode 100644
index 09f60377..00000000
--- a/sysdep/cf/linux-v6.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Configuration for Linux based systems running IPv6
- *
- * (c) 1998--1999 Martin Mares <mj@ucw.cz>
- *
- * Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-#define IPV6
-
-#define CONFIG_AUTO_ROUTES
-#define CONFIG_SELF_CONSCIOUS
-#define CONFIG_MULTIPLE_TABLES
-#define CONFIG_ALL_TABLES_AT_ONCE
-
-#define CONFIG_RESTRICTED_PRIVILEGES
-
-/*
-Link: sysdep/linux
-Link: sysdep/unix
- */
diff --git a/sysdep/cf/linux.h b/sysdep/cf/linux.h
index 9e34f869..cec9499c 100644
--- a/sysdep/cf/linux.h
+++ b/sysdep/cf/linux.h
@@ -14,7 +14,12 @@
#define CONFIG_MC_PROPER_SRC
#define CONFIG_UNIX_DONTROUTE
+#define CONFIG_INCLUDE_SYSIO_H "sysdep/linux/sysio.h"
+#define CONFIG_INCLUDE_KRTSYS_H "sysdep/linux/krt-sys.h"
+
#define CONFIG_RESTRICTED_PRIVILEGES
+#define CONFIG_INCLUDE_SYSPRIV_H "sysdep/linux/syspriv.h"
+
/*
Link: sysdep/linux
diff --git a/sysdep/linux/Makefile b/sysdep/linux/Makefile
new file mode 100644
index 00000000..23cf1d9d
--- /dev/null
+++ b/sysdep/linux/Makefile
@@ -0,0 +1,4 @@
+src := netlink.c
+obj := $(src-o-files)
+$(all-daemon)
+$(conf-y-targets): $(s)netlink.Y
diff --git a/sysdep/linux/Modules b/sysdep/linux/Modules
deleted file mode 100644
index 940660b6..00000000
--- a/sysdep/linux/Modules
+++ /dev/null
@@ -1,5 +0,0 @@
-krt-sys.h
-netlink.c
-netlink.Y
-sysio.h
-syspriv.h
diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c
index b42e7b6f..8146072b 100644
--- a/sysdep/linux/netlink.c
+++ b/sysdep/linux/netlink.c
@@ -6,6 +6,7 @@
* Can be freely distributed and used under the terms of the GNU GPL.
*/
+#include <alloca.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
@@ -20,9 +21,9 @@
#include "nest/protocol.h"
#include "nest/iface.h"
#include "lib/alloca.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/socket.h"
#include "lib/string.h"
#include "lib/hash.h"
@@ -249,18 +250,16 @@ static struct nl_want_attrs ifla_attr_want[BIRD_IFLA_MAX] = {
#define BIRD_IFA_MAX (IFA_ANYCAST+1)
-#ifndef IPV6
static struct nl_want_attrs ifa_attr_want4[BIRD_IFA_MAX] = {
[IFA_ADDRESS] = { 1, 1, sizeof(ip4_addr) },
[IFA_LOCAL] = { 1, 1, sizeof(ip4_addr) },
[IFA_BROADCAST] = { 1, 1, sizeof(ip4_addr) },
};
-#else
+
static struct nl_want_attrs ifa_attr_want6[BIRD_IFA_MAX] = {
[IFA_ADDRESS] = { 1, 1, sizeof(ip6_addr) },
[IFA_LOCAL] = { 1, 1, sizeof(ip6_addr) },
};
-#endif
#define BIRD_RTA_MAX (RTA_TABLE+1)
@@ -269,7 +268,6 @@ static struct nl_want_attrs mpnh_attr_want4[BIRD_RTA_MAX] = {
[RTA_GATEWAY] = { 1, 1, sizeof(ip4_addr) },
};
-#ifndef IPV6
static struct nl_want_attrs rtm_attr_want4[BIRD_RTA_MAX] = {
[RTA_DST] = { 1, 1, sizeof(ip4_addr) },
[RTA_OIF] = { 1, 1, sizeof(u32) },
@@ -281,7 +279,7 @@ static struct nl_want_attrs rtm_attr_want4[BIRD_RTA_MAX] = {
[RTA_FLOW] = { 1, 1, sizeof(u32) },
[RTA_TABLE] = { 1, 1, sizeof(u32) },
};
-#else
+
static struct nl_want_attrs rtm_attr_want6[BIRD_RTA_MAX] = {
[RTA_DST] = { 1, 1, sizeof(ip6_addr) },
[RTA_IIF] = { 1, 1, sizeof(u32) },
@@ -293,7 +291,6 @@ static struct nl_want_attrs rtm_attr_want6[BIRD_RTA_MAX] = {
[RTA_FLOW] = { 1, 1, sizeof(u32) },
[RTA_TABLE] = { 1, 1, sizeof(u32) },
};
-#endif
static int
@@ -309,7 +306,7 @@ nl_parse_attrs(struct rtattr *a, struct nl_want_attrs *want, struct rtattr **k,
if (want[a->rta_type].checksize && (RTA_PAYLOAD(a) != want[a->rta_type].size))
{
- log(L_ERR "nl_parse_attrs: Malformed message received");
+ log(L_ERR "nl_parse_attrs: Malformed attribute received");
return 0;
}
@@ -334,6 +331,13 @@ static inline ip4_addr rta_get_ip4(struct rtattr *a)
static inline ip6_addr rta_get_ip6(struct rtattr *a)
{ return ip6_ntoh(*(ip6_addr *) RTA_DATA(a)); }
+static inline ip_addr rta_get_ipa(struct rtattr *a)
+{
+ if (RTA_PAYLOAD(a) == sizeof(ip4_addr))
+ return ipa_from_ip4(rta_get_ip4(a));
+ else
+ return ipa_from_ip6(rta_get_ip6(a));
+}
struct rtattr *
nl_add_attr(struct nlmsghdr *h, uint bufsize, uint code, const void *data, uint dlen)
@@ -356,16 +360,32 @@ nl_add_attr(struct nlmsghdr *h, uint bufsize, uint code, const void *data, uint
}
static inline void
-nl_add_attr_u32(struct nlmsghdr *h, unsigned bufsize, int code, u32 data)
+nl_add_attr_u32(struct nlmsghdr *h, uint bufsize, int code, u32 data)
{
nl_add_attr(h, bufsize, code, &data, 4);
}
static inline void
-nl_add_attr_ipa(struct nlmsghdr *h, unsigned bufsize, int code, ip_addr ipa)
+nl_add_attr_ip4(struct nlmsghdr *h, uint bufsize, int code, ip4_addr ip4)
+{
+ ip4 = ip4_hton(ip4);
+ nl_add_attr(h, bufsize, code, &ip4, sizeof(ip4));
+}
+
+static inline void
+nl_add_attr_ip6(struct nlmsghdr *h, uint bufsize, int code, ip6_addr ip6)
{
- ipa_hton(ipa);
- nl_add_attr(h, bufsize, code, &ipa, sizeof(ipa));
+ ip6 = ip6_hton(ip6);
+ nl_add_attr(h, bufsize, code, &ip6, sizeof(ip6));
+}
+
+static inline void
+nl_add_attr_ipa(struct nlmsghdr *h, uint bufsize, int code, ip_addr ipa)
+{
+ if (ipa_is_ip4(ipa))
+ nl_add_attr_ip4(h, bufsize, code, ipa_to_ip4(ipa));
+ else
+ nl_add_attr_ip6(h, bufsize, code, ipa_to_ip6(ipa));
}
static inline struct rtattr *
@@ -401,7 +421,7 @@ nl_close_nexthop(struct nlmsghdr *h, struct rtnexthop *nh)
}
static void
-nl_add_multipath(struct nlmsghdr *h, unsigned bufsize, struct mpnh *nh)
+nl_add_multipath(struct nlmsghdr *h, uint bufsize, struct mpnh *nh)
{
struct rtattr *a = nl_open_attr(h, bufsize, RTA_MULTIPATH);
@@ -463,12 +483,12 @@ nl_parse_multipath(struct krt_proto *p, struct rtattr *ra)
nl_parse_attrs(RTNH_DATA(nh), mpnh_attr_want4, a, sizeof(a));
if (a[RTA_GATEWAY])
{
- memcpy(&rv->gw, RTA_DATA(a[RTA_GATEWAY]), sizeof(ip_addr));
- ipa_ntoh(rv->gw);
+ rv->gw = rta_get_ipa(a[RTA_GATEWAY]);
- neighbor *ng = neigh_find2(&p->p, &rv->gw, rv->iface,
- (nh->rtnh_flags & RTNH_F_ONLINK) ? NEF_ONLINK : 0);
- if (!ng || (ng->scope == SCOPE_HOST))
+ neighbor *nbr;
+ nbr = neigh_find2(&p->p, &rv->gw, rv->iface,
+ (nh->rtnh_flags & RTNH_F_ONLINK) ? NEF_ONLINK : 0);
+ if (!nbr || (nbr->scope == SCOPE_HOST))
return NULL;
}
else
@@ -603,40 +623,20 @@ nl_parse_link(struct nlmsghdr *h, int scan)
}
static void
-nl_parse_addr(struct nlmsghdr *h, int scan)
+nl_parse_addr4(struct ifaddrmsg *i, int scan, int new)
{
- struct ifaddrmsg *i;
struct rtattr *a[BIRD_IFA_MAX];
- int new = h->nlmsg_type == RTM_NEWADDR;
- struct ifa ifa;
struct iface *ifi;
int scope;
- if (!(i = nl_checkin(h, sizeof(*i))))
+ if (!nl_parse_attrs(IFA_RTA(i), ifa_attr_want4, a, sizeof(a)))
return;
- switch (i->ifa_family)
+ if (!a[IFA_LOCAL])
{
-#ifndef IPV6
- case AF_INET:
- if (!nl_parse_attrs(IFA_RTA(i), ifa_attr_want4, a, sizeof(a)))
- return;
- if (!a[IFA_LOCAL])
- {
- log(L_ERR "KIF: Malformed message received (missing IFA_LOCAL)");
- return;
- }
- break;
-#else
- case AF_INET6:
- if (!nl_parse_attrs(IFA_RTA(i), ifa_attr_want6, a, sizeof(a)))
- return;
- break;
-#endif
- default:
- return;
+ log(L_ERR "KIF: Malformed message received (missing IFA_LOCAL)");
+ return;
}
-
if (!a[IFA_ADDRESS])
{
log(L_ERR "KIF: Malformed message received (missing IFA_ADDRESS)");
@@ -650,59 +650,57 @@ nl_parse_addr(struct nlmsghdr *h, int scan)
return;
}
+ struct ifa ifa;
bzero(&ifa, sizeof(ifa));
ifa.iface = ifi;
if (i->ifa_flags & IFA_F_SECONDARY)
ifa.flags |= IA_SECONDARY;
- /* IFA_LOCAL can be unset for IPv6 interfaces */
- memcpy(&ifa.ip, RTA_DATA(a[IFA_LOCAL] ? : a[IFA_ADDRESS]), sizeof(ifa.ip));
- ipa_ntoh(ifa.ip);
- ifa.pxlen = i->ifa_prefixlen;
- if (i->ifa_prefixlen > BITS_PER_IP_ADDRESS)
+ ifa.ip = rta_get_ipa(a[IFA_LOCAL]);
+
+ if (i->ifa_prefixlen > IP4_MAX_PREFIX_LENGTH)
{
log(L_ERR "KIF: Invalid prefix length for interface %s: %d", ifi->name, i->ifa_prefixlen);
new = 0;
}
- if (i->ifa_prefixlen == BITS_PER_IP_ADDRESS)
+ if (i->ifa_prefixlen == IP4_MAX_PREFIX_LENGTH)
{
- ip_addr addr;
- memcpy(&addr, RTA_DATA(a[IFA_ADDRESS]), sizeof(addr));
- ipa_ntoh(addr);
- ifa.prefix = ifa.brd = addr;
+ ifa.brd = rta_get_ipa(a[IFA_ADDRESS]);
+ net_fill_ip4(&ifa.prefix, rta_get_ip4(a[IFA_ADDRESS]), i->ifa_prefixlen);
/* It is either a host address or a peer address */
- if (ipa_equal(ifa.ip, addr))
+ if (ipa_equal(ifa.ip, ifa.brd))
ifa.flags |= IA_HOST;
else
{
ifa.flags |= IA_PEER;
- ifa.opposite = addr;
+ ifa.opposite = ifa.brd;
}
}
else
{
- ip_addr netmask = ipa_mkmask(ifa.pxlen);
- ifa.prefix = ipa_and(ifa.ip, netmask);
- ifa.brd = ipa_or(ifa.ip, ipa_not(netmask));
- if (i->ifa_prefixlen == BITS_PER_IP_ADDRESS - 1)
+ net_fill_ip4(&ifa.prefix, ipa_to_ip4(ifa.ip), i->ifa_prefixlen);
+ net_normalize(&ifa.prefix);
+
+ if (i->ifa_prefixlen == IP4_MAX_PREFIX_LENGTH - 1)
ifa.opposite = ipa_opposite_m1(ifa.ip);
-#ifndef IPV6
- if (i->ifa_prefixlen == BITS_PER_IP_ADDRESS - 2)
+ if (i->ifa_prefixlen == IP4_MAX_PREFIX_LENGTH - 2)
ifa.opposite = ipa_opposite_m2(ifa.ip);
if ((ifi->flags & IF_BROADCAST) && a[IFA_BROADCAST])
{
- ip_addr xbrd;
- memcpy(&xbrd, RTA_DATA(a[IFA_BROADCAST]), sizeof(xbrd));
- ipa_ntoh(xbrd);
- if (ipa_equal(xbrd, ifa.prefix) || ipa_equal(xbrd, ifa.brd))
- ifa.brd = xbrd;
+ ip4_addr xbrd = rta_get_ip4(a[IFA_BROADCAST]);
+ ip4_addr ybrd = ip4_or(ipa_to_ip4(ifa.ip), ip4_not(ip4_mkmask(i->ifa_prefixlen)));
+
+ if (ip4_equal(xbrd, net4_prefix(&ifa.prefix)) || ip4_equal(xbrd, ybrd))
+ ifa.brd = ipa_from_ip4(xbrd);
else if (ifi->flags & IF_TMP_DOWN) /* Complain only during the first scan */
- log(L_ERR "KIF: Invalid broadcast address %I for %s", xbrd, ifi->name);
+ {
+ log(L_ERR "KIF: Invalid broadcast address %I4 for %s", xbrd, ifi->name);
+ ifa.brd = ipa_from_ip4(ybrd);
+ }
}
-#endif
}
scope = ipa_classify(ifa.ip);
@@ -713,10 +711,93 @@ nl_parse_addr(struct nlmsghdr *h, int scan)
}
ifa.scope = scope & IADDR_SCOPE_MASK;
- DBG("KIF: IF%d(%s): %s IPA %I, flg %x, net %I/%d, brd %I, opp %I\n",
+ DBG("KIF: IF%d(%s): %s IPA %I, flg %x, net %N, brd %I, opp %I\n",
+ ifi->index, ifi->name,
+ new ? "added" : "removed",
+ ifa.ip, ifa.flags, ifa.prefix, ifa.brd, ifa.opposite);
+
+ if (new)
+ ifa_update(&ifa);
+ else
+ ifa_delete(&ifa);
+
+ if (!scan)
+ if_end_partial_update(ifi);
+}
+
+static void
+nl_parse_addr6(struct ifaddrmsg *i, int scan, int new)
+{
+ struct rtattr *a[BIRD_IFA_MAX];
+ struct iface *ifi;
+ int scope;
+
+ if (!nl_parse_attrs(IFA_RTA(i), ifa_attr_want6, a, sizeof(a)))
+ return;
+
+ if (!a[IFA_ADDRESS])
+ {
+ log(L_ERR "KIF: Malformed message received (missing IFA_ADDRESS)");
+ return;
+ }
+
+ ifi = if_find_by_index(i->ifa_index);
+ if (!ifi)
+ {
+ log(L_ERR "KIF: Received address message for unknown interface %d", i->ifa_index);
+ return;
+ }
+
+ struct ifa ifa;
+ bzero(&ifa, sizeof(ifa));
+ ifa.iface = ifi;
+ if (i->ifa_flags & IFA_F_SECONDARY)
+ ifa.flags |= IA_SECONDARY;
+
+ /* IFA_LOCAL can be unset for IPv6 interfaces */
+
+ ifa.ip = rta_get_ipa(a[IFA_LOCAL] ? : a[IFA_ADDRESS]);
+
+ if (i->ifa_prefixlen > IP6_MAX_PREFIX_LENGTH)
+ {
+ log(L_ERR "KIF: Invalid prefix length for interface %s: %d", ifi->name, i->ifa_prefixlen);
+ new = 0;
+ }
+ if (i->ifa_prefixlen == IP6_MAX_PREFIX_LENGTH)
+ {
+ ifa.brd = rta_get_ipa(a[IFA_ADDRESS]);
+ net_fill_ip6(&ifa.prefix, rta_get_ip6(a[IFA_ADDRESS]), i->ifa_prefixlen);
+
+ /* It is either a host address or a peer address */
+ if (ipa_equal(ifa.ip, ifa.brd))
+ ifa.flags |= IA_HOST;
+ else
+ {
+ ifa.flags |= IA_PEER;
+ ifa.opposite = ifa.brd;
+ }
+ }
+ else
+ {
+ net_fill_ip6(&ifa.prefix, ipa_to_ip6(ifa.ip), i->ifa_prefixlen);
+ net_normalize(&ifa.prefix);
+
+ if (i->ifa_prefixlen == IP6_MAX_PREFIX_LENGTH - 1)
+ ifa.opposite = ipa_opposite_m1(ifa.ip);
+ }
+
+ scope = ipa_classify(ifa.ip);
+ if (scope < 0)
+ {
+ log(L_ERR "KIF: Invalid interface address %I for %s", ifa.ip, ifi->name);
+ return;
+ }
+ ifa.scope = scope & IADDR_SCOPE_MASK;
+
+ DBG("KIF: IF%d(%s): %s IPA %I, flg %x, net %N, brd %I, opp %I\n",
ifi->index, ifi->name,
new ? "added" : "removed",
- ifa.ip, ifa.flags, ifa.prefix, ifa.pxlen, ifa.brd, ifa.opposite);
+ ifa.ip, ifa.flags, ifa.prefix, ifa.brd, ifa.opposite);
if (new)
ifa_update(&ifa);
@@ -727,6 +808,26 @@ nl_parse_addr(struct nlmsghdr *h, int scan)
if_end_partial_update(ifi);
}
+static void
+nl_parse_addr(struct nlmsghdr *h, int scan)
+{
+ struct ifaddrmsg *i;
+
+ if (!(i = nl_checkin(h, sizeof(*i))))
+ return;
+
+ int new = (h->nlmsg_type == RTM_NEWADDR);
+
+ switch (i->ifa_family)
+ {
+ case AF_INET:
+ return nl_parse_addr4(i, scan, new);
+
+ case AF_INET6:
+ return nl_parse_addr6(i, scan, new);
+ }
+}
+
void
kif_do_scan(struct kif_proto *p UNUSED)
{
@@ -741,7 +842,14 @@ kif_do_scan(struct kif_proto *p UNUSED)
else
log(L_DEBUG "nl_scan_ifaces: Unknown packet received (type=%d)", h->nlmsg_type);
- nl_request_dump(BIRD_AF, RTM_GETADDR);
+ nl_request_dump(AF_INET, RTM_GETADDR);
+ while (h = nl_get_scan())
+ if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR)
+ nl_parse_addr(h, 1);
+ else
+ log(L_DEBUG "nl_scan_ifaces: Unknown packet received (type=%d)", h->nlmsg_type);
+
+ nl_request_dump(AF_INET6, RTM_GETADDR);
while (h = nl_get_scan())
if (h->nlmsg_type == RTM_NEWADDR || h->nlmsg_type == RTM_DELADDR)
nl_parse_addr(h, 1);
@@ -763,10 +871,10 @@ krt_table_id(struct krt_proto *p)
static HASH(struct krt_proto) nl_table_map;
-#define RTH_FN(k) u32_hash(k)
-#define RTH_EQ(k1,k2) k1 == k2
-#define RTH_KEY(p) krt_table_id(p)
-#define RTH_NEXT(p) p->sys.hash_next
+#define RTH_KEY(p) p->af, krt_table_id(p)
+#define RTH_NEXT(p) p->sys.hash_next
+#define RTH_EQ(a1,i1,a2,i2) a1 == a2 && i1 == i2
+#define RTH_FN(a,i) a ^ u32_hash(i)
#define RTH_REHASH rth_rehash
#define RTH_PARAMS /8, *2, 2, 2, 6, 20
@@ -813,44 +921,49 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int new)
eattr *ea;
net *net = e->net;
rta *a = e->attrs;
+ int bufsize = 128 + KRT_METRICS_MAX*8 + nh_bufsize(a->nexthops);
+
struct {
struct nlmsghdr h;
struct rtmsg r;
- char buf[128 + KRT_METRICS_MAX*8 + nh_bufsize(a->nexthops)];
- } r;
+ char buf[0];
+ } *r;
+
+ int rsize = sizeof(*r) + bufsize;
+ r = alloca(rsize);
- DBG("nl_send_route(%I/%d,new=%d)\n", net->n.prefix, net->n.pxlen, new);
+ DBG("nl_send_route(%N,new=%d)\n", net->n.addr, new);
- bzero(&r.h, sizeof(r.h));
- bzero(&r.r, sizeof(r.r));
- r.h.nlmsg_type = new ? RTM_NEWROUTE : RTM_DELROUTE;
- r.h.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
- r.h.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | (new ? NLM_F_CREATE|NLM_F_EXCL : 0);
+ bzero(&r->h, sizeof(r->h));
+ bzero(&r->r, sizeof(r->r));
+ r->h.nlmsg_type = new ? RTM_NEWROUTE : RTM_DELROUTE;
+ r->h.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
+ r->h.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | (new ? NLM_F_CREATE|NLM_F_EXCL : 0);
- r.r.rtm_family = BIRD_AF;
- r.r.rtm_dst_len = net->n.pxlen;
- r.r.rtm_protocol = RTPROT_BIRD;
- r.r.rtm_scope = RT_SCOPE_UNIVERSE;
- nl_add_attr_ipa(&r.h, sizeof(r), RTA_DST, net->n.prefix);
+ r->r.rtm_family = p->af;
+ r->r.rtm_dst_len = net_pxlen(net->n.addr);
+ r->r.rtm_protocol = RTPROT_BIRD;
+ r->r.rtm_scope = RT_SCOPE_UNIVERSE;
+ nl_add_attr_ipa(&r->h, rsize, RTA_DST, net_prefix(net->n.addr));
if (krt_table_id(p) < 256)
- r.r.rtm_table = krt_table_id(p);
+ r->r.rtm_table = krt_table_id(p);
else
- nl_add_attr_u32(&r.h, sizeof(r), RTA_TABLE, krt_table_id(p));
+ nl_add_attr_u32(&r->h, rsize, RTA_TABLE, krt_table_id(p));
/* For route delete, we do not specify route attributes */
if (!new)
- return nl_exchange(&r.h);
+ return nl_exchange(&r->h);
if (ea = ea_find(eattrs, EA_KRT_METRIC))
- nl_add_attr_u32(&r.h, sizeof(r), RTA_PRIORITY, ea->u.data);
+ nl_add_attr_u32(&r->h, rsize, RTA_PRIORITY, ea->u.data);
if (ea = ea_find(eattrs, EA_KRT_PREFSRC))
- nl_add_attr_ipa(&r.h, sizeof(r), RTA_PREFSRC, *(ip_addr *)ea->u.ptr->data);
+ nl_add_attr_ipa(&r->h, rsize, RTA_PREFSRC, *(ip_addr *)ea->u.ptr->data);
if (ea = ea_find(eattrs, EA_KRT_REALM))
- nl_add_attr_u32(&r.h, sizeof(r), RTA_FLOW, ea->u.data);
+ nl_add_attr_u32(&r->h, rsize, RTA_FLOW, ea->u.data);
u32 metrics[KRT_METRICS_MAX];
@@ -865,7 +978,7 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int new)
}
if (metrics[0])
- nl_add_metrics(&r.h, sizeof(r), metrics, KRT_METRICS_MAX);
+ nl_add_metrics(&r->h, rsize, metrics, KRT_METRICS_MAX);
/* a->iface != NULL checked in krt_capable() for router and device routes */
@@ -873,32 +986,32 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int new)
switch (a->dest)
{
case RTD_ROUTER:
- r.r.rtm_type = RTN_UNICAST;
- nl_add_attr_u32(&r.h, sizeof(r), RTA_OIF, a->iface->index);
- nl_add_attr_ipa(&r.h, sizeof(r), RTA_GATEWAY, a->gw);
+ r->r.rtm_type = RTN_UNICAST;
+ nl_add_attr_u32(&r->h, rsize, RTA_OIF, a->iface->index);
+ nl_add_attr_ipa(&r->h, rsize, RTA_GATEWAY, a->gw);
break;
case RTD_DEVICE:
- r.r.rtm_type = RTN_UNICAST;
- nl_add_attr_u32(&r.h, sizeof(r), RTA_OIF, a->iface->index);
+ r->r.rtm_type = RTN_UNICAST;
+ nl_add_attr_u32(&r->h, rsize, RTA_OIF, a->iface->index);
break;
case RTD_BLACKHOLE:
- r.r.rtm_type = RTN_BLACKHOLE;
+ r->r.rtm_type = RTN_BLACKHOLE;
break;
case RTD_UNREACHABLE:
- r.r.rtm_type = RTN_UNREACHABLE;
+ r->r.rtm_type = RTN_UNREACHABLE;
break;
case RTD_PROHIBIT:
- r.r.rtm_type = RTN_PROHIBIT;
+ r->r.rtm_type = RTN_PROHIBIT;
break;
case RTD_MULTIPATH:
- r.r.rtm_type = RTN_UNICAST;
- nl_add_multipath(&r.h, sizeof(r), a->nexthops);
+ r->r.rtm_type = RTN_UNICAST;
+ nl_add_multipath(&r->h, rsize, a->nexthops);
break;
default:
bug("krt_capable inconsistent with nl_send_route");
}
- return nl_exchange(&r.h);
+ return nl_exchange(&r->h);
}
void
@@ -936,9 +1049,9 @@ nl_parse_route(struct nlmsghdr *h, int scan)
struct rtattr *a[BIRD_RTA_MAX];
int new = h->nlmsg_type == RTM_NEWROUTE;
- ip_addr dst = IPA_NONE;
+ net_addr dst;
u32 oif = ~0;
- u32 table;
+ u32 table_id;
int src;
if (!(i = nl_checkin(h, sizeof(*i))))
@@ -946,54 +1059,54 @@ nl_parse_route(struct nlmsghdr *h, int scan)
switch (i->rtm_family)
{
-#ifndef IPV6
- case AF_INET:
- if (!nl_parse_attrs(RTM_RTA(i), rtm_attr_want4, a, sizeof(a)))
- return;
- break;
-#else
+ case AF_INET:
+ if (!nl_parse_attrs(RTM_RTA(i), rtm_attr_want4, a, sizeof(a)))
+ return;
+
+ if (a[RTA_DST])
+ net_fill_ip4(&dst, rta_get_ip4(a[RTA_DST]), i->rtm_dst_len);
+ else
+ net_fill_ip4(&dst, IP4_NONE, 0);
+ break;
+
case AF_INET6:
if (!nl_parse_attrs(RTM_RTA(i), rtm_attr_want6, a, sizeof(a)))
return;
- break;
-#endif
- default:
- return;
- }
+ if (a[RTA_DST])
+ net_fill_ip6(&dst, rta_get_ip6(a[RTA_DST]), i->rtm_dst_len);
+ else
+ net_fill_ip6(&dst, IP6_NONE, 0);
+ break;
- if (a[RTA_DST])
- {
- memcpy(&dst, RTA_DATA(a[RTA_DST]), sizeof(dst));
- ipa_ntoh(dst);
+ default:
+ return;
}
if (a[RTA_OIF])
oif = rta_get_u32(a[RTA_OIF]);
if (a[RTA_TABLE])
- table = rta_get_u32(a[RTA_TABLE]);
+ table_id = rta_get_u32(a[RTA_TABLE]);
else
- table = i->rtm_table;
+ table_id = i->rtm_table;
- p = HASH_FIND(nl_table_map, RTH, table); /* Do we know this table? */
- DBG("KRT: Got %I/%d, type=%d, oif=%d, table=%d, prid=%d, proto=%s\n", dst, i->rtm_dst_len, i->rtm_type, oif, table, i->rtm_protocol, p ? p->p.name : "(none)");
+ /* Do we know this table? */
+ p = HASH_FIND(nl_table_map, RTH, i->rtm_family, table_id);
if (!p)
SKIP("unknown table %d\n", table);
-#ifdef IPV6
if (a[RTA_IIF])
SKIP("IIF set\n");
-#else
+
if (i->rtm_tos != 0) /* We don't support TOS */
SKIP("TOS %02x\n", i->rtm_tos);
-#endif
if (scan && !new)
SKIP("RTM_DELROUTE in scan\n");
- int c = ipa_classify_net(dst);
+ int c = net_classify(&dst);
if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
SKIP("strange class/scope\n");
@@ -1025,7 +1138,7 @@ nl_parse_route(struct nlmsghdr *h, int scan)
src = KRT_SRC_ALIEN;
}
- net *net = net_get(p->p.table, dst, i->rtm_dst_len);
+ net *net = net_get(p->p.main_channel->table, &dst);
rta ra = {
.src= p->p.main_source,
@@ -1044,8 +1157,7 @@ nl_parse_route(struct nlmsghdr *h, int scan)
ra.nexthops = nl_parse_multipath(p, a[RTA_MULTIPATH]);
if (!ra.nexthops)
{
- log(L_ERR "KRT: Received strange multipath route %I/%d",
- net->n.prefix, net->n.pxlen);
+ log(L_ERR "KRT: Received strange multipath route %N", net->n.addr);
return;
}
@@ -1055,30 +1167,26 @@ nl_parse_route(struct nlmsghdr *h, int scan)
ra.iface = if_find_by_index(oif);
if (!ra.iface)
{
- log(L_ERR "KRT: Received route %I/%d with unknown ifindex %u",
- net->n.prefix, net->n.pxlen, oif);
+ log(L_ERR "KRT: Received route %N with unknown ifindex %u", net->n.addr, oif);
return;
}
if (a[RTA_GATEWAY])
{
- neighbor *ng;
ra.dest = RTD_ROUTER;
- memcpy(&ra.gw, RTA_DATA(a[RTA_GATEWAY]), sizeof(ra.gw));
- ipa_ntoh(ra.gw);
+ ra.gw = rta_get_ipa(a[RTA_GATEWAY]);
-#ifdef IPV6
/* Silently skip strange 6to4 routes */
- if (ipa_in_net(ra.gw, IPA_NONE, 96))
+ const net_addr_ip6 sit = NET_ADDR_IP6(IP6_NONE, 96);
+ if ((i->rtm_family == AF_INET6) && ipa_in_netX(ra.gw, (net_addr *) &sit))
return;
-#endif
- ng = neigh_find2(&p->p, &ra.gw, ra.iface,
- (i->rtm_flags & RTNH_F_ONLINK) ? NEF_ONLINK : 0);
- if (!ng || (ng->scope == SCOPE_HOST))
+ neighbor *nbr;
+ nbr = neigh_find2(&p->p, &ra.gw, ra.iface,
+ (i->rtm_flags & RTNH_F_ONLINK) ? NEF_ONLINK : 0);
+ if (!nbr || (nbr->scope == SCOPE_HOST))
{
- log(L_ERR "KRT: Received route %I/%d with strange next-hop %I",
- net->n.prefix, net->n.pxlen, ra.gw);
+ log(L_ERR "KRT: Received route %N with strange next-hop %I", net->n.addr, ra.gw);
return;
}
}
@@ -1116,9 +1224,7 @@ nl_parse_route(struct nlmsghdr *h, int scan)
if (a[RTA_PREFSRC])
{
- ip_addr ps;
- memcpy(&ps, RTA_DATA(a[RTA_PREFSRC]), sizeof(ps));
- ipa_ntoh(ps);
+ ip_addr ps = rta_get_ipa(a[RTA_PREFSRC]);
ea_list *ea = alloca(sizeof(ea_list) + sizeof(eattr));
ea->next = ra.eattrs;
@@ -1154,8 +1260,7 @@ nl_parse_route(struct nlmsghdr *h, int scan)
if (nl_parse_metrics(a[RTA_METRICS], metrics, ARRAY_SIZE(metrics)) < 0)
{
- log(L_ERR "KRT: Received route %I/%d with strange RTA_METRICS attribute",
- net->n.prefix, net->n.pxlen);
+ log(L_ERR "KRT: Received route %N with strange RTA_METRICS attribute", net->n.addr);
return;
}
@@ -1189,7 +1294,14 @@ krt_do_scan(struct krt_proto *p UNUSED) /* CONFIG_ALL_TABLES_AT_ONCE => p is NUL
{
struct nlmsghdr *h;
- nl_request_dump(BIRD_AF, RTM_GETROUTE);
+ nl_request_dump(AF_INET, RTM_GETROUTE);
+ while (h = nl_get_scan())
+ if (h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)
+ nl_parse_route(h, 1);
+ else
+ log(L_DEBUG "nl_scan_fire: Unknown packet received (type=%d)", h->nlmsg_type);
+
+ nl_request_dump(AF_INET6, RTM_GETROUTE);
while (h = nl_get_scan())
if (h->nlmsg_type == RTM_NEWROUTE || h->nlmsg_type == RTM_DELROUTE)
nl_parse_route(h, 1);
@@ -1305,11 +1417,10 @@ nl_open_async(void)
bzero(&sa, sizeof(sa));
sa.nl_family = AF_NETLINK;
-#ifdef IPV6
- sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE;
-#else
- sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE;
-#endif
+ sa.nl_groups = RTMGRP_LINK |
+ RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE |
+ RTMGRP_IPV6_IFADDR | RTMGRP_IPV6_ROUTE;
+
if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0)
{
log(L_ERR "Unable to bind asynchronous rtnetlink socket: %m");
@@ -1341,7 +1452,7 @@ krt_sys_io_init(void)
int
krt_sys_start(struct krt_proto *p)
{
- struct krt_proto *old = HASH_FIND(nl_table_map, RTH, krt_table_id(p));
+ struct krt_proto *old = HASH_FIND(nl_table_map, RTH, p->af, krt_table_id(p));
if (old)
{
diff --git a/sysdep/linux/sysio.h b/sysdep/linux/sysio.h
index 58644417..3c07a3e7 100644
--- a/sysdep/linux/sysio.h
+++ b/sysdep/linux/sysio.h
@@ -184,7 +184,7 @@ sk_set_md5_auth(sock *s, ip_addr local UNUSED, ip_addr remote, struct iface *ifa
struct tcp_md5sig md5;
memset(&md5, 0, sizeof(md5));
- sockaddr_fill((sockaddr *) &md5.tcpm_addr, s->af, remote, ifa, 0);
+ sockaddr_fill((sockaddr *) &md5.tcpm_addr, fam_to_af[s->fam], remote, ifa, 0);
if (passwd)
{
diff --git a/sysdep/unix/Makefile b/sysdep/unix/Makefile
new file mode 100644
index 00000000..c5d55431
--- /dev/null
+++ b/sysdep/unix/Makefile
@@ -0,0 +1,5 @@
+src := io.c krt.c log.c main.c random.c
+obj := $(src-o-files)
+$(all-daemon)
+$(cf-local)
+$(conf-y-targets): $(s)krt.Y
diff --git a/sysdep/unix/Modules b/sysdep/unix/Modules
deleted file mode 100644
index 2c6514df..00000000
--- a/sysdep/unix/Modules
+++ /dev/null
@@ -1,12 +0,0 @@
-log.c
-main.c
-timer.h
-io.c
-unix.h
-endian.h
-config.Y
-random.c
-
-krt.c
-krt.h
-krt.Y
diff --git a/sysdep/unix/config.Y b/sysdep/unix/config.Y
index d6ab8cab..ebadd454 100644
--- a/sysdep/unix/config.Y
+++ b/sysdep/unix/config.Y
@@ -8,7 +8,7 @@
CF_HDR
-#include "lib/unix.h"
+#include "sysdep/unix/unix.h"
#include <stdio.h>
CF_DECLS
@@ -92,6 +92,7 @@ timeformat_which:
| PROTOCOL { $$ = &new_config->tf_proto; }
| BASE { $$ = &new_config->tf_base; }
| LOG { $$ = &new_config->tf_log; }
+ ;
timeformat_spec:
timeformat_which TEXT { *$1 = (struct timeformat){$2, NULL, 0}; }
diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c
index 486319ff..69c17d60 100644
--- a/sysdep/unix/io.c
+++ b/sysdep/unix/io.c
@@ -32,14 +32,14 @@
#include "nest/bird.h"
#include "lib/lists.h"
#include "lib/resource.h"
-#include "lib/timer.h"
+#include "sysdep/unix/timer.h"
#include "lib/socket.h"
#include "lib/event.h"
#include "lib/string.h"
#include "nest/iface.h"
-#include "lib/unix.h"
-#include "lib/sysio.h"
+#include "sysdep/unix/unix.h"
+#include CONFIG_INCLUDE_SYSIO_H
/* Maximum number of calls of tx handler for one socket in one
* poll iteration. Should be small enough to not monopolize CPU by
@@ -587,6 +587,7 @@ sockaddr_read(sockaddr *sa, int af, ip_addr *a, struct iface **ifa, uint *port)
return -1;
}
+const int fam_to_af[] = { [SK_FAM_IPV4] = AF_INET, [SK_FAM_IPV6] = AF_INET6 };
/*
* IPv6 multicast syscalls
@@ -1193,7 +1194,7 @@ sk_setup(sock *s)
if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0)
ERR("O_NONBLOCK");
- if (!s->af)
+ if (!s->fam)
return 0;
if (ipa_nonzero(s->saddr) && !(s->flags & SKF_BIND))
@@ -1294,7 +1295,7 @@ sk_tcp_connected(sock *s)
int sa_len = sizeof(sa);
if ((getsockname(s->fd, &sa.sa, &sa_len) < 0) ||
- (sockaddr_read(&sa, s->af, &s->saddr, &s->iface, &s->sport) < 0))
+ (sockaddr_read(&sa, fam_to_af[s->fam], &s->saddr, &s->iface, &s->sport) < 0))
log(L_WARN "SOCK: Cannot get local IP address for TCP>");
s->type = SK_TCP;
@@ -1319,8 +1320,8 @@ sk_passive_connected(sock *s, int type)
sock *t = sk_new(s->pool);
t->type = type;
+ t->fam = s->fam;
t->fd = fd;
- t->af = s->af;
t->ttl = s->ttl;
t->tos = s->tos;
t->rbsize = s->rbsize;
@@ -1329,10 +1330,10 @@ sk_passive_connected(sock *s, int type)
if (type == SK_TCP)
{
if ((getsockname(fd, &loc_sa.sa, &loc_sa_len) < 0) ||
- (sockaddr_read(&loc_sa, s->af, &t->saddr, &t->iface, &t->sport) < 0))
+ (sockaddr_read(&loc_sa, fam_to_af[s->fam], &t->saddr, &t->iface, &t->sport) < 0))
log(L_WARN "SOCK: Cannot get local IP address for TCP<");
- if (sockaddr_read(&rem_sa, s->af, &t->daddr, &t->iface, &t->dport) < 0)
+ if (sockaddr_read(&rem_sa, fam_to_af[s->fam], &t->daddr, &t->iface, &t->dport) < 0)
log(L_WARN "SOCK: Cannot get remote IP address for TCP<");
}
@@ -1367,7 +1368,6 @@ sk_passive_connected(sock *s, int type)
int
sk_open(sock *s)
{
- int af = BIRD_AF;
int fd = -1;
int do_bind = 0;
int bind_port = 0;
@@ -1380,28 +1380,28 @@ sk_open(sock *s)
s->ttx = ""; /* Force s->ttx != s->tpos */
/* Fall thru */
case SK_TCP_PASSIVE:
- fd = socket(af, SOCK_STREAM, IPPROTO_TCP);
+ fd = socket(fam_to_af[s->fam], SOCK_STREAM, IPPROTO_TCP);
bind_port = s->sport;
bind_addr = s->saddr;
do_bind = bind_port || ipa_nonzero(bind_addr);
break;
case SK_UDP:
- fd = socket(af, SOCK_DGRAM, IPPROTO_UDP);
+ fd = socket(fam_to_af[s->fam], SOCK_DGRAM, IPPROTO_UDP);
bind_port = s->sport;
bind_addr = (s->flags & SKF_BIND) ? s->saddr : IPA_NONE;
do_bind = 1;
break;
case SK_IP:
- fd = socket(af, SOCK_RAW, s->dport);
+ fd = socket(fam_to_af[s->fam], SOCK_RAW, s->dport);
bind_port = 0;
bind_addr = (s->flags & SKF_BIND) ? s->saddr : IPA_NONE;
do_bind = ipa_nonzero(bind_addr);
break;
case SK_MAGIC:
- af = 0;
+ s->fam = SK_FAM_NONE;
fd = s->fd;
break;
@@ -1412,7 +1412,6 @@ sk_open(sock *s)
if (fd < 0)
ERR("socket");
- s->af = af;
s->fd = fd;
if (sk_setup(s) < 0)
@@ -1441,7 +1440,7 @@ sk_open(sock *s)
if (sk_set_high_port(s) < 0)
log(L_WARN "Socket error: %s%#m", s->err);
- sockaddr_fill(&sa, af, bind_addr, s->iface, bind_port);
+ sockaddr_fill(&sa, fam_to_af[s->fam], bind_addr, s->iface, bind_port);
if (bind(fd, &sa.sa, SA_LEN(sa)) < 0)
ERR2("bind");
}
@@ -1453,7 +1452,7 @@ sk_open(sock *s)
switch (s->type)
{
case SK_TCP_ACTIVE:
- sockaddr_fill(&sa, af, s->daddr, s->iface, s->dport);
+ sockaddr_fill(&sa, fam_to_af[s->fam], s->daddr, s->iface, s->dport);
if (connect(fd, &sa.sa, SA_LEN(sa)) >= 0)
sk_tcp_connected(s);
else if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS &&
@@ -1560,7 +1559,7 @@ sk_sendmsg(sock *s)
byte cmsg_buf[CMSG_TX_SPACE];
sockaddr dst;
- sockaddr_fill(&dst, s->af, s->daddr, s->iface, s->dport);
+ sockaddr_fill(&dst, fam_to_af[s->fam], s->daddr, s->iface, s->dport);
struct msghdr msg = {
.msg_name = &dst.sa,
@@ -1613,7 +1612,7 @@ sk_recvmsg(sock *s)
// rv = ipv4_skip_header(pbuf, rv);
//endif
- sockaddr_read(&src, s->af, &s->faddr, NULL, &s->fport);
+ sockaddr_read(&src, fam_to_af[s->fam], &s->faddr, NULL, &s->fport);
sk_process_cmsgs(s, &msg);
if (msg.msg_flags & MSG_TRUNC)
@@ -1833,7 +1832,7 @@ sk_write(sock *s)
case SK_TCP_ACTIVE:
{
sockaddr sa;
- sockaddr_fill(&sa, s->af, s->daddr, s->iface, s->dport);
+ sockaddr_fill(&sa, fam_to_af[s->fam], s->daddr, s->iface, s->dport);
if (connect(s->fd, &sa.sa, SA_LEN(sa)) >= 0 || errno == EISCONN)
sk_tcp_connected(s);
@@ -1853,6 +1852,12 @@ sk_write(sock *s)
}
}
+int sk_is_ipv4(sock *s)
+{ return s->fam == SK_FAM_IPV4; }
+
+int sk_is_ipv6(sock *s)
+{ return s->fam == SK_FAM_IPV6; }
+
void
sk_dump_all(void)
{
diff --git a/sysdep/unix/krt.Y b/sysdep/unix/krt.Y
index e036081d..91317d97 100644
--- a/sysdep/unix/krt.Y
+++ b/sysdep/unix/krt.Y
@@ -8,13 +8,23 @@
CF_HDR
-#include "lib/krt.h"
+#include "sysdep/unix/krt.h"
CF_DEFINES
#define THIS_KRT ((struct krt_config *) this_proto)
#define THIS_KIF ((struct kif_config *) this_proto)
+static void
+krt_set_merge_paths(struct channel_config *cc, uint merge, uint limit)
+{
+ if ((limit <= 0) || (limit > 255))
+ cf_error("Merge paths limit must be in range 1-255");
+
+ cc->ra_mode = merge ? RA_MERGED : RA_OPTIMAL;
+ cc->merge_limit = limit;
+}
+
CF_DECLS
CF_KEYWORDS(KERNEL, PERSIST, SCAN, TIME, LEARN, DEVICE, ROUTES, GRACEFUL, RESTART, KRT_SOURCE, KRT_METRIC, MERGE, PATHS)
@@ -25,15 +35,18 @@ CF_GRAMMAR
CF_ADDTO(proto, kern_proto '}')
-kern_proto_start: proto_start KERNEL { this_proto = krt_init_config($1); }
+kern_proto_start: proto_start KERNEL {
+ this_proto = krt_init_config($1);
+}
;
CF_ADDTO(kern_proto, kern_proto_start proto_name '{')
-CF_ADDTO(kern_proto, kern_proto proto_item ';')
CF_ADDTO(kern_proto, kern_proto kern_item ';')
kern_item:
- PERSIST bool { THIS_KRT->persist = $2; }
+ proto_item
+ | proto_channel { this_proto->net_type = $1->net_type; }
+ | PERSIST bool { THIS_KRT->persist = $2; }
| SCAN TIME expr {
/* Scan time of 0 means scan on startup only */
THIS_KRT->scan_time = $3;
@@ -47,8 +60,8 @@ kern_item:
}
| DEVICE ROUTES bool { THIS_KRT->devroutes = $3; }
| GRACEFUL RESTART bool { THIS_KRT->graceful_restart = $3; }
- | MERGE PATHS bool { THIS_KRT->merge_paths = $3 ? KRT_DEFAULT_ECMP_LIMIT : 0; }
- | MERGE PATHS bool LIMIT expr { THIS_KRT->merge_paths = $3 ? $5 : 0; if (($5 <= 0) || ($5 > 255)) cf_error("Merge paths limit must be in range 1-255"); }
+ | MERGE PATHS bool { krt_set_merge_paths(this_channel, $3, KRT_DEFAULT_ECMP_LIMIT); }
+ | MERGE PATHS bool LIMIT expr { krt_set_merge_paths(this_channel, $3, $5); }
;
/* Kernel interface protocol */
@@ -59,19 +72,17 @@ kif_proto_start: proto_start DEVICE { this_proto = kif_init_config($1); }
;
CF_ADDTO(kif_proto, kif_proto_start proto_name '{')
-CF_ADDTO(kif_proto, kif_proto proto_item ';')
CF_ADDTO(kif_proto, kif_proto kif_item ';')
kif_item:
- SCAN TIME expr {
+ proto_item
+ | SCAN TIME expr {
/* Scan time of 0 means scan on startup only */
THIS_KIF->scan_time = $3;
}
- | PRIMARY text_or_none prefix_or_ipa {
+ | PRIMARY opttext net_or_ipa {
struct kif_primary_item *kpi = cfg_alloc(sizeof (struct kif_primary_item));
- kpi->pattern = $2;
- kpi->prefix = $3.addr;
- kpi->pxlen = $3.len;
+ kpi->addr = $3;
add_tail(&THIS_KIF->primary, &kpi->n);
}
;
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c
index f5dee877..6531bb28 100644
--- a/sysdep/unix/krt.c
+++ b/sysdep/unix/krt.c
@@ -56,7 +56,7 @@
#include "nest/route.h"
#include "nest/protocol.h"
#include "filter/filter.h"
-#include "lib/timer.h"
+#include "sysdep/unix/timer.h"
#include "conf/conf.h"
#include "lib/string.h"
@@ -131,14 +131,14 @@ prefer_addr(struct ifa *a, struct ifa *b)
}
static inline struct ifa *
-find_preferred_ifa(struct iface *i, ip_addr prefix, ip_addr mask)
+find_preferred_ifa(struct iface *i, const net_addr *n)
{
struct ifa *a, *b = NULL;
WALK_LIST(a, i->addrs)
{
if (!(a->flags & IA_SECONDARY) &&
- ipa_equal(ipa_and(a->ip, mask), prefix) &&
+ (!n || ipa_in_netX(a->ip, n)) &&
(!b || prefer_addr(a, b)))
b = a;
}
@@ -156,21 +156,21 @@ kif_choose_primary(struct iface *i)
WALK_LIST(it, cf->primary)
{
if (!it->pattern || patmatch(it->pattern, i->name))
- if (a = find_preferred_ifa(i, it->prefix, ipa_mkmask(it->pxlen)))
+ if (a = find_preferred_ifa(i, &it->addr))
return a;
}
if (a = kif_get_primary_ip(i))
return a;
- return find_preferred_ifa(i, IPA_NONE, IPA_NONE);
+ return find_preferred_ifa(i, NULL);
}
static struct proto *
kif_init(struct proto_config *c)
{
- struct kif_proto *p = proto_new(c, sizeof(struct kif_proto));
+ struct kif_proto *p = proto_new(c);
kif_sys_init(p);
return &p->p;
@@ -266,9 +266,6 @@ kif_copy_config(struct proto_config *dest, struct proto_config *src)
struct kif_config *d = (struct kif_config *) dest;
struct kif_config *s = (struct kif_config *) src;
- /* Shallow copy of everything (just scan_time currently) */
- proto_copy_rest(dest, src, sizeof(struct kif_config));
-
/* Copy primary addr list */
cfg_copy_list(&d->primary, &s->primary, sizeof(struct kif_primary_item));
@@ -280,7 +277,7 @@ kif_copy_config(struct proto_config *dest, struct proto_config *src)
struct protocol proto_unix_iface = {
.name = "Device",
.template = "device%d",
- .preference = DEF_PREF_DIRECT,
+ .proto_size = sizeof(struct kif_proto),
.config_size = sizeof(struct kif_config),
.preconfig = kif_preconfig,
.init = kif_init,
@@ -298,14 +295,14 @@ static inline void
krt_trace_in(struct krt_proto *p, rte *e, char *msg)
{
if (p->p.debug & D_PACKETS)
- log(L_TRACE "%s: %I/%d: %s", p->p.name, e->net->n.prefix, e->net->n.pxlen, msg);
+ log(L_TRACE "%s: %N: %s", p->p.name, e->net->n.addr, msg);
}
static inline void
krt_trace_in_rl(struct tbf *f, struct krt_proto *p, rte *e, char *msg)
{
if (p->p.debug & D_PACKETS)
- log_rl(f, L_TRACE "%s: %I/%d: %s", p->p.name, e->net->n.prefix, e->net->n.pxlen, msg);
+ log_rl(f, L_TRACE "%s: %N: %s", p->p.name, e->net->n.addr, msg);
}
/*
@@ -348,19 +345,15 @@ krt_learn_announce_update(struct krt_proto *p, rte *e)
net *n = e->net;
rta *aa = rta_clone(e->attrs);
rte *ee = rte_get_temp(aa);
- net *nn = net_get(p->p.table, n->n.prefix, n->n.pxlen);
- ee->net = nn;
ee->pflags = 0;
- ee->pref = p->p.preference;
ee->u.krt = e->u.krt;
- rte_update(&p->p, nn, ee);
+ rte_update(&p->p, n->n.addr, ee);
}
static void
krt_learn_announce_delete(struct krt_proto *p, net *n)
{
- n = net_find(p->p.table, n->n.prefix, n->n.pxlen);
- rte_update(&p->p, n, NULL);
+ rte_update(&p->p, n->n.addr, NULL);
}
/* Called when alien route is discovered during scan */
@@ -368,7 +361,7 @@ static void
krt_learn_scan(struct krt_proto *p, rte *e)
{
net *n0 = e->net;
- net *n = net_get(&p->krt_table, n0->n.prefix, n0->n.pxlen);
+ net *n = net_get(&p->krt_table, n0->n.addr);
rte *m, **mm;
e->attrs = rta_lookup(e->attrs);
@@ -412,9 +405,8 @@ krt_learn_prune(struct krt_proto *p)
FIB_ITERATE_INIT(&fit, fib);
again:
- FIB_ITERATE_START(fib, &fit, f)
+ FIB_ITERATE_START(fib, &fit, net, n)
{
- net *n = (net *) f;
rte *e, **ee, *best, **pbest, *old_best;
/*
@@ -455,8 +447,8 @@ again:
if (old_best)
krt_learn_announce_delete(p, n);
- FIB_ITERATE_PUT(&fit, f);
- fib_delete(fib, f);
+ FIB_ITERATE_PUT(&fit);
+ fib_delete(fib, n);
goto again;
}
@@ -473,7 +465,7 @@ again:
else
DBG("%I/%d: uptodate (metric=%d)\n", n->n.prefix, n->n.pxlen, best->u.krt.metric);
}
- FIB_ITERATE_END(f);
+ FIB_ITERATE_END;
p->reload = 0;
}
@@ -482,7 +474,7 @@ static void
krt_learn_async(struct krt_proto *p, rte *e, int new)
{
net *n0 = e->net;
- net *n = net_get(&p->krt_table, n0->n.prefix, n0->n.pxlen);
+ net *n = net_get(&p->krt_table, n0->n.addr);
rte *g, **gg, *best, **bestp, *old_best;
e->attrs = rta_lookup(e->attrs);
@@ -588,12 +580,11 @@ krt_dump_attrs(rte *e)
static void
krt_flush_routes(struct krt_proto *p)
{
- struct rtable *t = p->p.table;
+ struct rtable *t = p->p.main_channel->table;
KRT_TRACE(p, D_EVENTS, "Flushing kernel routes");
- FIB_WALK(&t->fib, f)
+ FIB_WALK(&t->fib, net, n)
{
- net *n = (net *) f;
rte *e = n->routes;
if (rte_is_valid(e) && (n->n.flags & KRF_INSTALLED))
{
@@ -608,12 +599,12 @@ krt_flush_routes(struct krt_proto *p)
static struct rte *
krt_export_net(struct krt_proto *p, net *net, rte **rt_free, ea_list **tmpa)
{
- struct announce_hook *ah = p->p.main_ahook;
- struct filter *filter = ah->out_filter;
+ struct channel *c = p->p.main_channel;
+ struct filter *filter = c->out_filter;
rte *rt;
- if (p->p.accept_ra_types == RA_MERGED)
- return rt_export_merged(ah, net, rt_free, tmpa, 1);
+ if (c->ra_mode == RA_MERGED)
+ return rt_export_merged(c, net, rt_free, tmpa, 1);
rt = net->routes;
*rt_free = NULL;
@@ -760,13 +751,12 @@ krt_got_route(struct krt_proto *p, rte *e)
static void
krt_prune(struct krt_proto *p)
{
- struct rtable *t = p->p.table;
+ struct rtable *t = p->p.main_channel->table;
KRT_TRACE(p, D_EVENTS, "Pruning table %s", t->name);
- FIB_WALK(&t->fib, f)
+ FIB_WALK(&t->fib, net, n)
{
- net *n = (net *) f;
- int verdict = f->flags & KRF_VERDICT_MASK;
+ int verdict = n->n.flags & KRF_VERDICT_MASK;
rte *new, *old, *rt_free = NULL;
ea_list *tmpa = NULL;
@@ -795,7 +785,7 @@ krt_prune(struct krt_proto *p)
switch (verdict)
{
case KRF_CREATE:
- if (new && (f->flags & KRF_INSTALLED))
+ if (new && (n->n.flags & KRF_INSTALLED))
{
krt_trace_in(p, new, "reinstalling");
krt_replace_rte(p, n, new, NULL, tmpa);
@@ -822,7 +812,7 @@ krt_prune(struct krt_proto *p)
if (rt_free)
rte_free(rt_free);
lp_flush(krt_filter_lp);
- f->flags &= ~KRF_VERDICT_MASK;
+ n->n.flags &= ~KRF_VERDICT_MASK;
}
FIB_WALK_END;
@@ -1033,7 +1023,7 @@ krt_import_control(struct proto *P, rte **new, ea_list **attrs, struct linpool *
}
static void
-krt_rt_notify(struct proto *P, struct rtable *table UNUSED, net *net,
+krt_rt_notify(struct proto *P, struct channel *ch UNUSED, net *net,
rte *new, rte *old, struct ea_list *eattrs)
{
struct krt_proto *p = (struct krt_proto *) P;
@@ -1067,10 +1057,10 @@ krt_if_notify(struct proto *P, uint flags, struct iface *iface UNUSED)
krt_scan_timer_kick(p);
}
-static int
-krt_reload_routes(struct proto *P)
+static void
+krt_reload_routes(struct channel *C)
{
- struct krt_proto *p = (struct krt_proto *) P;
+ struct krt_proto *p = (void *) C->proto;
/* Although we keep learned routes in krt_table, we rather schedule a scan */
@@ -1079,14 +1069,12 @@ krt_reload_routes(struct proto *P)
p->reload = 1;
krt_scan_timer_kick(p);
}
-
- return 1;
}
static void
-krt_feed_end(struct proto *P)
+krt_feed_end(struct channel *C)
{
- struct krt_proto *p = (struct krt_proto *) P;
+ struct krt_proto *p = (void *) C->proto;
p->ready = 1;
krt_scan_timer_kick(p);
@@ -1107,14 +1095,42 @@ krt_rte_same(rte *a, rte *b)
struct krt_config *krt_cf;
+static void
+krt_preconfig(struct protocol *P UNUSED, struct config *c)
+{
+ krt_cf = NULL;
+ krt_sys_preconfig(c);
+}
+
+static void
+krt_postconfig(struct proto_config *CF)
+{
+ struct krt_config *cf = (void *) CF;
+
+ if (EMPTY_LIST(CF->channels))
+ cf_error("Channel not specified");
+
+#ifdef CONFIG_ALL_TABLES_AT_ONCE
+ if (krt_cf->scan_time != cf->scan_time)
+ cf_error("All kernel syncers must use the same table scan interval");
+#endif
+
+ struct rtable_config *tab = proto_cf_main_channel(CF)->table;
+ if (tab->krt_attached)
+ cf_error("Kernel syncer (%s) already attached to table %s", tab->krt_attached->name, tab->name);
+ tab->krt_attached = CF;
+
+ krt_sys_postconfig(cf);
+}
+
static struct proto *
-krt_init(struct proto_config *C)
+krt_init(struct proto_config *CF)
{
- struct krt_proto *p = proto_new(C, sizeof(struct krt_proto));
- struct krt_config *c = (struct krt_config *) C;
+ struct krt_proto *p = proto_new(CF);
+ // struct krt_config *cf = (void *) CF;
+
+ p->p.main_channel = proto_add_channel(&p->p, proto_cf_main_channel(CF));
- p->p.accept_ra_types = c->merge_paths ? RA_MERGED : RA_OPTIMAL;
- p->p.merge_limit = c->merge_paths;
p->p.import_control = krt_import_control;
p->p.rt_notify = krt_rt_notify;
p->p.if_notify = krt_if_notify;
@@ -1133,6 +1149,13 @@ krt_start(struct proto *P)
{
struct krt_proto *p = (struct krt_proto *) P;
+ switch (p->p.net_type)
+ {
+ case NET_IP4: p->af = AF_INET; break;
+ case NET_IP6: p->af = AF_INET6; break;
+ default: ASSERT(0);
+ }
+
add_tail(&krt_proto_list, &p->krt_node);
#ifdef KRT_ALLOW_LEARN
@@ -1147,8 +1170,8 @@ krt_start(struct proto *P)
krt_scan_timer_start(p);
- if (P->gr_recovery && KRT_CF->graceful_restart)
- P->gr_wait = 1;
+ if (p->p.gr_recovery && KRT_CF->graceful_restart)
+ p->p.main_channel->gr_wait = 1;
return PS_UP;
}
@@ -1177,40 +1200,19 @@ krt_shutdown(struct proto *P)
}
static int
-krt_reconfigure(struct proto *p, struct proto_config *new)
+krt_reconfigure(struct proto *p, struct proto_config *CF)
{
- struct krt_config *o = (struct krt_config *) p->cf;
- struct krt_config *n = (struct krt_config *) new;
+ struct krt_config *o = (void *) p->cf;
+ struct krt_config *n = (void *) CF;
+
+ if (!proto_configure_channel(p, &p->main_channel, proto_cf_main_channel(CF)))
+ return 0;
if (!krt_sys_reconfigure((struct krt_proto *) p, n, o))
return 0;
/* persist, graceful restart need not be the same */
- return o->scan_time == n->scan_time && o->learn == n->learn &&
- o->devroutes == n->devroutes && o->merge_paths == n->merge_paths;
-}
-
-static void
-krt_preconfig(struct protocol *P UNUSED, struct config *c)
-{
- krt_cf = NULL;
- krt_sys_preconfig(c);
-}
-
-static void
-krt_postconfig(struct proto_config *C)
-{
- struct krt_config *c = (struct krt_config *) C;
-
-#ifdef CONFIG_ALL_TABLES_AT_ONCE
- if (krt_cf->scan_time != c->scan_time)
- cf_error("All kernel syncers must use the same table scan interval");
-#endif
-
- if (C->table->krt_attached)
- cf_error("Kernel syncer (%s) already attached to table %s", C->table->krt_attached->name, C->table->name);
- C->table->krt_attached = C;
- krt_sys_postconfig(c);
+ return o->scan_time == n->scan_time && o->learn == n->learn && o->devroutes == n->devroutes;
}
struct proto_config *
@@ -1234,9 +1236,6 @@ krt_copy_config(struct proto_config *dest, struct proto_config *src)
struct krt_config *d = (struct krt_config *) dest;
struct krt_config *s = (struct krt_config *) src;
- /* Shallow copy of everything */
- proto_copy_rest(dest, src, sizeof(struct krt_config));
-
/* Fix sysdep parts */
krt_sys_copy_config(d, s);
}
@@ -1265,6 +1264,8 @@ struct protocol proto_unix_kernel = {
.template = "kernel%d",
.attr_class = EAP_KRT,
.preference = DEF_PREF_INHERITED,
+ .channel_mask = NB_IP,
+ .proto_size = sizeof(struct krt_proto),
.config_size = sizeof(struct krt_config),
.preconfig = krt_preconfig,
.postconfig = krt_postconfig,
diff --git a/sysdep/unix/krt.h b/sysdep/unix/krt.h
index d4a8717e..cb404de3 100644
--- a/sysdep/unix/krt.h
+++ b/sysdep/unix/krt.h
@@ -15,7 +15,8 @@ struct krt_proto;
struct kif_config;
struct kif_proto;
-#include "lib/krt-sys.h"
+#include "sysdep/config.h"
+#include CONFIG_INCLUDE_KRTSYS_H
/* Flags stored in net->n.flags, rest are in nest/route.h */
@@ -49,7 +50,6 @@ struct krt_config {
int learn; /* Learn routes from other sources */
int devroutes; /* Allow export of device routes */
int graceful_restart; /* Regard graceful restart recovery */
- int merge_paths; /* Exported routes are merged for ECMP */
};
struct krt_proto {
@@ -65,6 +65,7 @@ struct krt_proto {
#endif
node krt_node; /* Node in krt_proto_list */
+ byte af; /* Kernel address family (AF_*) */
byte ready; /* Initial feed has been finished */
byte initialized; /* First scan has been finished */
byte reload; /* Next scan is doing reload */
@@ -96,8 +97,7 @@ extern struct protocol proto_unix_iface;
struct kif_primary_item {
node n;
byte *pattern;
- ip_addr prefix;
- int pxlen;
+ net_addr addr;
};
struct kif_config {
@@ -112,7 +112,7 @@ struct kif_proto {
struct kif_state sys; /* Sysdep state */
};
-struct kif_proto *kif_proto;
+extern struct kif_proto *kif_proto;
#define KIF_CF ((struct kif_config *)p->p.cf)
diff --git a/sysdep/unix/log.c b/sysdep/unix/log.c
index 6665d035..9c56eb24 100644
--- a/sysdep/unix/log.c
+++ b/sysdep/unix/log.c
@@ -26,7 +26,7 @@
#include "nest/mrtdump.h"
#include "lib/string.h"
#include "lib/lists.h"
-#include "lib/unix.h"
+#include "sysdep/unix/unix.h"
static FILE *dbgf;
static list *current_log_list;
diff --git a/sysdep/unix/main.c b/sysdep/unix/main.c
index 11a4acc6..1f47680e 100644
--- a/sysdep/unix/main.c
+++ b/sysdep/unix/main.c
@@ -69,7 +69,7 @@ async_dump(void)
*/
#ifdef CONFIG_RESTRICTED_PRIVILEGES
-#include "lib/syspriv.h"
+#include CONFIG_INCLUDE_SYSPRIV_H
#else
static inline void
@@ -569,6 +569,10 @@ sysdep_shutdown_done(void)
* Signals
*/
+volatile int async_config_flag;
+volatile int async_dump_flag;
+volatile int async_shutdown_flag;
+
static void
handle_sighup(int sig UNUSED)
{
@@ -780,7 +784,7 @@ main(int argc, char **argv)
io_init();
rt_init();
if_init();
- roa_init();
+// roa_init();
config_init();
uid_t use_uid = get_uid(use_user);
diff --git a/sysdep/unix/unix.h b/sysdep/unix/unix.h
index 4e0ff841..80c99350 100644
--- a/sysdep/unix/unix.h
+++ b/sysdep/unix/unix.h
@@ -47,14 +47,6 @@ typedef struct sockaddr_bird {
} sockaddr;
-#ifdef IPV6
-#define BIRD_AF AF_INET6
-#define ipa_from_sa(x) ipa_from_sa6(x)
-#else
-#define BIRD_AF AF_INET
-#define ipa_from_sa(x) ipa_from_sa4(x)
-#endif
-
/* This is sloppy hack, it should be detected by configure script */
/* Linux systems have it defined so this is definition for BSD systems */
@@ -75,17 +67,21 @@ static inline ip_addr ipa_from_sa4(sockaddr *sa)
static inline ip_addr ipa_from_sa6(sockaddr *sa)
{ return ipa_from_in6(((struct sockaddr_in6 *) sa)->sin6_addr); }
+static inline ip_addr ipa_from_sa(sockaddr *sa)
+{
+ switch (sa->sa.sa_family)
+ {
+ case AF_INET: return ipa_from_sa4(sa);
+ case AF_INET6: return ipa_from_sa6(sa);
+ default: return IPA_NONE;
+ }
+}
+
static inline struct in_addr ipa_to_in4(ip_addr a)
{ return (struct in_addr) { htonl(ipa_to_u32(a)) }; }
-#ifdef IPV6
static inline struct in6_addr ipa_to_in6(ip_addr a)
{ return (struct in6_addr) { .s6_addr32 = { htonl(_I0(a)), htonl(_I1(a)), htonl(_I2(a)), htonl(_I3(a)) } }; }
-#else
-/* Temporary dummy */
-static inline struct in6_addr ipa_to_in6(ip_addr a)
-{ return (struct in6_addr) { .s6_addr32 = { 0, 0, 0, 0 } }; }
-#endif
void sockaddr_fill(sockaddr *sa, int af, ip_addr a, struct iface *ifa, uint port);
int sockaddr_read(sockaddr *sa, int af, ip_addr *a, struct iface **ifa, uint *port);
@@ -95,9 +91,9 @@ int sockaddr_read(sockaddr *sa, int af, ip_addr *a, struct iface **ifa, uint *po
#define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) + strlen ((ptr)->sun_path))
#endif
-volatile int async_config_flag;
-volatile int async_dump_flag;
-volatile int async_shutdown_flag;
+extern volatile int async_config_flag;
+extern volatile int async_dump_flag;
+extern volatile int async_shutdown_flag;
void io_init(void);
void io_loop(void);
@@ -106,6 +102,7 @@ int sk_open_unix(struct birdsock *s, char *name);
void *tracked_fopen(struct pool *, char *name, char *mode);
void test_old_bird(char *path);
+extern const int fam_to_af[];
/* krt.c bits */