mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2025-01-03 15:41:54 +00:00
Adapts BSD sysdep code for integrated branch.
Thanks to Alexander V. Chernikov for the original patch.
This commit is contained in:
parent
3da07ce1f0
commit
3de342dae1
@ -10,6 +10,7 @@
|
|||||||
#define _BIRD_SOCKET_H_
|
#define _BIRD_SOCKET_H_
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
#include "lib/resource.h"
|
#include "lib/resource.h"
|
||||||
|
|
||||||
|
@ -1231,9 +1231,9 @@ rt_addrsize(int addr_type)
|
|||||||
switch (addr_type)
|
switch (addr_type)
|
||||||
{
|
{
|
||||||
#ifdef MPLS_VPN
|
#ifdef MPLS_VPN
|
||||||
case RT_VPNV4:
|
case RT_VPN4:
|
||||||
return sizeof(vpn4_addr);
|
return sizeof(vpn4_addr);
|
||||||
case RT_VPNV6:
|
case RT_VPN6:
|
||||||
return sizeof(vpn6_addr);
|
return sizeof(vpn6_addr);
|
||||||
#endif
|
#endif
|
||||||
case RT_IPV4:
|
case RT_IPV4:
|
||||||
|
@ -65,6 +65,20 @@ krt_capable(rte *e)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
rt_to_af(int rt)
|
||||||
|
{
|
||||||
|
if (rt == RT_IPV4)
|
||||||
|
return AF_INET;
|
||||||
|
else if (rt == RT_IPV6)
|
||||||
|
return AF_INET6;
|
||||||
|
|
||||||
|
/* RT_IP (0) maps to 0 (every AF) */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define ROUNDUP(a) \
|
#define ROUNDUP(a) \
|
||||||
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
|
((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
|
||||||
|
|
||||||
@ -87,10 +101,10 @@ krt_sock_send(int cmd, rte *e)
|
|||||||
rta *a = e->attrs;
|
rta *a = e->attrs;
|
||||||
static int msg_seq;
|
static int msg_seq;
|
||||||
struct iface *j, *i = a->iface;
|
struct iface *j, *i = a->iface;
|
||||||
int l;
|
int af = 0, l;
|
||||||
struct ks_msg msg;
|
struct ks_msg msg;
|
||||||
char *body = (char *)msg.buf;
|
char *body = (char *)msg.buf;
|
||||||
sockaddr gate, mask, dst;
|
struct sockaddr_in6 gate, mask, dst;
|
||||||
ip_addr gw;
|
ip_addr gw;
|
||||||
|
|
||||||
DBG("krt-sock: send %F via %I\n", &net->n, a->gw);
|
DBG("krt-sock: send %F via %I\n", &net->n, a->gw);
|
||||||
@ -131,29 +145,43 @@ krt_sock_send(int cmd, rte *e)
|
|||||||
|
|
||||||
gw = a->gw;
|
gw = a->gw;
|
||||||
|
|
||||||
#ifdef IPV6
|
switch (net->n.addr_type)
|
||||||
/* Embed interface ID to link-local address */
|
{
|
||||||
if (ipa_has_link_scope(gw))
|
case RT_IPV4:
|
||||||
_I0(gw) = 0xfe800000 | (i->index & 0x0000ffff);
|
af = AF_INET;
|
||||||
#endif
|
dst.sin6_family = mask.sin6_family = gate.sin6_family = af;
|
||||||
|
sockaddr_fill((struct sockaddr *)&dst, *FPREFIX_IP(&net->n), NULL, 0);
|
||||||
|
sockaddr_fill((struct sockaddr *)&mask, ipa_mkmask(net->n.pxlen), NULL, 0);
|
||||||
|
sockaddr_fill((struct sockaddr *)&gate, gw, NULL, 0);
|
||||||
|
|
||||||
fill_in_sockaddr(&dst, net->n.prefix, NULL, 0);
|
if (net->n.pxlen == MAX_PREFIX_LENGTH)
|
||||||
fill_in_sockaddr(&mask, ipa_mkmask(net->n.pxlen), NULL, 0);
|
msg.rtm.rtm_flags |= RTF_HOST;
|
||||||
fill_in_sockaddr(&gate, gw, NULL, 0);
|
else
|
||||||
/* XXXX from patch
|
msg.rtm.rtm_addrs |= RTA_NETMASK;
|
||||||
if (net->n.addr_type == RT_IP)
|
break;
|
||||||
{
|
|
||||||
fill_in_sockaddr(&dst, *FPREFIX_IP(&net->n), 0);
|
|
||||||
fill_in_sockaddr(&mask, ipa_mkmask(net->n.pxlen), 0);
|
|
||||||
|
|
||||||
if (net->n.pxlen == MAX_PREFIX_LENGTH)
|
case RT_IPV6:
|
||||||
msg.rtm.rtm_flags |= RTF_HOST;
|
af = AF_INET6;
|
||||||
else
|
|
||||||
msg.rtm.rtm_addrs |= RTA_NETMASK;
|
/* Embed interface ID to link-local address */
|
||||||
}
|
if (ipa_is_link_local(gw))
|
||||||
*/
|
_I0(gw) = 0xfe800000 | (i->index & 0x0000ffff);
|
||||||
|
|
||||||
|
dst.sin6_family = mask.sin6_family = gate.sin6_family = af;
|
||||||
|
sockaddr_fill((struct sockaddr *)&dst, *FPREFIX_IP(&net->n), NULL, 0);
|
||||||
|
sockaddr_fill((struct sockaddr *)&mask, ipa_mkmask(net->n.pxlen), NULL, 0);
|
||||||
|
sockaddr_fill((struct sockaddr *)&gate, gw, NULL, 0);
|
||||||
|
|
||||||
|
if (net->n.pxlen == MAX_PREFIX_LENGTH)
|
||||||
|
msg.rtm.rtm_flags |= RTF_HOST;
|
||||||
|
else
|
||||||
|
msg.rtm.rtm_addrs |= RTA_NETMASK;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
log(L_ERR "Unsupported address family: %F", FPREFIX_IP(&net->n));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
switch (a->dest)
|
switch (a->dest)
|
||||||
{
|
{
|
||||||
@ -175,12 +203,13 @@ krt_sock_send(int cmd, rte *e)
|
|||||||
msg.rtm.rtm_flags |= RTF_CLONING;
|
msg.rtm.rtm_flags |= RTF_CLONING;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// XXXX: find proper IPv4 / IPv6 address ?
|
||||||
if(!i->addr) {
|
if(!i->addr) {
|
||||||
log(L_ERR "KRT: interface %s has no IP addess", i->name);
|
log(L_ERR "KRT: interface %s has no IP address", i->name);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fill_in_sockaddr(&gate, i->addr->ip, NULL, 0);
|
sockaddr_fill((struct sockaddr *)&gate, i->addr->ip, NULL, 0);
|
||||||
msg.rtm.rtm_addrs |= RTA_GATEWAY;
|
msg.rtm.rtm_addrs |= RTA_GATEWAY;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -230,15 +259,15 @@ krt_read_rt(struct ks_msg *msg, struct krt_proto *p, int scan)
|
|||||||
{
|
{
|
||||||
rte *e;
|
rte *e;
|
||||||
net *net;
|
net *net;
|
||||||
sockaddr dst, gate, mask;
|
struct sockaddr_in6 dst, gate, mask;
|
||||||
ip_addr idst, igate, imask;
|
ip_addr idst, igate, imask;
|
||||||
void *body = (char *)msg->buf;
|
void *body = (char *)msg->buf;
|
||||||
int new = (msg->rtm.rtm_type == RTM_ADD);
|
int new = (msg->rtm.rtm_type == RTM_ADD);
|
||||||
char *errmsg = "KRT: Invalid route received";
|
|
||||||
int flags = msg->rtm.rtm_flags;
|
int flags = msg->rtm.rtm_flags;
|
||||||
int addrs = msg->rtm.rtm_addrs;
|
int addrs = msg->rtm.rtm_addrs;
|
||||||
int src;
|
int af, pxlen, src;
|
||||||
byte src2;
|
byte src2;
|
||||||
|
char *errmsg = "KRT: Invalid route received";
|
||||||
|
|
||||||
if (!(flags & RTF_UP) && scan)
|
if (!(flags & RTF_UP) && scan)
|
||||||
SKIP("not up in scan\n");
|
SKIP("not up in scan\n");
|
||||||
@ -253,26 +282,52 @@ krt_read_rt(struct ks_msg *msg, struct krt_proto *p, int scan)
|
|||||||
GETADDR(&gate, RTA_GATEWAY);
|
GETADDR(&gate, RTA_GATEWAY);
|
||||||
GETADDR(&mask, RTA_NETMASK);
|
GETADDR(&mask, RTA_NETMASK);
|
||||||
|
|
||||||
if (sa_family_check(&dst))
|
af = dst.sin6_family;
|
||||||
get_sockaddr(&dst, &idst, NULL, NULL, 0);
|
|
||||||
else
|
/* XXX: AF_MPLS */
|
||||||
SKIP("invalid DST");
|
|
||||||
|
switch (af)
|
||||||
|
{
|
||||||
|
case AF_INET:
|
||||||
|
/* Silently discard */
|
||||||
|
if (p->addr_type != RT_IPV4)
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AF_INET6:
|
||||||
|
/* Silently discard */
|
||||||
|
if (p->addr_type != RT_IPV6)
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
SKIP("Invalid DST");
|
||||||
|
}
|
||||||
|
|
||||||
|
sockaddr_read((struct sockaddr *)&dst, &idst, NULL, NULL, 1);
|
||||||
|
|
||||||
/* We will check later whether we have valid gateway addr */
|
/* We will check later whether we have valid gateway addr */
|
||||||
if (sa_family_check(&gate))
|
if (gate.sin6_family == af)
|
||||||
get_sockaddr(&gate, &igate, NULL, NULL, 0);
|
sockaddr_read((struct sockaddr *)&gate, &igate, NULL, NULL, 0);
|
||||||
else
|
else
|
||||||
igate = IPA_NONE;
|
igate = IPA_NONE;
|
||||||
|
|
||||||
/* We do not test family for RTA_NETMASK, because BSD sends us
|
/* We do not test family for RTA_NETMASK, because BSD sends us
|
||||||
some strange values, but interpreting them as IPv4/IPv6 works */
|
some strange values, but interpreting them as IPv4/IPv6 works */
|
||||||
get_sockaddr(&mask, &imask, NULL, NULL, 0);
|
mask.sin6_family = dst.sin6_family;
|
||||||
|
|
||||||
|
sockaddr_read((struct sockaddr *)&mask, &imask, NULL, NULL, 1);
|
||||||
|
|
||||||
int c = ipa_classify_net(idst);
|
int c = ipa_classify_net(idst);
|
||||||
if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
|
if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
|
||||||
SKIP("strange class/scope\n");
|
SKIP("strange class/scope\n");
|
||||||
|
|
||||||
int pxlen = (flags & RTF_HOST) ? MAX_PREFIX_LENGTH : ipa_mklen(imask);
|
if (af == AF_INET6)
|
||||||
|
pxlen = (flags & RTF_HOST) ? MAX_PREFIX_LENGTH : ip6_masklen(&imask);
|
||||||
|
else
|
||||||
|
pxlen = (flags & RTF_HOST) ? MAX_PREFIX_LENGTH :
|
||||||
|
(ip4_masklen(ipa_to_ip4(imask)) + 96); // XXXX: Hack
|
||||||
|
|
||||||
if (pxlen < 0)
|
if (pxlen < 0)
|
||||||
{ log(L_ERR "%s (%I) - netmask %I", errmsg, idst, imask); return; }
|
{ log(L_ERR "%s (%I) - netmask %I", errmsg, idst, imask); return; }
|
||||||
|
|
||||||
@ -356,11 +411,12 @@ krt_read_rt(struct ks_msg *msg, struct krt_proto *p, int scan)
|
|||||||
a.dest = RTD_ROUTER;
|
a.dest = RTD_ROUTER;
|
||||||
a.gw = igate;
|
a.gw = igate;
|
||||||
|
|
||||||
#ifdef IPV6
|
if (af == AF_INET6)
|
||||||
/* Clean up embedded interface ID returned in link-local address */
|
{
|
||||||
if (ipa_has_link_scope(a.gw))
|
/* Clean up embedded interface ID returned in link-local address */
|
||||||
_I0(a.gw) = 0xfe800000;
|
if (ipa_is_link_local(a.gw))
|
||||||
#endif
|
_I0(a.gw) = 0xfe800000;
|
||||||
|
}
|
||||||
|
|
||||||
ng = neigh_find2(&p->p, &a.gw, a.iface, 0);
|
ng = neigh_find2(&p->p, &a.gw, a.iface, 0);
|
||||||
if (!ng || (ng->scope == SCOPE_HOST))
|
if (!ng || (ng->scope == SCOPE_HOST))
|
||||||
@ -503,13 +559,13 @@ krt_read_addr(struct ks_msg *msg)
|
|||||||
{
|
{
|
||||||
struct ifa_msghdr *ifam = (struct ifa_msghdr *)&msg->rtm;
|
struct ifa_msghdr *ifam = (struct ifa_msghdr *)&msg->rtm;
|
||||||
void *body = (void *)(ifam + 1);
|
void *body = (void *)(ifam + 1);
|
||||||
sockaddr addr, mask, brd;
|
struct sockaddr_in6 addr, mask, brd;
|
||||||
struct iface *iface = NULL;
|
struct iface *iface = NULL;
|
||||||
struct ifa ifa;
|
struct ifa ifa;
|
||||||
struct sockaddr null;
|
struct sockaddr null;
|
||||||
ip_addr iaddr, imask, ibrd;
|
ip_addr iaddr, imask, ibrd;
|
||||||
int addrs = ifam->ifam_addrs;
|
int addrs = ifam->ifam_addrs;
|
||||||
int scope, masklen = -1;
|
int ipv4, scope, masklen = -1, maxlen;
|
||||||
int new = (ifam->ifam_type == RTM_NEWADDR);
|
int new = (ifam->ifam_type == RTM_NEWADDR);
|
||||||
|
|
||||||
/* Strange messages with zero (invalid) ifindex appear on OpenBSD */
|
/* Strange messages with zero (invalid) ifindex appear on OpenBSD */
|
||||||
@ -531,20 +587,33 @@ krt_read_addr(struct ks_msg *msg)
|
|||||||
GETADDR (&null, RTA_AUTHOR);
|
GETADDR (&null, RTA_AUTHOR);
|
||||||
GETADDR (&brd, RTA_BRD);
|
GETADDR (&brd, RTA_BRD);
|
||||||
|
|
||||||
/* Some other family address */
|
/* Basic family check */
|
||||||
if (!sa_family_check(&addr))
|
if (addr.sin6_family != AF_INET && addr.sin6_family != AF_INET6)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
get_sockaddr(&addr, &iaddr, NULL, NULL, 0);
|
ipv4 = (addr.sin6_family == AF_INET) ? 1 : 0;
|
||||||
get_sockaddr(&mask, &imask, NULL, NULL, 0);
|
|
||||||
get_sockaddr(&brd, &ibrd, NULL, NULL, 0);
|
|
||||||
|
|
||||||
if ((masklen = ipa_mklen(imask)) < 0)
|
/*
|
||||||
|
* Work around (Free?)BSD bug with netmask
|
||||||
|
* family not being filled in IPv6 case.
|
||||||
|
* FreeBSD fix: r250815.
|
||||||
|
*/
|
||||||
|
if (addr.sin6_family == AF_INET6 && mask.sin6_family == 0)
|
||||||
|
mask.sin6_family = AF_INET6;
|
||||||
|
|
||||||
|
sockaddr_read((struct sockaddr *)&addr, &iaddr, NULL, NULL, 0);
|
||||||
|
sockaddr_read((struct sockaddr *)&mask, &imask, NULL, NULL, 0);
|
||||||
|
sockaddr_read((struct sockaddr *)&brd, &ibrd, NULL, NULL, 0);
|
||||||
|
|
||||||
|
masklen = ipv4 ? (ip4_masklen(ipa_to_ip4(imask)) + 96) : ip6_masklen(&imask); // XXXX: Hack
|
||||||
|
if (masklen < 0)
|
||||||
{
|
{
|
||||||
log("Invalid masklen");
|
log("Invalid masklen");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// log("got %I/%I (%d)", iaddr, imask, masklen);
|
||||||
|
|
||||||
bzero(&ifa, sizeof(ifa));
|
bzero(&ifa, sizeof(ifa));
|
||||||
|
|
||||||
ifa.iface = iface;
|
ifa.iface = iface;
|
||||||
@ -561,31 +630,25 @@ krt_read_addr(struct ks_msg *msg)
|
|||||||
}
|
}
|
||||||
ifa.scope = scope & IADDR_SCOPE_MASK;
|
ifa.scope = scope & IADDR_SCOPE_MASK;
|
||||||
|
|
||||||
#ifdef IPV6
|
|
||||||
/* Clean up embedded interface ID returned in link-local address */
|
/* Clean up embedded interface ID returned in link-local address */
|
||||||
if (ipa_has_link_scope(ifa.ip))
|
if (scope & SCOPE_LINK)
|
||||||
_I0(ifa.ip) = 0xfe800000;
|
_I0(ifa.ip) = 0xfe800000;
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef IPV6
|
// maxlen = ipv4 ? BITS_PER_IP_ADDRESS4 : BITS_PER_IP_ADDRESS6;
|
||||||
/* Why not the same check also for IPv4? */
|
maxlen = BITS_PER_IP_ADDRESS; // XXXX: Hack
|
||||||
if ((iface->flags & IF_MULTIACCESS) || (masklen != BITS_PER_IP_ADDRESS))
|
|
||||||
#else
|
if ((iface->flags & IF_MULTIACCESS) || (masklen != maxlen))
|
||||||
if (iface->flags & IF_MULTIACCESS)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
ifa.prefix = ipa_and(ifa.ip, ipa_mkmask(masklen));
|
ifa.prefix = ipa_and(ifa.ip, ipa_mkmask(masklen));
|
||||||
|
|
||||||
if (masklen == BITS_PER_IP_ADDRESS)
|
if (masklen == maxlen)
|
||||||
ifa.flags |= IA_HOST;
|
ifa.flags |= IA_HOST;
|
||||||
|
|
||||||
if (masklen == (BITS_PER_IP_ADDRESS - 1))
|
if (masklen == (maxlen - 1))
|
||||||
ifa.opposite = ipa_opposite_m1(ifa.ip);
|
ifa.opposite = ipa_opposite_m1(ifa.ip);
|
||||||
|
|
||||||
#ifndef IPV6
|
if (ipv4 && masklen == (maxlen - 2))
|
||||||
if (masklen == (BITS_PER_IP_ADDRESS - 2))
|
|
||||||
ifa.opposite = ipa_opposite_m2(ifa.ip);
|
ifa.opposite = ipa_opposite_m2(ifa.ip);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
else /* PtP iface */
|
else /* PtP iface */
|
||||||
{
|
{
|
||||||
@ -627,7 +690,7 @@ krt_read_msg(struct proto *p, struct ks_msg *msg, int scan)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
krt_sysctl_scan(struct proto *p, pool *pool, byte **buf, size_t *bl, int cmd)
|
krt_sysctl_scan(struct proto *p, pool *pool, byte **buf, size_t *bl, int cmd, int af)
|
||||||
{
|
{
|
||||||
byte *next;
|
byte *next;
|
||||||
int mib[6];
|
int mib[6];
|
||||||
@ -638,7 +701,7 @@ krt_sysctl_scan(struct proto *p, pool *pool, byte **buf, size_t *bl, int cmd)
|
|||||||
mib[0] = CTL_NET;
|
mib[0] = CTL_NET;
|
||||||
mib[1] = PF_ROUTE;
|
mib[1] = PF_ROUTE;
|
||||||
mib[2] = 0;
|
mib[2] = 0;
|
||||||
mib[3] = BIRD_PF;
|
mib[3] = af;
|
||||||
mib[4] = cmd;
|
mib[4] = cmd;
|
||||||
mib[5] = 0;
|
mib[5] = 0;
|
||||||
|
|
||||||
@ -686,7 +749,8 @@ static size_t kif_buflen = 4096;
|
|||||||
void
|
void
|
||||||
krt_do_scan(struct krt_proto *p)
|
krt_do_scan(struct krt_proto *p)
|
||||||
{
|
{
|
||||||
krt_sysctl_scan((struct proto *)p, p->krt_pool, &krt_buffer, &krt_buflen, NET_RT_DUMP);
|
krt_sysctl_scan((struct proto *)p, p->krt_pool, &krt_buffer, &krt_buflen,
|
||||||
|
NET_RT_DUMP, rt_to_af(p->addr_type));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -694,7 +758,7 @@ kif_do_scan(struct kif_proto *p)
|
|||||||
{
|
{
|
||||||
struct proto *P = (struct proto *)p;
|
struct proto *P = (struct proto *)p;
|
||||||
if_start_update();
|
if_start_update();
|
||||||
krt_sysctl_scan(P, P->pool, &kif_buffer, &kif_buflen, NET_RT_IFLIST);
|
krt_sysctl_scan(P, P->pool, &kif_buffer, &kif_buflen, NET_RT_IFLIST, 0);
|
||||||
if_end_update();
|
if_end_update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -747,6 +811,24 @@ krt_sys_shutdown(struct krt_proto *x UNUSED, int last UNUSED)
|
|||||||
krt_buffer = NULL;
|
krt_buffer = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u32 tables;
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_sys_preconfig(struct config *c UNUSED)
|
||||||
|
{
|
||||||
|
tables = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
krt_sys_postconfig(struct krt_config *x)
|
||||||
|
{
|
||||||
|
u32 id = x->c.table->addr_type;
|
||||||
|
|
||||||
|
if (tables & (1 << id))
|
||||||
|
cf_error("Multiple kernel protocols defined for AF %d", id);
|
||||||
|
tables |= (1 << id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
kif_sys_start(struct kif_proto *p UNUSED)
|
kif_sys_start(struct kif_proto *p UNUSED)
|
||||||
|
@ -40,8 +40,6 @@ struct krt_status {
|
|||||||
static inline void krt_sys_init(struct krt_proto *p UNUSED) { }
|
static inline void krt_sys_init(struct krt_proto *p UNUSED) { }
|
||||||
static inline int krt_sys_reconfigure(struct krt_proto *p UNUSED, struct krt_config *n UNUSED, struct krt_config *o UNUSED) { return 1; }
|
static inline int krt_sys_reconfigure(struct krt_proto *p UNUSED, struct krt_config *n UNUSED, struct krt_config *o UNUSED) { return 1; }
|
||||||
|
|
||||||
static inline void krt_sys_preconfig(struct config *c UNUSED) { }
|
|
||||||
static inline void krt_sys_postconfig(struct krt_config *c UNUSED) { }
|
|
||||||
static inline void krt_sys_init_config(struct krt_config *c UNUSED) { }
|
static inline void krt_sys_init_config(struct krt_config *c UNUSED) { }
|
||||||
static inline void krt_sys_copy_config(struct krt_config *d UNUSED, struct krt_config *s UNUSED) { }
|
static inline void krt_sys_copy_config(struct krt_config *d UNUSED, struct krt_config *s UNUSED) { }
|
||||||
|
|
||||||
|
@ -9,54 +9,22 @@
|
|||||||
#ifdef __DragonFly__
|
#ifdef __DragonFly__
|
||||||
#define TCP_MD5SIG TCP_SIGNATURE_ENABLE
|
#define TCP_MD5SIG TCP_SIGNATURE_ENABLE
|
||||||
#endif
|
#endif
|
||||||
#ifdef IPV6
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
set_inaddr(struct in6_addr * ia, ip_addr a)
|
|
||||||
{
|
|
||||||
ipa_hton(a);
|
|
||||||
memcpy(ia, &a, sizeof(a));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
get_inaddr(ip_addr *a, struct in6_addr *ia)
|
|
||||||
{
|
|
||||||
memcpy(a, ia, sizeof(*a));
|
|
||||||
ipa_ntoh(*a);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline char *
|
static inline char *
|
||||||
sysio_bind_to_iface(sock *s)
|
sk_bind_to_iface(sock *s)
|
||||||
{
|
{
|
||||||
/* Unfortunately not available */
|
/* Unfortunately not available */
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <net/if_dl.h>
|
#include <net/if_dl.h>
|
||||||
|
|
||||||
static inline void
|
|
||||||
set_inaddr(struct in_addr * ia, ip_addr a)
|
|
||||||
{
|
|
||||||
ipa_hton(a);
|
|
||||||
memcpy(&ia->s_addr, &a, sizeof(a));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
get_inaddr(ip_addr *a, struct in_addr *ia)
|
|
||||||
{
|
|
||||||
memcpy(a, &ia->s_addr, sizeof(*a));
|
|
||||||
ipa_ntoh(*a);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* BSD Multicast handling for IPv4 */
|
/* BSD Multicast handling for IPv4 */
|
||||||
|
|
||||||
static inline char *
|
static inline char *
|
||||||
sysio_setup_multicast(sock *s)
|
sk_setup_multicast4(sock *s)
|
||||||
{
|
{
|
||||||
struct in_addr m;
|
struct in_addr m;
|
||||||
u8 zero = 0;
|
u8 zero = 0;
|
||||||
@ -69,7 +37,7 @@ sysio_setup_multicast(sock *s)
|
|||||||
return "IP_MULTICAST_TTL";
|
return "IP_MULTICAST_TTL";
|
||||||
|
|
||||||
/* This defines where should we send _outgoing_ multicasts */
|
/* This defines where should we send _outgoing_ multicasts */
|
||||||
set_inaddr(&m, s->iface->addr->ip);
|
ipa_put_in4(&m, s->iface->addr->ip);
|
||||||
if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_IF, &m, sizeof(m)) < 0)
|
if (setsockopt(s->fd, IPPROTO_IP, IP_MULTICAST_IF, &m, sizeof(m)) < 0)
|
||||||
return "IP_MULTICAST_IF";
|
return "IP_MULTICAST_IF";
|
||||||
|
|
||||||
@ -78,13 +46,13 @@ sysio_setup_multicast(sock *s)
|
|||||||
|
|
||||||
|
|
||||||
static inline char *
|
static inline char *
|
||||||
sysio_join_group(sock *s, ip_addr maddr)
|
sk_join_group4(sock *s, ip_addr maddr)
|
||||||
{
|
{
|
||||||
struct ip_mreq mreq;
|
struct ip_mreq mreq;
|
||||||
|
|
||||||
bzero(&mreq, sizeof(mreq));
|
bzero(&mreq, sizeof(mreq));
|
||||||
set_inaddr(&mreq.imr_interface, s->iface->addr->ip);
|
ipa_put_in4(&mreq.imr_interface, s->iface->addr->ip);
|
||||||
set_inaddr(&mreq.imr_multiaddr, maddr);
|
ipa_put_in4(&mreq.imr_multiaddr, maddr);
|
||||||
|
|
||||||
/* And this one sets interface for _receiving_ multicasts from */
|
/* And this one sets interface for _receiving_ multicasts from */
|
||||||
if (setsockopt(s->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
|
if (setsockopt(s->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
|
||||||
@ -94,13 +62,13 @@ sysio_join_group(sock *s, ip_addr maddr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline char *
|
static inline char *
|
||||||
sysio_leave_group(sock *s, ip_addr maddr)
|
sk_leave_group4(sock *s, ip_addr maddr)
|
||||||
{
|
{
|
||||||
struct ip_mreq mreq;
|
struct ip_mreq mreq;
|
||||||
|
|
||||||
bzero(&mreq, sizeof(mreq));
|
bzero(&mreq, sizeof(mreq));
|
||||||
set_inaddr(&mreq.imr_interface, s->iface->addr->ip);
|
ipa_put_in4(&mreq.imr_interface, s->iface->addr->ip);
|
||||||
set_inaddr(&mreq.imr_multiaddr, maddr);
|
ipa_put_in4(&mreq.imr_multiaddr, maddr);
|
||||||
|
|
||||||
/* And this one sets interface for _receiving_ multicasts from */
|
/* And this one sets interface for _receiving_ multicasts from */
|
||||||
if (setsockopt(s->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
|
if (setsockopt(s->fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
|
||||||
@ -117,7 +85,7 @@ sysio_leave_group(sock *s, ip_addr maddr)
|
|||||||
#define CMSG_TX_SPACE CMSG_SPACE(sizeof(struct in_addr))
|
#define CMSG_TX_SPACE CMSG_SPACE(sizeof(struct in_addr))
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
sysio_register_cmsgs(sock *s)
|
sk_request_pktinfo4(sock *s)
|
||||||
{
|
{
|
||||||
int ok = 1;
|
int ok = 1;
|
||||||
if (s->flags & SKF_LADDR_RX)
|
if (s->flags & SKF_LADDR_RX)
|
||||||
@ -133,29 +101,18 @@ sysio_register_cmsgs(sock *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sysio_process_rx_cmsgs(sock *s, struct msghdr *msg)
|
sk_process_rx_cmsg4(sock *s, struct cmsghdr *cm)
|
||||||
{
|
{
|
||||||
struct cmsghdr *cm;
|
if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVDSTADDR)
|
||||||
|
|
||||||
if (!(s->flags & SKF_LADDR_RX))
|
|
||||||
return;
|
|
||||||
|
|
||||||
s->laddr = IPA_NONE;
|
|
||||||
s->lifindex = 0;
|
|
||||||
|
|
||||||
for (cm = CMSG_FIRSTHDR(msg); cm != NULL; cm = CMSG_NXTHDR(msg, cm))
|
|
||||||
{
|
{
|
||||||
if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVDSTADDR)
|
struct in_addr *ra = (struct in_addr *) CMSG_DATA(cm);
|
||||||
{
|
s->laddr = ipa_get_in4(ra);
|
||||||
struct in_addr *ra = (struct in_addr *) CMSG_DATA(cm);
|
}
|
||||||
get_inaddr(&s->laddr, ra);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVIF)
|
if (cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVIF)
|
||||||
{
|
{
|
||||||
struct sockaddr_dl *ri = (struct sockaddr_dl *) CMSG_DATA(cm);
|
struct sockaddr_dl *ri = (struct sockaddr_dl *) CMSG_DATA(cm);
|
||||||
s->lifindex = ri->sdl_index;
|
s->lifindex = ri->sdl_index;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// log(L_WARN "RX %I %d", s->laddr, s->lifindex);
|
// log(L_WARN "RX %I %d", s->laddr, s->lifindex);
|
||||||
@ -194,8 +151,6 @@ sysio_prepare_tx_cmsgs(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#ifndef TCP_KEYLEN_MAX
|
#ifndef TCP_KEYLEN_MAX
|
||||||
@ -212,7 +167,7 @@ sysio_prepare_tx_cmsgs(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
sk_set_md5_auth_int(sock *s, sockaddr *sa, char *passwd)
|
sk_set_md5_auth_int(sock *s, struct sockaddr *sa, int sa_len, char *passwd)
|
||||||
{
|
{
|
||||||
int enable = 0;
|
int enable = 0;
|
||||||
if (passwd)
|
if (passwd)
|
||||||
@ -242,45 +197,32 @@ sk_set_md5_auth_int(sock *s, sockaddr *sa, char *passwd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef IPV6
|
|
||||||
|
|
||||||
#ifdef IP_MINTTL
|
#ifdef IP_MINTTL
|
||||||
|
|
||||||
static int
|
static inline char *
|
||||||
sk_set_min_ttl4(sock *s, int ttl)
|
sk_set_min_ttl4(sock *s, int ttl)
|
||||||
{
|
{
|
||||||
if (setsockopt(s->fd, IPPROTO_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0)
|
if (setsockopt(s->fd, IPPROTO_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0)
|
||||||
{
|
return "IP_MINTTL";
|
||||||
if (errno == ENOPROTOOPT)
|
|
||||||
log(L_ERR "Kernel does not support IPv4 TTL security");
|
|
||||||
else
|
|
||||||
log(L_ERR "sk_set_min_ttl4: setsockopt: %m");
|
|
||||||
|
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else /* no IP_MINTTL */
|
#else /* no IP_MINTTL */
|
||||||
|
|
||||||
static int
|
static inline char *
|
||||||
sk_set_min_ttl4(sock *s, int ttl)
|
sk_set_min_ttl4(sock *s, int ttl)
|
||||||
{
|
{
|
||||||
log(L_ERR "IPv4 TTL security not supported");
|
errno = ENOPROTOOPT;
|
||||||
return -1;
|
return "IP_MINTTL";
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else /* IPv6 */
|
static inline char *
|
||||||
|
|
||||||
static int
|
|
||||||
sk_set_min_ttl6(sock *s, int ttl)
|
sk_set_min_ttl6(sock *s, int ttl)
|
||||||
{
|
{
|
||||||
log(L_ERR "IPv6 TTL security not supported");
|
errno = ENOPROTOOPT;
|
||||||
return -1;
|
return "IP_MINTTL";
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
@ -220,40 +220,22 @@ sysio_prepare_tx_cmsgs(sock *s, struct msghdr *msg, void *cbuf, size_t cbuflen)
|
|||||||
#define IPV6_MINHOPCOUNT 73
|
#define IPV6_MINHOPCOUNT 73
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static inline char *
|
||||||
// XXXX
|
|
||||||
#if 0
|
|
||||||
|
|
||||||
static int
|
|
||||||
sk_set_min_ttl4(sock *s, int ttl)
|
sk_set_min_ttl4(sock *s, int ttl)
|
||||||
{
|
{
|
||||||
if (setsockopt(s->fd, IPPROTO_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0)
|
if (setsockopt(s->fd, IPPROTO_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0)
|
||||||
{
|
return "IP_MINTTL";
|
||||||
if (errno == ENOPROTOOPT)
|
|
||||||
log(L_ERR "Kernel does not support IPv4 TTL security");
|
|
||||||
else
|
|
||||||
log(L_ERR "sk_set_min_ttl4: setsockopt: %m");
|
|
||||||
|
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static inline char *
|
||||||
sk_set_min_ttl6(sock *s, int ttl)
|
sk_set_min_ttl6(sock *s, int ttl)
|
||||||
{
|
{
|
||||||
if (setsockopt(s->fd, IPPROTO_IPV6, IPV6_MINHOPCOUNT, &ttl, sizeof(ttl)) < 0)
|
if (setsockopt(s->fd, IPPROTO_IPV6, IPV6_MINHOPCOUNT, &ttl, sizeof(ttl)) < 0)
|
||||||
{
|
return "IPV6_MINHOPCOUNT";
|
||||||
if (errno == ENOPROTOOPT)
|
|
||||||
log(L_ERR "Kernel does not support IPv6 TTL security");
|
|
||||||
else
|
|
||||||
log(L_ERR "sk_set_min_ttl6: setsockopt: %m");
|
|
||||||
|
|
||||||
return -1;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -590,23 +590,29 @@ static inline int sockaddr_size(int af)
|
|||||||
static inline void
|
static inline void
|
||||||
sockaddr_fill4(struct sockaddr_in *sa, ip_addr a, struct iface *ifa, unsigned port)
|
sockaddr_fill4(struct sockaddr_in *sa, ip_addr a, struct iface *ifa, unsigned port)
|
||||||
{
|
{
|
||||||
sa->sin_port = htons(port);
|
memset(sa, 0, sizeof(struct sockaddr_in));
|
||||||
#ifdef HAVE_SIN_LEN
|
#ifdef HAVE_SIN_LEN
|
||||||
sa->sin_len = sizeof(struct sockaddr_in);
|
sa->sin_len = sizeof(struct sockaddr_in);
|
||||||
#endif
|
#endif
|
||||||
|
sa->sin_family = AF_INET;
|
||||||
|
sa->sin_port = htons(port);
|
||||||
ipa_put_in4(&sa->sin_addr, a);
|
ipa_put_in4(&sa->sin_addr, a);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
sockaddr_fill6(struct sockaddr_in6 *sa, ip_addr a, struct iface *ifa, unsigned port)
|
sockaddr_fill6(struct sockaddr_in6 *sa, ip_addr a, struct iface *ifa, unsigned port)
|
||||||
{
|
{
|
||||||
sa->sin6_port = htons(port);
|
memset(sa, 0, sizeof(struct sockaddr_in6));
|
||||||
sa->sin6_flowinfo = 0;
|
|
||||||
#ifdef SIN6_LEN
|
#ifdef SIN6_LEN
|
||||||
sa->sin6_len = sizeof(struct sockaddr_in6);
|
sa->sin6_len = sizeof(struct sockaddr_in6);
|
||||||
#endif
|
#endif
|
||||||
|
sa->sin6_family = AF_INET6;
|
||||||
|
sa->sin6_port = htons(port);
|
||||||
|
sa->sin6_flowinfo = 0;
|
||||||
ipa_put_in6(&sa->sin6_addr, a);
|
ipa_put_in6(&sa->sin6_addr, a);
|
||||||
sa->sin6_scope_id = (ifa && ipa_is_link_local(a)) ? ifa->index : 0;
|
|
||||||
|
if (ifa && ipa_is_link_local(a))
|
||||||
|
sa->sin6_scope_id = ifa->index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -852,24 +858,21 @@ sk_set_min_ttl(sock *s, int ttl)
|
|||||||
char *err;
|
char *err;
|
||||||
|
|
||||||
if (sk_is_ipv4(s))
|
if (sk_is_ipv4(s))
|
||||||
{
|
err = sk_set_min_ttl4(s, ttl);
|
||||||
if (setsockopt(s->fd, IPPROTO_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0)
|
|
||||||
ERR("IP_MINTTL");
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
err = sk_set_min_ttl6(s, ttl);
|
||||||
if (setsockopt(s->fd, IPPROTO_IPV6, IPV6_MINHOPCOUNT, &ttl, sizeof(ttl)) < 0)
|
|
||||||
ERR("IPV6_MINHOPCOUNT");
|
if (err)
|
||||||
}
|
{
|
||||||
|
if (errno == ENOPROTOOPT)
|
||||||
|
log(L_ERR "Kernel does not support %s TTL security", sk_is_ipv4(s) ? "IPv4" : "IPv6");
|
||||||
|
else
|
||||||
|
log(L_ERR "sk_set_min_ttl: %s: %m", err);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
bad:
|
|
||||||
if (errno == ENOPROTOOPT)
|
|
||||||
log(L_ERR "Kernel does not support %s TTL security", sk_is_ipv4(s) ? "IPv4" : "IPv6");
|
|
||||||
else
|
|
||||||
log(L_ERR "sk_set_min_ttl: %s: %m", err);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1062,11 +1062,6 @@ krt_postconfig(struct proto_config *C)
|
|||||||
struct proto_config *
|
struct proto_config *
|
||||||
krt_init_config(int class)
|
krt_init_config(int class)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_MULTIPLE_TABLES
|
|
||||||
if (krt_cf)
|
|
||||||
cf_error("Kernel protocol already defined");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
krt_cf = (struct krt_config *) proto_config_new(&proto_unix_kernel, sizeof(struct krt_config), class);
|
krt_cf = (struct krt_config *) proto_config_new(&proto_unix_kernel, sizeof(struct krt_config), class);
|
||||||
krt_cf->scan_time = 60;
|
krt_cf->scan_time = 60;
|
||||||
|
|
||||||
|
@ -33,10 +33,11 @@ volatile int async_config_flag;
|
|||||||
volatile int async_dump_flag;
|
volatile int async_dump_flag;
|
||||||
volatile int async_shutdown_flag;
|
volatile int async_shutdown_flag;
|
||||||
|
|
||||||
// XXXX
|
struct sockaddr;
|
||||||
#define BIRD_PF PF_INET6
|
struct iface;
|
||||||
#define BIRD_AF AF_INET6
|
|
||||||
static inline int sa_family_check(struct sockaddr *sa) { return sa->sa_family == AF_INET6; }
|
void sockaddr_fill(struct sockaddr *sa, ip_addr a, struct iface *ifa, unsigned port);
|
||||||
|
void sockaddr_read(struct sockaddr *sa, ip_addr *a, struct iface **ifa, unsigned *port, int check);
|
||||||
|
|
||||||
|
|
||||||
#ifndef SUN_LEN
|
#ifndef SUN_LEN
|
||||||
|
Loading…
Reference in New Issue
Block a user