0
0
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:
Ondrej Zajicek 2013-06-28 00:57:22 +02:00
parent 3da07ce1f0
commit 3de342dae1
9 changed files with 215 additions and 211 deletions

View File

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

View File

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

View File

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

View File

@ -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) { }

View File

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

View File

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

View File

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

View File

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

View File

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