This commit is contained in:
purplerain 2025-02-05 06:25:40 +00:00
parent 54eb3e7d48
commit 55a56ce945
Signed by: purplerain
GPG key ID: F42C07F07E2E35B7
16 changed files with 572 additions and 110 deletions

View file

@ -2773,8 +2773,8 @@ install_sets() {
# Set default location to the first cdrom device if any are found. # Set default location to the first cdrom device if any are found.
[[ -n $_cddevs ]] && : ${_d:=cd0} [[ -n $_cddevs ]] && : ${_d:=cd0}
# In case none of the above applied, set HTTP as default location. # In case none of the above applied, set disk as default location.
: ${_d:=http} : ${_d:=disk}
# If the default location set so far is not one of the cdrom devices or # If the default location set so far is not one of the cdrom devices or
# is not in the list of valid locations, set a sane default. # is not in the list of valid locations, set a sane default.

View file

@ -3,5 +3,4 @@
# sh/ksh initialization # sh/ksh initialization
PATH=$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin PATH=$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin
export PS1="\[\033[38;5;69m\]┌─(\[\033[38;5;15m\]\u\[\033[38;5;69m\]@\[\033[38;5;15m\]\h\[\033[38;5;69m\])\[\033[38;5;69m\]─[\[\033[38;5;69m\]\w\[\033[38;5;69m\]]\n\[\033[38;5;69m\]└─$\[$(tput sgr0)\] "
export PATH HOME TERM export PATH HOME TERM

View file

@ -1,4 +1,4 @@
/* $OpenBSD: bn_recp.c,v 1.30 2025/01/22 12:53:16 tb Exp $ */ /* $OpenBSD: bn_recp.c,v 1.33 2025/02/04 20:22:20 tb Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved. * All rights reserved.
* *
@ -104,34 +104,6 @@ BN_RECP_CTX_free(BN_RECP_CTX *recp)
freezero(recp, sizeof(*recp)); freezero(recp, sizeof(*recp));
} }
/* len is the expected size of the result
* We actually calculate with an extra word of precision, so
* we can do faster division if the remainder is not required.
*/
/* r := 2^len / m */
static int
BN_reciprocal(BIGNUM *r, const BIGNUM *m, int len, BN_CTX *ctx)
{
int ret = -1;
BIGNUM *t;
BN_CTX_start(ctx);
if ((t = BN_CTX_get(ctx)) == NULL)
goto err;
if (!BN_set_bit(t, len))
goto err;
if (!BN_div_ct(r, NULL, t, m, ctx))
goto err;
ret = len;
err:
BN_CTX_end(ctx);
return ret;
}
int int
BN_div_reciprocal(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, BN_RECP_CTX *recp, BN_div_reciprocal(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, BN_RECP_CTX *recp,
BN_CTX *ctx) BN_CTX *ctx)
@ -139,34 +111,33 @@ BN_div_reciprocal(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, BN_RECP_CTX *recp,
int i, j, ret = 0; int i, j, ret = 0;
BIGNUM *a, *b, *d, *r; BIGNUM *a, *b, *d, *r;
BN_CTX_start(ctx);
a = BN_CTX_get(ctx);
b = BN_CTX_get(ctx);
if (dv != NULL)
d = dv;
else
d = BN_CTX_get(ctx);
if (rem != NULL)
r = rem;
else
r = BN_CTX_get(ctx);
if (a == NULL || b == NULL || d == NULL || r == NULL)
goto err;
if (BN_ucmp(m, recp->N) < 0) { if (BN_ucmp(m, recp->N) < 0) {
BN_zero(d); if (dv != NULL)
if (!bn_copy(r, m)) { BN_zero(dv);
BN_CTX_end(ctx); if (rem != NULL)
return 0; return bn_copy(rem, m);
}
BN_CTX_end(ctx);
return 1; return 1;
} }
/* We want the remainder BN_CTX_start(ctx);
* Given input of ABCDEF / ab if ((a = BN_CTX_get(ctx)) == NULL)
* we need multiply ABCDEF by 3 digests of the reciprocal of ab goto err;
* if ((b = BN_CTX_get(ctx)) == NULL)
goto err;
if ((d = dv) == NULL)
d = BN_CTX_get(ctx);
if (d == NULL)
goto err;
if ((r = rem) == NULL)
r = BN_CTX_get(ctx);
if (r == NULL)
goto err;
/*
* We want the remainder. Given input of ABCDEF / ab we need to
* multiply ABCDEF by 3 digits of the reciprocal of ab.
*/ */
/* i := max(BN_num_bits(m), 2*BN_num_bits(N)) */ /* i := max(BN_num_bits(m), 2*BN_num_bits(N)) */
@ -175,18 +146,21 @@ BN_div_reciprocal(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, BN_RECP_CTX *recp,
if (j > i) if (j > i)
i = j; i = j;
/* Nr := round(2^i / N) */ /* Compute Nr := (1 << i) / N if necessary. */
if (i != recp->shift) if (i != recp->shift) {
recp->shift = BN_reciprocal(recp->Nr, recp->N, i, ctx); BN_zero(recp->Nr);
if (!BN_set_bit(recp->Nr, i))
goto err;
if (!BN_div_ct(recp->Nr, NULL, recp->Nr, recp->N, ctx))
goto err;
recp->shift = i;
}
/* BN_reciprocal returns i, or -1 for an error */ /*
if (recp->shift == -1) * d := |((m >> BN_num_bits(N)) * recp->Nr) >> (i - BN_num_bits(N))|
goto err; * = |((m >> BN_num_bits(N)) * (1 << i) / N) >> (i - BN_num_bits(N))|
* <= |(m / 2^BN_num_bits(N)) * (2^i / N) * 2^BN_num_bits(N) / 2^i |
/* d := |round(round(m / 2^BN_num_bits(N)) * recp->Nr / 2^(i - BN_num_bits(N)))| * = |m / N|
* = |round(round(m / 2^BN_num_bits(N)) * round(2^i / N) / 2^(i - BN_num_bits(N)))|
* <= |(m / 2^BN_num_bits(N)) * (2^i / N) * (2^BN_num_bits(N) / 2^i)|
* = |m/N|
*/ */
if (!BN_rshift(a, m, recp->num_bits)) if (!BN_rshift(a, m, recp->num_bits))
goto err; goto err;

View file

@ -1,4 +1,4 @@
/* $OpenBSD: evp_pkey.c,v 1.32 2024/08/31 10:25:38 tb Exp $ */ /* $OpenBSD: evp_pkey.c,v 1.33 2025/02/04 04:51:34 tb Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 1999. * project 1999.
*/ */
@ -58,6 +58,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <openssl/err.h> #include <openssl/err.h>
#include <openssl/x509.h> #include <openssl/x509.h>
@ -84,7 +85,8 @@ EVP_PKCS82PKEY(const PKCS8_PRIV_KEY_INFO *p8)
if (!EVP_PKEY_set_type(pkey, OBJ_obj2nid(algoid))) { if (!EVP_PKEY_set_type(pkey, OBJ_obj2nid(algoid))) {
EVPerror(EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM); EVPerror(EVP_R_UNSUPPORTED_PRIVATE_KEY_ALGORITHM);
i2t_ASN1_OBJECT(obj_tmp, 80, algoid); if (i2t_ASN1_OBJECT(obj_tmp, sizeof(obj_tmp), algoid) == 0)
(void)strlcpy(obj_tmp, "unknown", sizeof(obj_tmp));
ERR_asprintf_error_data("TYPE=%s", obj_tmp); ERR_asprintf_error_data("TYPE=%s", obj_tmp);
goto error; goto error;
} }

View file

@ -1,4 +1,4 @@
.\" $OpenBSD: SSL_CTX_set_alpn_select_cb.3,v 1.10 2024/07/11 13:50:44 tb Exp $ .\" $OpenBSD: SSL_CTX_set_alpn_select_cb.3,v 1.11 2025/02/04 14:00:05 tb Exp $
.\" OpenSSL 87b81496 Apr 19 12:38:27 2017 -0400 .\" OpenSSL 87b81496 Apr 19 12:38:27 2017 -0400
.\" OpenSSL b97fdb57 Nov 11 09:33:09 2016 +0100 .\" OpenSSL b97fdb57 Nov 11 09:33:09 2016 +0100
.\" .\"
@ -49,7 +49,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
.\" OF THE POSSIBILITY OF SUCH DAMAGE. .\" OF THE POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.Dd $Mdocdate: July 11 2024 $ .Dd $Mdocdate: February 4 2025 $
.Dt SSL_CTX_SET_ALPN_SELECT_CB 3 .Dt SSL_CTX_SET_ALPN_SELECT_CB 3
.Os .Os
.Sh NAME .Sh NAME
@ -215,7 +215,7 @@ variable.
.Pp .Pp
For example: For example:
.Bd -literal .Bd -literal
const unsigned char *vector = "\e6" "spdy/1" "\e8" "http/1.1"; const unsigned char *vector = "\ex06" "spdy/1" "\ex08" "http/1.1";
unsigned int length = strlen(vector); unsigned int length = strlen(vector);
.Ed .Ed
.Pp .Pp

View file

@ -1,4 +1,4 @@
/* $OpenBSD: tcpthread.c,v 1.3 2025/01/13 12:55:13 bluhm Exp $ */ /* $OpenBSD: tcpthread.c,v 1.4 2025/02/04 22:00:20 bluhm Exp $ */
/* /*
* Copyright (c) 2025 Alexander Bluhm <bluhm@openbsd.org> * Copyright (c) 2025 Alexander Bluhm <bluhm@openbsd.org>
@ -114,9 +114,15 @@ connect_socket(volatile int *connectp, struct sockaddr *addr)
IPPROTO_TCP); IPPROTO_TCP);
if (sock < 0) if (sock < 0)
err(1, "%s: socket", __func__); err(1, "%s: socket", __func__);
if (connect(sock, addr, addr->sa_len) < 0 && if (connect(sock, addr, addr->sa_len) < 0) {
errno != EINPROGRESS) { if (errno == EADDRNOTAVAIL) {
err(1, "%s: connect %d", __func__, sock); /* kernel did run out of ports, ignore error */
if (close(sock) < 0)
err(1, "%s: close %d", __func__, sock);
return 0;
}
if (errno != EINPROGRESS)
err(1, "%s: connect %d", __func__, sock);
} }
if ((int)atomic_cas_uint(connectp, -1, sock) != -1) { if ((int)atomic_cas_uint(connectp, -1, sock) != -1) {
/* another thread has connect slot n */ /* another thread has connect slot n */

View file

@ -1,4 +1,4 @@
/* $OpenBSD: if_iwm.c,v 1.417 2024/09/01 03:08:59 jsg Exp $ */ /* $OpenBSD: if_iwm.c,v 1.418 2025/02/04 09:15:04 stsp Exp $ */
/* /*
* Copyright (c) 2014, 2016 genua gmbh <info@genua.de> * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>
@ -8529,7 +8529,7 @@ iwm_scan(struct iwm_softc *sc)
* The current mode might have been fixed during association. * The current mode might have been fixed during association.
* Ensure all channels get scanned. * Ensure all channels get scanned.
*/ */
if (IFM_SUBTYPE(ic->ic_media.ifm_cur->ifm_media) == IFM_AUTO) if (IFM_MODE(ic->ic_media.ifm_cur->ifm_media) == IFM_AUTO)
ieee80211_setmode(ic, IEEE80211_MODE_AUTO); ieee80211_setmode(ic, IEEE80211_MODE_AUTO);
sc->sc_flags |= IWM_FLAG_SCANNING; sc->sc_flags |= IWM_FLAG_SCANNING;

View file

@ -1,4 +1,4 @@
/* $OpenBSD: if_iwn.c,v 1.263 2024/05/24 06:02:53 jsg Exp $ */ /* $OpenBSD: if_iwn.c,v 1.264 2025/02/04 09:15:04 stsp Exp $ */
/*- /*-
* Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr> * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr>
@ -5356,7 +5356,7 @@ iwn_scan(struct iwn_softc *sc, uint16_t flags, int bgscan)
* The current mode might have been fixed during association. * The current mode might have been fixed during association.
* Ensure all channels get scanned. * Ensure all channels get scanned.
*/ */
if (IFM_SUBTYPE(ic->ic_media.ifm_cur->ifm_media) == IFM_AUTO) if (IFM_MODE(ic->ic_media.ifm_cur->ifm_media) == IFM_AUTO)
ieee80211_setmode(ic, IEEE80211_MODE_AUTO); ieee80211_setmode(ic, IEEE80211_MODE_AUTO);
sc->sc_flags |= IWN_FLAG_SCANNING; sc->sc_flags |= IWN_FLAG_SCANNING;

View file

@ -1,4 +1,4 @@
/* $OpenBSD: if_iwx.c,v 1.188 2024/11/08 09:12:46 kettenis Exp $ */ /* $OpenBSD: if_iwx.c,v 1.189 2025/02/04 09:15:04 stsp Exp $ */
/* /*
* Copyright (c) 2014, 2016 genua gmbh <info@genua.de> * Copyright (c) 2014, 2016 genua gmbh <info@genua.de>
@ -7877,7 +7877,7 @@ iwx_scan(struct iwx_softc *sc)
* The current mode might have been fixed during association. * The current mode might have been fixed during association.
* Ensure all channels get scanned. * Ensure all channels get scanned.
*/ */
if (IFM_SUBTYPE(ic->ic_media.ifm_cur->ifm_media) == IFM_AUTO) if (IFM_MODE(ic->ic_media.ifm_cur->ifm_media) == IFM_AUTO)
ieee80211_setmode(ic, IEEE80211_MODE_AUTO); ieee80211_setmode(ic, IEEE80211_MODE_AUTO);
sc->sc_flags |= IWX_FLAG_SCANNING; sc->sc_flags |= IWX_FLAG_SCANNING;

View file

@ -1,4 +1,4 @@
/* $OpenBSD: bgpd.h,v 1.511 2025/01/31 13:40:23 claudio Exp $ */ /* $OpenBSD: bgpd.h,v 1.512 2025/02/04 18:16:56 denis Exp $ */
/* /*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@ -25,6 +25,7 @@
#include <netinet/in.h> #include <netinet/in.h>
#include <arpa/inet.h> #include <arpa/inet.h>
#include <net/if.h> #include <net/if.h>
#include <netinet/if_ether.h>
#include <poll.h> #include <poll.h>
#include <stdarg.h> #include <stdarg.h>
@ -197,15 +198,33 @@ extern const struct aid aid_vals[];
{ AFI_IPv6, AF_INET6, SAFI_MPLSVPN, "IPv6 vpn" }, \ { AFI_IPv6, AF_INET6, SAFI_MPLSVPN, "IPv6 vpn" }, \
{ AFI_IPv4, AF_INET, SAFI_FLOWSPEC, "IPv4 flowspec" }, \ { AFI_IPv4, AF_INET, SAFI_FLOWSPEC, "IPv4 flowspec" }, \
{ AFI_IPv6, AF_INET6, SAFI_FLOWSPEC, "IPv6 flowspec" }, \ { AFI_IPv6, AF_INET6, SAFI_FLOWSPEC, "IPv6 flowspec" }, \
{ AFI_L2VPN, AF_UNSPEC, SAFI_EVPN, "L2VPN evpn" } \ { AFI_L2VPN, AF_UNSPEC, SAFI_EVPN, "EVPN" }, \
} }
#define BGP_MPLS_BOS 0x01 #define BGP_MPLS_BOS 0x01
#define ESI_ADDR_LEN 10
#define EVPN_ROUTE_TYPE_2 0x02
#define EVPN_ROUTE_TYPE_3 0x03
#define EVPN_ROUTE_TYPE_5 0x05
struct evpn_addr {
union {
struct in_addr v4;
struct in6_addr v6;
};
uint32_t ethtag;
uint8_t mac[ETHER_ADDR_LEN];
uint8_t esi[ESI_ADDR_LEN];
uint8_t aid;
uint8_t type;
};
struct bgpd_addr { struct bgpd_addr {
union { union {
struct in_addr v4; struct in_addr v4;
struct in6_addr v6; struct in6_addr v6;
struct evpn_addr evpn;
/* maximum size for a prefix is 256 bits */ /* maximum size for a prefix is 256 bits */
}; /* 128-bit address */ }; /* 128-bit address */
uint64_t rd; /* route distinguisher for VPN addrs */ uint64_t rd; /* route distinguisher for VPN addrs */
@ -1578,6 +1597,8 @@ time_t getmonotime(void);
/* util.c */ /* util.c */
char *ibuf_get_string(struct ibuf *, size_t); char *ibuf_get_string(struct ibuf *, size_t);
const char *log_addr(const struct bgpd_addr *); const char *log_addr(const struct bgpd_addr *);
const char *log_evpnaddr(const struct bgpd_addr *, struct sockaddr *,
socklen_t);
const char *log_in6addr(const struct in6_addr *); const char *log_in6addr(const struct in6_addr *);
const char *log_sockaddr(struct sockaddr *, socklen_t); const char *log_sockaddr(struct sockaddr *, socklen_t);
const char *log_as(uint32_t); const char *log_as(uint32_t);
@ -1605,6 +1626,7 @@ int nlri_get_vpn4(struct ibuf *, struct bgpd_addr *, uint8_t *,
int); int);
int nlri_get_vpn6(struct ibuf *, struct bgpd_addr *, uint8_t *, int nlri_get_vpn6(struct ibuf *, struct bgpd_addr *, uint8_t *,
int); int);
int nlri_get_evpn(struct ibuf *, struct bgpd_addr *, uint8_t *);
int prefix_compare(const struct bgpd_addr *, int prefix_compare(const struct bgpd_addr *,
const struct bgpd_addr *, int); const struct bgpd_addr *, int);
void inet4applymask(struct in_addr *, const struct in_addr *, int); void inet4applymask(struct in_addr *, const struct in_addr *, int);

