diff options
Diffstat (limited to 'sysdep')
-rw-r--r-- | sysdep/config.h | 2 | ||||
-rw-r--r-- | sysdep/linux/krt-sys.h | 6 | ||||
-rw-r--r-- | sysdep/linux/netlink.Y | 38 | ||||
-rw-r--r-- | sysdep/linux/netlink.c | 94 | ||||
-rw-r--r-- | sysdep/unix/config.Y | 26 | ||||
-rw-r--r-- | sysdep/unix/io.c | 71 | ||||
-rw-r--r-- | sysdep/unix/krt.c | 2 | ||||
-rw-r--r-- | sysdep/unix/log.c | 64 | ||||
-rw-r--r-- | sysdep/unix/unix.h | 8 |
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 |