sync with OpenBSD -current

This commit is contained in:
purplerain 2024-02-22 21:37:47 +00:00
parent 1b6040b16e
commit 8b26203154
Signed by: purplerain
GPG Key ID: F42C07F07E2E35B7
38 changed files with 1417 additions and 324 deletions

View File

@ -1,4 +1,4 @@
# $OpenBSD: Makefile.inc,v 1.36 2024/01/08 08:26:38 tb Exp $
# $OpenBSD: Makefile.inc,v 1.37 2024/02/22 12:51:50 job Exp $
.PATH: ${.CURDIR}/../../../../usr.sbin/rpki-client
@ -13,6 +13,7 @@ PROGS += test-tal
PROGS += test-rrdp
PROGS += test-aspa
PROGS += test-tak
PROGS += test-spl
.for p in ${PROGS}
REGRESS_TARGETS += run-regress-$p
@ -89,6 +90,12 @@ SRCS_test-tak+= test-tak.c tak.c cms.c x509.c ip.c as.c io.c \
run-regress-test-tak: test-tak
./test-tak -v ${.CURDIR}/../tak/*.tak
SRCS_test-spl+= test-spl.c spl.c cms.c x509.c ip.c as.c io.c \
encoding.c print.c validate.c cert.c crl.c mft.c json.c \
constraints-dummy.c repo-dummy.c rfc3779.c
run-regress-test-spl: test-spl
./test-spl -v ${.CURDIR}/../spl/*.spl
SRCS_test-rrdp+= test-rrdp.c rrdp_delta.c rrdp_notification.c cms.c \
rrdp_snapshot.c rrdp_util.c cert.c as.c mft.c io.c \
encoding.c ip.c validate.c crl.c x509.c \

View File

@ -0,0 +1,104 @@
/* $Id: test-spl.c,v 1.1 2024/02/22 12:51:50 job Exp $ */
/*
* Copyright (c) 2024 Job Snijders <job@fastly.com>
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <assert.h>
#include <err.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/x509v3.h>
#include "extern.h"
int outformats;
int verbose;
int filemode;
int
main(int argc, char *argv[])
{
int c, i, ppem = 0, verb = 0;
X509 *xp = NULL;
struct spl *p;
unsigned char *buf;
size_t len;
ERR_load_crypto_strings();
OpenSSL_add_all_ciphers();
OpenSSL_add_all_digests();
x509_init_oid();
while ((c = getopt(argc, argv, "pv")) != -1)
switch (c) {
case 'p':
if (ppem)
break;
ppem = 1;
break;
case 'v':
verb++;
break;
default:
errx(1, "bad argument %c", c);
}
argv += optind;
argc -= optind;
if (argc == 0)
errx(1, "argument missing");
for (i = 0; i < argc; i++) {
buf = load_file(argv[i], &len);
if ((p = spl_parse(&xp, argv[i], -1, buf, len)) == NULL) {
free(buf);
break;
}
if (verb)
spl_print(xp, p);
if (ppem) {
if (!PEM_write_X509(stdout, xp))
errx(1, "PEM_write_X509: unable to write cert");
}
free(buf);
spl_free(p);
X509_free(xp);
}
EVP_cleanup();
CRYPTO_cleanup_all_ex_data();
ERR_free_strings();
if (i < argc)
errx(1, "test failed for %s", argv[i]);
printf("OK\n");
return 0;
}
time_t
get_current_time(void)
{
return time(NULL);
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: db_ctf.c,v 1.33 2022/08/14 14:57:38 millert Exp $ */
/* $OpenBSD: db_ctf.c,v 1.34 2024/02/22 13:49:17 claudio Exp $ */
/*
* Copyright (c) 2016-2017 Martin Pieuchot
@ -55,11 +55,14 @@ static const char *db_ctf_off2name(uint32_t);
static Elf_Sym *db_ctf_idx2sym(size_t *, uint8_t);
static char *db_ctf_decompress(const char *, size_t, size_t);
uint32_t db_ctf_type_len(const struct ctf_type *);
size_t db_ctf_type_size(const struct ctf_type *);
const struct ctf_type *db_ctf_type_by_name(const char *, unsigned int);
const struct ctf_type *db_ctf_type_by_symbol(Elf_Sym *);
const struct ctf_type *db_ctf_type_by_index(uint16_t);
void db_ctf_pprint(const struct ctf_type *, vaddr_t);
void db_ctf_pprint_struct(const struct ctf_type *, vaddr_t);
void db_ctf_pprint_enum(const struct ctf_type *, vaddr_t);
void db_ctf_pprint_ptr(const struct ctf_type *, vaddr_t);
/*
@ -241,6 +244,68 @@ db_ctf_type_len(const struct ctf_type *ctt)
return tlen;
}
/*
* Return the size of the type.
*/
size_t
db_ctf_type_size(const struct ctf_type *ctt)
{
vaddr_t taddr = (vaddr_t)ctt;
const struct ctf_type *ref;
const struct ctf_array *arr;
size_t tlen = 0;
uint16_t kind;
uint32_t toff;
uint64_t size;
kind = CTF_INFO_KIND(ctt->ctt_info);
if (ctt->ctt_size <= CTF_MAX_SIZE) {
size = ctt->ctt_size;
toff = sizeof(struct ctf_stype);
} else {
size = CTF_TYPE_LSIZE(ctt);
toff = sizeof(struct ctf_type);
}
switch (kind) {
case CTF_K_UNKNOWN:
case CTF_K_FORWARD:
break;
case CTF_K_INTEGER:
case CTF_K_FLOAT:
tlen = size;
break;
case CTF_K_ARRAY:
arr = (struct ctf_array *)(taddr + toff);
ref = db_ctf_type_by_index(arr->cta_contents);
tlen = arr->cta_nelems * db_ctf_type_size(ref);
break;
case CTF_K_FUNCTION:
tlen = 0;
break;
case CTF_K_STRUCT:
case CTF_K_UNION:
case CTF_K_ENUM:
tlen = size;
break;
case CTF_K_POINTER:
tlen = sizeof(void *);
break;
case CTF_K_TYPEDEF:
case CTF_K_VOLATILE:
case CTF_K_CONST:
case CTF_K_RESTRICT:
ref = db_ctf_type_by_index(ctt->ctt_type);
tlen = db_ctf_type_size(ref);
break;
default:
return 0;
}
return tlen;
}
/*
* Return the CTF type associated to an ELF symbol.
*/
@ -347,8 +412,14 @@ db_ctf_pprint(const struct ctf_type *ctt, vaddr_t addr)
{
vaddr_t taddr = (vaddr_t)ctt;
const struct ctf_type *ref;
const struct ctf_array *arr;
uint16_t kind;
uint32_t eob, toff;
uint32_t eob, toff, i;
db_expr_t val;
size_t elm_size;
if (ctt == NULL)
return;
kind = CTF_INFO_KIND(ctt->ctt_info);
if (ctt->ctt_size <= CTF_MAX_SIZE)
@ -357,20 +428,58 @@ db_ctf_pprint(const struct ctf_type *ctt, vaddr_t addr)
toff = sizeof(struct ctf_type);
switch (kind) {
case CTF_K_FLOAT:
case CTF_K_ENUM:
case CTF_K_ARRAY:
arr = (struct ctf_array *)(taddr + toff);
ref = db_ctf_type_by_index(arr->cta_contents);
elm_size = db_ctf_type_size(ref);
db_printf("[");
for (i = 0; i < arr->cta_nelems; i++) {
db_ctf_pprint(ref, addr + i * elm_size);
if (i + 1 < arr->cta_nelems)
db_printf(",");
}
db_printf("]");
break;
case CTF_K_ENUM:
db_ctf_pprint_enum(ctt, addr);
break;
case CTF_K_FLOAT:
case CTF_K_FUNCTION:
db_printf("%lu", *((unsigned long *)addr));
val = db_get_value(addr, sizeof(val), 0);
db_printf("%lx", (unsigned long)val);
break;
case CTF_K_INTEGER:
eob = db_get_value((taddr + toff), sizeof(eob), 0);
switch (CTF_INT_BITS(eob)) {
case 64:
db_printf("0x%llx", *((long long *)addr));
#ifndef __LP64__
case 64: {
uint64_t val64;
#if BYTE_ORDER == LITTLE_ENDIAN
val64 = db_get_value(addr + 4, CTF_INT_BITS(eob) / 8,
CTF_INT_ENCODING(eob) & CTF_INT_SIGNED);
val64 <<= 32;
val64 |= db_get_value(addr, CTF_INT_BITS(eob) / 8, 0);
#else
val64 = db_get_value(addr, CTF_INT_BITS(eob) / 8,
CTF_INT_ENCODING(eob) & CTF_INT_SIGNED);
val64 <<= 32;
val64 |= db_get_value(addr + 4, CTF_INT_BITS(eob) / 8,
0);
#endif
if (CTF_INT_ENCODING(eob) & CTF_INT_SIGNED)
db_printf("%lld", val64);
else
db_printf("%llu", val64);
break;
}
#endif
default:
db_printf("0x%x", *((int *)addr));
val = db_get_value(addr, CTF_INT_BITS(eob) / 8,
CTF_INT_ENCODING(eob) & CTF_INT_SIGNED);
if (CTF_INT_ENCODING(eob) & CTF_INT_SIGNED)
db_printf("%ld", val);
else
db_printf("%lu", val);
break;
}
break;
@ -416,7 +525,6 @@ db_ctf_pprint_struct(const struct ctf_type *ctt, vaddr_t addr)
db_printf("{");
if (size < CTF_LSTRUCT_THRESH) {
for (i = 0; i < vlen; i++) {
struct ctf_member *ctm;
@ -451,6 +559,35 @@ db_ctf_pprint_struct(const struct ctf_type *ctt, vaddr_t addr)
db_printf("}");
}
void
db_ctf_pprint_enum(const struct ctf_type *ctt, vaddr_t addr)
{
const char *name = NULL, *p = (const char *)ctt;
struct ctf_enum *cte;
uint32_t toff;
int32_t val;
uint16_t i, vlen;
vlen = CTF_INFO_VLEN(ctt->ctt_info);
toff = sizeof(struct ctf_stype);
val = (int32_t)db_get_value(addr, sizeof(val), 1);
for (i = 0; i < vlen; i++) {
cte = (struct ctf_enum *)(p + toff);
toff += sizeof(*cte);
if (val == cte->cte_value) {
name = db_ctf_off2name(cte->cte_name);
break;
}
}
if (name != NULL)
db_printf("%s", name);
else
db_printf("#%d", val);
}
void
db_ctf_pprint_ptr(const struct ctf_type *ctt, vaddr_t addr)
{

View File

@ -1,4 +1,4 @@
/* $OpenBSD: qwx.c,v 1.48 2024/02/20 11:48:19 stsp Exp $ */
/* $OpenBSD: qwx.c,v 1.50 2024/02/22 09:08:08 stsp Exp $ */
/*
* Copyright 2023 Stefan Sperling <stsp@openbsd.org>
@ -299,6 +299,18 @@ qwx_stop(struct ifnet *ifp)
splx(s);
}
void
qwx_free_firmware(struct qwx_softc *sc)
{
int i;
for (i = 0; i < nitems(sc->fw_img); i++) {
free(sc->fw_img[i].data, M_DEVBUF, sc->fw_img[i].size);
sc->fw_img[i].data = NULL;
sc->fw_img[i].size = 0;
}
}
int
qwx_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
{
@ -322,7 +334,7 @@ qwx_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
if (ifp->if_flags & IFF_UP) {
if (!(ifp->if_flags & IFF_RUNNING)) {
/* Force reload of firmware image from disk. */
sc->have_firmware = 0;
qwx_free_firmware(sc);
err = qwx_init(ifp);
}
} else {
@ -8374,20 +8386,34 @@ err_free_req:
int
qwx_qmi_load_bdf_qmi(struct qwx_softc *sc, int regdb)
{
u_char *data;
u_char *data = NULL;
const u_char *boardfw;
size_t len, boardfw_len;
size_t len = 0, boardfw_len;
uint32_t fw_size;
int ret = 0, bdf_type;
#ifdef notyet
const uint8_t *tmp;
uint32_t file_type;
#endif
int fw_idx = regdb ? QWX_FW_REGDB : QWX_FW_BOARD;
ret = qwx_core_fetch_bdf(sc, &data, &len, &boardfw, &boardfw_len,
regdb ? ATH11K_REGDB_FILE : ATH11K_BOARD_API2_FILE);
if (ret)
return ret;
if (sc->fw_img[fw_idx].data) {
boardfw = sc->fw_img[fw_idx].data;
boardfw_len = sc->fw_img[fw_idx].size;
} else {
ret = qwx_core_fetch_bdf(sc, &data, &len,
&boardfw, &boardfw_len,
regdb ? ATH11K_REGDB_FILE : ATH11K_BOARD_API2_FILE);
if (ret)
return ret;
sc->fw_img[fw_idx].data = malloc(boardfw_len, M_DEVBUF,
M_NOWAIT);
if (sc->fw_img[fw_idx].data) {
memcpy(sc->fw_img[fw_idx].data, boardfw, boardfw_len);
sc->fw_img[fw_idx].size = boardfw_len;
}
}
if (regdb)
bdf_type = ATH11K_QMI_BDF_TYPE_REGDB;
@ -8506,16 +8532,24 @@ qwx_qmi_m3_load(struct qwx_softc *sc)
char path[PATH_MAX];
int ret;
ret = snprintf(path, sizeof(path), "%s-%s-%s",
ATH11K_FW_DIR, sc->hw_params.fw.dir, ATH11K_M3_FILE);
if (ret < 0 || ret >= sizeof(path))
return ENOSPC;
if (sc->fw_img[QWX_FW_M3].data) {
data = sc->fw_img[QWX_FW_M3].data;
len = sc->fw_img[QWX_FW_M3].size;
} else {
ret = snprintf(path, sizeof(path), "%s-%s-%s",
ATH11K_FW_DIR, sc->hw_params.fw.dir, ATH11K_M3_FILE);
if (ret < 0 || ret >= sizeof(path))
return ENOSPC;
ret = loadfirmware(path, &data, &len);
if (ret) {
printf("%s: could not read %s (error %d)\n",
sc->sc_dev.dv_xname, path, ret);
return ret;
ret = loadfirmware(path, &data, &len);
if (ret) {
printf("%s: could not read %s (error %d)\n",
sc->sc_dev.dv_xname, path, ret);
return ret;
}
sc->fw_img[QWX_FW_M3].data = data;
sc->fw_img[QWX_FW_M3].size = len;
}
if (sc->m3_mem == NULL || QWX_DMA_LEN(sc->m3_mem) < len) {
@ -8531,7 +8565,6 @@ qwx_qmi_m3_load(struct qwx_softc *sc)
}
memcpy(QWX_DMA_KVA(sc->m3_mem), data, len);
free(data, M_DEVBUF, len);
return 0;
}
@ -24709,6 +24742,8 @@ qwx_detach(struct qwx_softc *sc)
qwx_dmamem_free(sc->sc_dmat, sc->m3_mem);
sc->m3_mem = NULL;
}
qwx_free_firmware(sc);
}
struct qwx_dmamem *
@ -24762,3 +24797,33 @@ qwx_dmamem_free(bus_dma_tag_t dmat, struct qwx_dmamem *adm)
bus_dmamap_destroy(dmat, adm->map);
free(adm, M_DEVBUF, sizeof(*adm));
}
int
qwx_activate(struct device *self, int act)
{
struct qwx_softc *sc = (struct qwx_softc *)self;
struct ifnet *ifp = &sc->sc_ic.ic_if;
int err = 0;
switch (act) {
case DVACT_QUIESCE:
if (ifp->if_flags & IFF_RUNNING) {
rw_enter_write(&sc->ioctl_rwl);
qwx_stop(ifp);
rw_exit(&sc->ioctl_rwl);
}
break;
case DVACT_RESUME:
break;
case DVACT_WAKEUP:
if ((ifp->if_flags & (IFF_UP | IFF_RUNNING)) == IFF_UP) {
err = qwx_init(ifp);
if (err)
printf("%s: could not initialize hardware\n",
sc->sc_dev.dv_xname);
}
break;
}
return 0;
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: qwxvar.h,v 1.20 2024/02/16 14:13:45 stsp Exp $ */
/* $OpenBSD: qwxvar.h,v 1.22 2024/02/22 09:08:08 stsp Exp $ */
/*
* Copyright (c) 2018-2019 The Linux Foundation.
@ -1782,7 +1782,14 @@ struct qwx_softc {
struct qwx_survey_info survey[IEEE80211_CHAN_MAX];
int attached;
int have_firmware;
struct {
u_char *data;
size_t size;
} fw_img[4];
#define QWX_FW_AMSS 0
#define QWX_FW_BOARD 1
#define QWX_FW_M3 2
#define QWX_FW_REGDB 3
int sc_tx_timer;
uint32_t qfullmsk;
@ -1901,6 +1908,7 @@ int qwx_dp_service_srng(struct qwx_softc *, int);
int qwx_init_hw_params(struct qwx_softc *);
int qwx_attach(struct qwx_softc *);
void qwx_detach(struct qwx_softc *);
int qwx_activate(struct device *, int);
void qwx_core_deinit(struct qwx_softc *);
void qwx_ce_cleanup_pipes(struct qwx_softc *);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: if_qwx_pci.c,v 1.10 2024/02/16 16:37:42 stsp Exp $ */
/* $OpenBSD: if_qwx_pci.c,v 1.14 2024/02/22 09:15:34 stsp Exp $ */
/*
* Copyright 2023 Stefan Sperling <stsp@openbsd.org>
@ -323,16 +323,6 @@ struct qwx_pci_cmd_ring {
struct qwx_pci_ops;
struct qwx_msi_config;
struct qwx_mhi_newstate {
struct {
int mhi_state;
int ee;
} queue[4];
int cur;
int tail;
int queued;
};
#define QWX_NUM_MSI_VEC 32
struct qwx_pci_softc {
@ -366,12 +356,8 @@ struct qwx_pci_softc {
uint64_t wake_db;
struct qwx_mhi_newstate mhi_newstate;
struct task mhi_newstate_task;
struct taskq *mhi_taskq;
/*
* DMA memory for AMMS.bin firmware image.
* DMA memory for AMSS.bin firmware image.
* This memory must remain available to the device until
* the device is powered down.
*/
@ -402,7 +388,6 @@ int qwx_pci_match(struct device *, void *, void *);
void qwx_pci_attach(struct device *, struct device *, void *);
int qwx_pci_detach(struct device *, int);
void qwx_pci_attach_hook(struct device *);
int qwx_pci_activate(struct device *, int);
void qwx_pci_free_xfer_rings(struct qwx_pci_softc *);
int qwx_pci_alloc_xfer_ring(struct qwx_softc *, struct qwx_pci_xfer_ring *,
uint32_t, uint32_t, uint32_t, size_t);
@ -463,7 +448,6 @@ int qwx_mhi_fw_load_handler(struct qwx_pci_softc *);
int qwx_mhi_await_device_reset(struct qwx_softc *);
int qwx_mhi_await_device_ready(struct qwx_softc *);
void qwx_mhi_ready_state_transition(struct qwx_pci_softc *);
void qwx_mhi_ee_amss_state_transition(struct qwx_pci_softc *);
void qwx_mhi_mission_mode_state_transition(struct qwx_pci_softc *);
void qwx_mhi_low_power_mode_state_transition(struct qwx_pci_softc *);
void qwx_mhi_set_state(struct qwx_softc *, uint32_t);
@ -473,8 +457,6 @@ int qwx_mhi_fw_load_bhie(struct qwx_pci_softc *, uint8_t *, size_t);
void qwx_rddm_prepare(struct qwx_pci_softc *);
void qwx_rddm_task(void *);
void * qwx_pci_event_ring_get_elem(struct qwx_pci_event_ring *, uint64_t);
void qwx_mhi_queue_state_change(struct qwx_pci_softc *, int, int);
void qwx_mhi_state_change(void *);
void qwx_pci_intr_ctrl_event_mhi(struct qwx_pci_softc *, uint32_t);
void qwx_pci_intr_ctrl_event_ee(struct qwx_pci_softc *, uint32_t);
void qwx_pci_intr_ctrl_event_cmd_complete(struct qwx_pci_softc *,
@ -526,7 +508,7 @@ const struct cfattach qwx_pci_ca = {
qwx_pci_match,
qwx_pci_attach,
qwx_pci_detach,
qwx_pci_activate
qwx_activate
};
/* XXX pcidev */
@ -1037,10 +1019,6 @@ unsupported_wcn6855_soc:
if (sc->sc_nswq == NULL)
goto err_ce_free;
psc->mhi_taskq = taskq_create("qwxmhi", 1, IPL_NET, 0);
if (psc->mhi_taskq == NULL)
goto err_ce_free;
qwx_pci_init_qmi_ce_config(sc);
error = qwx_pcic_config_irq(sc, pa);
@ -1067,7 +1045,6 @@ unsupported_wcn6855_soc:
goto err_irq_affinity_cleanup;
}
#endif
task_set(&psc->mhi_newstate_task, qwx_mhi_state_change, psc);
task_set(&psc->rddm_task, qwx_rddm_task, psc);
ic->ic_phytype = IEEE80211_T_OFDM; /* not only, but not used */
@ -1204,19 +1181,6 @@ qwx_pci_attach_hook(struct device *self)
splx(s);
}
int
qwx_pci_activate(struct device *self, int act)
{
switch (act) {
case DVACT_SUSPEND:
break;
case DVACT_WAKEUP:
break;
}
return 0;
}
void
qwx_pci_free_xfer_rings(struct qwx_pci_softc *psc)
{
@ -2203,12 +2167,8 @@ int
qwx_pci_power_up(struct qwx_softc *sc)
{
struct qwx_pci_softc *psc = (struct qwx_pci_softc *)sc;
struct qwx_mhi_newstate *ns = &psc->mhi_newstate;
int error;
task_del(psc->mhi_taskq, &psc->mhi_newstate_task);
memset(ns, 0, sizeof(*ns));
psc->register_window = 0;
clear_bit(ATH11K_FLAG_DEVICE_INIT_DONE, sc->sc_flags);
@ -2234,12 +2194,6 @@ qwx_pci_power_up(struct qwx_softc *sc)
void
qwx_pci_power_down(struct qwx_softc *sc)
{
struct qwx_pci_softc *psc = (struct qwx_pci_softc *)sc;
struct qwx_mhi_newstate *ns = &psc->mhi_newstate;
task_del(psc->mhi_taskq, &psc->mhi_newstate_task);
memset(ns, 0, sizeof(*ns));
/* restore aspm in case firmware bootup fails */
qwx_pci_aspm_restore(sc);
@ -2951,6 +2905,10 @@ qwx_mhi_start(struct qwx_pci_softc *psc)
ret = qwx_mhi_fw_load_handler(psc);
if (ret)
return ret;
/* XXX without this delay starting the channels may fail */
delay(1000);
qwx_mhi_start_channels(psc);
} else {
/* XXX Handle partially initialized device...?!? */
ee = qwx_pci_read(sc, psc->bhi_off + MHI_BHI_EXECENV);
@ -3046,23 +3004,31 @@ qwx_mhi_fw_load_handler(struct qwx_pci_softc *psc)
u_char *data;
size_t len;
ret = snprintf(amss_path, sizeof(amss_path), "%s-%s-%s",
ATH11K_FW_DIR, sc->hw_params.fw.dir, ATH11K_AMSS_FILE);
if (ret < 0 || ret >= sizeof(amss_path))
return ENOSPC;
if (sc->fw_img[QWX_FW_AMSS].data) {
data = sc->fw_img[QWX_FW_AMSS].data;
len = sc->fw_img[QWX_FW_AMSS].size;
} else {
ret = snprintf(amss_path, sizeof(amss_path), "%s-%s-%s",
ATH11K_FW_DIR, sc->hw_params.fw.dir, ATH11K_AMSS_FILE);
if (ret < 0 || ret >= sizeof(amss_path))
return ENOSPC;
ret = loadfirmware(amss_path, &data, &len);
if (ret) {
printf("%s: could not read %s (error %d)\n",
sc->sc_dev.dv_xname, amss_path, ret);
return ret;
}
ret = loadfirmware(amss_path, &data, &len);
if (ret) {
printf("%s: could not read %s (error %d)\n",
sc->sc_dev.dv_xname, amss_path, ret);
return ret;
}
if (len < MHI_DMA_VEC_CHUNK_SIZE) {
printf("%s: %s is too short, have only %zu bytes\n",
sc->sc_dev.dv_xname, amss_path, len);
free(data, M_DEVBUF, len);
return EINVAL;
if (len < MHI_DMA_VEC_CHUNK_SIZE) {
printf("%s: %s is too short, have only %zu bytes\n",
sc->sc_dev.dv_xname, amss_path, len);
free(data, M_DEVBUF, len);
return EINVAL;
}
sc->fw_img[QWX_FW_AMSS].data = data;
sc->fw_img[QWX_FW_AMSS].size = len;
}
/* Second-stage boot loader sits in the first 512 KB of image. */
@ -3070,7 +3036,6 @@ qwx_mhi_fw_load_handler(struct qwx_pci_softc *psc)
if (ret != 0) {
printf("%s: could not load firmware %s\n",
sc->sc_dev.dv_xname, amss_path);
free(data, M_DEVBUF, len);
return ret;
}
@ -3079,6 +3044,7 @@ qwx_mhi_fw_load_handler(struct qwx_pci_softc *psc)
if (ret != 0) {
printf("%s: could not load firmware %s\n",
sc->sc_dev.dv_xname, amss_path);
return ret;
}
while (psc->bhi_ee < MHI_EE_AMSS) {
@ -3090,11 +3056,8 @@ qwx_mhi_fw_load_handler(struct qwx_pci_softc *psc)
if (ret != 0) {
printf("%s: device failed to enter AMSS EE\n",
sc->sc_dev.dv_xname);
free(data, M_DEVBUF, len);
return ret;
}
free(data, M_DEVBUF, len);
return ret;
}
@ -3182,15 +3145,6 @@ qwx_mhi_ready_state_transition(struct qwx_pci_softc *psc)
qwx_mhi_set_state(sc, MHI_STATE_M0);
}
void
qwx_mhi_ee_amss_state_transition(struct qwx_pci_softc *psc)
{
/* XXX without this delay starting the channels may fail */
delay(1000);
qwx_mhi_start_channels(psc);
}
void
qwx_mhi_mission_mode_state_transition(struct qwx_pci_softc *psc)
{
@ -3627,120 +3581,87 @@ qwx_pci_event_ring_get_elem(struct qwx_pci_event_ring *ring, uint64_t rp)
}
void
qwx_mhi_state_change(void *arg)
qwx_mhi_state_change(struct qwx_pci_softc *psc, int ee, int mhi_state)
{
struct qwx_pci_softc *psc = arg;
struct qwx_softc *sc = &psc->sc_sc;
struct qwx_mhi_newstate *ns = &psc->mhi_newstate;
int s = splnet();
uint32_t old_ee = psc->bhi_ee;
uint32_t old_mhi_state = psc->mhi_state;
while (ns->tail != ns->cur) {
int mhi_state = ns->queue[ns->tail].mhi_state;
int ee = ns->queue[ns->tail].ee;
uint32_t old_ee = psc->bhi_ee;
uint32_t old_mhi_state = psc->mhi_state;
KASSERT(ns->queued > 0);
if (ee != -1 && psc->bhi_ee != ee) {
switch (ee) {
case MHI_EE_PBL:
DNPRINTF(QWX_D_MHI, "%s: new EE PBL\n",
sc->sc_dev.dv_xname);
psc->bhi_ee = ee;
break;
case MHI_EE_SBL:
psc->bhi_ee = ee;
DNPRINTF(QWX_D_MHI, "%s: new EE SBL\n",
sc->sc_dev.dv_xname);
break;
case MHI_EE_AMSS:
DNPRINTF(QWX_D_MHI, "%s: new EE AMSS\n",
sc->sc_dev.dv_xname);
psc->bhi_ee = ee;
qwx_mhi_ee_amss_state_transition(psc);
/* Wake thread loading the full AMSS image. */
wakeup(&psc->bhie_off);
break;
case MHI_EE_WFW:
DNPRINTF(QWX_D_MHI, "%s: new EE WFW\n",
sc->sc_dev.dv_xname);
psc->bhi_ee = ee;
break;
default:
printf("%s: unhandled EE change to %x\n",
sc->sc_dev.dv_xname, ee);
break;
}
if (ee != -1 && psc->bhi_ee != ee) {
switch (ee) {
case MHI_EE_PBL:
DNPRINTF(QWX_D_MHI, "%s: new EE PBL\n",
sc->sc_dev.dv_xname);
psc->bhi_ee = ee;
break;
case MHI_EE_SBL:
psc->bhi_ee = ee;
DNPRINTF(QWX_D_MHI, "%s: new EE SBL\n",
sc->sc_dev.dv_xname);
break;
case MHI_EE_AMSS:
DNPRINTF(QWX_D_MHI, "%s: new EE AMSS\n",
sc->sc_dev.dv_xname);
psc->bhi_ee = ee;
/* Wake thread loading the full AMSS image. */
wakeup(&psc->bhie_off);
break;
case MHI_EE_WFW:
DNPRINTF(QWX_D_MHI, "%s: new EE WFW\n",
sc->sc_dev.dv_xname);
psc->bhi_ee = ee;
break;
default:
printf("%s: unhandled EE change to %x\n",
sc->sc_dev.dv_xname, ee);
break;
}
if (mhi_state != -1 && psc->mhi_state != mhi_state) {
switch (mhi_state) {
case -1:
break;
case MHI_STATE_RESET:
DNPRINTF(QWX_D_MHI, "%s: new MHI state RESET\n",
sc->sc_dev.dv_xname);
psc->mhi_state = mhi_state;
break;
case MHI_STATE_READY:
DNPRINTF(QWX_D_MHI, "%s: new MHI state READY\n",
sc->sc_dev.dv_xname);
psc->mhi_state = mhi_state;
qwx_mhi_ready_state_transition(psc);
break;
case MHI_STATE_M0:
DNPRINTF(QWX_D_MHI, "%s: new MHI state M0\n",
sc->sc_dev.dv_xname);
psc->mhi_state = mhi_state;
qwx_mhi_mission_mode_state_transition(psc);
break;
case MHI_STATE_M1:
DNPRINTF(QWX_D_MHI, "%s: new MHI state M1\n",
sc->sc_dev.dv_xname);
psc->mhi_state = mhi_state;
qwx_mhi_low_power_mode_state_transition(psc);
break;
case MHI_STATE_SYS_ERR:
DNPRINTF(QWX_D_MHI,
"%s: new MHI state SYS ERR\n",
sc->sc_dev.dv_xname);
psc->mhi_state = mhi_state;
break;
default:
printf("%s: unhandled MHI state change to %x\n",
sc->sc_dev.dv_xname, mhi_state);
break;
}
}
if (old_ee != psc->bhi_ee)
wakeup(&psc->bhi_ee);
if (old_mhi_state != psc->mhi_state)
wakeup(&psc->mhi_state);
ns->tail = (ns->tail + 1) % nitems(ns->queue);
ns->queued--;
}
splx(s);
}
void
qwx_mhi_queue_state_change(struct qwx_pci_softc *psc, int ee, int mhi_state)
{
struct qwx_mhi_newstate *ns = &psc->mhi_newstate;
if (ns->queued >= nitems(ns->queue)) {
printf("%s: event queue full, dropping event\n", __func__);
return;
if (mhi_state != -1 && psc->mhi_state != mhi_state) {
switch (mhi_state) {
case -1:
break;
case MHI_STATE_RESET:
DNPRINTF(QWX_D_MHI, "%s: new MHI state RESET\n",
sc->sc_dev.dv_xname);
psc->mhi_state = mhi_state;
break;
case MHI_STATE_READY:
DNPRINTF(QWX_D_MHI, "%s: new MHI state READY\n",
sc->sc_dev.dv_xname);
psc->mhi_state = mhi_state;
qwx_mhi_ready_state_transition(psc);
break;
case MHI_STATE_M0:
DNPRINTF(QWX_D_MHI, "%s: new MHI state M0\n",
sc->sc_dev.dv_xname);
psc->mhi_state = mhi_state;
qwx_mhi_mission_mode_state_transition(psc);
break;
case MHI_STATE_M1:
DNPRINTF(QWX_D_MHI, "%s: new MHI state M1\n",
sc->sc_dev.dv_xname);
psc->mhi_state = mhi_state;
qwx_mhi_low_power_mode_state_transition(psc);
break;
case MHI_STATE_SYS_ERR:
DNPRINTF(QWX_D_MHI,
"%s: new MHI state SYS ERR\n",
sc->sc_dev.dv_xname);
psc->mhi_state = mhi_state;
break;
default:
printf("%s: unhandled MHI state change to %x\n",
sc->sc_dev.dv_xname, mhi_state);
break;
}
}
ns->queue[ns->cur].ee = ee;
ns->queue[ns->cur].mhi_state = mhi_state;
ns->queued++;
ns->cur = (ns->cur + 1) % nitems(ns->queue);
task_add(psc->mhi_taskq, &psc->mhi_newstate_task);
if (old_ee != psc->bhi_ee)
wakeup(&psc->bhi_ee);
if (old_mhi_state != psc->mhi_state)
wakeup(&psc->mhi_state);
}
void
@ -3750,7 +3671,7 @@ qwx_pci_intr_ctrl_event_mhi(struct qwx_pci_softc *psc, uint32_t mhi_state)
psc->mhi_state, mhi_state);
if (psc->mhi_state != mhi_state)
qwx_mhi_queue_state_change(psc, -1, mhi_state);
qwx_mhi_state_change(psc, -1, mhi_state);
}
void
@ -3760,7 +3681,7 @@ qwx_pci_intr_ctrl_event_ee(struct qwx_pci_softc *psc, uint32_t ee)
psc->bhi_ee, ee);
if (psc->bhi_ee != ee)
qwx_mhi_queue_state_change(psc, ee, -1);
qwx_mhi_state_change(psc, ee, -1);
}
void
@ -4169,7 +4090,7 @@ qwx_pci_intr(void *arg)
new_mhi_state = state;
if (new_ee != -1 || new_mhi_state != -1)
qwx_mhi_queue_state_change(psc, new_ee, new_mhi_state);
qwx_mhi_state_change(psc, new_ee, new_mhi_state);
ret = 1;
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: route.c,v 1.432 2024/02/13 12:22:09 bluhm Exp $ */
/* $OpenBSD: route.c,v 1.433 2024/02/22 14:25:58 bluhm Exp $ */
/* $NetBSD: route.c,v 1.14 1996/02/13 22:00:46 christos Exp $ */
/*
@ -202,7 +202,8 @@ route_init(void)
}
int
route_cache(struct route *ro, struct in_addr addr, u_int rtableid)
route_cache(struct route *ro, const struct in_addr *dst,
const struct in_addr *src, u_int rtableid)
{
u_long gen;
@ -213,28 +214,35 @@ route_cache(struct route *ro, struct in_addr addr, u_int rtableid)
ro->ro_generation == gen &&
ro->ro_tableid == rtableid &&
ro->ro_dstsa.sa_family == AF_INET &&
ro->ro_dstsin.sin_addr.s_addr == addr.s_addr) {
ipstat_inc(ips_rtcachehit);
return (0);
ro->ro_dstsin.sin_addr.s_addr == dst->s_addr) {
if (src == NULL || !ipmultipath ||
!ISSET(ro->ro_rt->rt_flags, RTF_MPATH) ||
(ro->ro_srcin.s_addr != INADDR_ANY &&
ro->ro_srcin.s_addr == src->s_addr)) {
ipstat_inc(ips_rtcachehit);
return (0);
}
}
ipstat_inc(ips_rtcachemiss);
rtfree(ro->ro_rt);
ro->ro_rt = NULL;
memset(ro, 0, sizeof(*ro));
ro->ro_generation = gen;
ro->ro_tableid = rtableid;
memset(&ro->ro_dst, 0, sizeof(ro->ro_dst));
ro->ro_dstsin.sin_family = AF_INET;
ro->ro_dstsin.sin_len = sizeof(struct sockaddr_in);
ro->ro_dstsin.sin_addr = addr;
ro->ro_dstsin.sin_addr = *dst;
if (src != NULL)
ro->ro_srcin = *src;
return (ESRCH);
}
#ifdef INET6
int
route6_cache(struct route *ro, const struct in6_addr *addr, u_int rtableid)
route6_cache(struct route *ro, const struct in6_addr *dst,
const struct in6_addr *src, u_int rtableid)
{
u_long gen;
@ -245,21 +253,27 @@ route6_cache(struct route *ro, const struct in6_addr *addr, u_int rtableid)
ro->ro_generation == gen &&
ro->ro_tableid == rtableid &&
ro->ro_dstsa.sa_family == AF_INET6 &&
IN6_ARE_ADDR_EQUAL(&ro->ro_dstsin6.sin6_addr, addr)) {
ip6stat_inc(ip6s_rtcachehit);
return (0);
IN6_ARE_ADDR_EQUAL(&ro->ro_dstsin6.sin6_addr, dst)) {
if (src == NULL || !ip6_multipath ||
!ISSET(ro->ro_rt->rt_flags, RTF_MPATH) ||
(!IN6_IS_ADDR_UNSPECIFIED(&ro->ro_srcin6) &&
IN6_ARE_ADDR_EQUAL(&ro->ro_srcin6, src))) {
ip6stat_inc(ip6s_rtcachehit);
return (0);
}
}
ip6stat_inc(ip6s_rtcachemiss);
rtfree(ro->ro_rt);
ro->ro_rt = NULL;
memset(ro, 0, sizeof(*ro));
ro->ro_generation = gen;
ro->ro_tableid = rtableid;
memset(&ro->ro_dst, 0, sizeof(ro->ro_dst));
ro->ro_dstsin6.sin6_family = AF_INET6;
ro->ro_dstsin6.sin6_len = sizeof(struct sockaddr_in6);
ro->ro_dstsin6.sin6_addr = *addr;
ro->ro_dstsin6.sin6_addr = *dst;
if (src != NULL)
ro->ro_srcin6 = *src;
return (ESRCH);
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: route.h,v 1.206 2024/02/13 12:22:09 bluhm Exp $ */
/* $OpenBSD: route.h,v 1.207 2024/02/22 14:25:58 bluhm Exp $ */
/* $NetBSD: route.h,v 1.9 1996/02/13 22:00:49 christos Exp $ */
/*
@ -393,13 +393,14 @@ struct route {
u_long ro_generation;
u_long ro_tableid; /* u_long because of alignment */
union {
struct sockaddr rod_sa;
struct sockaddr_in rod_sin;
struct sockaddr_in6 rod_sin6;
} ro_dst;
#define ro_dstsa ro_dst.rod_sa
#define ro_dstsin ro_dst.rod_sin
#define ro_dstsin6 ro_dst.rod_sin6
struct sockaddr ro_dstsa;
struct sockaddr_in ro_dstsin;
struct sockaddr_in6 ro_dstsin6;
};
union {
struct in_addr ro_srcin;
struct in6_addr ro_srcin6;
};
};
#endif /* __BSD_VISIBLE */
@ -462,8 +463,10 @@ struct if_ieee80211_data;
struct bfd_config;
void route_init(void);
int route_cache(struct route *, struct in_addr, u_int);
int route6_cache(struct route *, const struct in6_addr *, u_int);
int route_cache(struct route *, const struct in_addr *,
const struct in_addr *, u_int);
int route6_cache(struct route *, const struct in6_addr *,
const struct in6_addr *, u_int);
void rtm_ifchg(struct ifnet *);
void rtm_ifannounce(struct ifnet *, int);
void rtm_bfd(struct bfd_config *);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: in_pcb.c,v 1.293 2024/02/13 12:22:09 bluhm Exp $ */
/* $OpenBSD: in_pcb.c,v 1.294 2024/02/22 14:25:58 bluhm Exp $ */
/* $NetBSD: in_pcb.c,v 1.25 1996/02/13 23:41:53 christos Exp $ */
/*
@ -919,7 +919,8 @@ in_pcbrtentry(struct inpcb *inp)
if (inp->inp_faddr.s_addr == INADDR_ANY)
return (NULL);
if (route_cache(ro, inp->inp_faddr, inp->inp_rtableid)) {
if (route_cache(ro, &inp->inp_faddr, &inp->inp_laddr,
inp->inp_rtableid)) {
ro->ro_rt = rtalloc_mpath(&ro->ro_dstsa,
&inp->inp_laddr.s_addr, ro->ro_tableid);
}
@ -982,7 +983,7 @@ in_pcbselsrc(struct in_addr *insrc, struct sockaddr_in *sin,
* If route is known or can be allocated now,
* our src addr is taken from the i/f, else punt.
*/
if (route_cache(ro, sin->sin_addr, rtableid)) {
if (route_cache(ro, &sin->sin_addr, NULL, rtableid)) {
/* No route yet, so try to acquire one */
ro->ro_rt = rtalloc_mpath(&ro->ro_dstsa, NULL, ro->ro_tableid);
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ip_input.c,v 1.389 2024/02/13 12:22:09 bluhm Exp $ */
/* $OpenBSD: ip_input.c,v 1.390 2024/02/22 14:25:58 bluhm Exp $ */
/* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */
/*
@ -118,7 +118,6 @@ const struct sysctl_bounded_args ipctl_vars[] = {
{ IPCTL_IPPORT_HILASTAUTO, &ipport_hilastauto, 0, 65535 },
{ IPCTL_IPPORT_MAXQUEUE, &ip_maxqueue, 0, 10000 },
{ IPCTL_MFORWARDING, &ipmforwarding, 0, 1 },
{ IPCTL_MULTIPATH, &ipmultipath, 0, 1 },
{ IPCTL_ARPTIMEOUT, &arpt_keep, 0, INT_MAX },
{ IPCTL_ARPDOWN, &arpt_down, 0, INT_MAX },
};
@ -1491,7 +1490,7 @@ ip_forward(struct mbuf *m, struct ifnet *ifp, struct rtentry *rt, int srcrt)
}
ro.ro_rt = NULL;
route_cache(&ro, ip->ip_dst, m->m_pkthdr.ph_rtableid);
route_cache(&ro, &ip->ip_dst, &ip->ip_src, m->m_pkthdr.ph_rtableid);
if (!rtisvalid(rt)) {
rtfree(rt);
rt = rtalloc_mpath(&ro.ro_dstsa, &ip->ip_src.s_addr,
@ -1633,10 +1632,10 @@ int
ip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
size_t newlen)
{
int error;
#ifdef MROUTING
extern struct mrtstat mrtstat;
#endif
int oldval, error;
/* Almost all sysctl names at this level are terminal. */
if (namelen != 1 && name[0] != IPCTL_IFQUEUE &&
@ -1721,6 +1720,15 @@ ip_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
case IPCTL_MRTVIF:
return (EOPNOTSUPP);
#endif
case IPCTL_MULTIPATH:
NET_LOCK();
oldval = ipmultipath;
error = sysctl_int_bounded(oldp, oldlenp, newp, newlen,
&ipmultipath, 0, 1);
if (oldval != ipmultipath)
atomic_inc_long(&rtgeneration);
NET_UNLOCK();
return (error);
default:
NET_LOCK();
error = sysctl_bounded_arr(ipctl_vars, nitems(ipctl_vars),

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ip_output.c,v 1.395 2024/02/13 12:22:09 bluhm Exp $ */
/* $OpenBSD: ip_output.c,v 1.396 2024/02/22 14:25:58 bluhm Exp $ */
/* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */
/*
@ -166,7 +166,7 @@ reroute:
* If there is a cached route, check that it is to the same
* destination and is still up. If not, free it and try again.
*/
route_cache(ro, ip->ip_dst, m->m_pkthdr.ph_rtableid);
route_cache(ro, &ip->ip_dst, &ip->ip_src, m->m_pkthdr.ph_rtableid);
dst = &ro->ro_dstsin;
if ((IN_MULTICAST(ip->ip_dst.s_addr) ||

View File

@ -1,4 +1,4 @@
/* $OpenBSD: in6_pcb.c,v 1.138 2024/02/13 12:22:09 bluhm Exp $ */
/* $OpenBSD: in6_pcb.c,v 1.139 2024/02/22 14:25:58 bluhm Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
@ -565,7 +565,8 @@ in6_pcbrtentry(struct inpcb *inp)
if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6))
return (NULL);
if (route6_cache(ro, &inp->inp_faddr6, inp->inp_rtableid)) {
if (route6_cache(ro, &inp->inp_faddr6, &inp->inp_laddr6,
inp->inp_rtableid)) {
ro->ro_rt = rtalloc_mpath(&ro->ro_dstsa,
&inp->inp_laddr6.s6_addr32[0], ro->ro_tableid);
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: in6_src.c,v 1.94 2024/02/13 12:22:09 bluhm Exp $ */
/* $OpenBSD: in6_src.c,v 1.95 2024/02/22 14:25:58 bluhm Exp $ */
/* $KAME: in6_src.c,v 1.36 2001/02/06 04:08:17 itojun Exp $ */
/*
@ -179,8 +179,8 @@ in6_pcbselsrc(const struct in6_addr **in6src, struct sockaddr_in6 *dstsock,
* If route is known or can be allocated now,
* our src addr is taken from the i/f, else punt.
*/
if (route6_cache(ro, dst, rtableid)) {
ro->ro_rt = rtalloc(&ro->ro_dstsa, RT_RESOLVE, ro->ro_tableid);
if (route6_cache(ro, dst, NULL, rtableid)) {
ro->ro_rt = rtalloc_mpath(&ro->ro_dstsa, NULL, ro->ro_tableid);
}
/*
@ -304,7 +304,7 @@ in6_selectroute(const struct in6_addr *dst, struct ip6_pktopts *opts,
* a new one.
*/
if (ro) {
if (route6_cache(ro, dst, rtableid)) {
if (route6_cache(ro, dst, NULL, rtableid)) {
/* No route yet, so try to acquire one */
ro->ro_rt = rtalloc_mpath(&ro->ro_dstsa, NULL,
ro->ro_tableid);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ip6_forward.c,v 1.114 2024/02/13 12:22:09 bluhm Exp $ */
/* $OpenBSD: ip6_forward.c,v 1.115 2024/02/22 14:25:58 bluhm Exp $ */
/* $KAME: ip6_forward.c,v 1.75 2001/06/29 12:42:13 jinmei Exp $ */
/*
@ -166,7 +166,8 @@ reroute:
#endif /* IPSEC */
ro.ro_rt = NULL;
route6_cache(&ro, &ip6->ip6_dst, m->m_pkthdr.ph_rtableid);
route6_cache(&ro, &ip6->ip6_dst, &ip6->ip6_src,
m->m_pkthdr.ph_rtableid);
dst = &ro.ro_dstsa;
if (!rtisvalid(rt)) {
rtfree(rt);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ip6_input.c,v 1.257 2023/12/03 20:36:24 bluhm Exp $ */
/* $OpenBSD: ip6_input.c,v 1.258 2024/02/22 14:25:58 bluhm Exp $ */
/* $KAME: ip6_input.c,v 1.188 2001/03/29 05:34:31 itojun Exp $ */
/*
@ -1451,7 +1451,6 @@ const struct sysctl_bounded_args ipv6ctl_vars[] = {
{ IPV6CTL_USE_DEPRECATED, &ip6_use_deprecated, 0, 1 },
{ IPV6CTL_MAXFRAGS, &ip6_maxfrags, 0, 1000 },
{ IPV6CTL_MFORWARDING, &ip6_mforwarding, 0, 1 },
{ IPV6CTL_MULTIPATH, &ip6_multipath, 0, 1 },
{ IPV6CTL_MCAST_PMTU, &ip6_mcast_pmtu, 0, 1 },
{ IPV6CTL_NEIGHBORGCTHRESH, &ip6_neighborgcthresh, -1, 5 * 2048 },
{ IPV6CTL_MAXDYNROUTES, &ip6_maxdynroutes, -1, 5 * 4096 },
@ -1499,7 +1498,7 @@ ip6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
#ifdef MROUTING
extern struct mrt6stat mrt6stat;
#endif
int error;
int oldval, error;
/* Almost all sysctl names at this level are terminal. */
if (namelen != 1 && name[0] != IPV6CTL_IFQUEUE)
@ -1551,6 +1550,15 @@ ip6_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
oldp, oldlenp, newp, newlen, &ip6intrq));
case IPV6CTL_SOIIKEY:
return (ip6_sysctl_soiikey(oldp, oldlenp, newp, newlen));
case IPV6CTL_MULTIPATH:
NET_LOCK();
oldval = ip6_multipath;
error = sysctl_int_bounded(oldp, oldlenp, newp, newlen,
&ip6_multipath, 0, 1);
if (oldval != ip6_multipath)
atomic_inc_long(&rtgeneration);
NET_UNLOCK();
return (error);
default:
NET_LOCK();
error = sysctl_bounded_arr(ipv6ctl_vars, nitems(ipv6ctl_vars),

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ip6_output.c,v 1.286 2024/02/13 12:22:09 bluhm Exp $ */
/* $OpenBSD: ip6_output.c,v 1.287 2024/02/22 14:25:58 bluhm Exp $ */
/* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $ */
/*
@ -480,7 +480,7 @@ reroute:
goto bad;
}
} else {
route6_cache(ro, &ip6->ip6_dst, m->m_pkthdr.ph_rtableid);
route6_cache(ro, &ip6->ip6_dst, NULL, m->m_pkthdr.ph_rtableid);
}
if (rt && (rt->rt_flags & RTF_GATEWAY) &&

View File

@ -1,4 +1,4 @@
/* $OpenBSD: generate.c,v 1.5 2022/08/14 14:54:13 millert Exp $ */
/* $OpenBSD: generate.c,v 1.6 2024/02/22 13:15:17 claudio Exp $ */
/*
* Copyright (c) 2017 Martin Pieuchot
@ -196,7 +196,20 @@ imcs_add_type(struct imcs *imcs, struct itype *it)
ctt.ctt_type = it->it_refp->it_idx;
ctsz = sizeof(struct ctf_stype);
} else if (size <= CTF_MAX_SIZE) {
ctt.ctt_size = size;
if (kind == CTF_K_INTEGER || kind == CTF_K_FLOAT) {
assert(size <= 64);
if (size == 0)
ctt.ctt_size = 0;
else if (size <= 8)
ctt.ctt_size = 1;
else if (size <= 16)
ctt.ctt_size = 2;
else if (size <= 32)
ctt.ctt_size = 4;
else
ctt.ctt_size = 8;
} else
ctt.ctt_size = size;
ctsz = sizeof(struct ctf_stype);
} else {
ctt.ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(size);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: parse.c,v 1.19 2024/02/21 13:24:37 claudio Exp $ */
/* $OpenBSD: parse.c,v 1.20 2024/02/22 13:17:18 claudio Exp $ */
/*
* Copyright (c) 2016-2017 Martin Pieuchot
@ -323,20 +323,30 @@ it_free(struct itype *it)
int
it_cmp(struct itype *a, struct itype *b)
{
int diff;
if (a->it_type > b->it_type)
return 1;
if (a->it_type < b->it_type)
return -1;
if ((diff = (a->it_type - b->it_type)) != 0)
return diff;
/* Basic types need to have the same size. */
if ((a->it_type == CTF_K_INTEGER || a->it_type == CTF_K_FLOAT) &&
(diff = (a->it_size - b->it_size) != 0))
return diff;
/* Basic types need to have the same encoding and size. */
if ((a->it_type == CTF_K_INTEGER || a->it_type == CTF_K_FLOAT)) {
if (a->it_enc > b->it_enc)
return 1;
if (a->it_enc < b->it_enc)
return -1;
if (a->it_size > b->it_size)
return 1;
if (a->it_size < b->it_size)
return -1;
}
/* Arrays need to have same number of elements */
if ((a->it_type == CTF_K_ARRAY) &&
(diff = (a->it_nelems - b->it_nelems) != 0))
return diff;
if (a->it_type == CTF_K_ARRAY) {
if (a->it_nelems > b->it_nelems)
return 1;
if (a->it_nelems < b->it_nelems)
return -1;
}
/* Match by name */
if (!(a->it_flags & ITF_ANON) && !(b->it_flags & ITF_ANON))
@ -349,6 +359,10 @@ it_cmp(struct itype *a, struct itype *b)
/* Match by reference */
if ((a->it_refp != NULL) && (b->it_refp != NULL))
return it_cmp(a->it_refp, b->it_refp);
if (a->it_refp == NULL)
return -1;
if (b->it_refp == NULL)
return 1;
return 0;
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: ctfdump.c,v 1.27 2022/08/14 15:01:18 millert Exp $ */
/* $OpenBSD: ctfdump.c,v 1.28 2024/02/22 13:21:03 claudio Exp $ */
/*
* Copyright (c) 2016 Martin Pieuchot <mpi@openbsd.org>
@ -490,16 +490,16 @@ ctf_dump_type(struct ctf_header *cth, const char *data, size_t dlen,
case CTF_K_INTEGER:
eob = *((uint32_t *)(p + toff));
toff += sizeof(uint32_t);
printf(" encoding=%s offset=%u bits=%u",
printf(" encoding=%s offset=%u bits=%u (%llu bytes)",
ctf_enc2name(CTF_INT_ENCODING(eob)), CTF_INT_OFFSET(eob),
CTF_INT_BITS(eob));
CTF_INT_BITS(eob), size);
break;
case CTF_K_FLOAT:
eob = *((uint32_t *)(p + toff));
toff += sizeof(uint32_t);
printf(" encoding=%s offset=%u bits=%u",
printf(" encoding=%s offset=%u bits=%u (%llu bytes)",
ctf_fpenc2name(CTF_FP_ENCODING(eob)), CTF_FP_OFFSET(eob),
CTF_FP_BITS(eob));
CTF_FP_BITS(eob), size);
break;
case CTF_K_ARRAY:
cta = (struct ctf_array *)(p + toff);
@ -563,7 +563,8 @@ ctf_dump_type(struct ctf_header *cth, const char *data, size_t dlen,
}
break;
case CTF_K_ENUM:
printf("\n");
printf(" (%llu bytes)\n", size);
for (i = 0; i < vlen; i++) {
struct ctf_enum *cte;

View File

@ -1,4 +1,4 @@
# $OpenBSD: Makefile,v 1.33 2023/10/13 12:06:49 job Exp $
# $OpenBSD: Makefile,v 1.34 2024/02/22 12:49:42 job Exp $
PROG= rpki-client
SRCS= as.c aspa.c cert.c cms.c constraints.c crl.c encoding.c filemode.c \
@ -6,7 +6,7 @@ SRCS= as.c aspa.c cert.c cms.c constraints.c crl.c encoding.c filemode.c \
output.c output-bgpd.c output-bird.c output-csv.c output-json.c \
output-ometric.c parser.c print.c repo.c rfc3779.c roa.c \
rrdp.c rrdp_delta.c rrdp_notification.c rrdp_snapshot.c rrdp_util.c \
rsc.c rsync.c tak.c tal.c validate.c x509.c
rsc.c rsync.c spl.c tak.c tal.c validate.c x509.c
MAN= rpki-client.8
LDADD+= -lexpat -ltls -lssl -lcrypto -lutil -lz

View File

@ -1,4 +1,4 @@
/* $OpenBSD: extern.h,v 1.207 2024/02/21 12:48:25 tb Exp $ */
/* $OpenBSD: extern.h,v 1.208 2024/02/22 12:49:42 job Exp $ */
/*
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
*
@ -178,6 +178,7 @@ enum rtype {
RTYPE_ASPA,
RTYPE_TAK,
RTYPE_GEOFEED,
RTYPE_SPL,
};
enum location {
@ -280,6 +281,34 @@ struct rsc {
time_t expires; /* when the signature path expires */
};
/*
* An IP address prefix in a given SignedPrefixList.
*/
struct spl_pfx {
enum afi afi;
struct ip_addr prefix;
};
/*
* An SPL, draft-ietf-sidrops-rpki-prefixlist
* This consists of an ASID and its IP prefixes.
*/
struct spl {
uint32_t asid;
struct spl_pfx *pfxs;
size_t pfxsz;
int talid;
char *aia;
char *aki;
char *sia;
char *ski;
time_t signtime; /* CMS signing-time attribute */
time_t notbefore; /* EE cert's Not Before */
time_t notafter; /* EE cert's Not After */
time_t expires; /* when the certification path expires */
int valid;
};
/*
* Datastructure representing the TAKey sequence inside TAKs.
*/
@ -409,6 +438,26 @@ struct vrp {
RB_HEAD(vrp_tree, vrp);
RB_PROTOTYPE(vrp_tree, vrp, entry, vrpcmp);
/*
* Validated SignedPrefixList Payload
* A single VSP element (including ASID)
* draft-ietf-sidrops-rpki-prefixlist
*/
struct vsp {
RB_ENTRY(vsp) entry;
uint32_t asid;
struct spl_pfx *prefixes;
size_t prefixesz;
time_t expires;
int talid;
unsigned int repoid;
};
/*
* Tree of VSP sorted by asid
*/
RB_HEAD(vsp_tree, vsp);
RB_PROTOTYPE(vsp_tree, vsp, entry, vspcmp);
/*
* A single BGPsec Router Key (including ASID)
*/
@ -561,6 +610,11 @@ struct repotalstats {
uint32_t vaps_pas; /* total number of providers */
uint32_t vrps; /* total number of Validated ROA Payloads */
uint32_t vrps_uniqs; /* number of unique vrps */
uint32_t spls; /* signed prefix list */
uint32_t spls_fail; /* failing syntactic parse */
uint32_t spls_invalid; /* invalid asid */
uint32_t vsps; /* total number of Validated SPL Payloads */
uint32_t vsps_uniqs; /* number of unique vsps */
};
struct repostats {
@ -637,6 +691,14 @@ struct roa *roa_read(struct ibuf *);
void roa_insert_vrps(struct vrp_tree *, struct roa *,
struct repo *);
void spl_buffer(struct ibuf *, const struct spl *);
void spl_free(struct spl *);
struct spl *spl_parse(X509 **, const char *, int, const unsigned char *,
size_t);
struct spl *spl_read(struct ibuf *);
void spl_insert_vsps(struct vsp_tree *, struct spl *,
struct repo *);
void gbr_free(struct gbr *);
struct gbr *gbr_parse(X509 **, const char *, int, const unsigned char *,
size_t);
@ -690,6 +752,7 @@ int valid_aspa(const char *, struct cert *, struct aspa *);
int valid_geofeed(const char *, struct cert *, struct geofeed *);
int valid_uuid(const char *);
int valid_ca_pkey(const char *, EVP_PKEY *);
int valid_spl(const char *, struct cert *, struct spl *);
/* Working with CMS. */
unsigned char *cms_parse_validate(X509 **, const char *,
@ -870,6 +933,7 @@ void rsc_print(const X509 *, const struct rsc *);
void aspa_print(const X509 *, const struct aspa *);
void tak_print(const X509 *, const struct tak *);
void geofeed_print(const X509 *, const struct geofeed *);
void spl_print(const X509 *, const struct spl *);
/* Missing RFC 3779 API */
IPAddrBlocks *IPAddrBlocks_new(void);
@ -885,22 +949,22 @@ extern int outformats;
#define FORMAT_OMETRIC 0x10
int outputfiles(struct vrp_tree *v, struct brk_tree *b,
struct vap_tree *, struct stats *);
struct vap_tree *, struct vsp_tree *, struct stats *);
int outputheader(FILE *, struct stats *);
int output_bgpd(FILE *, struct vrp_tree *, struct brk_tree *,
struct vap_tree *, struct stats *);
struct vap_tree *, struct vsp_tree *, struct stats *);
int output_bird1v4(FILE *, struct vrp_tree *, struct brk_tree *,
struct vap_tree *, struct stats *);
struct vap_tree *, struct vsp_tree *, struct stats *);
int output_bird1v6(FILE *, struct vrp_tree *, struct brk_tree *,
struct vap_tree *, struct stats *);
struct vap_tree *, struct vsp_tree *, struct stats *);
int output_bird2(FILE *, struct vrp_tree *, struct brk_tree *,
struct vap_tree *, struct stats *);
struct vap_tree *, struct vsp_tree *, struct stats *);
int output_csv(FILE *, struct vrp_tree *, struct brk_tree *,
struct vap_tree *, struct stats *);
struct vap_tree *, struct vsp_tree *, struct stats *);
int output_json(FILE *, struct vrp_tree *, struct brk_tree *,
struct vap_tree *, struct stats *);
struct vap_tree *, struct vsp_tree *, struct stats *);
int output_ometric(FILE *, struct vrp_tree *, struct brk_tree *,
struct vap_tree *, struct stats *);
struct vap_tree *, struct vsp_tree *, struct stats *);
void logx(const char *fmt, ...)
__attribute__((format(printf, 1, 2)));

View File

@ -1,4 +1,4 @@
/* $OpenBSD: filemode.c,v 1.37 2024/01/23 09:32:57 job Exp $ */
/* $OpenBSD: filemode.c,v 1.38 2024/02/22 12:49:42 job Exp $ */
/*
* Copyright (c) 2019 Claudio Jeker <claudio@openbsd.org>
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@ -296,6 +296,7 @@ proc_parser_file(char *file, unsigned char *buf, size_t len)
struct mft *mft = NULL;
struct roa *roa = NULL;
struct rsc *rsc = NULL;
struct spl *spl = NULL;
struct tak *tak = NULL;
struct tal *tal = NULL;
char *aia = NULL, *aki = NULL;
@ -422,6 +423,15 @@ proc_parser_file(char *file, unsigned char *buf, size_t len)
expires = &rsc->expires;
notafter = &rsc->notafter;
break;
case RTYPE_SPL:
spl = spl_parse(&x509, file, -1, buf, len);
if (spl == NULL)
break;
aia = spl->aia;
aki = spl->aki;
expires = &spl->expires;
notafter = &spl->notafter;
break;
case RTYPE_TAK:
tak = tak_parse(&x509, file, -1, buf, len);
if (tak == NULL)
@ -464,6 +474,8 @@ proc_parser_file(char *file, unsigned char *buf, size_t len)
case RTYPE_RSC:
status = rsc->valid;
break;
case RTYPE_SPL:
status = spl->valid;
default:
break;
}
@ -523,6 +535,9 @@ proc_parser_file(char *file, unsigned char *buf, size_t len)
case RTYPE_RSC:
rsc_print(x509, rsc);
break;
case RTYPE_SPL:
spl_print(x509, spl);
break;
case RTYPE_TAK:
tak_print(x509, tak);
break;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: main.c,v 1.250 2024/02/21 12:48:25 tb Exp $ */
/* $OpenBSD: main.c,v 1.251 2024/02/22 12:49:42 job Exp $ */
/*
* Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@ -557,7 +557,8 @@ queue_add_from_cert(const struct cert *cert)
*/
static void
entity_process(struct ibuf *b, struct stats *st, struct vrp_tree *tree,
struct brk_tree *brktree, struct vap_tree *vaptree)
struct brk_tree *brktree, struct vap_tree *vaptree,
struct vsp_tree *vsptree)
{
enum rtype type;
struct tal *tal;
@ -565,6 +566,7 @@ entity_process(struct ibuf *b, struct stats *st, struct vrp_tree *tree,
struct mft *mft;
struct roa *roa;
struct aspa *aspa;
struct spl *spl;
struct repo *rp;
char *file;
time_t mtime;
@ -665,6 +667,19 @@ entity_process(struct ibuf *b, struct stats *st, struct vrp_tree *tree,
repo_stat_inc(rp, talid, type, STYPE_INVALID);
aspa_free(aspa);
break;
case RTYPE_SPL:
io_read_buf(b, &c, sizeof(c));
if (c == 0) {
repo_stat_inc(rp, talid, type, STYPE_FAIL);
break;
}
spl = spl_read(b);
if (spl->valid)
spl_insert_vsps(vsptree, spl, rp);
else
repo_stat_inc(rp, talid, type, STYPE_INVALID);
spl_free(spl);
break;
case RTYPE_TAK:
break;
case RTYPE_FILE:
@ -755,6 +770,11 @@ sum_stats(const struct repo *rp, const struct repotalstats *in, void *arg)
out->vaps += in->vaps;
out->vaps_uniqs += in->vaps_uniqs;
out->vaps_pas += in->vaps_pas;
out->spls += in->spls;
out->spls_fail += in->spls_fail;
out->spls_invalid += in->spls_invalid;
out->vsps += in->vsps;
out->vsps_uniqs += in->vsps_uniqs;
}
static void
@ -947,6 +967,7 @@ main(int argc, char *argv[])
const char *errs, *name;
const char *skiplistfile = NULL;
struct vrp_tree vrps = RB_INITIALIZER(&vrps);
struct vsp_tree vsps = RB_INITIALIZER(&vsps);
struct brk_tree brks = RB_INITIALIZER(&brks);
struct vap_tree vaps = RB_INITIALIZER(&vaps);
struct rusage ru;
@ -1341,7 +1362,8 @@ main(int argc, char *argv[])
if ((pfd[0].revents & POLLIN)) {
b = io_buf_read(proc, &procbuf);
if (b != NULL) {
entity_process(b, &stats, &vrps, &brks, &vaps);
entity_process(b, &stats, &vrps, &brks, &vaps,
&vsps);
ibuf_free(b);
}
}
@ -1434,7 +1456,7 @@ main(int argc, char *argv[])
}
repo_stats_collect(sum_repostats, &stats.repo_stats);
if (outputfiles(&vrps, &brks, &vaps, &stats))
if (outputfiles(&vrps, &brks, &vaps, &vsps, &stats))
rc = 1;
printf("Processing time %lld seconds "
@ -1451,6 +1473,9 @@ main(int argc, char *argv[])
"invalid)\n", stats.repo_tal_stats.aspas,
stats.repo_tal_stats.aspas_fail,
stats.repo_tal_stats.aspas_invalid);
printf("Signed Prefix Lists: %u (%u failed parse, %u invalid)\n",
stats.repo_tal_stats.spls, stats.repo_tal_stats.spls_fail,
stats.repo_tal_stats.spls_invalid);
printf("BGPsec Router Certificates: %u\n", stats.repo_tal_stats.brks);
printf("Certificates: %u (%u invalid)\n",
stats.repo_tal_stats.certs, stats.repo_tal_stats.certs_fail);
@ -1470,6 +1495,8 @@ main(int argc, char *argv[])
stats.repo_tal_stats.vrps_uniqs);
printf("VAP Entries: %u (%u unique)\n", stats.repo_tal_stats.vaps,
stats.repo_tal_stats.vaps_uniqs);
printf("VSP Entries: %u (%u unique)\n", stats.repo_tal_stats.vsps,
stats.repo_tal_stats.vsps_uniqs);
/* Memory cleanup. */
repo_free();

View File

@ -1,4 +1,4 @@
/* $OpenBSD: mft.c,v 1.111 2024/02/21 09:17:06 tb Exp $ */
/* $OpenBSD: mft.c,v 1.112 2024/02/22 12:49:42 job Exp $ */
/*
* Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@ -121,6 +121,8 @@ rtype_from_file_extension(const char *fn)
return RTYPE_TAK;
if (strcasecmp(fn + sz - 4, ".csv") == 0)
return RTYPE_GEOFEED;
if (strcasecmp(fn + sz - 4, ".spl") == 0)
return RTYPE_SPL;
return RTYPE_INVALID;
}
@ -162,6 +164,7 @@ rtype_from_mftfile(const char *fn)
case RTYPE_GBR:
case RTYPE_ROA:
case RTYPE_ASPA:
case RTYPE_SPL:
case RTYPE_TAK:
return type;
default:

View File

@ -1,4 +1,4 @@
/* $OpenBSD: output-bgpd.c,v 1.28 2023/06/26 18:39:53 job Exp $ */
/* $OpenBSD: output-bgpd.c,v 1.29 2024/02/22 12:49:42 job Exp $ */
/*
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
*
@ -21,7 +21,7 @@
int
output_bgpd(FILE *out, struct vrp_tree *vrps, struct brk_tree *brks,
struct vap_tree *vaps, struct stats *st)
struct vap_tree *vaps, struct vsp_tree *vsps, struct stats *st)
{
struct vrp *vrp;
struct vap *vap;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: output-bird.c,v 1.18 2023/05/30 12:14:48 claudio Exp $ */
/* $OpenBSD: output-bird.c,v 1.19 2024/02/22 12:49:42 job Exp $ */
/*
* Copyright (c) 2019 Claudio Jeker <claudio@openbsd.org>
* Copyright (c) 2020 Robert Scheck <robert@fedoraproject.org>
@ -22,7 +22,7 @@
int
output_bird1v4(FILE *out, struct vrp_tree *vrps, struct brk_tree *brks,
struct vap_tree *vaps, struct stats *st)
struct vap_tree *vaps, struct vsp_tree *vsps, struct stats *st)
{
extern const char *bird_tablename;
struct vrp *v;
@ -51,7 +51,7 @@ output_bird1v4(FILE *out, struct vrp_tree *vrps, struct brk_tree *brks,
int
output_bird1v6(FILE *out, struct vrp_tree *vrps, struct brk_tree *brks,
struct vap_tree *vaps, struct stats *st)
struct vap_tree *vaps, struct vsp_tree *vsps, struct stats *st)
{
extern const char *bird_tablename;
struct vrp *v;
@ -80,7 +80,7 @@ output_bird1v6(FILE *out, struct vrp_tree *vrps, struct brk_tree *brks,
int
output_bird2(FILE *out, struct vrp_tree *vrps, struct brk_tree *brks,
struct vap_tree *vaps, struct stats *st)
struct vap_tree *vaps, struct vsp_tree *vsps, struct stats *st)
{
extern const char *bird_tablename;
struct vrp *v;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: output-csv.c,v 1.13 2022/08/30 18:56:49 job Exp $ */
/* $OpenBSD: output-csv.c,v 1.14 2024/02/22 12:49:42 job Exp $ */
/*
* Copyright (c) 2019 Claudio Jeker <claudio@openbsd.org>
*
@ -21,7 +21,7 @@
int
output_csv(FILE *out, struct vrp_tree *vrps, struct brk_tree *brks,
struct vap_tree *vaps, struct stats *st)
struct vap_tree *vaps, struct vsp_tree *vsps, struct stats *st)
{
struct vrp *v;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: output-json.c,v 1.42 2024/02/13 20:41:22 job Exp $ */
/* $OpenBSD: output-json.c,v 1.43 2024/02/22 12:49:42 job Exp $ */
/*
* Copyright (c) 2019 Claudio Jeker <claudio@openbsd.org>
*
@ -47,6 +47,9 @@ outputheader_json(struct stats *st)
json_do_int("roas", st->repo_tal_stats.roas);
json_do_int("failedroas", st->repo_tal_stats.roas_fail);
json_do_int("invalidroas", st->repo_tal_stats.roas_invalid);
json_do_int("spls", st->repo_tal_stats.spls);
json_do_int("failedspls", st->repo_tal_stats.spls_fail);
json_do_int("invalidspls", st->repo_tal_stats.spls_invalid);
json_do_int("aspas", st->repo_tal_stats.aspas);
json_do_int("failedaspas", st->repo_tal_stats.aspas_fail);
json_do_int("invalidaspas", st->repo_tal_stats.aspas_invalid);
@ -69,6 +72,8 @@ outputheader_json(struct stats *st)
json_do_int("repositories", st->repos);
json_do_int("vrps", st->repo_tal_stats.vrps);
json_do_int("uniquevrps", st->repo_tal_stats.vrps_uniqs);
json_do_int("vsps", st->repo_tal_stats.vsps);
json_do_int("uniquevsps", st->repo_tal_stats.vsps_uniqs);
json_do_int("vaps", st->repo_tal_stats.vaps);
json_do_int("uniquevaps", st->repo_tal_stats.vaps_uniqs);
json_do_int("cachedir_del_files", st->repo_stats.del_files);
@ -109,11 +114,13 @@ output_aspa(struct vap_tree *vaps)
int
output_json(FILE *out, struct vrp_tree *vrps, struct brk_tree *brks,
struct vap_tree *vaps, struct stats *st)
struct vap_tree *vaps, struct vsp_tree *vsps, struct stats *st)
{
char buf[64];
struct vrp *v;
struct brk *b;
struct vsp *vsp;
size_t i;
json_do_start(out);
outputheader_json(st);
@ -147,5 +154,22 @@ output_json(FILE *out, struct vrp_tree *vrps, struct brk_tree *brks,
if (!excludeaspa)
output_aspa(vaps);
json_do_array("signedprefixlists");
RB_FOREACH(vsp, vsp_tree, vsps) {
json_do_object("vsp", 1);
json_do_int("origin_as", vsp->asid);
json_do_array("prefixes");
for (i = 0; i < vsp->prefixesz; i++) {
ip_addr_print(&vsp->prefixes[i].prefix,
vsp->prefixes[i].afi, buf, sizeof(buf));
json_do_string("prefix", buf);
}
json_do_end();
json_do_int("expires", vsp->expires);
json_do_string("ta", taldescs[vsp->talid]);
json_do_end();
}
json_do_end();
return json_do_finish();
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: output-ometric.c,v 1.7 2024/02/13 20:41:22 job Exp $ */
/* $OpenBSD: output-ometric.c,v 1.8 2024/02/22 12:49:42 job Exp $ */
/*
* Copyright (c) 2022 Claudio Jeker <claudio@openbsd.org>
*
@ -82,6 +82,18 @@ set_common_stats(const struct repotalstats *in, struct ometric *metric,
OKV("type", "state"), OKV("vap", "unique"), ol);
ometric_set_int_with_labels(metric, in->vaps_pas,
OKV("type", "state"), OKV("vap providers", "total"), ol);
ometric_set_int_with_labels(metric, in->spls,
OKV("type", "state"), OKV("spl", "valid"), ol);
ometric_set_int_with_labels(metric, in->spls_fail,
OKV("type", "state"), OKV("spl", "failed parse"), ol);
ometric_set_int_with_labels(metric, in->spls_invalid,
OKV("type", "state"), OKV("spl", "invalid"), ol);
ometric_set_int_with_labels(metric, in->vsps,
OKV("type", "state"), OKV("vsp", "total"), ol);
ometric_set_int_with_labels(metric, in->vsps_uniqs,
OKV("type", "state"), OKV("vsp", "unique"), ol);
}
static void
@ -146,7 +158,7 @@ repo_stats(const struct repo *rp, const struct repostats *in, void *arg)
int
output_ometric(FILE *out, struct vrp_tree *vrps, struct brk_tree *brks,
struct vap_tree *vaps, struct stats *st)
struct vap_tree *vaps, struct vsp_tree *vsps, struct stats *st)
{
struct olabels *ol;
const char *keys[4] = { "nodename", "domainname", "release", NULL };

View File

@ -1,4 +1,4 @@
/* $OpenBSD: output.c,v 1.32 2024/02/03 14:30:47 job Exp $ */
/* $OpenBSD: output.c,v 1.33 2024/02/22 12:49:42 job Exp $ */
/*
* Copyright (c) 2019 Theo de Raadt <deraadt@openbsd.org>
*
@ -64,7 +64,7 @@ static const struct outputs {
int format;
char *name;
int (*fn)(FILE *, struct vrp_tree *, struct brk_tree *,
struct vap_tree *, struct stats *);
struct vap_tree *, struct vsp_tree *, struct stats *);
} outputs[] = {
{ FORMAT_OPENBGPD, "openbgpd", output_bgpd },
{ FORMAT_BIRD, "bird1v4", output_bird1v4 },
@ -84,7 +84,7 @@ static void set_signal_handler(void);
int
outputfiles(struct vrp_tree *v, struct brk_tree *b, struct vap_tree *a,
struct stats *st)
struct vsp_tree *p, struct stats *st)
{
int i, rc = 0;
@ -103,7 +103,7 @@ outputfiles(struct vrp_tree *v, struct brk_tree *b, struct vap_tree *a,
rc = 1;
continue;
}
if ((*outputs[i].fn)(fout, v, b, a, st) != 0) {
if ((*outputs[i].fn)(fout, v, b, a, p, st) != 0) {
warn("output for %s format failed", outputs[i].name);
fclose(fout);
output_cleantmp();

View File

@ -1,4 +1,4 @@
/* $OpenBSD: parser.c,v 1.128 2024/02/03 14:30:47 job Exp $ */
/* $OpenBSD: parser.c,v 1.129 2024/02/22 12:49:42 job Exp $ */
/*
* Copyright (c) 2019 Claudio Jeker <claudio@openbsd.org>
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@ -157,6 +157,41 @@ proc_parser_roa(char *file, const unsigned char *der, size_t len,
return roa;
}
/*
* Parse and validate a draft-ietf-sidrops-rpki-prefixlist SPL.
* Returns the spl on success, NULL on failure.
*/
static struct spl *
proc_parser_spl(char *file, const unsigned char *der, size_t len,
const struct entity *entp)
{
struct spl *spl;
struct auth *a;
struct crl *crl;
X509 *x509;
const char *errstr;
if ((spl = spl_parse(&x509, file, entp->talid, der, len)) == NULL)
return NULL;
a = valid_ski_aki(file, &auths, spl->ski, spl->aki, entp->mftaki);
crl = crl_get(&crlt, a);
if (!valid_x509(file, ctx, x509, a, crl, &errstr)) {
warnx("%s: %s", file, errstr);
X509_free(x509);
spl_free(spl);
return NULL;
}
X509_free(x509);
spl->talid = a->cert->talid;
spl->expires = x509_find_expires(spl->notafter, a, &crlt);
return spl;
}
/*
* Check all files and their hashes in a MFT structure.
* Return zero on failure, non-zero on success.
@ -681,6 +716,7 @@ parse_entity(struct entityq *q, struct msgbuf *msgq)
struct aspa *aspa;
struct gbr *gbr;
struct tak *tak;
struct spl *spl;
struct ibuf *b;
unsigned char *f;
time_t mtime, crlmtime;
@ -822,6 +858,19 @@ parse_entity(struct entityq *q, struct msgbuf *msgq)
io_simple_buffer(b, &mtime, sizeof(mtime));
tak_free(tak);
break;
case RTYPE_SPL:
file = parse_load_file(entp, &f, &flen);
io_str_buffer(b, file);
spl = proc_parser_spl(file, f, flen, entp);
if (spl != NULL)
mtime = spl->signtime;
io_simple_buffer(b, &mtime, sizeof(mtime));
c = (spl != NULL);
io_simple_buffer(b, &c, sizeof(int));
if (spl != NULL)
spl_buffer(b, spl);
spl_free(spl);
break;
case RTYPE_CRL:
default:
file = parse_filepath(entp->repoid, entp->path,

View File

@ -1,4 +1,4 @@
/* $OpenBSD: print.c,v 1.49 2024/02/16 05:18:29 tb Exp $ */
/* $OpenBSD: print.c,v 1.51 2024/02/22 19:29:55 tb Exp $ */
/*
* Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@ -507,6 +507,60 @@ roa_print(const X509 *x, const struct roa *p)
json_do_end();
}
void
spl_print(const X509 *x, const struct spl *s)
{
char buf[128];
size_t i;
if (outformats & FORMAT_JSON) {
json_do_string("type", "spl");
json_do_string("ski", pretty_key_id(s->ski));
x509_print(x);
json_do_string("aki", pretty_key_id(s->aki));
json_do_string("aia", s->aia);
json_do_string("sia", s->sia);
if (s->signtime != 0)
json_do_int("signing_time", s->signtime);
json_do_int("valid_since", s->notbefore);
json_do_int("valid_until", s->notafter);
if (s->expires)
json_do_int("expires", s->expires);
json_do_int("asid", s->asid);
} else {
printf("Subject key identifier: %s\n", pretty_key_id(s->ski));
x509_print(x);
printf("Authority key identifier: %s\n", pretty_key_id(s->aki));
printf("Authority info access: %s\n", s->aia);
printf("Subject info access: %s\n", s->sia);
if (s->signtime != 0)
printf("Signing time: %s\n",
time2str(s->signtime));
printf("SPL not before: %s\n",
time2str(s->notbefore));
printf("SPL not after: %s\n", time2str(s->notafter));
printf("asID: %u\n", s->asid);
printf("Originated IP Prefixes: ");
}
if (outformats & FORMAT_JSON)
json_do_array("prefixes");
for (i = 0; i < s->pfxsz; i++) {
ip_addr_print(&s->pfxs[i].prefix, s->pfxs[i].afi, buf,
sizeof(buf));
if (outformats & FORMAT_JSON) {
json_do_string("prefix", buf);
} else {
if (i > 0)
printf("%26s", "");
printf("%s\n", buf);
}
}
if (outformats & FORMAT_JSON)
json_do_end();
}
void
gbr_print(const X509 *x, const struct gbr *p)
{

View File

@ -1,4 +1,4 @@
/* $OpenBSD: repo.c,v 1.52 2024/02/03 14:30:47 job Exp $ */
/* $OpenBSD: repo.c,v 1.53 2024/02/22 12:49:42 job Exp $ */
/*
* Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
@ -1480,6 +1480,30 @@ repo_stat_inc(struct repo *rp, int talid, enum rtype type, enum stype subtype)
break;
}
break;
case RTYPE_SPL:
switch (subtype) {
case STYPE_OK:
rp->stats[talid].spls++;
break;
case STYPE_FAIL:
rp->stats[talid].spls_fail++;
break;
case STYPE_INVALID:
rp->stats[talid].spls_invalid++;
break;
case STYPE_TOTAL:
rp->stats[talid].vsps++;
break;
case STYPE_UNIQUE:
rp->stats[talid].vsps_uniqs++;
break;
case STYPE_DEC_UNIQUE:
rp->stats[talid].vsps_uniqs--;
break;
default:
break;
}
break;
case RTYPE_CRL:
rp->stats[talid].crls++;
break;

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: rpki-client.8,v 1.100 2024/01/31 17:19:02 job Exp $
.\" $OpenBSD: rpki-client.8,v 1.102 2024/02/22 17:54:08 tb Exp $
.\"
.\" Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
.\"
@ -14,7 +14,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
.Dd $Mdocdate: January 31 2024 $
.Dd $Mdocdate: February 22 2024 $
.Dt RPKI-CLIENT 8
.Os
.Sh NAME
@ -269,7 +269,8 @@ file imposes constraints on the Trust Anchor reachable via the same-named
.Em .tal
file.
One entry per line.
Entries can be IP prefixes, IP address ranges, AS identifiers, or AS identifier ranges.
Entries can be IP prefixes, IP address ranges,
AS identifiers, or AS identifier ranges.
Ranges are a minimum and maximum separated by a hyphen
.Pq Sq - .
Comments can be put anywhere in the file using a hash mark
@ -451,6 +452,12 @@ agreement regarding ARIN service restrictions.
.%U https://datatracker.ietf.org/doc/html/draft-spaghetti-sidrops-rrdp-desynchronization-00
.%D Jan, 2024
.Re
.Pp
.Rs
.%T A profile for Signed Prefix Lists for Use in the Resource Public Key Infrastructure (RPKI)
.%U https://datatracker.ietf.org/doc/html/draft-ietf-sidrops-rpki-prefixlist-02
.%D Jan, 2024
.Re
.Sh HISTORY
.Nm
first appeared in

487
usr.sbin/rpki-client/spl.c Normal file
View File

@ -0,0 +1,487 @@
/* $OpenBSD: spl.c,v 1.2 2024/02/22 19:29:55 tb Exp $ */
/*
* Copyright (c) 2024 Job Snijders <job@fastly.com>
* Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <assert.h>
#include <err.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <openssl/asn1.h>
#include <openssl/asn1t.h>
#include <openssl/stack.h>
#include <openssl/safestack.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#include "extern.h"
extern ASN1_OBJECT *spl_oid;
/*
* Types and templates for the SPL eContent.
*/
ASN1_ITEM_EXP AddressFamilyPrefixes_it;
ASN1_ITEM_EXP SignedPrefixList_it;
DECLARE_STACK_OF(ASN1_BIT_STRING);
typedef struct {
ASN1_OCTET_STRING *addressFamily;
STACK_OF(ASN1_BIT_STRING) *addressPrefixes;
} AddressFamilyPrefixes;
DECLARE_STACK_OF(AddressFamilyPrefixes);
ASN1_SEQUENCE(AddressFamilyPrefixes) = {
ASN1_SIMPLE(AddressFamilyPrefixes, addressFamily, ASN1_OCTET_STRING),
ASN1_SEQUENCE_OF(AddressFamilyPrefixes, addressPrefixes,
ASN1_BIT_STRING),
} ASN1_SEQUENCE_END(AddressFamilyPrefixes);
#ifndef DEFINE_STACK_OF
#define sk_ASN1_BIT_STRING_num(st) SKM_sk_num(ASN1_BIT_STRING, (st))
#define sk_ASN1_BIT_STRING_value(st, i) SKM_sk_value(ASN1_BIT_STRING, (st), (i))
#define sk_AddressFamilyPrefixes_num(st) \
SKM_sk_num(AddressFamilyPrefixes, (st))
#define sk_AddressFamilyPrefixes_value(st, i) \
SKM_sk_value(AddressFamilyPrefixes, (st), (i))
#endif
typedef struct {
ASN1_INTEGER *version;
ASN1_INTEGER *asid;
STACK_OF(AddressFamilyPrefixes) *prefixBlocks;
} SignedPrefixList;
ASN1_SEQUENCE(SignedPrefixList) = {
ASN1_EXP_OPT(SignedPrefixList, version, ASN1_INTEGER, 0),
ASN1_SIMPLE(SignedPrefixList, asid, ASN1_INTEGER),
ASN1_SEQUENCE_OF(SignedPrefixList, prefixBlocks, AddressFamilyPrefixes)
} ASN1_SEQUENCE_END(SignedPrefixList);
DECLARE_ASN1_FUNCTIONS(SignedPrefixList);
IMPLEMENT_ASN1_FUNCTIONS(SignedPrefixList);
/*
* Comparator to help sorting elements in SPL prefixBlocks and VSPs.
* Returns -1 if 'a' should precede 'b', 1 if 'b' should precede 'a',
* or '0' if a and b are equal.
*/
static int
prefix_cmp(enum afi afi, const struct ip_addr *a, const struct ip_addr *b)
{
int cmp;
switch (afi) {
case AFI_IPV4:
cmp = memcmp(&a->addr, &b->addr, 4);
if (cmp < 0)
return -1;
if (cmp > 0)
return 1;
break;
case AFI_IPV6:
cmp = memcmp(&a->addr, &b->addr, 16);
if (cmp < 0)
return -1;
if (cmp > 0)
return 1;
break;
default:
break;
}
if (a->prefixlen < b->prefixlen)
return -1;
if (a->prefixlen > b->prefixlen)
return 1;
return 0;
}
/*
* Parses the eContent section of a SPL file,
* draft-ietf-sidrops-rpki-prefixlist-02 section 3.
* Returns zero on failure, non-zero on success.
*/
static int
spl_parse_econtent(const char *fn, struct spl *spl, const unsigned char *d,
size_t dsz)
{
const unsigned char *oder;
SignedPrefixList *spl_asn1;
const AddressFamilyPrefixes *afp;
const STACK_OF(ASN1_BIT_STRING) *prefixes;
const ASN1_BIT_STRING *prefix_asn1;
int afpsz, prefixesz;
enum afi afi;
struct ip_addr ip_addr;
struct spl_pfx *prefix;
int ipv4_seen = 0, ipv6_seen = 0;
int i, j, rc = 0;
oder = d;
if ((spl_asn1 = d2i_SignedPrefixList(NULL, &d, dsz)) == NULL) {
warnx("%s: RFC 6482 section 3: failed to parse "
"SignedPrefixList", fn);
goto out;
}
if (d != oder + dsz) {
warnx("%s: %td bytes trailing garbage in eContent", fn,
oder + dsz - d);
goto out;
}
if (!valid_econtent_version(fn, spl_asn1->version, 0))
goto out;
if (!as_id_parse(spl_asn1->asid, &spl->asid)) {
warnx("%s: asid: malformed AS identifier", fn);
goto out;
}
afpsz = sk_AddressFamilyPrefixes_num(spl_asn1->prefixBlocks);
if (afpsz < 0 || afpsz > 2) {
warnx("%s: unexpected number of AddressFamilyAddressPrefixes"
"(got %d, expected 0, 1, or 2)", fn, afpsz);
goto out;
}
for (i = 0; i < afpsz; i++) {
struct ip_addr *prev_ip_addr = NULL;
afp = sk_AddressFamilyPrefixes_value(spl_asn1->prefixBlocks, i);
prefixes = afp->addressPrefixes;
prefixesz = sk_ASN1_BIT_STRING_num(afp->addressPrefixes);
if (prefixesz == 0) {
warnx("%s: empty AddressFamilyAddressPrefixes", fn);
goto out;
}
if (spl->pfxsz + prefixesz >= MAX_IP_SIZE) {
warnx("%s: too many addressPrefixes entries", fn);
goto out;
}
if (!ip_addr_afi_parse(fn, afp->addressFamily, &afi))
goto out;
switch (afi) {
case AFI_IPV4:
if (ipv4_seen++ > 0) {
warnx("%s: addressFamilyIPv4 appeared twice",
fn);
goto out;
}
if (ipv6_seen > 0) {
warnx("%s: invalid sorting, IPv6 before IPv4",
fn);
goto out;
}
break;
case AFI_IPV6:
if (ipv6_seen++ > 0) {
warnx("%s: addressFamilyIPv6 appeared twice",
fn);
goto out;
}
}
spl->pfxs = recallocarray(spl->pfxs, spl->pfxsz,
spl->pfxsz + prefixesz, sizeof(struct spl_pfx));
if (spl->pfxs == NULL)
err(1, NULL);
for (j = 0; j < prefixesz; j++) {
prefix_asn1 = sk_ASN1_BIT_STRING_value(prefixes, j);
if (!ip_addr_parse(prefix_asn1, afi, fn, &ip_addr))
goto out;
if (j > 0 &&
prefix_cmp(afi, prev_ip_addr, &ip_addr) != -1) {
warnx("%s: invalid addressPrefixes sorting", fn);
goto out;
}
prefix = &spl->pfxs[spl->pfxsz++];
prefix->prefix = ip_addr;
prefix->afi = afi;
prev_ip_addr = &prefix->prefix;
}
}
rc = 1;
out:
SignedPrefixList_free(spl_asn1);
return rc;
}
/*
* Parse a full Signed Prefix List file.
* Returns the SPL, or NULL if the object was malformed.
*/
struct spl *
spl_parse(X509 **x509, const char *fn, int talid, const unsigned char *der,
size_t len)
{
struct spl *spl;
size_t cmsz;
unsigned char *cms;
struct cert *cert = NULL;
time_t signtime = 0;
int rc = 0;
cms = cms_parse_validate(x509, fn, der, len, spl_oid, &cmsz, &signtime);
if (cms == NULL)
return NULL;
if ((spl = calloc(1, sizeof(*spl))) == NULL)
err(1, NULL);
spl->signtime = signtime;
if (!x509_get_aia(*x509, fn, &spl->aia))
goto out;
if (!x509_get_aki(*x509, fn, &spl->aki))
goto out;
if (!x509_get_sia(*x509, fn, &spl->sia))
goto out;
if (!x509_get_ski(*x509, fn, &spl->ski))
goto out;
if (spl->aia == NULL || spl->aki == NULL || spl->sia == NULL ||
spl->ski == NULL) {
warnx("%s: RFC 6487 section 4.8: "
"missing AIA, AKI, SIA, or SKI X509 extension", fn);
goto out;
}
if (!x509_get_notbefore(*x509, fn, &spl->notbefore))
goto out;
if (!x509_get_notafter(*x509, fn, &spl->notafter))
goto out;
if (!spl_parse_econtent(fn, spl, cms, cmsz))
goto out;
if (x509_any_inherits(*x509)) {
warnx("%s: inherit elements not allowed in EE cert", fn);
goto out;
}
if ((cert = cert_parse_ee_cert(fn, talid, *x509)) == NULL)
goto out;
if (cert->asz == 0) {
warnx("%s: AS Resources extension missing", fn);
goto out;
}
if (cert->ipsz > 0) {
warnx("%s: superfluous IP Resources extension present", fn);
goto out;
}
/*
* If the SPL isn't valid, we accept it anyway and depend upon
* the code around spl_read() to check the "valid" field itself.
*/
spl->valid = valid_spl(fn, cert, spl);
rc = 1;
out:
if (rc == 0) {
spl_free(spl);
spl = NULL;
X509_free(*x509);
*x509 = NULL;
}
cert_free(cert);
free(cms);
return spl;
}
void
spl_free(struct spl *s)
{
if (s == NULL)
return;
free(s->aia);
free(s->aki);
free(s->sia);
free(s->ski);
free(s->pfxs);
free(s);
}
/*
* Serialize parsed SPL content.
* See spl_read() for reader.
*/
void
spl_buffer(struct ibuf *b, const struct spl *s)
{
io_simple_buffer(b, &s->valid, sizeof(s->valid));
io_simple_buffer(b, &s->asid, sizeof(s->asid));
io_simple_buffer(b, &s->talid, sizeof(s->talid));
io_simple_buffer(b, &s->pfxsz, sizeof(s->pfxsz));
io_simple_buffer(b, &s->expires, sizeof(s->expires));
io_simple_buffer(b, s->pfxs, s->pfxsz * sizeof(s->pfxs[0]));
io_str_buffer(b, s->aia);
io_str_buffer(b, s->aki);
io_str_buffer(b, s->ski);
}
/*
* Read parsed SPL content from descriptor.
* See spl_buffer() for writer.
* Result must be passed to spl_free().
*/
struct spl *
spl_read(struct ibuf *b)
{
struct spl *s;
if ((s = calloc(1, sizeof(struct spl))) == NULL)
err(1, NULL);
io_read_buf(b, &s->valid, sizeof(s->valid));
io_read_buf(b, &s->asid, sizeof(s->asid));
io_read_buf(b, &s->talid, sizeof(s->talid));
io_read_buf(b, &s->pfxsz, sizeof(s->pfxsz));
io_read_buf(b, &s->expires, sizeof(s->expires));
if ((s->pfxs = calloc(s->pfxsz, sizeof(struct spl_pfx))) == NULL)
err(1, NULL);
io_read_buf(b, s->pfxs, s->pfxsz * sizeof(s->pfxs[0]));
io_read_str(b, &s->aia);
io_read_str(b, &s->aki);
io_read_str(b, &s->ski);
assert(s->aia && s->aki && s->ski);
return s;
}
static int
spl_pfx_cmp(const struct spl_pfx *a, const struct spl_pfx *b)
{
if (a->afi > b->afi)
return 1;
if (a->afi < b->afi)
return -1;
return prefix_cmp(a->afi, &a->prefix, &b->prefix);
}
static void
insert_vsp(struct vsp *vsp, size_t idx, struct spl_pfx *pfx)
{
if (idx < vsp->prefixesz)
memmove(vsp->prefixes + idx + 1, vsp->prefixes + idx,
(vsp->prefixesz - idx) * sizeof(*vsp->prefixes));
vsp->prefixes[idx] = *pfx;
vsp->prefixesz++;
}
/*
* Add each prefix in the SPL into the VSP tree.
* Updates "vsps" to be the number of VSPs and "uniqs" to be the unique
* number of prefixes.
*/
void
spl_insert_vsps(struct vsp_tree *tree, struct spl *spl, struct repo *rp)
{
struct vsp *vsp, *found;
size_t i, j;
int cmp;
if ((vsp = calloc(1, sizeof(*vsp))) == NULL)
err(1, NULL);
vsp->asid = spl->asid;
vsp->talid = spl->talid;
vsp->expires = spl->expires;
if (rp != NULL)
vsp->repoid = repo_id(rp);
if ((found = RB_INSERT(vsp_tree, tree, vsp)) != NULL) {
/* already exists */
if (found->expires < vsp->expires) {
/* adjust unique count */
repo_stat_inc(repo_byid(found->repoid),
found->talid, RTYPE_SPL, STYPE_DEC_UNIQUE);
found->expires = vsp->expires;
found->talid = vsp->talid;
found->repoid = vsp->repoid;
repo_stat_inc(rp, vsp->talid, RTYPE_SPL,
STYPE_UNIQUE);
}
free(vsp);
vsp = found;
} else
repo_stat_inc(rp, vsp->talid, RTYPE_SPL, STYPE_UNIQUE);
repo_stat_inc(rp, spl->talid, RTYPE_SPL, STYPE_TOTAL);
/* merge content of multiple SPLs */
vsp->prefixes = reallocarray(vsp->prefixes,
vsp->prefixesz + spl->pfxsz, sizeof(struct spl_pfx));
if (vsp->prefixes == NULL)
err(1, NULL);
/*
* Merge all data from the new SPL at hand into 'vsp': loop over
* all SPL->pfxs, and insert them in the right place in
* vsp->prefixes while keeping the order of the array.
*/
for (i = 0, j = 0; i < spl->pfxsz; ) {
cmp = -1;
if (j == vsp->prefixesz ||
(cmp = spl_pfx_cmp(&spl->pfxs[i], &vsp->prefixes[j])) < 0) {
insert_vsp(vsp, j, &spl->pfxs[i]);
i++;
} else if (cmp == 0)
i++;
if (j < vsp->prefixesz)
j++;
}
}
/*
* Comparison function for the RB tree
*/
static inline int
vspcmp(const struct vsp *a, const struct vsp *b)
{
if (a->asid > b->asid)
return 1;
if (a->asid < b->asid)
return -1;
return 0;
}
RB_GENERATE(vsp_tree, vsp, entry, vspcmp);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: validate.c,v 1.71 2024/02/01 15:11:38 tb Exp $ */
/* $OpenBSD: validate.c,v 1.72 2024/02/22 12:49:42 job Exp $ */
/*
* Copyright (c) 2019 Kristaps Dzonsons <kristaps@bsd.lv>
*
@ -194,6 +194,22 @@ valid_roa(const char *fn, struct cert *cert, struct roa *roa)
return 1;
}
/*
* Validate our SPL: check that the asID is contained in the end-entity
* certificate's resources.
* Returns 1 if valid, 0 otherwise.
*/
int
valid_spl(const char *fn, struct cert *cert, struct spl *spl)
{
if (as_check_covered(spl->asid, spl->asid, cert->as, cert->asz) > 0)
return 1;
warnx("%s: SPL: uncovered ASID: %u", fn, spl->asid);
return 0;
}
/*
* Validate a file by verifying the SHA256 hash of that file.
* The file to check is passed as a file descriptor.

View File

@ -1,4 +1,4 @@
/* $OpenBSD: x509.c,v 1.80 2024/02/16 05:18:29 tb Exp $ */
/* $OpenBSD: x509.c,v 1.81 2024/02/22 12:49:42 job Exp $ */
/*
* Copyright (c) 2022 Theo Buehler <tb@openbsd.org>
* Copyright (c) 2021 Claudio Jeker <claudio@openbsd.org>
@ -44,6 +44,7 @@ ASN1_OBJECT *rsc_oid; /* id-ct-signedChecklist */
ASN1_OBJECT *aspa_oid; /* id-ct-ASPA */
ASN1_OBJECT *tak_oid; /* id-ct-SignedTAL */
ASN1_OBJECT *geofeed_oid; /* id-ct-geofeedCSVwithCRLF */
ASN1_OBJECT *spl_oid; /* id-ct-signedPrefixList */
static const struct {
const char *oid;
@ -117,6 +118,10 @@ static const struct {
.oid = "1.2.840.113549.1.9.16.1.50",
.ptr = &tak_oid,
},
{
.oid = "1.2.840.113549.1.9.16.1.51",
.ptr = &spl_oid,
},
};
void