View file

@ -1,4 +1,4 @@
/* $OpenBSD: kroute.c,v 1.312 2025/01/27 15:22:11 claudio Exp $ */ /* $OpenBSD: kroute.c,v 1.313 2025/02/04 16:07:46 claudio Exp $ */
/* /*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@ -1338,13 +1338,8 @@ ktable_postload(void)
if (kt->state == RECONF_DELETE) { if (kt->state == RECONF_DELETE) {
ktable_free(i - 1); ktable_free(i - 1);
continue; continue;
} else if (kt->state == RECONF_REINIT) { } else if (kt->state == RECONF_REINIT)
if (kt->fib_sync != kt->fib_conf) { kt->fib_sync = kt->fib_conf;
kt->fib_sync = kt->fib_conf;
if (kt->fib_sync)
fetchtable(kt);
}
}
/* cleanup old networks */ /* cleanup old networks */
TAILQ_FOREACH_SAFE(n, &kt->krn, entry, xn) { TAILQ_FOREACH_SAFE(n, &kt->krn, entry, xn) {

View file

@ -1,4 +1,4 @@
/* $OpenBSD: parse.y,v 1.478 2025/01/31 13:40:23 claudio Exp $ */ /* $OpenBSD: parse.y,v 1.479 2025/02/04 18:16:56 denis Exp $ */
/* /*
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@ -267,7 +267,7 @@ typedef struct {
%token PREPEND_SELF PREPEND_PEER PFTABLE WEIGHT RTLABEL ORIGIN PRIORITY %token PREPEND_SELF PREPEND_PEER PFTABLE WEIGHT RTLABEL ORIGIN PRIORITY
%token ERROR INCLUDE %token ERROR INCLUDE
%token IPSEC ESP AH SPI IKE %token IPSEC ESP AH SPI IKE
%token IPV4 IPV6 %token IPV4 IPV6 EVPN
%token QUALIFY VIA %token QUALIFY VIA
%token NE LE GE XRANGE LONGER MAXLEN MAX %token NE LE GE XRANGE LONGER MAXLEN MAX
%token <v.string> STRING %token <v.string> STRING
@ -1970,6 +1970,12 @@ peeropts : REMOTEAS as4number {
curpeer->conf.capabilities.mp[aid] = 1; curpeer->conf.capabilities.mp[aid] = 1;
} }
} }
| ANNOUNCE EVPN enforce {
if ($3)
curpeer->conf.capabilities.mp[AID_EVPN] = 2;
else
curpeer->conf.capabilities.mp[AID_EVPN] = 1;
}
| ANNOUNCE REFRESH yesnoenforce { | ANNOUNCE REFRESH yesnoenforce {
curpeer->conf.capabilities.refresh = $3; curpeer->conf.capabilities.refresh = $3;
} }
@ -3546,6 +3552,7 @@ lookup(char *s)
/* this has to be sorted always */ /* this has to be sorted always */
static const struct keywords keywords[] = { static const struct keywords keywords[] = {
{ "AS", AS }, { "AS", AS },
{ "EVPN", EVPN },
{ "IPv4", IPV4 }, { "IPv4", IPV4 },
{ "IPv6", IPV6 }, { "IPv6", IPV6 },
{ "add-path", ADDPATH }, { "add-path", ADDPATH },

View file

@ -1,4 +1,4 @@
/* $OpenBSD: rde.c,v 1.650 2025/01/27 15:22:11 claudio Exp $ */ /* $OpenBSD: rde.c,v 1.651 2025/02/04 18:16:56 denis Exp $ */
/* /*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@ -1596,6 +1596,16 @@ rde_update_dispatch(struct rde_peer *peer, struct ibuf *buf)
goto done; goto done;
} }
break; break;
case AID_EVPN:
if (nlri_get_evpn(&unreachbuf,
&prefix, &prefixlen) == -1) {
log_peer_warnx(&peer->conf,
"bad EVPN withdraw prefix");
rde_update_err(peer, ERR_UPDATE,
ERR_UPD_OPTATTR, &unreachbuf);
goto done;
}
break;
case AID_FLOWSPECv4: case AID_FLOWSPECv4:
case AID_FLOWSPECv6: case AID_FLOWSPECv6:
/* ignore flowspec for now */ /* ignore flowspec for now */
@ -1790,6 +1800,16 @@ rde_update_dispatch(struct rde_peer *peer, struct ibuf *buf)
goto done; goto done;
} }
break; break;
case AID_EVPN:
if (nlri_get_evpn(&reachbuf,
&prefix, &prefixlen) == -1) {
log_peer_warnx(&peer->conf,
"bad EVPN nlri prefix");
rde_update_err(peer, ERR_UPDATE,
ERR_UPD_OPTATTR, &reachbuf);
goto done;
}
break;
case AID_FLOWSPECv4: case AID_FLOWSPECv4:
case AID_FLOWSPECv6: case AID_FLOWSPECv6:
/* ignore flowspec for now */ /* ignore flowspec for now */
@ -2517,6 +2537,36 @@ rde_get_mp_nexthop(struct ibuf *buf, uint8_t aid,
} }
} }
break; break;
case AID_EVPN:
switch (nhlen) {
case 4:
if (ibuf_get_h32(&nhbuf, &nexthop.v4.s_addr) == -1)
return (-1);
nexthop.aid = AID_INET;
break;
case 16:
case 32:
if (ibuf_get(&nhbuf, &nexthop.v6,
sizeof(nexthop.v6)) == -1)
return (-1);
nexthop.aid = AID_INET6;
if (IN6_IS_ADDR_LINKLOCAL(&nexthop.v6)) {
if (peer->local_if_scope != 0) {
nexthop.scope_id = peer->local_if_scope;
} else {
log_peer_warnx(&peer->conf,
"unexpected link-local nexthop: %s",
log_addr(&nexthop));
return (-1);
}
}
break;
default:
log_peer_warnx(&peer->conf, "bad %s nexthop, "
"bad size %d", aid2str(aid), nhlen);
return (-1);
}
break;
case AID_FLOWSPECv4: case AID_FLOWSPECv4:
case AID_FLOWSPECv6: case AID_FLOWSPECv6:
/* nexthop must be 0 and ignored for flowspec */ /* nexthop must be 0 and ignored for flowspec */

