sync with OpenBSD -current

This commit is contained in:
purplerain 2024-01-11 02:33:10 +00:00
parent 46994dfb53
commit caf62be22c
Signed by: purplerain
GPG key ID: F42C07F07E2E35B7
18 changed files with 499 additions and 445 deletions

View file

@ -1,4 +1,4 @@
/* $OpenBSD: err_prn.c,v 1.20 2023/07/07 13:54:45 beck Exp $ */
/* $OpenBSD: err_prn.c,v 1.22 2024/01/10 14:23:37 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@ -56,6 +56,7 @@
* [including the GNU Public Licence.]
*/
#include <limits.h>
#include <stdio.h>
#include <string.h>
@ -93,12 +94,9 @@ LCRYPTO_ALIAS(ERR_print_errors_cb);
static int
print_fp(const char *str, size_t len, void *fp)
{
BIO bio;
BIO_set(&bio, BIO_s_file());
BIO_set_fp(&bio, fp, BIO_NOCLOSE);
return BIO_printf(&bio, "%s", str);
if (len > INT_MAX)
return -1;
return fprintf(fp, "%.*s", (int)len, str);
}
void
@ -111,7 +109,7 @@ LCRYPTO_ALIAS(ERR_print_errors_fp);
static int
print_bio(const char *str, size_t len, void *bp)
{
return BIO_write((BIO *)bp, str, len);
return BIO_write(bp, str, len);
}
void

View file

