Taught Netlink how to behave in IPv6 world.
This commit is contained in:
parent
4f22c98185
commit
4532a89e31
4 changed files with 53 additions and 13 deletions
|
@ -15,6 +15,12 @@
|
||||||
* to krt-set.h, krt-iface.h and this file.
|
* to krt-set.h, krt-iface.h and this file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef IPV6
|
||||||
|
#define NL_NUM_TABLES 1
|
||||||
|
#else
|
||||||
|
#define NL_NUM_TABLES 256
|
||||||
|
#endif
|
||||||
|
|
||||||
struct krt_scan_params {
|
struct krt_scan_params {
|
||||||
int async; /* Allow asynchronous events */
|
int async; /* Allow asynchronous events */
|
||||||
int table_id; /* Kernel table ID we sync with */
|
int table_id; /* Kernel table ID we sync with */
|
||||||
|
|
|
@ -19,7 +19,7 @@ CF_ADDTO(kern_proto, kern_proto nl_item ';')
|
||||||
nl_item:
|
nl_item:
|
||||||
ASYNC bool { THIS_KRT->scan.async = $2; }
|
ASYNC bool { THIS_KRT->scan.async = $2; }
|
||||||
| KERNEL TABLE expr {
|
| KERNEL TABLE expr {
|
||||||
if ($3 <= 0 || $3 >= 255)
|
if ($3 <= 0 || $3 >= NL_NUM_TABLES)
|
||||||
cf_error("Kernel routing table number out of range");
|
cf_error("Kernel routing table number out of range");
|
||||||
THIS_KRT->scan.table_id = $3;
|
THIS_KRT->scan.table_id = $3;
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,7 @@ nl_request_dump(int cmd)
|
||||||
req.nh.nlmsg_type = cmd;
|
req.nh.nlmsg_type = cmd;
|
||||||
req.nh.nlmsg_len = sizeof(req);
|
req.nh.nlmsg_len = sizeof(req);
|
||||||
req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
|
req.nh.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
|
||||||
req.g.rtgen_family = PF_INET;
|
req.g.rtgen_family = BIRD_PF;
|
||||||
nl_send(&req.nh);
|
nl_send(&req.nh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,16 +322,26 @@ nl_parse_addr(struct nlmsghdr *h)
|
||||||
|
|
||||||
if (!(i = nl_checkin(h, sizeof(*i))) || !nl_parse_attrs(IFA_RTA(i), a, sizeof(a)))
|
if (!(i = nl_checkin(h, sizeof(*i))) || !nl_parse_attrs(IFA_RTA(i), a, sizeof(a)))
|
||||||
return;
|
return;
|
||||||
if (i->ifa_family != AF_INET)
|
if (i->ifa_family != BIRD_AF)
|
||||||
return;
|
return;
|
||||||
if (!a[IFA_ADDRESS] || RTA_PAYLOAD(a[IFA_ADDRESS]) != sizeof(ip_addr) ||
|
if (!a[IFA_ADDRESS] || RTA_PAYLOAD(a[IFA_ADDRESS]) != sizeof(ip_addr)
|
||||||
!a[IFA_LOCAL] || RTA_PAYLOAD(a[IFA_LOCAL]) != sizeof(ip_addr) ||
|
#ifdef IPV6
|
||||||
(a[IFA_BROADCAST] && RTA_PAYLOAD(a[IFA_BROADCAST]) != sizeof(ip_addr)))
|
|| 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
|
||||||
|
)
|
||||||
{
|
{
|
||||||
log(L_ERR "nl_parse_addr: Malformed message received");
|
log(L_ERR "nl_parse_addr: Malformed message received");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef IPV6
|
||||||
|
if (i->ifa_scope == RT_SCOPE_LINK)
|
||||||
|
return;
|
||||||
|
#endif
|
||||||
|
|
||||||
ifi = if_find_by_index(i->ifa_index);
|
ifi = if_find_by_index(i->ifa_index);
|
||||||
if (!ifi)
|
if (!ifi)
|
||||||
{
|
{
|
||||||
|
@ -339,18 +349,21 @@ nl_parse_addr(struct nlmsghdr *h)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef IPV6
|
||||||
if (i->ifa_prefixlen > 32 || i->ifa_prefixlen == 31 ||
|
if (i->ifa_prefixlen > 32 || i->ifa_prefixlen == 31 ||
|
||||||
(ifi->flags & IF_UNNUMBERED) && i->ifa_prefixlen != 32)
|
(ifi->flags & IF_UNNUMBERED) && i->ifa_prefixlen != 32)
|
||||||
{
|
{
|
||||||
log(L_ERR "KIF: Invalid prefix length for interface %s: %d\n", ifi->name, i->ifa_prefixlen);
|
log(L_ERR "KIF: Invalid prefix length for interface %s: %d", ifi->name, i->ifa_prefixlen);
|
||||||
new = 0;
|
new = 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bzero(&ifa, sizeof(ifa));
|
bzero(&ifa, sizeof(ifa));
|
||||||
ifa.iface = ifi;
|
ifa.iface = ifi;
|
||||||
if (i->ifa_flags & IFA_F_SECONDARY)
|
if (i->ifa_flags & IFA_F_SECONDARY)
|
||||||
ifa.flags |= IA_SECONDARY;
|
ifa.flags |= IA_SECONDARY;
|
||||||
memcpy(&ifa.ip, RTA_DATA(a[IFA_LOCAL]), sizeof(ifa.ip));
|
/* 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);
|
ipa_ntoh(ifa.ip);
|
||||||
ifa.pxlen = i->ifa_prefixlen;
|
ifa.pxlen = i->ifa_prefixlen;
|
||||||
if (ifi->flags & IF_UNNUMBERED)
|
if (ifi->flags & IF_UNNUMBERED)
|
||||||
|
@ -359,11 +372,13 @@ nl_parse_addr(struct nlmsghdr *h)
|
||||||
ipa_ntoh(ifa.opposite);
|
ipa_ntoh(ifa.opposite);
|
||||||
ifa.brd = ifa.opposite;
|
ifa.brd = ifa.opposite;
|
||||||
}
|
}
|
||||||
|
#ifndef IPV6
|
||||||
else if ((ifi->flags & IF_BROADCAST) && a[IFA_BROADCAST])
|
else if ((ifi->flags & IF_BROADCAST) && a[IFA_BROADCAST])
|
||||||
{
|
{
|
||||||
memcpy(&ifa.brd, RTA_DATA(a[IFA_BROADCAST]), sizeof(ifa.brd));
|
memcpy(&ifa.brd, RTA_DATA(a[IFA_BROADCAST]), sizeof(ifa.brd));
|
||||||
ipa_ntoh(ifa.brd);
|
ipa_ntoh(ifa.brd);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
/* else a NBMA link */
|
/* else a NBMA link */
|
||||||
ifa.prefix = ipa_and(ifa.ip, ipa_mkmask(ifa.pxlen));
|
ifa.prefix = ipa_and(ifa.ip, ipa_mkmask(ifa.pxlen));
|
||||||
|
|
||||||
|
@ -405,7 +420,7 @@ krt_if_scan(struct kif_proto *p)
|
||||||
* Routes
|
* Routes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static struct krt_proto *nl_table_map[256];
|
static struct krt_proto *nl_table_map[NL_NUM_TABLES];
|
||||||
|
|
||||||
int
|
int
|
||||||
krt_capable(rte *e)
|
krt_capable(rte *e)
|
||||||
|
@ -413,7 +428,7 @@ krt_capable(rte *e)
|
||||||
rta *a = e->attrs;
|
rta *a = e->attrs;
|
||||||
|
|
||||||
if (a->cast != RTC_UNICAST
|
if (a->cast != RTC_UNICAST
|
||||||
#ifdef IPV6
|
#if 0
|
||||||
&& a->cast != RTC_ANYCAST
|
&& a->cast != RTC_ANYCAST
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
|
@ -455,7 +470,7 @@ nl_send_route(struct krt_proto *p, rte *e, int new)
|
||||||
r.h.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | (new ? NLM_F_CREATE|NLM_F_REPLACE : 0);
|
r.h.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | (new ? NLM_F_CREATE|NLM_F_REPLACE : 0);
|
||||||
/* FIXME: Do we really need to process ACKs? */
|
/* FIXME: Do we really need to process ACKs? */
|
||||||
|
|
||||||
r.r.rtm_family = AF_INET;
|
r.r.rtm_family = BIRD_AF;
|
||||||
r.r.rtm_dst_len = net->n.pxlen;
|
r.r.rtm_dst_len = net->n.pxlen;
|
||||||
r.r.rtm_tos = 0;
|
r.r.rtm_tos = 0;
|
||||||
r.r.rtm_table = KRT_CF->scan.table_id;
|
r.r.rtm_table = KRT_CF->scan.table_id;
|
||||||
|
@ -546,11 +561,14 @@ nl_parse_route(struct nlmsghdr *h, int scan)
|
||||||
|
|
||||||
if (!(i = nl_checkin(h, sizeof(*i))) || !nl_parse_attrs(RTM_RTA(i), a, sizeof(a)))
|
if (!(i = nl_checkin(h, sizeof(*i))) || !nl_parse_attrs(RTM_RTA(i), a, sizeof(a)))
|
||||||
return;
|
return;
|
||||||
if (i->rtm_family != AF_INET)
|
if (i->rtm_family != BIRD_AF)
|
||||||
return;
|
return;
|
||||||
if ((a[RTA_DST] && RTA_PAYLOAD(a[RTA_DST]) != sizeof(ip_addr)) ||
|
if ((a[RTA_DST] && RTA_PAYLOAD(a[RTA_DST]) != sizeof(ip_addr)) ||
|
||||||
(a[RTA_OIF] && RTA_PAYLOAD(a[RTA_OIF]) != 4) ||
|
(a[RTA_OIF] && RTA_PAYLOAD(a[RTA_OIF]) != 4) ||
|
||||||
(a[RTA_PRIORITY] && RTA_PAYLOAD(a[RTA_PRIORITY]) != 4) ||
|
(a[RTA_PRIORITY] && RTA_PAYLOAD(a[RTA_PRIORITY]) != 4) ||
|
||||||
|
#ifdef IPV6
|
||||||
|
(a[RTA_IIF] && RTA_PAYLOAD(a[RTA_IIF]) != 4) ||
|
||||||
|
#endif
|
||||||
(a[RTA_GATEWAY] && RTA_PAYLOAD(a[RTA_GATEWAY]) != sizeof(ip_addr)))
|
(a[RTA_GATEWAY] && RTA_PAYLOAD(a[RTA_GATEWAY]) != sizeof(ip_addr)))
|
||||||
{
|
{
|
||||||
log(L_ERR "nl_parse_route: Malformed message received");
|
log(L_ERR "nl_parse_route: Malformed message received");
|
||||||
|
@ -561,11 +579,19 @@ nl_parse_route(struct nlmsghdr *h, int scan)
|
||||||
if (!p)
|
if (!p)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#ifdef IPV6
|
||||||
|
if (a[RTA_IIF])
|
||||||
|
{
|
||||||
|
DBG("KRT: Ignoring route with IIF set\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (i->rtm_tos != 0) /* We don't support TOS */
|
if (i->rtm_tos != 0) /* We don't support TOS */
|
||||||
{
|
{
|
||||||
DBG("KRT: Ignoring route with TOS %02x\n", i->rtm_tos);
|
DBG("KRT: Ignoring route with TOS %02x\n", i->rtm_tos);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (scan && !new)
|
if (scan && !new)
|
||||||
{
|
{
|
||||||
|
@ -784,7 +810,11 @@ nl_open_async(void)
|
||||||
|
|
||||||
bzero(&sa, sizeof(sa));
|
bzero(&sa, sizeof(sa));
|
||||||
sa.nl_family = AF_NETLINK;
|
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;
|
sa.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV4_ROUTE;
|
||||||
|
#endif
|
||||||
if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0)
|
if (bind(fd, (struct sockaddr *) &sa, sizeof(sa)) < 0)
|
||||||
{
|
{
|
||||||
log(L_ERR "Unable to bind asynchronous rtnetlink socket: %m");
|
log(L_ERR "Unable to bind asynchronous rtnetlink socket: %m");
|
||||||
|
@ -806,7 +836,7 @@ nl_open_async(void)
|
||||||
* Interface to the UNIX krt module
|
* Interface to the UNIX krt module
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static u8 nl_cf_table[256 / 8];
|
static u8 nl_cf_table[(NL_NUM_TABLES+7) / 8];
|
||||||
|
|
||||||
void
|
void
|
||||||
krt_scan_preconfig(struct config *c)
|
krt_scan_preconfig(struct config *c)
|
||||||
|
@ -828,7 +858,9 @@ void
|
||||||
krt_scan_construct(struct krt_config *x)
|
krt_scan_construct(struct krt_config *x)
|
||||||
{
|
{
|
||||||
x->scan.async = 1;
|
x->scan.async = 1;
|
||||||
|
#ifndef IPV6
|
||||||
x->scan.table_id = RT_TABLE_MAIN;
|
x->scan.table_id = RT_TABLE_MAIN;
|
||||||
|
#endif
|
||||||
/* FIXME: Use larger defaults for scanning times? */
|
/* FIXME: Use larger defaults for scanning times? */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,9 +23,11 @@ volatile int async_shutdown_flag;
|
||||||
|
|
||||||
#ifdef IPV6
|
#ifdef IPV6
|
||||||
#define BIRD_PF PF_INET6
|
#define BIRD_PF PF_INET6
|
||||||
|
#define BIRD_AF AF_INET6
|
||||||
typedef struct sockaddr_in6 sockaddr;
|
typedef struct sockaddr_in6 sockaddr;
|
||||||
#else
|
#else
|
||||||
#define BIRD_PF PF_INET
|
#define BIRD_PF PF_INET
|
||||||
|
#define BIRD_AF AF_INET
|
||||||
typedef struct sockaddr_in sockaddr;
|
typedef struct sockaddr_in sockaddr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue