Taught Netlink how to behave in IPv6 world.

This commit is contained in:
Martin Mares 1999-08-03 19:37:37 +00:00
parent 4f22c98185
commit 4532a89e31
4 changed files with 53 additions and 13 deletions

View file

@ -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 */

View file

@ -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;
} }

View file

@ -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? */
} }

View file

@ -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