@ -1,4 +1,4 @@
/* $OpenBSD: rsa_ameth.c,v 1.56 2024/01/04 17:01:26 tb Exp $ */
/* $OpenBSD: rsa_ameth.c,v 1.57 2024/01/10 14:59:19 tb Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2006.
*/
@ -74,10 +74,6 @@
#include "rsa_local.h"
#include "x509_local.h"
/* Macros to test if a pkey or ctx is for a PSS key */
#define pkey_is_pss(pkey) (pkey->ameth->pkey_id == EVP_PKEY_RSA_PSS)
#define pkey_ctx_is_pss(ctx) (ctx->pmeth->pkey_id == EVP_PKEY_RSA_PSS)
#ifndef OPENSSL_NO_CMS
static int rsa_cms_sign(CMS_SignerInfo *si);
static int rsa_cms_verify(CMS_SignerInfo *si);
@ -453,7 +449,8 @@ pkey_rsa_print(BIO *bp, const EVP_PKEY *pkey, int off, int priv)
if (!BIO_indent(bp, off, 128))
goto err;
if (BIO_printf(bp, "%s ", pkey_is_pss(pkey) ? "RSA-PSS" : "RSA") <= 0)
if (BIO_printf(bp, "%s ",
pkey->ameth->pkey_id == EVP_PKEY_RSA_PSS ? "RSA-PSS" : "RSA") <= 0)
goto err;
if (priv && x->d != NULL) {
@ -485,7 +482,8 @@ pkey_rsa_print(BIO *bp, const EVP_PKEY *pkey, int off, int priv)
if (!bn_printf(bp, x->iqmp, off, "coefficient:"))
goto err;
}
if (pkey_is_pss(pkey) && !rsa_pss_param_print(bp, 1, x->pss, off))
if (pkey->ameth->pkey_id == EVP_PKEY_RSA_PSS &&
!rsa_pss_param_print(bp, 1, x->pss, off))
goto err;
ret = 1;
err:
@ -539,7 +537,7 @@ rsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
break;
case ASN1_PKEY_CTRL_PKCS7_ENCRYPT:
if (pkey_is_pss(pkey))
if (pkey->ameth->pkey_id == EVP_PKEY_RSA_PSS)
return -2;
if (arg1 == 0)
PKCS7_RECIP_INFO_get0_alg(arg2, &alg);
@ -553,7 +551,7 @@ rsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
break;
case ASN1_PKEY_CTRL_CMS_ENVELOPE:
if (pkey_is_pss(pkey))
if (pkey->ameth->pkey_id == EVP_PKEY_RSA_PSS)
return -2;
if (arg1 == 0)
return rsa_cms_encrypt(arg2);
@ -562,7 +560,7 @@ rsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
break;
case ASN1_PKEY_CTRL_CMS_RI_TYPE:
if (pkey_is_pss(pkey))
if (pkey->ameth->pkey_id == EVP_PKEY_RSA_PSS)
return -2;
*(int *)arg2 = CMS_RECIPINFO_TRANS;
return 1;
@ -852,7 +850,7 @@ rsa_cms_verify(CMS_SignerInfo *si)
if (nid == EVP_PKEY_RSA_PSS)
return rsa_pss_to_ctx(NULL, pkey_ctx, alg, NULL);
/* Only PSS allowed for PSS keys */
if (pkey_ctx_is_pss(pkey_ctx)) {
if (pkey_ctx->pmeth->pkey_id == EVP_PKEY_RSA_PSS) {
RSAerror(RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
return 0;
}

View file

@ -1,4 +1,4 @@
/* $OpenBSD: x509_trs.c,v 1.35 2024/01/08 03:32:01 tb Exp $ */
/* $OpenBSD: x509_trs.c,v 1.39 2024/01/10 21:34:53 tb Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 1999.
*/
@ -57,19 +57,72 @@
*/
#include <stdio.h>
#include <string.h>
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include "x509_local.h"
static int trust_1oidany(X509_TRUST *trust, X509 *x, int flags);
static int trust_1oid(X509_TRUST *trust, X509 *x, int flags);
static int trust_compat(X509_TRUST *trust, X509 *x, int flags);
static int
obj_trust(int id, X509 *x, int flags)
{
ASN1_OBJECT *obj;
int i, nid;
X509_CERT_AUX *ax;
static int obj_trust(int id, X509 *x, int flags);
static int (*default_trust)(int id, X509 *x, int flags) = obj_trust;
ax = x->aux;
if (!ax)
return X509_TRUST_UNTRUSTED;
if (ax->reject) {
for (i = 0; i < sk_ASN1_OBJECT_num(ax->reject); i++) {
obj = sk_ASN1_OBJECT_value(ax->reject, i);
nid = OBJ_obj2nid(obj);
if (nid == id || nid == NID_anyExtendedKeyUsage)
return X509_TRUST_REJECTED;
}
}
if (ax->trust) {
for (i = 0; i < sk_ASN1_OBJECT_num(ax->trust); i++) {
obj = sk_ASN1_OBJECT_value(ax->trust, i);
nid = OBJ_obj2nid(obj);
if (nid == id || nid == NID_anyExtendedKeyUsage)
return X509_TRUST_TRUSTED;
}
}
return X509_TRUST_UNTRUSTED;
}
static int
trust_compat(X509_TRUST *trust, X509 *x, int flags)
{
X509_check_purpose(x, -1, 0);
if (x->ex_flags & EXFLAG_SS)
return X509_TRUST_TRUSTED;
else
return X509_TRUST_UNTRUSTED;
}
static int
trust_1oidany(X509_TRUST *trust, X509 *x, int flags)
{
if (x->aux && (x->aux->trust || x->aux->reject))
return obj_trust(trust->arg1, x, flags);
/* we don't have any trust settings: for compatibility
* we return trusted if it is self signed
*/
return trust_compat(trust, x, flags);
}
static int
trust_1oid(X509_TRUST *trust, X509 *x, int flags)
{
if (x->aux)
return obj_trust(trust->arg1, x, flags);
return X509_TRUST_UNTRUSTED;
}
/* WARNING: the following table should be kept in order of trust
* and without any gaps so we can just subtract the minimum trust
@ -128,6 +181,8 @@ static X509_TRUST trstandard[] = {
#define X509_TRUST_COUNT (sizeof(trstandard) / sizeof(trstandard[0]))
static int (*default_trust)(int id, X509 *x, int flags) = obj_trust;
int
(*X509_TRUST_set_default(int (*trust)(int , X509 *, int)))(int, X509 *, int)
{
@ -249,61 +304,3 @@ X509_TRUST_get_trust(const X509_TRUST *xp)
return xp->trust;
}
LCRYPTO_ALIAS(X509_TRUST_get_trust);
static int
trust_1oidany(X509_TRUST *trust, X509 *x, int flags)
{
if (x->aux && (x->aux->trust || x->aux->reject))
return obj_trust(trust->arg1, x, flags);
/* we don't have any trust settings: for compatibility
* we return trusted if it is self signed
*/
return trust_compat(trust, x, flags);
}
static int
trust_1oid(X509_TRUST *trust, X509 *x, int flags)
{
if (x->aux)
return obj_trust(trust->arg1, x, flags);
return X509_TRUST_UNTRUSTED;
}
static int
trust_compat(X509_TRUST *trust, X509 *x, int flags)
{
X509_check_purpose(x, -1, 0);
if (x->ex_flags & EXFLAG_SS)
return X509_TRUST_TRUSTED;
else
return X509_TRUST_UNTRUSTED;
}
static int
obj_trust(int id, X509 *x, int flags)
{
ASN1_OBJECT *obj;
int i, nid;
X509_CERT_AUX *ax;
ax = x->aux;
if (!ax)
return X509_TRUST_UNTRUSTED;
if (ax->reject) {
for (i = 0; i < sk_ASN1_OBJECT_num(ax->reject); i++) {
obj = sk_ASN1_OBJECT_value(ax->reject, i);
nid = OBJ_obj2nid(obj);
if (nid == id || nid == NID_anyExtendedKeyUsage)
return X509_TRUST_REJECTED;
}
}
if (ax->trust) {
for (i = 0; i < sk_ASN1_OBJECT_num(ax->trust); i++) {
obj = sk_ASN1_OBJECT_value(ax->trust, i);
nid = OBJ_obj2nid(obj);
if (nid == id || nid == NID_anyExtendedKeyUsage)
return X509_TRUST_TRUSTED;
}
}
return X509_TRUST_UNTRUSTED;
}

View file

@ -1,4 +1,4 @@
/* $OpenBSD: x509_vfy.c,v 1.138 2024/01/09 07:25:57 tb Exp $ */
/* $OpenBSD: x509_vfy.c,v 1.139 2024/01/10 17:31:28 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@ -2182,54 +2182,53 @@ X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
}
LCRYPTO_ALIAS(X509_STORE_CTX_purpose_inherit);
static int
x509_vfy_purpose_inherit(X509_STORE_CTX *ctx, int purpose, int trust)
int
X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose_id)
{
/* If we have a purpose then check it is valid */
if (purpose != 0) {
const X509_PURPOSE *purp;
int purpose_idx;
const X509_PURPOSE *purpose;
int idx;
if (purpose < X509_PURPOSE_MIN || purpose > X509_PURPOSE_MAX) {
/* XXX - Match wacky/documented behavior. Do we need to keep this? */
if (purpose_id == 0)
return 1;
if (purpose_id < X509_PURPOSE_MIN || purpose_id > X509_PURPOSE_MAX) {
X509error(X509_R_UNKNOWN_PURPOSE_ID);
return 0;
}
purpose_idx = purpose - X509_PURPOSE_MIN;
if ((purp = X509_PURPOSE_get0(purpose_idx)) == NULL) {
idx = purpose_id - X509_PURPOSE_MIN;
if ((purpose = X509_PURPOSE_get0(idx)) == NULL) {
X509error(X509_R_UNKNOWN_PURPOSE_ID);
return 0;
}
/* If trust is unset, use the purpose's trust. */
if (trust == 0)
trust = purp->trust;
}
if (trust != 0) {
if (trust < X509_TRUST_MIN || trust > X509_TRUST_MAX) {
X509error(X509_R_UNKNOWN_TRUST_ID);
return 0;
}
}
if (purpose != 0 && ctx->param->purpose == 0)
ctx->param->purpose = purpose;
if (trust != 0 && ctx->param->trust == 0)
ctx->param->trust = trust;
/* XXX - Succeeding while ignoring purpose_id and trust is awful. */
if (ctx->param->purpose == 0)
ctx->param->purpose = purpose_id;
if (ctx->param->trust == 0)
ctx->param->trust = purpose->trust;
return 1;
}
int
X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose)
{
return x509_vfy_purpose_inherit(ctx, purpose, 0);
}
LCRYPTO_ALIAS(X509_STORE_CTX_set_purpose);
int
X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust)
X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust_id)
{
return x509_vfy_purpose_inherit(ctx, 0, trust);
/* XXX - Match wacky/documented behavior. Do we need to keep this? */
if (trust_id == 0)
return 1;
if (trust_id < X509_TRUST_MIN || trust_id > X509_TRUST_MAX) {
X509error(X509_R_UNKNOWN_TRUST_ID);
return 0;
}
/* XXX - Succeeding while ignoring the trust_id is awful. */
if (ctx->param->trust == 0)
ctx->param->trust = trust_id;
return 1;
}
LCRYPTO_ALIAS(X509_STORE_CTX_set_trust);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: kern_sysctl.c,v 1.420 2023/10/01 15:58:12 krw Exp $ */
/* $OpenBSD: kern_sysctl.c,v 1.421 2024/01/10 16:44:30 bluhm Exp $ */
/* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */
/*-
@ -1493,6 +1493,12 @@ sysctl_file(int *name, u_int namelen, char *where, size_t *sizep,
TAILQ_FOREACH(inp, &udbtable.inpt_queue, inp_queue)
FILLSO(inp->inp_socket);
mtx_leave(&udbtable.inpt_mtx);
#ifdef INET6
mtx_enter(&udb6table.inpt_mtx);
TAILQ_FOREACH(inp, &udb6table.inpt_queue, inp_queue)
FILLSO(inp->inp_socket);
mtx_leave(&udb6table.inpt_mtx);
#endif
mtx_enter(&rawcbtable.inpt_mtx);
TAILQ_FOREACH(inp, &rawcbtable.inpt_queue, inp_queue)
FILLSO(inp->inp_socket);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: pf.c,v 1.1192 2024/01/01 22:16:51 bluhm Exp $ */
/* $OpenBSD: pf.c,v 1.1193 2024/01/10 16:44:30 bluhm Exp $ */
/*
* Copyright (c) 2001 Daniel Hartmeier
@ -3841,6 +3841,8 @@ pf_socket_lookup(struct pf_pdesc *pd)
break;
#ifdef INET6
case AF_INET6:
if (pd->virtual_proto == IPPROTO_UDP)
tb = &udb6table;
inp = in6_pcblookup(tb, &saddr->v6, sport, &daddr->v6,
dport, pd->rdomain);
if (inp == NULL) {

View file

@ -1,4 +1,4 @@
/* $OpenBSD: udp_usrreq.c,v 1.312 2023/12/01 15:30:47 bluhm Exp $ */
/* $OpenBSD: udp_usrreq.c,v 1.313 2024/01/10 16:44:30 bluhm Exp $ */
/* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */
/*
@ -161,6 +161,9 @@ const struct sysctl_bounded_args udpctl_vars[] = {
};
struct inpcbtable udbtable;
#ifdef INET6
struct inpcbtable udb6table;
#endif
struct cpumem *udpcounters;
void udp_sbappend(struct inpcb *, struct mbuf *, struct ip *,
@ -179,6 +182,9 @@ udp_init(void)
{
udpcounters = counters_alloc(udps_ncounters);
in_pcbinit(&udbtable, UDB_INITIAL_HASH_SIZE);
#ifdef INET6
in_pcbinit(&udb6table, UDB_INITIAL_HASH_SIZE);
#endif
}
int
@ -375,6 +381,7 @@ udp_input(struct mbuf **mp, int *offp, int proto, int af)
if (m->m_flags & (M_BCAST|M_MCAST)) {
SIMPLEQ_HEAD(, inpcb) inpcblist;
struct inpcbtable *tb;
/*
* Deliver a multicast or broadcast datagram to *all* sockets
@ -397,17 +404,24 @@ udp_input(struct mbuf **mp, int *offp, int proto, int af)
* (Algorithm copied from raw_intr().)
*/
SIMPLEQ_INIT(&inpcblist);
rw_enter_write(&udbtable.inpt_notify);
mtx_enter(&udbtable.inpt_mtx);
TAILQ_FOREACH(inp, &udbtable.inpt_queue, inp_queue) {
#ifdef INET6
if (ip6)
tb = &udb6table;
else
#endif
tb = &udbtable;
rw_enter_write(&tb->inpt_notify);
mtx_enter(&tb->inpt_mtx);
TAILQ_FOREACH(inp, &tb->inpt_queue, inp_queue) {
if (inp->inp_socket->so_rcv.sb_state & SS_CANTRCVMORE)
continue;
#ifdef INET6
/* don't accept it if AF does not match */
if (ip6 && !(inp->inp_flags & INP_IPV6))
continue;
if (!ip6 && (inp->inp_flags & INP_IPV6))
continue;
/* table is per AF, panic if it does not match */
if (ip6)
KASSERT(ISSET(inp->inp_flags, INP_IPV6));
else
KASSERT(!ISSET(inp->inp_flags, INP_IPV6));
#endif
if (rtable_l2(inp->inp_rtableid) !=
rtable_l2(m->m_pkthdr.ph_rtableid))
@ -467,10 +481,10 @@ udp_input(struct mbuf **mp, int *offp, int proto, int af)
SO_REUSEADDR)) == 0)
break;
}
mtx_leave(&udbtable.inpt_mtx);
mtx_leave(&tb->inpt_mtx);
if (SIMPLEQ_EMPTY(&inpcblist)) {
rw_exit_write(&udbtable.inpt_notify);
rw_exit_write(&tb->inpt_notify);
/*
* No matching pcb found; discard datagram.
@ -495,7 +509,7 @@ udp_input(struct mbuf **mp, int *offp, int proto, int af)
}
in_pcbunref(inp);
}
rw_exit_write(&udbtable.inpt_notify);
rw_exit_write(&tb->inpt_notify);
return IPPROTO_DONE;
}
@ -507,26 +521,31 @@ udp_input(struct mbuf **mp, int *offp, int proto, int af)
#endif
if (inp == NULL) {
#ifdef INET6
if (ip6)
inp = in6_pcblookup(&udbtable, &ip6->ip6_src,
if (ip6) {
inp = in6_pcblookup(&udb6table, &ip6->ip6_src,
uh->uh_sport, &ip6->ip6_dst, uh->uh_dport,
m->m_pkthdr.ph_rtableid);
else
} else
#endif /* INET6 */
inp = in_pcblookup(&udbtable, ip->ip_src, uh->uh_sport,
ip->ip_dst, uh->uh_dport, m->m_pkthdr.ph_rtableid);
{
inp = in_pcblookup(&udbtable, ip->ip_src,
uh->uh_sport, ip->ip_dst, uh->uh_dport,
m->m_pkthdr.ph_rtableid);
}
}
if (inp == NULL) {
udpstat_inc(udps_pcbhashmiss);
#ifdef INET6
if (ip6) {
inp = in6_pcblookup_listen(&udbtable, &ip6->ip6_dst,
inp = in6_pcblookup_listen(&udb6table, &ip6->ip6_dst,
uh->uh_dport, m, m->m_pkthdr.ph_rtableid);
} else
#endif /* INET6 */
{
inp = in_pcblookup_listen(&udbtable, ip->ip_dst,
uh->uh_dport, m, m->m_pkthdr.ph_rtableid);
}
}
#ifdef IPSEC
if (ipsec_in_use) {
@ -809,7 +828,7 @@ udp6_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *d)
* corresponding to the address in the ICMPv6 message
* payload.
*/
inp = in6_pcblookup(&udbtable, &sa6.sin6_addr,
inp = in6_pcblookup(&udb6table, &sa6.sin6_addr,
uh.uh_dport, &sa6_src.sin6_addr, uh.uh_sport,
rdomain);
#if 0
@ -821,7 +840,7 @@ udp6_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *d)
* is really ours.
*/
if (inp == NULL) {
inp = in6_pcblookup_listen(&udbtable,
inp = in6_pcblookup_listen(&udb6table,
&sa6_src.sin6_addr, uh.uh_sport, NULL,
rdomain))
}
@ -847,10 +866,10 @@ udp6_ctlinput(int cmd, struct sockaddr *sa, u_int rdomain, void *d)
*/
}
in6_pcbnotify(&udbtable, &sa6, uh.uh_dport,
in6_pcbnotify(&udb6table, &sa6, uh.uh_dport,
&sa6_src, uh.uh_sport, rdomain, cmd, cmdarg, notify);
} else {
in6_pcbnotify(&udbtable, &sa6, 0,
in6_pcbnotify(&udb6table, &sa6, 0,
&sa6_any, 0, rdomain, cmd, cmdarg, notify);
}
}
@ -1079,6 +1098,7 @@ release:
int
udp_attach(struct socket *so, int proto, int wait)
{
struct inpcbtable *tb;
int error;
if (so->so_pcb != NULL)
@ -1088,7 +1108,13 @@ udp_attach(struct socket *so, int proto, int wait)
return error;
NET_ASSERT_LOCKED();
if ((error = in_pcballoc(so, &udbtable, wait)))
#ifdef INET6
if (so->so_proto->pr_domain->dom_family == PF_INET6)
tb = &udb6table;
else
#endif
tb = &udbtable;
if ((error = in_pcballoc(so, tb, wait)))
return error;
#ifdef INET6
if (sotoinpcb(so)->inp_flags & INP_IPV6)

View file

@ -1,4 +1,4 @@
/* $OpenBSD: udp_var.h,v 1.49 2022/10/17 14:49:02 mvs Exp $ */
/* $OpenBSD: udp_var.h,v 1.50 2024/01/10 16:44:30 bluhm Exp $ */
/* $NetBSD: udp_var.h,v 1.12 1996/02/13 23:44:41 christos Exp $ */
/*
@ -123,7 +123,7 @@ udpstat_inc(enum udpstat_counters c)
counters_inc(udpcounters, c);
}
extern struct inpcbtable udbtable;
extern struct inpcbtable udbtable, udb6table;
extern struct udpstat udpstat;
extern const struct pr_usrreqs udp_usrreqs;

View file

@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $OpenBSD: ssh_config.5,v 1.392 2024/01/09 22:19:00 djm Exp $
.Dd $Mdocdate: January 9 2024 $
.\" $OpenBSD: ssh_config.5,v 1.393 2024/01/10 06:33:13 jmc Exp $
.Dd $Mdocdate: January 10 2024 $
.Dt SSH_CONFIG 5
.Os
.Sh NAME
@ -481,7 +481,7 @@ Specifying a zero value disables the inactivity timeout.
.Pp
The special timeout
.Dq global
Applies to all active channels, taken together.
applies to all active channels, taken together.
Traffic on any active channel will reset the timeout, but when the timeout
expires then all open channels will be closed.
Note that this global timeout is not matched by wildcards and must be

View file

@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" $OpenBSD: sshd_config.5,v 1.351 2024/01/09 22:19:00 djm Exp $
.Dd $Mdocdate: January 9 2024 $
.\" $OpenBSD: sshd_config.5,v 1.352 2024/01/10 06:33:13 jmc Exp $
.Dd $Mdocdate: January 10 2024 $
.Dt SSHD_CONFIG 5
.Os
.Sh NAME
@ -428,7 +428,7 @@ Specifying a zero value disables the inactivity timeout.
.Pp
The special timeout
.Dq global
Applies to all active channels, taken together.
applies to all active channels, taken together.
Traffic on any active channel will reset the timeout, but when the timeout
expires then all open channels will be closed.
Note that this global timeout is not matched by wildcards and must be

View file

@ -1,4 +1,4 @@
/* $OpenBSD: output.c,v 1.43 2023/12/19 10:32:20 claudio Exp $ */
/* $OpenBSD: output.c,v 1.44 2024/01/10 14:59:41 claudio Exp $ */
/*
* Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
@ -1185,14 +1185,14 @@ show_rtr(struct ctl_show_rtr *rtr)
printf(" Last sent error: %s\n",
log_rtr_error(rtr->last_sent_error));
if (rtr->last_sent_msg[0])
printf(" with reason \"%s\"",
printf(" with reason \"%s\"\n",
log_reason(rtr->last_sent_msg));
}
if (rtr->last_recv_error != NO_ERROR) {
printf(" Last received error: %s\n",
log_rtr_error(rtr->last_recv_error));
if (rtr->last_recv_msg[0])
printf(" with reason \"%s\"",
printf(" with reason \"%s\"\n",
log_reason(rtr->last_recv_msg));
}

View file

@ -1,4 +1,4 @@
/* $OpenBSD: bgpd.h,v 1.479 2024/01/08 15:08:34 claudio Exp $ */
/* $OpenBSD: bgpd.h,v 1.480 2024/01/10 13:31:09 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@ -1541,6 +1541,8 @@ const char *log_as(uint32_t);
const char *log_rd(uint64_t);
const char *log_ext_subtype(int, uint8_t);
const char *log_reason(const char *);
const char *log_roa(struct roa *);
const char *log_aspa(struct aspa_set *);
const char *log_rtr_error(enum rtr_error);
const char *log_policy(enum role);
int aspath_snprint(char *, size_t, void *, uint16_t);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: control.c,v 1.114 2023/11/07 11:18:35 claudio Exp $ */
/* $OpenBSD: control.c,v 1.115 2024/01/10 11:08:04 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@ -219,7 +219,7 @@ int
control_close(struct ctl_conn *c)
{
if (c->terminate && c->ibuf.pid)
imsg_ctl_rde(IMSG_CTL_TERMINATE, 0, c->ibuf.pid, NULL, 0);
imsg_ctl_rde_msg(IMSG_CTL_TERMINATE, 0, c->ibuf.pid);
msgbuf_clear(&c->ibuf.w);
TAILQ_REMOVE(&ctl_conns, c, entry);
@ -234,12 +234,14 @@ int
control_dispatch_msg(struct pollfd *pfd, struct peer_head *peers)
{
struct imsg imsg;
struct ctl_neighbor neighbor;
struct ctl_show_rib_request ribreq;
struct ctl_conn *c;
ssize_t n;
int verbose, matched;
struct peer *p;
struct ctl_neighbor *neighbor;
struct ctl_show_rib_request *ribreq;
ssize_t n;
uint32_t type;
pid_t pid;
int verbose, matched;
if ((c = control_connbyfd(pfd->fd)) == NULL) {
log_warn("control_dispatch_msg: fd %d: not found", pfd->fd);
@ -250,8 +252,7 @@ control_dispatch_msg(struct pollfd *pfd, struct peer_head *peers)
if (msgbuf_write(&c->ibuf.w) <= 0 && errno != EAGAIN)
return control_close(c);
if (c->throttled && c->ibuf.w.queued < CTL_MSG_LOW_MARK) {
if (imsg_ctl_rde(IMSG_XON, 0, c->ibuf.pid, NULL, 0) !=
-1)
if (imsg_ctl_rde_msg(IMSG_XON, 0, c->ibuf.pid) != -1)
c->throttled = 0;
}
}
@ -270,8 +271,10 @@ control_dispatch_msg(struct pollfd *pfd, struct peer_head *peers)
if (n == 0)
break;
type = imsg_get_type(&imsg);
pid = imsg_get_pid(&imsg);
if (c->restricted) {
switch (imsg.hdr.type) {
switch (type) {
case IMSG_CTL_SHOW_NEIGHBOR:
case IMSG_CTL_SHOW_NEXTHOP:
case IMSG_CTL_SHOW_INTERFACE:
@ -287,20 +290,25 @@ control_dispatch_msg(struct pollfd *pfd, struct peer_head *peers)
break;
default:
/* clear imsg type to prevent processing */
imsg.hdr.type = IMSG_NONE;
type = IMSG_NONE;
control_result(c, CTL_RES_DENIED);
break;
}
}
switch (imsg.hdr.type) {
/*
* TODO: this is wrong and shoud work the other way around.
* The imsg.hdr.pid is from the remote end and should not
* be trusted.
*/
c->ibuf.pid = pid;
switch (type) {
case IMSG_NONE:
/* message was filtered out, nothing to do */
break;
case IMSG_CTL_FIB_COUPLE:
case IMSG_CTL_FIB_DECOUPLE:
imsg_ctl_parent(imsg.hdr.type, imsg.hdr.peerid,
0, NULL, 0);
imsg_ctl_parent(&imsg);
break;
case IMSG_CTL_SHOW_TERSE:
RB_FOREACH(p, peer_head, peers)
@ -309,23 +317,19 @@ control_dispatch_msg(struct pollfd *pfd, struct peer_head *peers)
imsg_compose(&c->ibuf, IMSG_CTL_END, 0, 0, -1, NULL, 0);
break;
case IMSG_CTL_SHOW_NEIGHBOR:
c->ibuf.pid = imsg.hdr.pid;
if (imsg_get_data(&imsg, &neighbor,
sizeof(neighbor)) == -1)
memset(&neighbor, 0, sizeof(neighbor));
if (imsg.hdr.len == IMSG_HEADER_SIZE +
sizeof(struct ctl_neighbor)) {
neighbor = imsg.data;
} else {
neighbor = NULL;
}
matched = 0;
RB_FOREACH(p, peer_head, peers) {
if (!peer_matched(p, neighbor))
if (!peer_matched(p, &neighbor))
continue;
matched = 1;
if (!neighbor || !neighbor->show_timers) {
imsg_ctl_rde(imsg.hdr.type, p->conf.id,
imsg.hdr.pid, NULL, 0);
if (!neighbor.show_timers) {
imsg_ctl_rde_msg(type,
p->conf.id, pid);
} else {
u_int i;
time_t d;
@ -348,9 +352,8 @@ control_dispatch_msg(struct pollfd *pfd, struct peer_head *peers)
}
if (!matched && RB_EMPTY(peers)) {
control_result(c, CTL_RES_NOSUCHPEER);
} else if (!neighbor || !neighbor->show_timers) {
imsg_ctl_rde(IMSG_CTL_END, 0, imsg.hdr.pid,
NULL, 0);
} else if (!neighbor.show_timers) {
imsg_ctl_rde_msg(IMSG_CTL_END, 0, pid);
} else {
imsg_compose(&c->ibuf, IMSG_CTL_END, 0, 0, -1,
NULL, 0);
@ -361,23 +364,21 @@ control_dispatch_msg(struct pollfd *pfd, struct peer_head *peers)
case IMSG_CTL_NEIGHBOR_CLEAR:
case IMSG_CTL_NEIGHBOR_RREFRESH:
case IMSG_CTL_NEIGHBOR_DESTROY:
if (imsg.hdr.len != IMSG_HEADER_SIZE +
sizeof(struct ctl_neighbor)) {
if (imsg_get_data(&imsg, &neighbor,
sizeof(neighbor)) == -1) {
log_warnx("got IMSG_CTL_NEIGHBOR_ with "
"wrong length");
break;
}
neighbor = imsg.data;
matched = 0;
RB_FOREACH(p, peer_head, peers) {
if (!peer_matched(p, neighbor))
if (!peer_matched(p, &neighbor))
continue;
matched = 1;
switch (imsg.hdr.type) {
switch (type) {
case IMSG_CTL_NEIGHBOR_UP:
bgp_fsm(p, EVNT_START);
p->conf.down = 0;
@ -388,22 +389,20 @@ control_dispatch_msg(struct pollfd *pfd, struct peer_head *peers)
control_result(c, CTL_RES_OK);
break;
case IMSG_CTL_NEIGHBOR_DOWN:
neighbor->reason[
sizeof(neighbor->reason) - 1] =
'\0';
neighbor.reason[
sizeof(neighbor.reason) - 1] = '\0';
strlcpy(p->conf.reason,
neighbor->reason,
neighbor.reason,
sizeof(p->conf.reason));
p->conf.down = 1;
session_stop(p, ERR_CEASE_ADMIN_DOWN);
control_result(c, CTL_RES_OK);
break;
case IMSG_CTL_NEIGHBOR_CLEAR:
neighbor->reason[
sizeof(neighbor->reason) - 1] =
'\0';
neighbor.reason[
sizeof(neighbor.reason) - 1] = '\0';
strlcpy(p->conf.reason,
neighbor->reason,
neighbor.reason,
sizeof(p->conf.reason));
p->IdleHoldTime =
INTERVAL_IDLE_HOLD_INITIAL;
@ -455,51 +454,40 @@ control_dispatch_msg(struct pollfd *pfd, struct peer_head *peers)
case IMSG_CTL_SHOW_INTERFACE:
case IMSG_CTL_SHOW_FIB_TABLES:
case IMSG_CTL_SHOW_RTR:
c->ibuf.pid = imsg.hdr.pid;
imsg_ctl_parent(imsg.hdr.type, 0, imsg.hdr.pid,
imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
imsg_ctl_parent(&imsg);
break;
case IMSG_CTL_KROUTE:
case IMSG_CTL_KROUTE_ADDR:
case IMSG_CTL_SHOW_NEXTHOP:
c->ibuf.pid = imsg.hdr.pid;
imsg_ctl_parent(imsg.hdr.type, imsg.hdr.peerid,
imsg.hdr.pid, imsg.data, imsg.hdr.len -
IMSG_HEADER_SIZE);
imsg_ctl_parent(&imsg);
break;
case IMSG_CTL_SHOW_RIB:
case IMSG_CTL_SHOW_RIB_PREFIX:
if (imsg.hdr.len != IMSG_HEADER_SIZE +
sizeof(struct ctl_show_rib_request)) {
if (imsg_get_data(&imsg, &ribreq, sizeof(ribreq)) ==
-1) {
log_warnx("got IMSG_CTL_SHOW_RIB with "
"wrong length");
break;
}
ribreq = imsg.data;
neighbor = &ribreq->neighbor;
/* check if at least one neighbor exists */
RB_FOREACH(p, peer_head, peers)
if (peer_matched(p, neighbor))
if (peer_matched(p, &ribreq.neighbor))
break;
if (p == NULL && RB_EMPTY(peers)) {
control_result(c, CTL_RES_NOSUCHPEER);
break;
}
if ((imsg.hdr.type == IMSG_CTL_SHOW_RIB_PREFIX)
&& (ribreq->prefix.aid == AID_UNSPEC)) {
if (type == IMSG_CTL_SHOW_RIB_PREFIX &&
ribreq.prefix.aid == AID_UNSPEC) {
/* malformed request, must specify af */
control_result(c, CTL_RES_PARSE_ERROR);
break;
}
c->ibuf.pid = imsg.hdr.pid;
c->terminate = 1;
imsg_ctl_rde(imsg.hdr.type, 0, imsg.hdr.pid,
imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
imsg_ctl_rde(&imsg);
break;
case IMSG_CTL_SHOW_NETWORK:
case IMSG_CTL_SHOW_FLOWSPEC:
@ -507,9 +495,7 @@ control_dispatch_msg(struct pollfd *pfd, struct peer_head *peers)
/* FALLTHROUGH */
case IMSG_CTL_SHOW_RIB_MEM:
case IMSG_CTL_SHOW_SET:
c->ibuf.pid = imsg.hdr.pid;
imsg_ctl_rde(imsg.hdr.type, 0, imsg.hdr.pid,
imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
imsg_ctl_rde(&imsg);
break;
case IMSG_NETWORK_ADD:
case IMSG_NETWORK_ASPATH:
@ -522,21 +508,16 @@ control_dispatch_msg(struct pollfd *pfd, struct peer_head *peers)
case IMSG_FLOWSPEC_DONE:
case IMSG_FLOWSPEC_FLUSH:
case IMSG_FILTER_SET:
imsg_ctl_rde(imsg.hdr.type, 0, 0,
imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
imsg_ctl_rde(&imsg);
break;
case IMSG_CTL_LOG_VERBOSE:
if (imsg.hdr.len != IMSG_HEADER_SIZE +
sizeof(verbose))
if (imsg_get_data(&imsg, &verbose, sizeof(verbose)) ==
-1)
break;
/* forward to other processes */
imsg_ctl_parent(imsg.hdr.type, 0, imsg.hdr.pid,
imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
imsg_ctl_rde(imsg.hdr.type, 0, imsg.hdr.pid,
imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
memcpy(&verbose, imsg.data, sizeof(verbose));
imsg_ctl_parent(&imsg);
imsg_ctl_rde(&imsg);
log_setverbose(verbose);
break;
default:
@ -552,23 +533,28 @@ int
control_imsg_relay(struct imsg *imsg, struct peer *p)
{
struct ctl_conn *c;
uint32_t type;
pid_t pid;
if ((c = control_connbypid(imsg->hdr.pid)) == NULL)
type = imsg_get_type(imsg);
pid = imsg_get_pid(imsg);
if ((c = control_connbypid(pid)) == NULL)
return (0);
/* special handling for peers since only the stats are sent from RDE */
if (imsg->hdr.type == IMSG_CTL_SHOW_NEIGHBOR) {
if (type == IMSG_CTL_SHOW_NEIGHBOR) {
struct rde_peer_stats stats;
if (imsg->hdr.len > IMSG_HEADER_SIZE + sizeof(stats)) {
log_warnx("wrong imsg len");
return (0);
}
if (p == NULL) {
log_warnx("no such peer: id=%u", imsg->hdr.peerid);
log_warnx("%s: no such peer: id=%u", __func__,
imsg_get_id(imsg));
return (0);
}
if (imsg_get_data(imsg, &stats, sizeof(stats)) == -1) {
log_warnx("%s: imsg_get_data", __func__);
return (0);
}
memcpy(&stats, imsg->data, sizeof(stats));
p->stats.prefix_cnt = stats.prefix_cnt;
p->stats.prefix_out_cnt = stats.prefix_out_cnt;
p->stats.prefix_rcvd_update = stats.prefix_rcvd_update;
@ -580,21 +566,19 @@ control_imsg_relay(struct imsg *imsg, struct peer *p)
p->stats.pending_update = stats.pending_update;
p->stats.pending_withdraw = stats.pending_withdraw;
return (imsg_compose(&c->ibuf, imsg->hdr.type, 0,
imsg->hdr.pid, -1, p, sizeof(*p)));
return imsg_compose(&c->ibuf, type, 0, pid, -1, p, sizeof(*p));
}
/* if command finished no need to send exit message */
if (imsg->hdr.type == IMSG_CTL_END || imsg->hdr.type == IMSG_CTL_RESULT)
if (type == IMSG_CTL_END || type == IMSG_CTL_RESULT)
c->terminate = 0;
if (!c->throttled && c->ibuf.w.queued > CTL_MSG_HIGH_MARK) {
if (imsg_ctl_rde(IMSG_XOFF, 0, imsg->hdr.pid, NULL, 0) != -1)
if (imsg_ctl_rde_msg(IMSG_XOFF, 0, pid) != -1)
c->throttled = 1;
}
return (imsg_compose(&c->ibuf, imsg->hdr.type, 0, imsg->hdr.pid, -1,
imsg->data, imsg->hdr.len - IMSG_HEADER_SIZE));
return (imsg_forward(&c->ibuf, imsg));
}
void

View file

@ -1,4 +1,4 @@
/* $OpenBSD: printconf.c,v 1.168 2023/08/16 08:26:35 claudio Exp $ */
/* $OpenBSD: printconf.c,v 1.169 2024/01/10 13:31:09 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@ -687,22 +687,13 @@ void
print_roa(struct roa_tree *r)
{
struct roa *roa;
struct bgpd_addr addr;
if (RB_EMPTY(r))
return;
printf("roa-set {");
RB_FOREACH(roa, roa_tree, r) {
printf("\n\t");
addr.aid = roa->aid;
addr.v6 = roa->prefix.inet6;
printf("%s/%u", log_addr(&addr), roa->prefixlen);
if (roa->prefixlen != roa->maxlen)
printf(" maxlen %u", roa->maxlen);
printf(" source-as %u", roa->asnum);
if (roa->expires != 0)
printf(" expires %lld", (long long)roa->expires);
printf("\n\t%s", log_roa(roa));
}
printf("\n}\n\n");
}
@ -711,21 +702,13 @@ void
print_aspa(struct aspa_tree *a)
{
struct aspa_set *aspa;
uint32_t i;
if (RB_EMPTY(a))
return;
printf("aspa-set {");
RB_FOREACH(aspa, aspa_tree, a) {
printf("\n\t");
printf("customer-as %s", log_as(aspa->as));
if (aspa->expires != 0)
printf(" expires %lld", (long long)aspa->expires);
printf(" provider-as { ");
for (i = 0; i < aspa->num; i++)
printf("%s ", log_as(aspa->tas[i]));
printf("}");
printf("\n\t%s", log_aspa(aspa));
}
printf("\n}\n\n");
}

View file

@ -1,4 +1,4 @@
/* $OpenBSD: rtr_proto.c,v 1.27 2024/01/09 15:13:49 claudio Exp $ */
/* $OpenBSD: rtr_proto.c,v 1.28 2024/01/10 16:08:36 claudio Exp $ */
/*
* Copyright (c) 2020 Claudio Jeker <claudio@openbsd.org>
@ -246,7 +246,7 @@ log_rtr_type(enum rtr_pdu_type type)
case ERROR_REPORT:
return "error report";
case ASPA:
return "aspa pdu";
return "aspa";
default:
snprintf(buf, sizeof(buf), "unknown %u", type);
return buf;
@ -296,23 +296,33 @@ rtr_newmsg(struct rtr_session *rs, enum rtr_pdu_type type, uint32_t len,
return NULL;
}
static void rtr_send_error(struct rtr_session *, struct ibuf *, enum rtr_error,
const char *, ...) __attribute__((__format__ (printf, 4, 5)));
/*
* Try to send an error PDU to cache, put connection into error
* state.
*/
static void
rtr_send_error(struct rtr_session *rs, enum rtr_error err, char *msg,
struct ibuf *pdu)
rtr_send_error(struct rtr_session *rs, struct ibuf *pdu, enum rtr_error err,
const char *fmt, ...)
{
struct ibuf *buf;
va_list ap;
size_t len = 0, mlen = 0;
rs->last_sent_error = err;
if (msg != NULL) {
mlen = strlen(msg);
strlcpy(rs->last_sent_msg, msg, sizeof(rs->last_sent_msg));
} else
memset(rs->last_sent_msg, 0, sizeof(rs->last_sent_msg));
if (fmt != NULL) {
va_start(ap, fmt);
vsnprintf(rs->last_sent_msg, sizeof(rs->last_sent_msg),
fmt, ap);
mlen = strlen(rs->last_sent_msg);
va_end(ap);
}
log_warnx("rtr %s: sending error: %s%s%s", log_rtr(rs),
log_rtr_error(err), mlen > 0 ? ": " : "", rs->last_sent_msg);
if (pdu != NULL) {
ibuf_rewind(pdu);
@ -331,13 +341,10 @@ rtr_send_error(struct rtr_session *rs, enum rtr_error err, char *msg,
}
if (ibuf_add_n32(buf, mlen) == -1)
goto fail;
if (ibuf_add(buf, msg, mlen) == -1)
if (ibuf_add(buf, rs->last_sent_msg, mlen) == -1)
goto fail;
ibuf_close(&rs->w, buf);
log_warnx("rtr %s: sending error: %s%s%s", log_rtr(rs),
log_rtr_error(err), msg ? ": " : "", msg ? msg : "");
rtr_fsm(rs, RTR_EVNT_SEND_ERROR);
return;
@ -352,12 +359,15 @@ rtr_send_reset_query(struct rtr_session *rs)
struct ibuf *buf;
buf = rtr_newmsg(rs, RESET_QUERY, 0, 0);
if (buf == NULL) {
log_warn("rtr %s: send reset query", log_rtr(rs));
rtr_send_error(rs, INTERNAL_ERROR, "out of memory", NULL);
return;
}
if (buf == NULL)
goto fail;
ibuf_close(&rs->w, buf);
return;
fail:
rtr_send_error(rs, NULL, INTERNAL_ERROR,
"send %s: %s", log_rtr_type(RESET_QUERY), strerror(errno));
ibuf_free(buf);
}
static void
@ -374,9 +384,9 @@ rtr_send_serial_query(struct rtr_session *rs)
return;
fail:
log_warn("rtr %s: send serial query", log_rtr(rs));
rtr_send_error(rs, NULL, INTERNAL_ERROR,
"send %s: %s", log_rtr_type(SERIAL_QUERY), strerror(errno));
ibuf_free(buf);
rtr_send_error(rs, INTERNAL_ERROR, "out of memory", NULL);
}
/*
@ -388,10 +398,9 @@ rtr_check_session_id(struct rtr_session *rs, uint16_t session_id,
struct rtr_header *rh, struct ibuf *pdu)
{
if (session_id != ntohs(rh->session_id)) {
log_warnx("rtr %s: received %s: bad session_id: %d != %d",
log_rtr(rs), log_rtr_type(rh->type), ntohs(rh->session_id),
session_id);
rtr_send_error(rs, CORRUPT_DATA, "bad session_id", pdu);
rtr_send_error(rs, pdu, CORRUPT_DATA,
"%s: bad session_id %d (expected %d)",
log_rtr_type(rh->type), ntohs(rh->session_id), session_id);
return -1;
}
return 0;
@ -416,9 +425,8 @@ rtr_parse_header(struct rtr_session *rs, struct ibuf *hdr,
len = ntohl(rh.length);
if (len > RTR_MAX_LEN) {
log_warnx("rtr %s: received %s: pdu too big: %zu byte",
log_rtr(rs), log_rtr_type(rh.type), len);
rtr_send_error(rs, CORRUPT_DATA, "pdu too big", hdr);
rtr_send_error(rs, hdr, CORRUPT_DATA, "%s: too big: %zu bytes",
log_rtr_type(rh.type), len);
return -1;
}
@ -435,9 +443,8 @@ rtr_parse_header(struct rtr_session *rs, struct ibuf *hdr,
/* ignore SERIAL_NOTIFY */
break;
default:
log_warnx("rtr %s: received %s: out of context",
log_rtr(rs), log_rtr_type(rh.type));
rtr_send_error(rs, CORRUPT_DATA, "out of context", hdr);
rtr_send_error(rs, hdr, CORRUPT_DATA,
"%s: out of context", log_rtr_type(rh.type));
return -1;
}
} else if (rh.version != rs->version && rh.type != ERROR_REPORT) {
@ -491,9 +498,8 @@ rtr_parse_header(struct rtr_session *rs, struct ibuf *hdr,
goto badlen;
break;
default:
log_warnx("rtr %s: received unsupported pdu: type %s",
log_rtr(rs), log_rtr_type(rh.type));
rtr_send_error(rs, UNSUPP_PDU_TYPE, NULL, hdr);
rtr_send_error(rs, hdr, UNSUPP_PDU_TYPE, "type %s",
log_rtr_type(rh.type));
return -1;
}
@ -503,15 +509,13 @@ rtr_parse_header(struct rtr_session *rs, struct ibuf *hdr,
return 0;
badlen:
log_warnx("rtr %s: received %s: bad pdu length: %zu bytes",
log_rtr(rs), log_rtr_type(rh.type), len);
rtr_send_error(rs, CORRUPT_DATA, "bad length", hdr);
rtr_send_error(rs, hdr, CORRUPT_DATA, "%s: bad length: %zu bytes",
log_rtr_type(rh.type), len);
return -1;
badversion:
log_warnx("rtr %s: received %s message: unexpected version %d",
log_rtr(rs), log_rtr_type(rh.type), rh.version);
rtr_send_error(rs, UNEXP_PROTOCOL_VERS, NULL, hdr);
rtr_send_error(rs, hdr, UNEXP_PROTOCOL_VERS, "%s: version %d",
log_rtr_type(rh.type), rh.version);
return -1;
}
@ -524,12 +528,8 @@ rtr_parse_notify(struct rtr_session *rs, struct ibuf *pdu)
if (rs->state == RTR_STATE_NEGOTIATION)
return 0;
if (ibuf_get(pdu, &notify, sizeof(notify)) == -1) {
log_warnx("rtr %s: received %s: bad pdu length",
log_rtr(rs), log_rtr_type(SERIAL_NOTIFY));
rtr_send_error(rs, CORRUPT_DATA, "bad length", pdu);
return -1;
}
if (ibuf_get(pdu, &notify, sizeof(notify)) == -1)
goto badlen;
if (rtr_check_session_id(rs, rs->session_id, &notify.hdr, pdu) == -1)
return -1;
@ -543,6 +543,11 @@ rtr_parse_notify(struct rtr_session *rs, struct ibuf *pdu)
rtr_fsm(rs, RTR_EVNT_SERIAL_NOTIFY);
return 0;
badlen:
rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: bad length",
log_rtr_type(SERIAL_NOTIFY));
return -1;
}
static int
@ -550,12 +555,8 @@ rtr_parse_cache_response(struct rtr_session *rs, struct ibuf *pdu)
{
struct rtr_response resp;
if (ibuf_get(pdu, &resp, sizeof(resp)) == -1) {
log_warnx("rtr %s: received %s: bad pdu length",
log_rtr(rs), log_rtr_type(CACHE_RESPONSE));
rtr_send_error(rs, CORRUPT_DATA, "bad length", pdu);
return -1;
}
if (ibuf_get(pdu, &resp, sizeof(resp)) == -1)
goto badlen;
/* set session_id if not yet happened */
if (rs->session_id == -1)
@ -565,14 +566,18 @@ rtr_parse_cache_response(struct rtr_session *rs, struct ibuf *pdu)
return -1;
if (rs->state != RTR_STATE_ESTABLISHED) {
log_warnx("rtr %s: received %s: out of context",
log_rtr(rs), log_rtr_type(CACHE_RESPONSE));
rtr_send_error(rs, CORRUPT_DATA, "out of context", pdu);
rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: out of context",
log_rtr_type(CACHE_RESPONSE));
return -1;
}
rtr_fsm(rs, RTR_EVNT_CACHE_RESPONSE);
return 0;
badlen:
rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: bad length",
log_rtr_type(CACHE_RESPONSE));
return -1;
}
static int
@ -581,35 +586,27 @@ rtr_parse_ipv4_prefix(struct rtr_session *rs, struct ibuf *pdu)
struct rtr_ipv4 ip4;
struct roa *roa;
if (ibuf_get(pdu, &ip4, sizeof(ip4)) == -1) {
log_warnx("rtr %s: received %s: bad pdu length",
log_rtr(rs), log_rtr_type(IPV4_PREFIX));
rtr_send_error(rs, CORRUPT_DATA, "bad length", pdu);
return -1;
}
if (ibuf_get(pdu, &ip4, sizeof(ip4)) == -1)
goto badlen;
if (rtr_check_session_id(rs, 0, &ip4.hdr, pdu) == -1)
return -1;
if (rs->state != RTR_STATE_EXCHANGE) {
log_warnx("rtr %s: received %s: out of context",
log_rtr(rs), log_rtr_type(IPV4_PREFIX));
rtr_send_error(rs, CORRUPT_DATA, "out of context", pdu);
rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: out of context",
log_rtr_type(IPV4_PREFIX));
return -1;
}
if (ip4.prefixlen > 32 || ip4.maxlen > 32 ||
ip4.prefixlen > ip4.maxlen) {
log_warnx("rtr: %s: received %s: bad prefixlen / maxlen",
log_rtr(rs), log_rtr_type(IPV4_PREFIX));
rtr_send_error(rs, CORRUPT_DATA, "bad prefixlen / maxlen", pdu);
rtr_send_error(rs, pdu, CORRUPT_DATA,
"%s: bad prefixlen / maxlen", log_rtr_type(IPV4_PREFIX));
return -1;
}
if ((roa = calloc(1, sizeof(*roa))) == NULL) {
log_warn("rtr %s: received %s",
log_rtr(rs), log_rtr_type(IPV4_PREFIX));
rtr_send_error(rs, INTERNAL_ERROR, "out of memory", NULL);
rtr_send_error(rs, NULL, INTERNAL_ERROR, "out of memory");
return -1;
}
roa->aid = AID_INET;
@ -620,9 +617,8 @@ rtr_parse_ipv4_prefix(struct rtr_session *rs, struct ibuf *pdu)
if (ip4.flags & FLAG_ANNOUNCE) {
if (RB_INSERT(roa_tree, &rs->roa_set, roa) != NULL) {
log_warnx("rtr %s: received %s: duplicate announcement",
log_rtr(rs), log_rtr_type(IPV4_PREFIX));
rtr_send_error(rs, DUP_REC_RECV, NULL, pdu);
rtr_send_error(rs, pdu, DUP_REC_RECV, "%s %s",
log_rtr_type(IPV4_PREFIX), log_roa(roa));
free(roa);
return -1;
}
@ -631,9 +627,8 @@ rtr_parse_ipv4_prefix(struct rtr_session *rs, struct ibuf *pdu)
r = RB_FIND(roa_tree, &rs->roa_set, roa);
if (r == NULL) {
log_warnx("rtr %s: received %s: unknown withdrawal",
log_rtr(rs), log_rtr_type(IPV4_PREFIX));
rtr_send_error(rs, UNK_REC_WDRAWL, NULL, pdu);
rtr_send_error(rs, pdu, UNK_REC_WDRAWL, "%s %s",
log_rtr_type(IPV4_PREFIX), log_roa(roa));
free(roa);
return -1;
}
@ -643,6 +638,11 @@ rtr_parse_ipv4_prefix(struct rtr_session *rs, struct ibuf *pdu)
}
return 0;
badlen:
rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: bad length",
log_rtr_type(IPV4_PREFIX));
return -1;
}
static int
@ -651,35 +651,27 @@ rtr_parse_ipv6_prefix(struct rtr_session *rs, struct ibuf *pdu)
struct rtr_ipv6 ip6;
struct roa *roa;
if (ibuf_get(pdu, &ip6, sizeof(ip6)) == -1) {
log_warnx("rtr %s: received %s: bad pdu length",
log_rtr(rs), log_rtr_type(IPV6_PREFIX));
rtr_send_error(rs, CORRUPT_DATA, "bad length", pdu);
return -1;
}
if (ibuf_get(pdu, &ip6, sizeof(ip6)) == -1)
goto badlen;
if (rtr_check_session_id(rs, 0, &ip6.hdr, pdu) == -1)
return -1;
if (rs->state != RTR_STATE_EXCHANGE) {
log_warnx("rtr %s: received %s: out of context",
log_rtr(rs), log_rtr_type(IPV6_PREFIX));
rtr_send_error(rs, CORRUPT_DATA, "out of context", pdu);
rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: out of context",
log_rtr_type(IPV6_PREFIX));
return -1;
}
if (ip6.prefixlen > 128 || ip6.maxlen > 128 ||
ip6.prefixlen > ip6.maxlen) {
log_warnx("rtr: %s: received %s: bad prefixlen / maxlen",
log_rtr(rs), log_rtr_type(IPV6_PREFIX));
rtr_send_error(rs, CORRUPT_DATA, "bad prefixlen / maxlen", pdu);
rtr_send_error(rs, pdu, CORRUPT_DATA,
"%s: bad prefixlen / maxlen", log_rtr_type(IPV6_PREFIX));
return -1;
}
if ((roa = calloc(1, sizeof(*roa))) == NULL) {
log_warn("rtr %s: received %s",
log_rtr(rs), log_rtr_type(IPV6_PREFIX));
rtr_send_error(rs, INTERNAL_ERROR, "out of memory", NULL);
rtr_send_error(rs, NULL, INTERNAL_ERROR, "out of memory");
return -1;
}
roa->aid = AID_INET6;
@ -690,9 +682,8 @@ rtr_parse_ipv6_prefix(struct rtr_session *rs, struct ibuf *pdu)
if (ip6.flags & FLAG_ANNOUNCE) {
if (RB_INSERT(roa_tree, &rs->roa_set, roa) != NULL) {
log_warnx("rtr %s: received %s: duplicate announcement",
log_rtr(rs), log_rtr_type(IPV6_PREFIX));
rtr_send_error(rs, DUP_REC_RECV, NULL, pdu);
rtr_send_error(rs, pdu, DUP_REC_RECV, "%s %s",
log_rtr_type(IPV6_PREFIX), log_roa(roa));
free(roa);
return -1;
}
@ -701,9 +692,8 @@ rtr_parse_ipv6_prefix(struct rtr_session *rs, struct ibuf *pdu)
r = RB_FIND(roa_tree, &rs->roa_set, roa);
if (r == NULL) {
log_warnx("rtr %s: received %s: unknown withdrawal",
log_rtr(rs), log_rtr_type(IPV6_PREFIX));
rtr_send_error(rs, UNK_REC_WDRAWL, NULL, pdu);
rtr_send_error(rs, pdu, UNK_REC_WDRAWL, "%s %s",
log_rtr_type(IPV6_PREFIX), log_roa(roa));
free(roa);
return -1;
}
@ -712,6 +702,11 @@ rtr_parse_ipv6_prefix(struct rtr_session *rs, struct ibuf *pdu)
free(roa);
}
return 0;
badlen:
rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: bad length",
log_rtr_type(IPV6_PREFIX));
return -1;
}
static int
@ -722,24 +717,16 @@ rtr_parse_aspa(struct rtr_session *rs, struct ibuf *pdu)
struct aspa_set *aspa, *a;
uint16_t cnt, i;
if (ibuf_get(pdu, &rtr_aspa, sizeof(rtr_aspa)) == -1) {
log_warnx("rtr %s: received %s: bad pdu length",
log_rtr(rs), log_rtr_type(ASPA));
rtr_send_error(rs, CORRUPT_DATA, "bad length", pdu);
return -1;
}
if (ibuf_get(pdu, &rtr_aspa, sizeof(rtr_aspa)) == -1)
goto badlen;
cnt = ntohs(rtr_aspa.cnt);
if (ibuf_size(pdu) != cnt * sizeof(uint32_t)) {
log_warnx("rtr %s: received %s: bad pdu length",
log_rtr(rs), log_rtr_type(ASPA));
rtr_send_error(rs, CORRUPT_DATA, "bad length", pdu);
return -1;
}
if (ibuf_size(pdu) != cnt * sizeof(uint32_t))
goto badlen;
if (rs->state != RTR_STATE_EXCHANGE) {
log_warnx("rtr %s: received %s: out of context",
log_rtr(rs), log_rtr_type(ASPA));
rtr_send_error(rs, CORRUPT_DATA, "out of context", pdu);
rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: out of context",
log_rtr_type(ASPA));
return -1;
}
@ -751,9 +738,7 @@ rtr_parse_aspa(struct rtr_session *rs, struct ibuf *pdu)
/* create aspa_set entry from the rtr aspa pdu */
if ((aspa = calloc(1, sizeof(*aspa))) == NULL) {
log_warn("rtr %s: received %s",
log_rtr(rs), log_rtr_type(ASPA));
rtr_send_error(rs, INTERNAL_ERROR, "out of memory", NULL);
rtr_send_error(rs, NULL, INTERNAL_ERROR, "out of memory");
return -1;
}
aspa->as = ntohl(rtr_aspa.cas);
@ -761,20 +746,13 @@ rtr_parse_aspa(struct rtr_session *rs, struct ibuf *pdu)
if (cnt > 0) {
if ((aspa->tas = calloc(cnt, sizeof(uint32_t))) == NULL) {
free_aspa(aspa);
log_warn("rtr %s: received %s",
log_rtr(rs), log_rtr_type(ASPA));
rtr_send_error(rs, INTERNAL_ERROR, "out of memory",
NULL);
rtr_send_error(rs, NULL, INTERNAL_ERROR,
"out of memory");
return -1;
}
for (i = 0; i < cnt; i++) {
if (ibuf_get_n32(pdu, &aspa->tas[i]) == -1) {
log_warnx("rtr %s: received %s: bad pdu length",
log_rtr(rs), log_rtr_type(ASPA));
rtr_send_error(rs, CORRUPT_DATA, "bad length",
pdu);
return -1;
}
if (ibuf_get_n32(pdu, &aspa->tas[i]) == -1)
goto badlen;
}
}
@ -785,10 +763,8 @@ rtr_parse_aspa(struct rtr_session *rs, struct ibuf *pdu)
free_aspa(a);
if (RB_INSERT(aspa_tree, aspatree, aspa) != NULL) {
log_warnx("rtr %s: received %s: corrupt tree",
log_rtr(rs), log_rtr_type(ASPA));
rtr_send_error(rs, INTERNAL_ERROR,
"corrupt aspa tree", NULL);
rtr_send_error(rs, NULL, INTERNAL_ERROR,
"corrupt aspa tree");
free_aspa(aspa);
return -1;
}
@ -796,9 +772,8 @@ rtr_parse_aspa(struct rtr_session *rs, struct ibuf *pdu)
} else {
a = RB_FIND(aspa_tree, aspatree, aspa);
if (a == NULL) {
log_warnx("rtr %s: received %s: unknown withdrawal",
log_rtr(rs), log_rtr_type(ASPA));
rtr_send_error(rs, UNK_REC_WDRAWL, NULL, pdu);
rtr_send_error(rs, pdu, UNK_REC_WDRAWL, "%s %s",
log_rtr_type(ASPA), log_aspa(aspa));
free_aspa(aspa);
return -1;
}
@ -808,6 +783,11 @@ rtr_parse_aspa(struct rtr_session *rs, struct ibuf *pdu)
}
return 0;
badlen:
rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: bad length",
log_rtr_type(ASPA));
return -1;
}
static int
@ -815,20 +795,15 @@ rtr_parse_end_of_data_v0(struct rtr_session *rs, struct ibuf *pdu)
{
struct rtr_endofdata_v0 eod;
if (ibuf_get(pdu, &eod, sizeof(eod)) == -1) {
log_warnx("rtr %s: received %s: bad pdu length",
log_rtr(rs), log_rtr_type(END_OF_DATA));
rtr_send_error(rs, CORRUPT_DATA, "bad length", pdu);
return -1;
}
if (ibuf_get(pdu, &eod, sizeof(eod)) == -1)
goto badlen;
if (rtr_check_session_id(rs, rs->session_id, &eod.hdr, pdu) == -1)
return -1;
if (rs->state != RTR_STATE_EXCHANGE) {
log_warnx("rtr %s: received %s: out of context",
log_rtr(rs), log_rtr_type(END_OF_DATA));
rtr_send_error(rs, CORRUPT_DATA, "out of context", pdu);
rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: out of context",
log_rtr_type(END_OF_DATA));
return -1;
}
@ -836,6 +811,11 @@ rtr_parse_end_of_data_v0(struct rtr_session *rs, struct ibuf *pdu)
rtr_fsm(rs, RTR_EVNT_END_OF_DATA);
return 0;
badlen:
rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: bad length",
log_rtr_type(END_OF_DATA));
return -1;
}
static int
@ -848,20 +828,15 @@ rtr_parse_end_of_data(struct rtr_session *rs, struct ibuf *pdu)
if (rs->version == 0)
return rtr_parse_end_of_data_v0(rs, pdu);
if (ibuf_get(pdu, &eod, sizeof(eod)) == -1) {
log_warnx("rtr %s: received %s: bad pdu length",
log_rtr(rs), log_rtr_type(END_OF_DATA));
rtr_send_error(rs, CORRUPT_DATA, "bad length", pdu);
return -1;
}
if (ibuf_get(pdu, &eod, sizeof(eod)) == -1)
goto badlen;
if (rtr_check_session_id(rs, rs->session_id, &eod.hdr, pdu) == -1)
return -1;
if (rs->state != RTR_STATE_EXCHANGE) {
log_warnx("rtr %s: received %s: out of context",
log_rtr(rs), log_rtr_type(END_OF_DATA));
rtr_send_error(rs, CORRUPT_DATA, "out of context", pdu);
rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: out of context",
log_rtr_type(END_OF_DATA));
return -1;
}
@ -886,9 +861,13 @@ rtr_parse_end_of_data(struct rtr_session *rs, struct ibuf *pdu)
return 0;
bad:
log_warnx("rtr %s: received %s: bad timeout values",
log_rtr(rs), log_rtr_type(END_OF_DATA));
rtr_send_error(rs, CORRUPT_DATA, "bad timeout values", pdu);
rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: bad timeout values",
log_rtr_type(END_OF_DATA));
return -1;
badlen:
rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: bad length",
log_rtr_type(END_OF_DATA));
return -1;
}
@ -897,25 +876,25 @@ rtr_parse_cache_reset(struct rtr_session *rs, struct ibuf *pdu)
{
struct rtr_reset reset;
if (ibuf_get(pdu, &reset, sizeof(reset)) == -1) {
log_warnx("rtr %s: received %s: bad pdu length",
log_rtr(rs), log_rtr_type(CACHE_RESET));
rtr_send_error(rs, CORRUPT_DATA, "bad length", pdu);
return -1;
}
if (ibuf_get(pdu, &reset, sizeof(reset)) == -1)
goto badlen;
if (rtr_check_session_id(rs, 0, &reset.hdr, pdu) == -1)
return -1;
if (rs->state != RTR_STATE_ESTABLISHED) {
log_warnx("rtr %s: received %s: out of context",
log_rtr(rs), log_rtr_type(CACHE_RESET));
rtr_send_error(rs, CORRUPT_DATA, "out of context", pdu);
rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: out of context",
log_rtr_type(CACHE_RESET));
return -1;
}
rtr_fsm(rs, RTR_EVNT_CACHE_RESET);
return 0;
badlen:
rtr_send_error(rs, pdu, CORRUPT_DATA, "%s: bad length",
log_rtr_type(CACHE_RESET));
return -1;
}
static char *
@ -1062,9 +1041,9 @@ rtr_process_msg(struct rtr_session *rs)
return;
break;
default:
log_warnx("rtr %s: received %s: unsupported pdu type",
log_rtr(rs), log_rtr_type(msgtype));
rtr_send_error(rs, UNSUPP_PDU_TYPE, NULL, &msg);
/* unreachable, checked in rtr_parse_header() */
rtr_send_error(rs, &msg, UNSUPP_PDU_TYPE, "type %s",
log_rtr_type(msgtype));
return;
}
}
@ -1093,10 +1072,8 @@ rtr_fsm(struct rtr_session *rs, enum rtr_event event)
* highest version number.
*/
rs->version = RTR_MAX_VERSION;
log_warnx("rtr %s: version negotiation failed",
log_rtr(rs));
rtr_send_error(rs, UNSUPP_PROTOCOL_VERS,
NULL, NULL);
rtr_send_error(rs, NULL, UNSUPP_PROTOCOL_VERS,
"negotiation failed");
return;
}