View file

@ -1,4 +1,4 @@
/* $OpenBSD: rde_prefix.c,v 1.56 2024/12/30 17:14:02 denis Exp $ */ /* $OpenBSD: rde_prefix.c,v 1.57 2025/02/04 18:16:56 denis Exp $ */
/* /*
* Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org> * Copyright (c) 2003, 2004 Claudio Jeker <claudio@openbsd.org>
@ -95,6 +95,26 @@ struct pt_entry_vpn6 {
uint8_t pad2; uint8_t pad2;
}; };
struct pt_entry_evpn {
RB_ENTRY(pt_entry) pt_e;
uint8_t aid;
uint8_t prefixlen;
uint16_t len;
uint32_t refcnt;
uint64_t rd;
uint32_t ethtag;
uint8_t esi[ESI_ADDR_LEN];
uint8_t mac[ETHER_ADDR_LEN];
uint8_t labelstack[6];
uint8_t labellen;
uint8_t type;
uint8_t vpnaid;
union {
struct in_addr prefix4;
struct in6_addr prefix6;
};
};
struct pt_entry_flow { struct pt_entry_flow {
RB_ENTRY(pt_entry) pt_e; RB_ENTRY(pt_entry) pt_e;
uint8_t aid; uint8_t aid;
@ -130,6 +150,7 @@ void
pt_getaddr(struct pt_entry *pte, struct bgpd_addr *addr) pt_getaddr(struct pt_entry *pte, struct bgpd_addr *addr)
{ {
struct pt_entry_flow *pflow; struct pt_entry_flow *pflow;
struct pt_entry_evpn *evpn;
memset(addr, 0, sizeof(struct bgpd_addr)); memset(addr, 0, sizeof(struct bgpd_addr));
addr->aid = pte->aid; addr->aid = pte->aid;
@ -157,6 +178,25 @@ pt_getaddr(struct pt_entry *pte, struct bgpd_addr *addr)
((struct pt_entry_vpn6 *)pte)->labelstack, ((struct pt_entry_vpn6 *)pte)->labelstack,
addr->labellen); addr->labellen);
break; break;
case AID_EVPN:
evpn = (struct pt_entry_evpn *)pte;
addr->evpn.type = evpn->type;
addr->rd = evpn->rd;
addr->evpn.ethtag = evpn->ethtag;
addr->labellen = evpn->labellen;
addr->evpn.aid = evpn->vpnaid;
memcpy(addr->labelstack, evpn->labelstack, addr->labellen);
memcpy(addr->evpn.esi, evpn->esi, sizeof(evpn->esi));
memcpy(addr->evpn.mac, evpn->mac, sizeof(evpn->mac));
switch (evpn->vpnaid) {
case AID_INET:
addr->evpn.v4 = evpn->prefix4;
break;
case AID_INET6:
addr->evpn.v6 = evpn->prefix6;
break;
}
break;
case AID_FLOWSPECv4: case AID_FLOWSPECv4:
case AID_FLOWSPECv6: case AID_FLOWSPECv6:
pflow = (struct pt_entry_flow *)pte; pflow = (struct pt_entry_flow *)pte;
@ -192,6 +232,7 @@ pt_fill(struct bgpd_addr *prefix, int prefixlen)
static struct pt_entry6 pte6; static struct pt_entry6 pte6;
static struct pt_entry_vpn4 pte_vpn4; static struct pt_entry_vpn4 pte_vpn4;
static struct pt_entry_vpn6 pte_vpn6; static struct pt_entry_vpn6 pte_vpn6;
static struct pt_entry_evpn pte_evpn;
switch (prefix->aid) { switch (prefix->aid) {
case AID_INET: case AID_INET:
@ -242,6 +283,37 @@ pt_fill(struct bgpd_addr *prefix, int prefixlen)
memcpy(pte_vpn6.labelstack, prefix->labelstack, memcpy(pte_vpn6.labelstack, prefix->labelstack,
prefix->labellen); prefix->labellen);
return ((struct pt_entry *)&pte_vpn6); return ((struct pt_entry *)&pte_vpn6);
case AID_EVPN:
memset(&pte_evpn, 0, sizeof(pte_evpn));
pte_evpn.len = sizeof(pte_evpn);
pte_evpn.refcnt = UINT32_MAX;
switch (prefix->evpn.aid) {
case AID_UNSPEC:
/* See rfc7432 section 7.2 */
break;
case AID_INET:
pte_evpn.prefix4 = prefix->evpn.v4;
break;
case AID_INET6:
pte_evpn.prefix6 = prefix->evpn.v6;
break;
default:
fatalx("pt_fill: bad EVPN prefixlen");
}
pte_evpn.aid = prefix->aid;
pte_evpn.vpnaid = prefix->evpn.aid;
pte_evpn.prefixlen = prefixlen;
pte_evpn.type = prefix->evpn.type;
pte_evpn.rd = prefix->rd;
pte_evpn.ethtag = prefix->evpn.ethtag;
pte_evpn.labellen = prefix->labellen;
memcpy(pte_evpn.labelstack, prefix->labelstack,
pte_evpn.labellen);
memcpy(pte_evpn.esi, prefix->evpn.esi,
sizeof(prefix->evpn.esi));
memcpy(pte_evpn.mac, prefix->evpn.mac,
sizeof(prefix->evpn.mac));
return ((struct pt_entry *)&pte_evpn);
default: default:
fatalx("pt_fill: unknown af"); fatalx("pt_fill: unknown af");
} }
@ -357,6 +429,7 @@ pt_prefix_cmp(const struct pt_entry *a, const struct pt_entry *b)
const struct pt_entry_vpn4 *va4, *vb4; const struct pt_entry_vpn4 *va4, *vb4;
const struct pt_entry_vpn6 *va6, *vb6; const struct pt_entry_vpn6 *va6, *vb6;
const struct pt_entry_flow *af, *bf; const struct pt_entry_flow *af, *bf;
const struct pt_entry_evpn *ea, *eb;
int i; int i;
if (a->aid > b->aid) if (a->aid > b->aid)
@ -425,6 +498,47 @@ pt_prefix_cmp(const struct pt_entry *a, const struct pt_entry *b)
if (va6->prefixlen < vb6->prefixlen) if (va6->prefixlen < vb6->prefixlen)
return (-1); return (-1);
return (0); return (0);
case AID_EVPN:
/* XXXX Need different comparator for different types */
ea = (const struct pt_entry_evpn *)a;
eb = (const struct pt_entry_evpn *)b;
if (ea->ethtag > eb->ethtag)
return (1);
if (ea->ethtag < eb->ethtag)
return (-1);
/* MAC length is always 48 */
i = memcmp(&ea->mac, &eb->mac, sizeof(ea->mac));
if (i > 0)
return (1);
if (i < 0)
return (-1);
if (ea->prefixlen > eb->prefixlen)
return (1);
if (ea->prefixlen < eb->prefixlen)
return (-1);
switch (ea->vpnaid) {
case AID_UNSPEC:
break;
case AID_INET:
i = memcmp(&ea->prefix4, &eb->prefix4,
sizeof(struct in_addr));
if (i > 0)
return (1);
if (i < 0)
return (-1);
break;
case AID_INET6:
i = memcmp(&ea->prefix6, &eb->prefix6,
sizeof(struct in6_addr));
if (i > 0)
return (1);
if (i < 0)
return (-1);
break;
default:
fatalx("pt_prefix_cmp: unknown evpn af %d", ea->vpnaid);
}
return (0);
case AID_FLOWSPECv4: case AID_FLOWSPECv4:
case AID_FLOWSPECv6: case AID_FLOWSPECv6:
af = (const struct pt_entry_flow *)a; af = (const struct pt_entry_flow *)a;
@ -433,7 +547,7 @@ pt_prefix_cmp(const struct pt_entry *a, const struct pt_entry *b)
bf->flow, bf->len - PT_FLOW_SIZE, bf->flow, bf->len - PT_FLOW_SIZE,
a->aid == AID_FLOWSPECv6); a->aid == AID_FLOWSPECv6);
default: default:
fatalx("pt_prefix_cmp: unknown af"); fatalx("pt_prefix_cmp: unknown af %d", a->aid);
} }
return (-1); return (-1);
} }
@ -474,9 +588,10 @@ pt_writebuf(struct ibuf *buf, struct pt_entry *pte, int withdraw,
struct pt_entry_vpn4 *pvpn4 = (struct pt_entry_vpn4 *)pte; struct pt_entry_vpn4 *pvpn4 = (struct pt_entry_vpn4 *)pte;
struct pt_entry_vpn6 *pvpn6 = (struct pt_entry_vpn6 *)pte; struct pt_entry_vpn6 *pvpn6 = (struct pt_entry_vpn6 *)pte;
struct pt_entry_flow *pflow = (struct pt_entry_flow *)pte; struct pt_entry_flow *pflow = (struct pt_entry_flow *)pte;
struct pt_entry_evpn *pevpn = (struct pt_entry_evpn *)pte;
struct ibuf *tmp; struct ibuf *tmp;
int flowlen, psize; int flowlen, psize;
uint8_t plen; uint16_t plen;
if ((tmp = ibuf_dynamic(32, UINT16_MAX)) == NULL) if ((tmp = ibuf_dynamic(32, UINT16_MAX)) == NULL)
goto fail; goto fail;
@ -549,6 +664,80 @@ pt_writebuf(struct ibuf *buf, struct pt_entry *pte, int withdraw,
ibuf_add(tmp, &pvpn6->prefix6, psize) == -1) ibuf_add(tmp, &pvpn6->prefix6, psize) == -1)
goto fail; goto fail;
break; break;
case AID_EVPN:
if (ibuf_add_n8(tmp, pevpn->type) == -1)
goto fail;
switch (pevpn->type) {
case EVPN_ROUTE_TYPE_2:
plen = sizeof(pevpn->rd) * 8;
plen += sizeof(pevpn->esi) * 8;
plen += sizeof(pevpn->ethtag) * 8;
plen += 8; /* MAC length */
plen += sizeof(pevpn->mac) * 8;
plen += 8; /* IP length */
plen += pevpn->prefixlen;
plen += pevpn->labellen * 8;
if (ibuf_add_n8(tmp, PREFIX_SIZE(plen) - 1) == -1)
goto fail;
if (ibuf_add_h64(tmp, pevpn->rd) == -1 ||
ibuf_add(tmp, pevpn->esi,
sizeof(pevpn->esi)) == -1 ||
ibuf_add_h32(tmp, pevpn->ethtag) == -1)
goto fail;
if (ibuf_add_n8(tmp, sizeof(pevpn->mac) * 8) == -1 ||
ibuf_add(tmp, pevpn->mac, sizeof(pevpn->mac)) == -1)
goto fail;
if (ibuf_add_n8(tmp, pevpn->prefixlen) == -1)
goto fail;
switch(pevpn->vpnaid) {
case AID_UNSPEC:
/* See rfc7432 section 7.2 */
break;
case AID_INET:
if (ibuf_add(tmp, &pevpn->prefix4,
sizeof(pevpn->prefix4)) == -1)
goto fail;
break;
case AID_INET6:
if (ibuf_add(tmp, &pevpn->prefix6,
sizeof(pevpn->prefix6)) == -1)
goto fail;
break;
default:
goto fail;
}
if (ibuf_add(tmp, pevpn->labelstack,
pevpn->labellen) == -1)
goto fail;
break;
case EVPN_ROUTE_TYPE_3:
plen = sizeof(pevpn->rd) * 8;
plen += sizeof(pevpn->ethtag) * 8;
plen += 8; /* IP length */
plen += pevpn->prefixlen;
if (ibuf_add_n8(tmp, PREFIX_SIZE(plen) - 1) == -1)
goto fail;
if (ibuf_add_h64(tmp, pevpn->rd) == -1 ||
ibuf_add_h32(tmp, pevpn->ethtag) == -1)
goto fail;
if (ibuf_add_n8(tmp, pevpn->prefixlen) == -1)
goto fail;
switch(pevpn->vpnaid) {
case AID_INET:
if (ibuf_add(tmp, &pevpn->prefix4,
sizeof(pevpn->prefix4)) == -1)
goto fail;
break;
case AID_INET6:
if (ibuf_add(tmp, &pevpn->prefix6,
sizeof(pevpn->prefix6)) == -1)
goto fail;
break;
default:
goto fail;
}
}
break;
case AID_FLOWSPECv4: case AID_FLOWSPECv4:
case AID_FLOWSPECv6: case AID_FLOWSPECv6:
flowlen = pflow->len - PT_FLOW_SIZE; flowlen = pflow->len - PT_FLOW_SIZE;

