summaryrefslogtreecommitdiff
path: root/sysdep
diff options
context:
space:
mode:
Diffstat (limited to 'sysdep')
-rw-r--r--sysdep/config.h2
-rw-r--r--sysdep/linux/krt-sys.h6
-rw-r--r--sysdep/linux/netlink.Y38
-rw-r--r--sysdep/linux/netlink.c94
-rw-r--r--sysdep/unix/config.Y26
-rw-r--r--sysdep/unix/io.c71
-rw-r--r--sysdep/unix/krt.c2
-rw-r--r--sysdep/unix/log.c64
-rw-r--r--sysdep/unix/unix.h8
9 files changed, 269 insertions, 42 deletions
diff --git a/sysdep/config.h b/sysdep/config.h
index ffab1670..54aa4021 100644
--- a/sysdep/config.h
+++ b/sysdep/config.h
@@ -13,7 +13,7 @@
#ifdef GIT_LABEL
#define BIRD_VERSION XSTR1(GIT_LABEL)
#else
-#define BIRD_VERSION "2.14"
+#define BIRD_VERSION "2.15"
#endif
/* Include parameters determined by configure script */
diff --git a/sysdep/linux/krt-sys.h b/sysdep/linux/krt-sys.h
index 8897f889..2db32ddd 100644
--- a/sysdep/linux/krt-sys.h
+++ b/sysdep/linux/krt-sys.h
@@ -39,7 +39,7 @@ static inline struct ifa * kif_get_primary_ip(struct iface *i UNUSED) { return N
#define EA_KRT_SCOPE EA_CODE(PROTOCOL_KERNEL, 0x12)
-#define KRT_METRICS_MAX 0x10 /* RTAX_QUICKACK+1 */
+#define KRT_METRICS_MAX 0x12 /* RTAX_FASTOPEN_NO_COOKIE+1 */
#define KRT_METRICS_OFFSET 0x20 /* Offset of EA_KRT_* vs RTAX_* */
#define KRT_FEATURES_MAX 4
@@ -54,7 +54,7 @@ static inline struct ifa * kif_get_primary_ip(struct iface *i UNUSED) { return N
#define EA_KRT_WINDOW EA_CODE(PROTOCOL_KERNEL, 0x23)
#define EA_KRT_RTT EA_CODE(PROTOCOL_KERNEL, 0x24)
#define EA_KRT_RTTVAR EA_CODE(PROTOCOL_KERNEL, 0x25)
-#define EA_KRT_SSTRESH EA_CODE(PROTOCOL_KERNEL, 0x26)
+#define EA_KRT_SSTHRESH EA_CODE(PROTOCOL_KERNEL, 0x26)
#define EA_KRT_CWND EA_CODE(PROTOCOL_KERNEL, 0x27)
#define EA_KRT_ADVMSS EA_CODE(PROTOCOL_KERNEL, 0x28)
#define EA_KRT_REORDERING EA_CODE(PROTOCOL_KERNEL, 0x29)
@@ -64,6 +64,8 @@ static inline struct ifa * kif_get_primary_ip(struct iface *i UNUSED) { return N
#define EA_KRT_RTO_MIN EA_CODE(PROTOCOL_KERNEL, 0x2d)
#define EA_KRT_INITRWND EA_CODE(PROTOCOL_KERNEL, 0x2e)
#define EA_KRT_QUICKACK EA_CODE(PROTOCOL_KERNEL, 0x2f)
+#define EA_KRT_CONGCTL EA_CODE(PROTOCOL_KERNEL, 0x30)
+#define EA_KRT_FASTOPEN_NO_COOKIE EA_CODE(PROTOCOL_KERNEL, 0x31)
struct krt_params {
diff --git a/sysdep/linux/netlink.Y b/sysdep/linux/netlink.Y
index 487ad1d8..9c820da9 100644
--- a/sysdep/linux/netlink.Y
+++ b/sysdep/linux/netlink.Y
@@ -12,11 +12,19 @@ CF_DECLS
CF_KEYWORDS(KERNEL, TABLE, METRIC, NETLINK, RX, BUFFER,
KRT_PREFSRC, KRT_REALM, KRT_SCOPE, KRT_MTU, KRT_WINDOW,
- KRT_RTT, KRT_RTTVAR, KRT_SSTRESH, KRT_CWND, KRT_ADVMSS, KRT_REORDERING,
+ KRT_RTT, KRT_RTTVAR, KRT_SSTHRESH, KRT_CWND, KRT_ADVMSS, KRT_REORDERING,
KRT_HOPLIMIT, KRT_INITCWND, KRT_RTO_MIN, KRT_INITRWND, KRT_QUICKACK,
- KRT_LOCK_MTU, KRT_LOCK_WINDOW, KRT_LOCK_RTT, KRT_LOCK_RTTVAR,
- KRT_LOCK_SSTRESH, KRT_LOCK_CWND, KRT_LOCK_ADVMSS, KRT_LOCK_REORDERING,
- KRT_LOCK_HOPLIMIT, KRT_LOCK_RTO_MIN, KRT_FEATURE_ECN, KRT_FEATURE_ALLFRAG)
+ KRT_CONGCTL, KRT_FASTOPEN_NO_COOKIE)
+
+CF_KEYWORDS(KRT_LOCK_MTU, KRT_LOCK_WINDOW, KRT_LOCK_RTT, KRT_LOCK_RTTVAR,
+ KRT_LOCK_SSTHRESH, KRT_LOCK_CWND, KRT_LOCK_ADVMSS, KRT_LOCK_REORDERING,
+ KRT_LOCK_HOPLIMIT, KRT_LOCK_INITCWND, KRT_LOCK_RTO_MIN, KRT_LOCK_INITRWND,
+ KRT_LOCK_QUICKACK, KRT_LOCK_CONGCTL, KRT_LOCK_FASTOPEN_NO_COOKIE,
+ KRT_FEATURE_ECN, KRT_FEATURE_ALLFRAG)
+
+/* Deprecated names for backward compatiblity */
+CF_KEYWORDS(KRT_SSTRESH, KRT_LOCK_SSTRESH)
+
CF_GRAMMAR
@@ -36,7 +44,9 @@ dynamic_attr: KRT_MTU { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_MTU
dynamic_attr: KRT_WINDOW { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_WINDOW); } ;
dynamic_attr: KRT_RTT { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_RTT); } ;
dynamic_attr: KRT_RTTVAR { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_RTTVAR); } ;
-dynamic_attr: KRT_SSTRESH { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_SSTRESH); } ;
+dynamic_attr: KRT_SSTHRESH { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_SSTHRESH); } ;
+dynamic_attr: KRT_SSTRESH { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_SSTHRESH);
+ cf_warn("Attribute krt_sstresh is deprecated (typo), use krt_ssthresh"); } ;
dynamic_attr: KRT_CWND { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_CWND); } ;
dynamic_attr: KRT_ADVMSS { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_ADVMSS); } ;
dynamic_attr: KRT_REORDERING { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_REORDERING); } ;
@@ -45,6 +55,8 @@ dynamic_attr: KRT_INITCWND { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT
dynamic_attr: KRT_RTO_MIN { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_RTO_MIN); } ;
dynamic_attr: KRT_INITRWND { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_INITRWND); } ;
dynamic_attr: KRT_QUICKACK { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_QUICKACK); } ;
+dynamic_attr: KRT_CONGCTL { $$ = f_new_dynamic_attr(EAF_TYPE_STRING, T_STRING, EA_KRT_CONGCTL); } ;
+dynamic_attr: KRT_FASTOPEN_NO_COOKIE { $$ = f_new_dynamic_attr(EAF_TYPE_INT, T_INT, EA_KRT_FASTOPEN_NO_COOKIE); } ;
/* Bits of EA_KRT_LOCK, based on RTAX_* constants */
@@ -52,15 +64,23 @@ dynamic_attr: KRT_LOCK_MTU { $$ = f_new_dynamic_attr_bit(2, T_BOOL, EA_KRT_LOCK)
dynamic_attr: KRT_LOCK_WINDOW { $$ = f_new_dynamic_attr_bit(3, T_BOOL, EA_KRT_LOCK); } ;
dynamic_attr: KRT_LOCK_RTT { $$ = f_new_dynamic_attr_bit(4, T_BOOL, EA_KRT_LOCK); } ;
dynamic_attr: KRT_LOCK_RTTVAR { $$ = f_new_dynamic_attr_bit(5, T_BOOL, EA_KRT_LOCK); } ;
-dynamic_attr: KRT_LOCK_SSTRESH { $$ = f_new_dynamic_attr_bit(6, T_BOOL, EA_KRT_LOCK); } ;
+dynamic_attr: KRT_LOCK_SSTHRESH { $$ = f_new_dynamic_attr_bit(6, T_BOOL, EA_KRT_LOCK); } ;
+dynamic_attr: KRT_LOCK_SSTRESH { $$ = f_new_dynamic_attr_bit(6, T_BOOL, EA_KRT_LOCK);
+ cf_warn("Attribute krt_lock_sstresh is deprecated (typo), use krt_lock_ssthresh"); } ;
dynamic_attr: KRT_LOCK_CWND { $$ = f_new_dynamic_attr_bit(7, T_BOOL, EA_KRT_LOCK); } ;
dynamic_attr: KRT_LOCK_ADVMSS { $$ = f_new_dynamic_attr_bit(8, T_BOOL, EA_KRT_LOCK); } ;
dynamic_attr: KRT_LOCK_REORDERING { $$ = f_new_dynamic_attr_bit(9, T_BOOL, EA_KRT_LOCK); } ;
-dynamic_attr: KRT_LOCK_HOPLIMIT { $$ = f_new_dynamic_attr_bit(10, T_BOOL, EA_KRT_LOCK); } ;
-dynamic_attr: KRT_LOCK_RTO_MIN { $$ = f_new_dynamic_attr_bit(13, T_BOOL, EA_KRT_LOCK); } ;
+dynamic_attr: KRT_LOCK_HOPLIMIT { $$ = f_new_dynamic_attr_bit(10, T_BOOL, EA_KRT_LOCK); } ;
+dynamic_attr: KRT_LOCK_INITCWND { $$ = f_new_dynamic_attr_bit(11, T_BOOL, EA_KRT_LOCK); } ;
+/* No lock for FEATURES bitfield */
+dynamic_attr: KRT_LOCK_RTO_MIN { $$ = f_new_dynamic_attr_bit(13, T_BOOL, EA_KRT_LOCK); } ;
+dynamic_attr: KRT_LOCK_INITRWND { $$ = f_new_dynamic_attr_bit(14, T_BOOL, EA_KRT_LOCK); } ;
+dynamic_attr: KRT_LOCK_QUICKACK { $$ = f_new_dynamic_attr_bit(15, T_BOOL, EA_KRT_LOCK); } ;
+dynamic_attr: KRT_LOCK_CONGCTL { $$ = f_new_dynamic_attr_bit(16, T_BOOL, EA_KRT_LOCK); } ;
+dynamic_attr: KRT_LOCK_FASTOPEN_NO_COOKIE { $$ = f_new_dynamic_attr_bit(17, T_BOOL, EA_KRT_LOCK); } ;
dynamic_attr: KRT_FEATURE_ECN { $$ = f_new_dynamic_attr_bit(0, T_BOOL, EA_KRT_FEATURES); } ;
-dynamic_attr: KRT_FEATURE_ALLFRAG { $$ = f_new_dynamic_attr(3, T_BOOL, EA_KRT_FEATURES); } ;
+dynamic_attr: KRT_FEATURE_ALLFRAG { $$ = f_new_dynamic_attr_bit(3, T_BOOL, EA_KRT_FEATURES); } ;
CF_CODE
diff --git a/sysdep/linux/netlink.c b/sysdep/linux/netlink.c
index 29446cab..6b4fc80c 100644
--- a/sysdep/linux/netlink.c
+++ b/sysdep/linux/netlink.c
@@ -479,6 +479,9 @@ static inline u16 rta_get_u16(struct rtattr *a)
static inline u32 rta_get_u32(struct rtattr *a)
{ return *(u32 *) RTA_DATA(a); }
+static inline const char *rta_get_str(struct rtattr *a)
+{ return RTA_DATA(a); }
+
static inline ip4_addr rta_get_ip4(struct rtattr *a)
{ return ip4_ntoh(*(ip4_addr *) RTA_DATA(a)); }
@@ -570,6 +573,12 @@ nl_add_attr_u32(struct nlmsghdr *h, uint bufsize, int code, u32 data)
}
static inline void
+nl_add_attr_str(struct nlmsghdr *h, unsigned bufsize, int code, const char *str)
+{
+ nl_add_attr(h, bufsize, code, str, strlen(str) + 1);
+}
+
+static inline void
nl_add_attr_ip4(struct nlmsghdr *h, uint bufsize, int code, ip4_addr ip4)
{
ip4 = ip4_hton(ip4);
@@ -822,21 +831,26 @@ err:
return NULL;
}
+STATIC_ASSERT(EA_KRT_METRICS + RTAX_CC_ALGO == EA_KRT_CONGCTL);
+
static void
-nl_add_metrics(struct nlmsghdr *h, uint bufsize, u32 *metrics, int max)
+nl_add_metrics(struct nlmsghdr *h, uint bufsize, u32 *metrics, const char *cc_algo, int max)
{
struct rtattr *a = nl_open_attr(h, bufsize, RTA_METRICS);
int t;
for (t = 1; t < max; t++)
if (metrics[0] & (1 << t))
- nl_add_attr_u32(h, bufsize, t, metrics[t]);
+ if (t == RTAX_CC_ALGO)
+ nl_add_attr_str(h, bufsize, t, cc_algo);
+ else
+ nl_add_attr_u32(h, bufsize, t, metrics[t]);
nl_close_attr(h, a);
}
static int
-nl_parse_metrics(struct rtattr *hdr, u32 *metrics, int max)
+nl_parse_metrics(struct rtattr *hdr, u32 *metrics, const char **cc_algo, int max)
{
struct rtattr *a = RTA_DATA(hdr);
int len = RTA_PAYLOAD(hdr);
@@ -844,17 +858,31 @@ nl_parse_metrics(struct rtattr *hdr, u32 *metrics, int max)
metrics[0] = 0;
for (; RTA_OK(a, len); a = RTA_NEXT(a, len))
{
- if (a->rta_type == RTA_UNSPEC)
+ if (a->rta_type == RTAX_UNSPEC)
continue;
if (a->rta_type >= max)
continue;
- if (RTA_PAYLOAD(a) != 4)
- return -1;
+ if (a->rta_type == RTAX_CC_ALGO)
+ {
+ *cc_algo = rta_get_str(a);
+ int slen = RTA_PAYLOAD(a);
+
+ if (!slen || ((*cc_algo)[slen - 1] != 0))
+ return -1;
- metrics[0] |= 1 << a->rta_type;
- metrics[a->rta_type] = rta_get_u32(a);
+ metrics[0] |= 1 << a->rta_type;
+ metrics[a->rta_type] = 0;
+ }
+ else
+ {
+ if (RTA_PAYLOAD(a) != 4)
+ return -1;
+
+ metrics[0] |= 1 << a->rta_type;
+ metrics[a->rta_type] = rta_get_u32(a);
+ }
}
if (len > 0)
@@ -1382,6 +1410,7 @@ nl_send_route(struct krt_proto *p, rte *e, int op)
u32 metrics[KRT_METRICS_MAX];
+ const char *cc_algo = NULL;
metrics[0] = 0;
struct ea_walk_state ews = { .eattrs = eattrs };
@@ -1389,11 +1418,15 @@ nl_send_route(struct krt_proto *p, rte *e, int op)
{
int id = ea->id - EA_KRT_METRICS;
metrics[0] |= 1 << id;
- metrics[id] = ea->u.data;
+
+ if (id == RTAX_CC_ALGO)
+ cc_algo = ea->u.ptr->data;
+ else
+ metrics[id] = ea->u.data;
}
if (metrics[0])
- nl_add_metrics(&r->h, rsize, metrics, KRT_METRICS_MAX);
+ nl_add_metrics(&r->h, rsize, metrics, cc_algo, KRT_METRICS_MAX);
switch (a->dest)
{
@@ -1795,10 +1828,11 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
if (a[RTA_METRICS])
{
u32 metrics[KRT_METRICS_MAX];
+ const char *cc_algo = NULL;
ea_list *ea = lp_alloc(s->pool, sizeof(ea_list) + KRT_METRICS_MAX * sizeof(eattr));
int t, n = 0;
- if (nl_parse_metrics(a[RTA_METRICS], metrics, ARRAY_SIZE(metrics)) < 0)
+ if (nl_parse_metrics(a[RTA_METRICS], metrics, &cc_algo, ARRAY_SIZE(metrics)) < 0)
{
log(L_ERR "KRT: Received route %N with strange RTA_METRICS attribute", net->n.addr);
return;
@@ -1806,12 +1840,33 @@ nl_parse_route(struct nl_parse_state *s, struct nlmsghdr *h)
for (t = 1; t < KRT_METRICS_MAX; t++)
if (metrics[0] & (1 << t))
- ea->attrs[n++] = (eattr) {
- .id = EA_CODE(PROTOCOL_KERNEL, KRT_METRICS_OFFSET + t),
- .flags = 0,
- .type = EAF_TYPE_INT, /* FIXME: Some are EAF_TYPE_BITFIELD */
- .u.data = metrics[t],
- };
+ if ((t == RTAX_LOCK) || (t == RTAX_FEATURES))
+ {
+ ea->attrs[n++] = (eattr) {
+ .id = EA_KRT_METRICS + t,
+ .type = EAF_TYPE_BITFIELD,
+ .u.data = metrics[t],
+ };
+ }
+ else if (t == RTAX_CC_ALGO)
+ {
+ struct adata *ad = lp_alloc_adata(s->pool, strlen(cc_algo));
+ memcpy(ad->data, cc_algo, ad->length);
+
+ ea->attrs[n++] = (eattr) {
+ .id = EA_KRT_CONGCTL,
+ .type = EAF_TYPE_STRING,
+ .u.ptr = ad,
+ };
+ }
+ else
+ {
+ ea->attrs[n++] = (eattr) {
+ .id = EA_KRT_METRICS + t,
+ .type = EAF_TYPE_INT,
+ .u.data = metrics[t],
+ };
+ }
if (n > 0)
{
@@ -2093,8 +2148,9 @@ krt_sys_copy_config(struct krt_config *d, struct krt_config *s)
}
static const char *krt_metrics_names[KRT_METRICS_MAX] = {
- NULL, "lock", "mtu", "window", "rtt", "rttvar", "sstresh", "cwnd", "advmss",
- "reordering", "hoplimit", "initcwnd", "features", "rto_min", "initrwnd", "quickack"
+ NULL, "lock", "mtu", "window", "rtt", "rttvar", "ssthresh", "cwnd", "advmss",
+ "reordering", "hoplimit", "initcwnd", "features", "rto_min", "initrwnd", "quickack",
+ "congctl", "fastopen_no_cookie"
};
static const char *krt_features_names[KRT_FEATURES_MAX] = {
diff --git a/sysdep/unix/config.Y b/sysdep/unix/config.Y
index fce64794..8de79600 100644
--- a/sysdep/unix/config.Y
+++ b/sysdep/unix/config.Y
@@ -17,9 +17,9 @@ static struct log_config *this_log;
CF_DECLS
-CF_KEYWORDS(LOG, SYSLOG, ALL, DEBUG, TRACE, INFO, REMOTE, WARNING, ERROR, AUTH, FATAL, BUG, STDERR, SOFT)
-CF_KEYWORDS(NAME, CONFIRM, UNDO, CHECK, TIMEOUT, DEBUG, LATENCY, LIMIT, WATCHDOG, WARNING, STATUS)
-CF_KEYWORDS(GRACEFUL, RESTART, THREADS)
+CF_KEYWORDS(LOG, SYSLOG, NAME, STDERR, UDP, PORT)
+CF_KEYWORDS(ALL, DEBUG, TRACE, INFO, REMOTE, WARNING, ERROR, AUTH, FATAL, BUG)
+CF_KEYWORDS(DEBUG, LATENCY, LIMIT, WATCHDOG, WARNING, TIMEOUT, THREADS)
%type <i> log_mask log_mask_list log_cat cfg_timeout
%type <t> cfg_name
@@ -64,8 +64,28 @@ log_file:
}
| SYSLOG syslog_name { this_log->fh = NULL; new_config->syslog_name = $2; }
| STDERR { this_log->fh = stderr; }
+ | UDP log_udp_host log_udp_port {
+ this_log->udp_flag = 1;
+
+ if (!parse_and_exit)
+ log_open_udp(this_log, new_config->pool);
+ }
;
+log_udp_host: text_or_ipa
+{
+ if ($1.type == T_STRING)
+ this_log->host = $1.val.s;
+ else if ($1.type == T_IP)
+ this_log->ip = $1.val.ip;
+ else bug("Bad text_or_ipa");
+};
+
+log_udp_port:
+ /* empty */ { this_log->port = 514; }
+ | PORT NUM { check_u16($2); this_log->port = $2; }
+ ;
+
log_mask:
ALL { $$ = ~0; }
| '{' log_mask_list '}' { $$ = $2; }
diff --git a/sysdep/unix/io.c b/sysdep/unix/io.c
index 4b3eef48..9b499020 100644
--- a/sysdep/unix/io.c
+++ b/sysdep/unix/io.c
@@ -30,6 +30,7 @@
#include <netinet/tcp.h>
#include <netinet/udp.h>
#include <netinet/icmp6.h>
+#include <netdb.h>
#include "nest/bird.h"
#include "lib/lists.h"
@@ -94,12 +95,25 @@ struct rfile *
rf_open(pool *p, const char *name, const char *mode)
{
FILE *f = fopen(name, mode);
+ if (!f)
+ return NULL;
+
+ struct rfile *r = ralloc(p, &rf_class);
+ r->f = f;
+ return r;
+}
+
+struct rfile *
+rf_fdopen(pool *p, int fd, const char *mode)
+{
+ FILE *f = fdopen(fd, mode);
if (!f)
return NULL;
struct rfile *r = ralloc(p, &rf_class);
r->f = f;
+
return r;
}
@@ -1048,6 +1062,14 @@ sk_insert(sock *s)
add_tail(&sock_list, &s->n);
}
+static int
+sk_connect(sock *s)
+{
+ sockaddr sa;
+ sockaddr_fill(&sa, s->af, s->daddr, s->iface, s->dport);
+ return connect(s->fd, &sa.sa, SA_LEN(sa));
+}
+
static void
sk_tcp_connected(sock *s)
{
@@ -1465,8 +1487,7 @@ sk_open(sock *s)
switch (s->type)
{
case SK_TCP_ACTIVE:
- sockaddr_fill(&sa, s->af, s->daddr, s->iface, s->dport);
- if (connect(fd, &sa.sa, SA_LEN(sa)) >= 0)
+ if (sk_connect(s) >= 0)
sk_tcp_connected(s);
else if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS &&
errno != ECONNREFUSED && errno != EHOSTUNREACH && errno != ENETUNREACH)
@@ -1478,6 +1499,14 @@ sk_open(sock *s)
ERR2("listen");
break;
+ case SK_UDP:
+ if (s->flags & SKF_CONNECT)
+ if (sk_connect(s) < 0)
+ ERR2("connect");
+
+ sk_alloc_bufs(s);
+ break;
+
case SK_SSH_ACTIVE:
case SK_MAGIC:
break;
@@ -1945,10 +1974,7 @@ sk_write_noflush(sock *s)
{
case SK_TCP_ACTIVE:
{
- sockaddr sa;
- sockaddr_fill(&sa, s->af, s->daddr, s->iface, s->dport);
-
- if (connect(s->fd, &sa.sa, SA_LEN(sa)) >= 0 || errno == EISCONN)
+ if (sk_connect(s) >= 0 || errno == EISCONN)
sk_tcp_connected(s);
else if (errno != EINTR && errno != EAGAIN && errno != EINPROGRESS)
s->err_hook(s, errno);
@@ -2418,3 +2444,36 @@ test_old_bird(char *path)
die("I found another BIRD running.");
close(fd);
}
+
+
+/*
+ * DNS resolver
+ */
+
+ip_addr
+resolve_hostname(const char *host, int type, const char **err_msg)
+{
+ struct addrinfo *res;
+ struct addrinfo hints = {
+ .ai_family = AF_UNSPEC,
+ .ai_socktype = (type == SK_UDP) ? SOCK_DGRAM : SOCK_STREAM,
+ .ai_flags = AI_ADDRCONFIG,
+ };
+
+ *err_msg = NULL;
+
+ int err_code = getaddrinfo(host, NULL, &hints, &res);
+ if (err_code != 0)
+ {
+ *err_msg = gai_strerror(err_code);
+ return IPA_NONE;
+ }
+
+ ip_addr addr = IPA_NONE;
+ uint unused;
+
+ sockaddr_read((sockaddr *) res->ai_addr, res->ai_family, &addr, NULL, &unused);
+ freeaddrinfo(res);
+
+ return addr;
+}
diff --git a/sysdep/unix/krt.c b/sysdep/unix/krt.c
index 3a4b24dc..7a078fb9 100644
--- a/sysdep/unix/krt.c
+++ b/sysdep/unix/krt.c
@@ -619,7 +619,7 @@ krt_same_dest(rte *k, rte *e)
return 0;
if (ka->dest == RTD_UNICAST)
- return nexthop_same(&(ka->nh), &(ea->nh));
+ return nexthop_equal(&(ka->nh), &(ea->nh));
return 1;
}
diff --git a/sysdep/unix/log.c b/sysdep/unix/log.c
index 53122aee..613a6aa5 100644
--- a/sysdep/unix/log.c
+++ b/sysdep/unix/log.c
@@ -29,6 +29,7 @@
#include "conf/conf.h"
#include "lib/string.h"
#include "lib/lists.h"
+#include "lib/socket.h"
#include "sysdep/unix/unix.h"
static int dbg_fd = -1;
@@ -138,6 +139,55 @@ log_rotate(struct log_config *l)
return log_open(l);
}
+/* Expected to be called during config parsing */
+int
+log_open_udp(struct log_config *l, pool *p)
+{
+ ASSERT(l->host || ipa_nonzero(l->ip));
+
+ if (l->host && ipa_zero(l->ip))
+ {
+ const char *err_msg;
+ l->ip = resolve_hostname(l->host, SK_UDP, &err_msg);
+
+ if (ipa_zero(l->ip))
+ {
+ cf_warn("Cannot resolve hostname '%s': %s", l->host, err_msg);
+ goto err0;
+ }
+ }
+
+ sock *sk = sk_new(p);
+ sk->type = SK_UDP;
+ sk->daddr = l->ip;
+ sk->dport = l->port;
+ sk->flags = SKF_CONNECT | SKF_THREAD;
+
+ if (sk_open(sk) < 0)
+ {
+ cf_warn("Cannot open UDP log socket: %s%#m", sk->err);
+ goto err1;
+ }
+
+ /* Move fd from sk resource to rf resource */
+ l->rf = rf_fdopen(p, sk->fd, "a");
+ if (!l->rf)
+ goto err1;
+
+ l->fh = rf_file(l->rf);
+
+ sk->fd = -1;
+ rfree(sk);
+
+ return 0;
+
+err1:
+ rfree(sk);
+err0:
+ l->mask = 0;
+ return -1;
+}
+
/**
* log_commit - commit a log message
* @class: message class information (%L_DEBUG to %L_BUG, see |lib/birdlib.h|)
@@ -168,6 +218,18 @@ log_commit(int class, buffer *buf)
{
if (l->terminal_flag)
fputs("bird: ", l->fh);
+ else if (l->udp_flag)
+ {
+ int pri = LOG_DAEMON | syslog_priorities[class];
+ char tbuf[TM_DATETIME_BUFFER_SIZE];
+ const char *hostname = (config && config->hostname) ? config->hostname : "<none>";
+ const char *fmt = "%b %d %T.%6f";
+ if (!tm_format_real_time(tbuf, sizeof(tbuf), fmt, current_real_time()))
+ strcpy(tbuf, "<error>");
+
+ /* Legacy RFC 3164 format, but with us precision */
+ fprintf(l->fh, "<%d>%s %s %s: ", pri, tbuf, hostname, bird_name);
+ }
else
{
byte tbuf[TM_DATETIME_BUFFER_SIZE];
@@ -400,7 +462,7 @@ log_switch(int initial, list *logs, const char *new_syslog_name)
/* Close the logs to avoid pinning them on disk when deleted */
if (current_log_list)
WALK_LIST(l, *current_log_list)
- if (l->rf)
+ if (l->filename && l->rf)
log_close(l);
/* Reopen the logs, needed for 'configure undo' */
diff --git a/sysdep/unix/unix.h b/sysdep/unix/unix.h
index ad85d1ea..c1d966f9 100644
--- a/sysdep/unix/unix.h
+++ b/sysdep/unix/unix.h
@@ -109,9 +109,11 @@ void io_loop(void);
void io_log_dump(void);
int sk_open_unix(struct birdsock *s, char *name);
struct rfile *rf_open(struct pool *, const char *name, const char *mode);
+struct rfile *rf_fdopen(pool *p, int fd, const char *mode);
void *rf_file(struct rfile *f);
int rf_fileno(struct rfile *f);
void test_old_bird(char *path);
+ip_addr resolve_hostname(const char *host, int type, const char **err_msg);
/* krt.c bits */
@@ -133,6 +135,12 @@ struct log_config {
off_t pos; /* Position/size of current log */
off_t limit; /* Log size limit */
int terminal_flag;
+ int udp_flag;
+ const char *host; /* UDP log dst host name */
+ ip_addr ip; /* UDP log dst IP address */
+ uint port; /* UDP log dst port */
};
+int log_open_udp(struct log_config *l, pool *p);
+
#endif