View file

@ -1,4 +1,4 @@
/* $OpenBSD: session.c,v 1.456 2023/12/14 13:52:38 claudio Exp $ */
/* $OpenBSD: session.c,v 1.457 2024/01/10 11:08:04 claudio Exp $ */
/*
* Copyright (c) 2003, 2004, 2005 Henning Brauer <henning@openbsd.org>
@ -3576,14 +3576,25 @@ session_up(struct peer *p)
}
int
imsg_ctl_parent(int type, uint32_t peerid, pid_t pid, void *data,
uint16_t datalen)
imsg_ctl_parent(struct imsg *imsg)
{
return imsg_compose(ibuf_main, type, peerid, pid, -1, data, datalen);
return imsg_forward(ibuf_main, imsg);
}
int
imsg_ctl_rde(int type, uint32_t peerid, pid_t pid, void *data, uint16_t datalen)
imsg_ctl_rde(struct imsg *imsg)
{
if (ibuf_rde_ctl == NULL)
return (0);
/*
* Use control socket to talk to RDE to bypass the queue of the
* regular imsg socket.
*/
return imsg_forward(ibuf_rde_ctl, imsg);
}
int
imsg_ctl_rde_msg(int type, uint32_t peerid, pid_t pid)
{
if (ibuf_rde_ctl == NULL)
return (0);
@ -3592,7 +3603,7 @@ imsg_ctl_rde(int type, uint32_t peerid, pid_t pid, void *data, uint16_t datalen)
* Use control socket to talk to RDE to bypass the queue of the
* regular imsg socket.
*/
return imsg_compose(ibuf_rde_ctl, type, peerid, pid, -1, data, datalen);
return imsg_compose(ibuf_rde_ctl, type, peerid, pid, -1, NULL, 0);
}
int