View file

@ -1,4 +1,4 @@
/* $OpenBSD: rde_update.c,v 1.174 2025/01/13 13:50:34 claudio Exp $ */ /* $OpenBSD: rde_update.c,v 1.175 2025/02/04 18:16:56 denis Exp $ */
/* /*
* Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org> * Copyright (c) 2004 Claudio Jeker <claudio@openbsd.org>
@ -478,6 +478,12 @@ up_get_nexthop(struct rde_peer *peer, struct filterstate *state, uint8_t aid)
if (peer->local_v6_addr.aid == AID_INET6) if (peer->local_v6_addr.aid == AID_INET6)
peer_local = &peer->local_v6_addr; peer_local = &peer->local_v6_addr;
break; break;
case AID_EVPN:
if (peer->local_v4_addr.aid == AID_INET)
peer_local = &peer->local_v4_addr;
else if (peer->local_v6_addr.aid == AID_INET6)
peer_local = &peer->local_v6_addr;
break;
case AID_FLOWSPECv4: case AID_FLOWSPECv4:
case AID_FLOWSPECv6: case AID_FLOWSPECv6:
/* flowspec has no nexthop */ /* flowspec has no nexthop */
@ -946,6 +952,24 @@ up_generate_mp_reach(struct ibuf *buf, struct rde_peer *peer,
if (ibuf_add(buf, &nexthop->v6, sizeof(nexthop->v6)) == -1) if (ibuf_add(buf, &nexthop->v6, sizeof(nexthop->v6)) == -1)
return -1; return -1;
break; break;
case AID_EVPN:
if (nh == NULL)
return -1;
nexthop = &nh->exit_nexthop;
if (nexthop->aid == AID_INET) {
if (ibuf_add(buf, &nexthop->v4,
sizeof(nexthop->v4)) == -1)
return -1;
break;
} else if (nexthop->aid == AID_INET6) {
if (ibuf_add(buf, &nexthop->v6,
sizeof(nexthop->v6)) == -1)
return -1;
} else {
/* can't encode nexthop, give up and withdraw prefix */
return -1;
}
break;
case AID_FLOWSPECv4: case AID_FLOWSPECv4:
case AID_FLOWSPECv6: case AID_FLOWSPECv6:
/* no NH */ /* no NH */

View file

@ -1,4 +1,4 @@
/* $OpenBSD: util.c,v 1.92 2025/01/27 15:22:11 claudio Exp $ */ /* $OpenBSD: util.c,v 1.93 2025/02/04 18:16:56 denis Exp $ */
/* /*
* Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org> * Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org>
@ -49,10 +49,78 @@ log_addr(const struct bgpd_addr *addr)
snprintf(buf, sizeof(buf), "%s %s", log_rd(addr->rd), snprintf(buf, sizeof(buf), "%s %s", log_rd(addr->rd),
log_sockaddr(sa, len)); log_sockaddr(sa, len));
return (buf); return (buf);
case AID_EVPN:
return log_evpnaddr(addr, sa, len);
break;
} }
return ("???"); return ("???");
} }
static const char *
log_mac(const uint8_t mac[ETHER_ADDR_LEN])
{
static char buf[18];
snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x", mac[0],
mac[1], mac[2], mac[3], mac[4], mac[5]);
return (buf);
}
static const uint8_t zero_esi[ESI_ADDR_LEN];
static const char *
log_esi(const uint8_t esi[ESI_ADDR_LEN])
{
static char buf[30];
if (memcmp(esi, zero_esi, sizeof(zero_esi)) == 0)
return ("");
snprintf(buf, sizeof(buf),
"%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", esi[0],
esi[1], esi[2], esi[3], esi[4], esi[5], esi[6], esi[7], esi[8],
esi[9]);
return (buf);
}
const char *
log_evpnaddr(const struct bgpd_addr *addr, struct sockaddr *sa,
socklen_t salen)
{
static char buf[138];
uint32_t vni;
uint8_t len;
switch(addr->evpn.type) {
case EVPN_ROUTE_TYPE_2:
memcpy(&vni, addr->labelstack, addr->labellen);
snprintf(buf, sizeof(buf), "[2]:[%s]:[%s]:[%d]:[48]:[%s]",
log_rd(addr->rd),log_esi(addr->evpn.esi), htonl(vni)>>8,
log_mac(addr->evpn.mac));
if (sa != NULL) {
len = strlen(buf);
snprintf(buf+len, sizeof(buf)-len, ":[%d]:[%s]",
sa->sa_family == AF_INET ? 32 : 128,
log_sockaddr(sa, salen));
}
break;
case EVPN_ROUTE_TYPE_3:
if (sa != NULL) {
memcpy(&vni, addr->labelstack, addr->labellen);
snprintf(buf, sizeof(buf), "[3]:[%s]:[%d]:[%s]",
log_rd(addr->rd),
sa->sa_family == AF_INET ? 32 : 128,
log_sockaddr(sa, salen));
}
break;
default:
break;
}
return (buf);
}
const char * const char *
log_in6addr(const struct in6_addr *addr) log_in6addr(const struct in6_addr *addr)
{ {
@ -818,6 +886,108 @@ nlri_get_vpn6(struct ibuf *buf, struct bgpd_addr *prefix,
return (0); return (0);
} }
int
nlri_get_evpn(struct ibuf *buf, struct bgpd_addr *prefix,
uint8_t *prefixlen)
{
struct ibuf evpnbuf;
uint8_t nlrilen, type, pfxlen = 0, maclen = 0;
if (ibuf_get_n8(buf, &type) == -1)
return (-1);
if (ibuf_get_n8(buf, &nlrilen) == -1)
return (-1);
memset(prefix, 0, sizeof(struct bgpd_addr));
prefix->aid = AID_EVPN;
switch (type) {
case EVPN_ROUTE_TYPE_2:
if (ibuf_get_ibuf(buf, nlrilen, &evpnbuf) == -1)
return (-1);
prefix->evpn.type = EVPN_ROUTE_TYPE_2;
/* RD */
if (ibuf_get_h64(&evpnbuf, &prefix->rd) == -1)
return (-1);
/* ESI */
if (ibuf_get(&evpnbuf, &prefix->evpn.esi,
sizeof(prefix->evpn.esi)) == -1)
return (-1);
/* Ethernet Tag */
if (ibuf_get_h32(&evpnbuf, &prefix->evpn.ethtag) == -1)
return (-1);
/* MAC length */
if (ibuf_get_n8(&evpnbuf, &maclen) == -1)
return (-1);
if (maclen != 48)
return (-1);
/* MAC address */
if (ibuf_get(&evpnbuf, &prefix->evpn.mac,
sizeof(prefix->evpn.mac)) == -1)
return (-1);
/* Prefix length */
if (ibuf_get_n8(&evpnbuf, &pfxlen) == -1)
return (-1);
/* Destination */
if (pfxlen == 0) {
/* nothing */
} else if (pfxlen == 32) {
prefix->evpn.aid = AID_INET;
if (ibuf_get(&evpnbuf, &prefix->evpn.v4,
sizeof(prefix->evpn.v4)) == -1)
return (-1);
} else if (pfxlen == 128) {
prefix->evpn.aid = AID_INET6;
if (ibuf_get(&evpnbuf, &prefix->evpn.v6,
sizeof(prefix->evpn.v6)) == -1)
return (-1);
} else
return (-1);
/* VNI */
if (ibuf_size(&evpnbuf) != 3 && ibuf_size(&evpnbuf) != 6)
return (-1);
prefix->labellen = ibuf_size(&evpnbuf);
if (ibuf_get(&evpnbuf, prefix->labelstack,
prefix->labellen) == -1)
return (-1);
break;
case EVPN_ROUTE_TYPE_3:
if (ibuf_get_ibuf(buf, nlrilen, &evpnbuf) == -1)
return (-1);
prefix->evpn.type = EVPN_ROUTE_TYPE_3;
/* RD */
if (ibuf_get_h64(&evpnbuf, &prefix->rd) == -1)
return (-1);
/* Ethernet Tag */
if (ibuf_get_h32(&evpnbuf, &prefix->evpn.ethtag) == -1)
return (-1);
/* Prefix length */
if (ibuf_get_n8(&evpnbuf, &pfxlen) == -1)
return (-1);
/* Destination */
if (pfxlen == 32) {
prefix->evpn.aid = AID_INET;
if (ibuf_get(&evpnbuf, &prefix->evpn.v4,
sizeof(prefix->evpn.v4)) == -1)
return (-1);
} else if (pfxlen == 128) {
prefix->evpn.aid = AID_INET6;
if (ibuf_get(&evpnbuf, &prefix->evpn.v6,
sizeof(prefix->evpn.v6)) == -1)
return (-1);
} else
return (-1);
if (ibuf_size(&evpnbuf) != 0)
return (-1);
break;
default:
return (-1);
}
*prefixlen = pfxlen;
return (0);
}
static in_addr_t static in_addr_t
prefixlen2mask(uint8_t prefixlen) prefixlen2mask(uint8_t prefixlen)
{ {
@ -1003,6 +1173,26 @@ af2aid(sa_family_t af, uint8_t safi, uint8_t *aid)
return (-1); return (-1);
} }
static socklen_t
addr2sa_in6(struct sockaddr_in6 *sin6, struct in6_addr in6, uint16_t port,
uint32_t scope_id)
{
sin6->sin6_family = AF_INET6;
memcpy(&sin6->sin6_addr, &in6, sizeof(sin6->sin6_addr));
sin6->sin6_port = htons(port);
sin6->sin6_scope_id = scope_id;
return (sizeof(struct sockaddr_in6));
}
static socklen_t
addr2sa_in(struct sockaddr_in *sin, struct in_addr in, uint16_t port)
{
sin->sin_family = AF_INET;
sin->sin_addr.s_addr = in.s_addr;
sin->sin_port = htons(port);
return (sizeof(struct sockaddr_in));
}
/* /*
* Convert a struct bgpd_addr into a struct sockaddr. For VPN addresses * Convert a struct bgpd_addr into a struct sockaddr. For VPN addresses
* the included label stack is ignored and needs to be handled by the caller. * the included label stack is ignored and needs to be handled by the caller.
@ -1021,22 +1211,26 @@ addr2sa(const struct bgpd_addr *addr, uint16_t port, socklen_t *len)
switch (addr->aid) { switch (addr->aid) {
case AID_INET: case AID_INET:
case AID_VPN_IPv4: case AID_VPN_IPv4:
sa_in->sin_family = AF_INET; *len = addr2sa_in(sa_in, addr->v4, port);
sa_in->sin_addr.s_addr = addr->v4.s_addr;
sa_in->sin_port = htons(port);
*len = sizeof(struct sockaddr_in);
break; break;
case AID_INET6: case AID_INET6:
case AID_VPN_IPv6: case AID_VPN_IPv6:
sa_in6->sin6_family = AF_INET6; *len = addr2sa_in6(sa_in6, addr->v6, port, addr->scope_id);
memcpy(&sa_in6->sin6_addr, &addr->v6, break;
sizeof(sa_in6->sin6_addr)); case AID_EVPN:
sa_in6->sin6_port = htons(port); if (addr->evpn.aid == AID_INET)
sa_in6->sin6_scope_id = addr->scope_id; *len = addr2sa_in(sa_in, addr->evpn.v4, port);
*len = sizeof(struct sockaddr_in6); else if (addr->evpn.aid == AID_INET6)
*len = addr2sa_in6(sa_in6, addr->evpn.v6, port,
addr->scope_id);
else {
*len = 0;
return (NULL);
}
break; break;
case AID_FLOWSPECv4: case AID_FLOWSPECv4:
case AID_FLOWSPECv6: case AID_FLOWSPECv6:
default:
return (NULL); return (NULL);
} }