|
|
|
@@ -25,6 +25,7 @@
|
|
|
|
|
#include "lib/krt.h"
|
|
|
|
|
#include "lib/socket.h"
|
|
|
|
|
#include "lib/string.h"
|
|
|
|
|
#include "lib/hash.h"
|
|
|
|
|
#include "conf/conf.h"
|
|
|
|
|
|
|
|
|
|
#include <asm/types.h>
|
|
|
|
@@ -32,6 +33,7 @@
|
|
|
|
|
#include <linux/netlink.h>
|
|
|
|
|
#include <linux/rtnetlink.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef MSG_TRUNC /* Hack: Several versions of glibc miss this one :( */
|
|
|
|
|
#define MSG_TRUNC 0x20
|
|
|
|
|
#endif
|
|
|
|
@@ -40,6 +42,11 @@
|
|
|
|
|
#define IFF_LOWER_UP 0x10000
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifndef RTA_TABLE
|
|
|
|
|
#define RTA_TABLE 15
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Synchronous Netlink interface
|
|
|
|
|
*/
|
|
|
|
@@ -219,27 +226,101 @@ nl_checkin(struct nlmsghdr *h, int lsize)
|
|
|
|
|
return NLMSG_DATA(h);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct nl_want_attrs {
|
|
|
|
|
u8 defined:1;
|
|
|
|
|
u8 checksize:1;
|
|
|
|
|
u8 size;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define BIRD_IFLA_MAX (IFLA_WIRELESS+1)
|
|
|
|
|
|
|
|
|
|
static struct nl_want_attrs ifla_attr_want[BIRD_IFLA_MAX] = {
|
|
|
|
|
[IFLA_IFNAME] = { 1, 0, 0 },
|
|
|
|
|
[IFLA_MTU] = { 1, 1, sizeof(u32) },
|
|
|
|
|
[IFLA_WIRELESS] = { 1, 0, 0 },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#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)
|
|
|
|
|
|
|
|
|
|
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) },
|
|
|
|
|
[RTA_GATEWAY] = { 1, 1, sizeof(ip4_addr) },
|
|
|
|
|
[RTA_PRIORITY] = { 1, 1, sizeof(u32) },
|
|
|
|
|
[RTA_PREFSRC] = { 1, 1, sizeof(ip4_addr) },
|
|
|
|
|
[RTA_METRICS] = { 1, 0, 0 },
|
|
|
|
|
[RTA_MULTIPATH] = { 1, 0, 0 },
|
|
|
|
|
[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) },
|
|
|
|
|
[RTA_OIF] = { 1, 1, sizeof(u32) },
|
|
|
|
|
[RTA_GATEWAY] = { 1, 1, sizeof(ip6_addr) },
|
|
|
|
|
[RTA_PRIORITY] = { 1, 1, sizeof(u32) },
|
|
|
|
|
[RTA_PREFSRC] = { 1, 1, sizeof(ip6_addr) },
|
|
|
|
|
[RTA_METRICS] = { 1, 0, 0 },
|
|
|
|
|
[RTA_FLOW] = { 1, 1, sizeof(u32) },
|
|
|
|
|
[RTA_TABLE] = { 1, 1, sizeof(u32) },
|
|
|
|
|
};
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
nl_parse_attrs(struct rtattr *a, struct rtattr **k, int ksize)
|
|
|
|
|
nl_parse_attrs(struct rtattr *a, struct nl_want_attrs *want, struct rtattr **k, int ksize)
|
|
|
|
|
{
|
|
|
|
|
int max = ksize / sizeof(struct rtattr *);
|
|
|
|
|
bzero(k, ksize);
|
|
|
|
|
while (RTA_OK(a, nl_attr_len))
|
|
|
|
|
|
|
|
|
|
for ( ; RTA_OK(a, nl_attr_len); a = RTA_NEXT(a, nl_attr_len))
|
|
|
|
|
{
|
|
|
|
|
if (a->rta_type < max)
|
|
|
|
|
k[a->rta_type] = a;
|
|
|
|
|
a = RTA_NEXT(a, nl_attr_len);
|
|
|
|
|
if ((a->rta_type >= max) || !want[a->rta_type].defined)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (want[a->rta_type].checksize && (RTA_PAYLOAD(a) != want[a->rta_type].size))
|
|
|
|
|
{
|
|
|
|
|
log(L_ERR "nl_parse_attrs: Malformed message received");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
k[a->rta_type] = a;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nl_attr_len)
|
|
|
|
|
{
|
|
|
|
|
log(L_ERR "nl_parse_attrs: remnant of size %d", nl_attr_len);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline ip4_addr rta_get_u32(struct rtattr *a)
|
|
|
|
|
static inline u32 rta_get_u32(struct rtattr *a)
|
|
|
|
|
{ return *(u32 *) RTA_DATA(a); }
|
|
|
|
|
|
|
|
|
|
static inline ip4_addr rta_get_ip4(struct rtattr *a)
|
|
|
|
@@ -343,7 +424,7 @@ nl_parse_multipath(struct krt_proto *p, struct rtattr *ra)
|
|
|
|
|
static int nh_buf_size; /* in number of structures */
|
|
|
|
|
static int nh_buf_used;
|
|
|
|
|
|
|
|
|
|
struct rtattr *a[RTA_CACHEINFO+1];
|
|
|
|
|
struct rtattr *a[BIRD_RTA_MAX];
|
|
|
|
|
struct rtnexthop *nh = RTA_DATA(ra);
|
|
|
|
|
struct mpnh *rv, *first, **last;
|
|
|
|
|
int len = RTA_PAYLOAD(ra);
|
|
|
|
@@ -374,12 +455,9 @@ nl_parse_multipath(struct krt_proto *p, struct rtattr *ra)
|
|
|
|
|
|
|
|
|
|
/* Nonexistent RTNH_PAYLOAD ?? */
|
|
|
|
|
nl_attr_len = nh->rtnh_len - RTNH_LENGTH(0);
|
|
|
|
|
nl_parse_attrs(RTNH_DATA(nh), a, sizeof(a));
|
|
|
|
|
nl_parse_attrs(RTNH_DATA(nh), mpnh_attr_want4, a, sizeof(a));
|
|
|
|
|
if (a[RTA_GATEWAY])
|
|
|
|
|
{
|
|
|
|
|
if (RTA_PAYLOAD(a[RTA_GATEWAY]) != sizeof(ip_addr))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
memcpy(&rv->gw, RTA_DATA(a[RTA_GATEWAY]), sizeof(ip_addr));
|
|
|
|
|
ipa_ntoh(rv->gw);
|
|
|
|
|
|
|
|
|
@@ -448,7 +526,7 @@ static void
|
|
|
|
|
nl_parse_link(struct nlmsghdr *h, int scan)
|
|
|
|
|
{
|
|
|
|
|
struct ifinfomsg *i;
|
|
|
|
|
struct rtattr *a[IFLA_WIRELESS+1];
|
|
|
|
|
struct rtattr *a[BIRD_IFLA_MAX];
|
|
|
|
|
int new = h->nlmsg_type == RTM_NEWLINK;
|
|
|
|
|
struct iface f = {};
|
|
|
|
|
struct iface *ifi;
|
|
|
|
@@ -456,15 +534,23 @@ nl_parse_link(struct nlmsghdr *h, int scan)
|
|
|
|
|
u32 mtu;
|
|
|
|
|
uint fl;
|
|
|
|
|
|
|
|
|
|
if (!(i = nl_checkin(h, sizeof(*i))) || !nl_parse_attrs(IFLA_RTA(i), a, sizeof(a)))
|
|
|
|
|
if (!(i = nl_checkin(h, sizeof(*i))) || !nl_parse_attrs(IFLA_RTA(i), ifla_attr_want, a, sizeof(a)))
|
|
|
|
|
return;
|
|
|
|
|
if (!a[IFLA_IFNAME] || RTA_PAYLOAD(a[IFLA_IFNAME]) < 2 ||
|
|
|
|
|
!a[IFLA_MTU] || RTA_PAYLOAD(a[IFLA_MTU]) != 4)
|
|
|
|
|
if (!a[IFLA_IFNAME] || (RTA_PAYLOAD(a[IFLA_IFNAME]) < 2) || !a[IFLA_MTU])
|
|
|
|
|
{
|
|
|
|
|
if (scan || !a[IFLA_WIRELESS])
|
|
|
|
|
log(L_ERR "nl_parse_link: Malformed message received");
|
|
|
|
|
/*
|
|
|
|
|
* IFLA_IFNAME and IFLA_MTU are required, in fact, but there may also come
|
|
|
|
|
* a message with IFLA_WIRELESS set, where (e.g.) no IFLA_IFNAME exists.
|
|
|
|
|
* We simply ignore all such messages with IFLA_WIRELESS without notice.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
if (a[IFLA_WIRELESS])
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
log(L_ERR "KIF: Malformed message received");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
name = RTA_DATA(a[IFLA_IFNAME]);
|
|
|
|
|
mtu = rta_get_u32(a[IFLA_MTU]);
|
|
|
|
|
|
|
|
|
@@ -515,26 +601,40 @@ static void
|
|
|
|
|
nl_parse_addr(struct nlmsghdr *h, int scan)
|
|
|
|
|
{
|
|
|
|
|
struct ifaddrmsg *i;
|
|
|
|
|
struct rtattr *a[IFA_ANYCAST+1];
|
|
|
|
|
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))) || !nl_parse_attrs(IFA_RTA(i), a, sizeof(a)))
|
|
|
|
|
if (!(i = nl_checkin(h, sizeof(*i))))
|
|
|
|
|
return;
|
|
|
|
|
if (i->ifa_family != BIRD_AF)
|
|
|
|
|
return;
|
|
|
|
|
if (!a[IFA_ADDRESS] || RTA_PAYLOAD(a[IFA_ADDRESS]) != sizeof(ip_addr)
|
|
|
|
|
#ifdef IPV6
|
|
|
|
|
|| a[IFA_LOCAL] && RTA_PAYLOAD(a[IFA_LOCAL]) != sizeof(ip_addr)
|
|
|
|
|
#else
|
|
|
|
|
|| !a[IFA_LOCAL] || RTA_PAYLOAD(a[IFA_LOCAL]) != sizeof(ip_addr)
|
|
|
|
|
|| (a[IFA_BROADCAST] && RTA_PAYLOAD(a[IFA_BROADCAST]) != sizeof(ip_addr))
|
|
|
|
|
#endif
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
switch (i->ifa_family)
|
|
|
|
|
{
|
|
|
|
|
log(L_ERR "nl_parse_addr: Malformed message received");
|
|
|
|
|
#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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!a[IFA_ADDRESS])
|
|
|
|
|
{
|
|
|
|
|
log(L_ERR "KIF: Malformed message received (missing IFA_ADDRESS)");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -650,7 +750,23 @@ kif_do_scan(struct kif_proto *p UNUSED)
|
|
|
|
|
* Routes
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static struct krt_proto *nl_table_map[NL_NUM_TABLES];
|
|
|
|
|
static inline u32
|
|
|
|
|
krt_table_id(struct krt_proto *p)
|
|
|
|
|
{
|
|
|
|
|
return KRT_CF->sys.table_id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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_REHASH rth_rehash
|
|
|
|
|
#define RTH_PARAMS /8, *2, 2, 2, 6, 20
|
|
|
|
|
|
|
|
|
|
HASH_DEFINE_REHASH_FN(RTH, struct krt_proto)
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
krt_capable(rte *e)
|
|
|
|
@@ -708,12 +824,15 @@ nl_send_route(struct krt_proto *p, rte *e, struct ea_list *eattrs, int new)
|
|
|
|
|
|
|
|
|
|
r.r.rtm_family = BIRD_AF;
|
|
|
|
|
r.r.rtm_dst_len = net->n.pxlen;
|
|
|
|
|
r.r.rtm_tos = 0;
|
|
|
|
|
r.r.rtm_table = KRT_CF->sys.table_id;
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
if (krt_table_id(p) < 256)
|
|
|
|
|
r.r.rtm_table = krt_table_id(p);
|
|
|
|
|
else
|
|
|
|
|
nl_add_attr_u32(&r.h, sizeof(r), RTA_TABLE, krt_table_id(p));
|
|
|
|
|
|
|
|
|
|
/* For route delete, we do not specify route attributes */
|
|
|
|
|
if (!new)
|
|
|
|
|
return nl_exchange(&r.h);
|
|
|
|
@@ -809,31 +928,35 @@ nl_parse_route(struct nlmsghdr *h, int scan)
|
|
|
|
|
{
|
|
|
|
|
struct krt_proto *p;
|
|
|
|
|
struct rtmsg *i;
|
|
|
|
|
struct rtattr *a[RTA_CACHEINFO+1];
|
|
|
|
|
struct rtattr *a[BIRD_RTA_MAX];
|
|
|
|
|
int new = h->nlmsg_type == RTM_NEWROUTE;
|
|
|
|
|
|
|
|
|
|
ip_addr dst = IPA_NONE;
|
|
|
|
|
u32 oif = ~0;
|
|
|
|
|
u32 table;
|
|
|
|
|
int src;
|
|
|
|
|
|
|
|
|
|
if (!(i = nl_checkin(h, sizeof(*i))) || !nl_parse_attrs(RTM_RTA(i), a, sizeof(a)))
|
|
|
|
|
if (!(i = nl_checkin(h, sizeof(*i))))
|
|
|
|
|
return;
|
|
|
|
|
if (i->rtm_family != BIRD_AF)
|
|
|
|
|
return;
|
|
|
|
|
if ((a[RTA_DST] && RTA_PAYLOAD(a[RTA_DST]) != sizeof(ip_addr)) ||
|
|
|
|
|
#ifdef IPV6
|
|
|
|
|
(a[RTA_IIF] && RTA_PAYLOAD(a[RTA_IIF]) != 4) ||
|
|
|
|
|
#endif
|
|
|
|
|
(a[RTA_OIF] && RTA_PAYLOAD(a[RTA_OIF]) != 4) ||
|
|
|
|
|
(a[RTA_GATEWAY] && RTA_PAYLOAD(a[RTA_GATEWAY]) != sizeof(ip_addr)) ||
|
|
|
|
|
(a[RTA_PRIORITY] && RTA_PAYLOAD(a[RTA_PRIORITY]) != 4) ||
|
|
|
|
|
(a[RTA_PREFSRC] && RTA_PAYLOAD(a[RTA_PREFSRC]) != sizeof(ip_addr)) ||
|
|
|
|
|
(a[RTA_FLOW] && RTA_PAYLOAD(a[RTA_FLOW]) != 4))
|
|
|
|
|
|
|
|
|
|
switch (i->rtm_family)
|
|
|
|
|
{
|
|
|
|
|
log(L_ERR "KRT: Malformed message received");
|
|
|
|
|
return;
|
|
|
|
|
#ifndef IPV6
|
|
|
|
|
case AF_INET:
|
|
|
|
|
if (!nl_parse_attrs(RTM_RTA(i), rtm_attr_want4, a, sizeof(a)))
|
|
|
|
|
return;
|
|
|
|
|
break;
|
|
|
|
|
#else
|
|
|
|
|
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])
|
|
|
|
|
{
|
|
|
|
|
memcpy(&dst, RTA_DATA(a[RTA_DST]), sizeof(dst));
|
|
|
|
@@ -843,10 +966,15 @@ nl_parse_route(struct nlmsghdr *h, int scan)
|
|
|
|
|
if (a[RTA_OIF])
|
|
|
|
|
oif = rta_get_u32(a[RTA_OIF]);
|
|
|
|
|
|
|
|
|
|
p = nl_table_map[i->rtm_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, i->rtm_table, i->rtm_protocol, p ? p->p.name : "(none)");
|
|
|
|
|
if (a[RTA_TABLE])
|
|
|
|
|
table = rta_get_u32(a[RTA_TABLE]);
|
|
|
|
|
else
|
|
|
|
|
table = 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)");
|
|
|
|
|
if (!p)
|
|
|
|
|
SKIP("unknown table %d\n", i->rtm_table);
|
|
|
|
|
SKIP("unknown table %d\n", table);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef IPV6
|
|
|
|
@@ -905,7 +1033,7 @@ nl_parse_route(struct nlmsghdr *h, int scan)
|
|
|
|
|
{
|
|
|
|
|
case RTN_UNICAST:
|
|
|
|
|
|
|
|
|
|
if (a[RTA_MULTIPATH])
|
|
|
|
|
if (a[RTA_MULTIPATH] && (i->rtm_family == AF_INET))
|
|
|
|
|
{
|
|
|
|
|
ra.dest = RTD_MULTIPATH;
|
|
|
|
|
ra.nexthops = nl_parse_multipath(p, a[RTA_MULTIPATH]);
|
|
|
|
@@ -1079,12 +1207,14 @@ nl_async_msg(struct nlmsghdr *h)
|
|
|
|
|
case RTM_NEWLINK:
|
|
|
|
|
case RTM_DELLINK:
|
|
|
|
|
DBG("KRT: Received async link notification (%d)\n", h->nlmsg_type);
|
|
|
|
|
nl_parse_link(h, 0);
|
|
|
|
|
if (kif_proto)
|
|
|
|
|
nl_parse_link(h, 0);
|
|
|
|
|
break;
|
|
|
|
|
case RTM_NEWADDR:
|
|
|
|
|
case RTM_DELADDR:
|
|
|
|
|
DBG("KRT: Received async address notification (%d)\n", h->nlmsg_type);
|
|
|
|
|
nl_parse_addr(h, 0);
|
|
|
|
|
if (kif_proto)
|
|
|
|
|
nl_parse_addr(h, 0);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
DBG("KRT: Received unknown async notification (%d)\n", h->nlmsg_type);
|
|
|
|
@@ -1182,25 +1312,41 @@ nl_open_async(void)
|
|
|
|
|
bug("Netlink: sk_open failed");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Interface to the UNIX krt module
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static u8 nl_cf_table[(NL_NUM_TABLES+7) / 8];
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
krt_sys_io_init(void)
|
|
|
|
|
{
|
|
|
|
|
HASH_INIT(nl_table_map, krt_pool, 6);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
krt_sys_start(struct krt_proto *p)
|
|
|
|
|
{
|
|
|
|
|
nl_table_map[KRT_CF->sys.table_id] = p;
|
|
|
|
|
struct krt_proto *old = HASH_FIND(nl_table_map, RTH, krt_table_id(p));
|
|
|
|
|
|
|
|
|
|
if (old)
|
|
|
|
|
{
|
|
|
|
|
log(L_ERR "%s: Kernel table %u already registered by %s",
|
|
|
|
|
p->p.name, krt_table_id(p), old->p.name);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HASH_INSERT2(nl_table_map, RTH, krt_pool, p);
|
|
|
|
|
|
|
|
|
|
nl_open();
|
|
|
|
|
nl_open_async();
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
krt_sys_shutdown(struct krt_proto *p UNUSED)
|
|
|
|
|
krt_sys_shutdown(struct krt_proto *p)
|
|
|
|
|
{
|
|
|
|
|
nl_table_map[KRT_CF->sys.table_id] = NULL;
|
|
|
|
|
HASH_REMOVE2(nl_table_map, RTH, krt_pool, p);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
@@ -1209,23 +1355,6 @@ krt_sys_reconfigure(struct krt_proto *p UNUSED, struct krt_config *n, struct krt
|
|
|
|
|
return n->sys.table_id == o->sys.table_id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
krt_sys_preconfig(struct config *c UNUSED)
|
|
|
|
|
{
|
|
|
|
|
bzero(&nl_cf_table, sizeof(nl_cf_table));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
krt_sys_postconfig(struct krt_config *x)
|
|
|
|
|
{
|
|
|
|
|
int id = x->sys.table_id;
|
|
|
|
|
|
|
|
|
|
if (nl_cf_table[id/8] & (1 << (id%8)))
|
|
|
|
|
cf_error("Multiple kernel syncers defined for table #%d", id);
|
|
|
|
|
nl_cf_table[id/8] |= (1 << (id%8));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
krt_sys_init_config(struct krt_config *cf)
|
|
|
|
|
{
|
|
|
|
|