View file

@ -1,4 +1,4 @@
/* $OpenBSD: session.h,v 1.164 2023/10/19 07:02:46 claudio Exp $ */
/* $OpenBSD: session.h,v 1.165 2024/01/10 11:08:04 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@ -339,8 +339,9 @@ struct peer *getpeerbydesc(struct bgpd_config *, const char *);
struct peer *getpeerbyip(struct bgpd_config *, struct sockaddr *);
struct peer *getpeerbyid(struct bgpd_config *, uint32_t);
int peer_matched(struct peer *, struct ctl_neighbor *);
int imsg_ctl_parent(int, uint32_t, pid_t, void *, uint16_t);
int imsg_ctl_rde(int, uint32_t, pid_t, void *, uint16_t);
int imsg_ctl_parent(struct imsg *);
int imsg_ctl_rde(struct imsg *);
int imsg_ctl_rde_msg(int, uint32_t, pid_t);
void session_stop(struct peer *, uint8_t);
/* timer.c */

View file

@ -1,4 +1,4 @@
/* $OpenBSD: util.c,v 1.77 2023/04/17 08:02:21 claudio Exp $ */
/* $OpenBSD: util.c,v 1.78 2024/01/10 13:31:09 claudio Exp $ */
/*
* Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org>
@ -165,6 +165,76 @@ log_reason(const char *communication) {
return buf;
}
static const char *
log_expires(time_t expires)
{
static char buf[32];
buf[0] = '\0';
if (expires != 0)
snprintf(buf, sizeof(buf), " expires %lld", (long long)expires);
return buf;
}
const char *
log_roa(struct roa *roa)
{
static char buf[256];
struct bgpd_addr addr = { .aid = roa->aid, .v6 = roa->prefix.inet6 };
char maxbuf[32];
maxbuf[0] = '\0';
if (roa->prefixlen != roa->maxlen)
snprintf(maxbuf, sizeof(maxbuf), " maxlen %u", roa->maxlen);
snprintf(buf, sizeof(buf), "%s/%u%s source-as %u%s", log_addr(&addr),
roa->prefixlen, maxbuf, roa->asnum, log_expires(roa->expires));
return buf;
}
const char *
log_aspa(struct aspa_set *aspa)
{
static char errbuf[256];
static char *buf;
static size_t len;
char asbuf[16];
size_t needed;
uint32_t i;
/* include enough space for header and trailer */
if ((uint64_t)aspa->num > (SIZE_MAX / sizeof(asbuf) - 72))
goto fail;
needed = aspa->num * sizeof(asbuf) + 72;
if (needed > len) {
char *nbuf;
if ((nbuf = realloc(buf, needed)) == NULL)
goto fail;
len = needed;
buf = nbuf;
}
snprintf(buf, len, "customer-as %s%s provider-as { ",
log_as(aspa->as), log_expires(aspa->expires));
for (i = 0; i < aspa->num; i++) {
snprintf(asbuf, sizeof(asbuf), "%s ", log_as(aspa->tas[i]));
if (strlcat(buf, asbuf, len) >= len)
goto fail;
}
if (strlcat(buf, "}", len) >= len)
goto fail;
return buf;
fail:
free(buf);
buf = NULL;
len = 0;
snprintf(errbuf, sizeof(errbuf), "customer-as %s%s provider-as { ... }",
log_as(aspa->as), log_expires(aspa->expires));
return errbuf;
}
const char *
log_rtr_error(enum rtr_error err)
{