sync with OpenBSD -current
This commit is contained in:
parent
4b5c843641
commit
fe0bbab526
22 changed files with 1045 additions and 594 deletions
|
@ -1,4 +1,4 @@
|
|||
/* $OpenBSD: util.c,v 1.79 2024/01/23 16:13:35 claudio Exp $ */
|
||||
/* $OpenBSD: util.c,v 1.80 2024/01/30 13:50:09 claudio Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2006 Claudio Jeker <claudio@openbsd.org>
|
||||
|
@ -32,8 +32,6 @@
|
|||
#include "rde.h"
|
||||
#include "log.h"
|
||||
|
||||
const char *aspath_delim(uint8_t, int);
|
||||
|
||||
const char *
|
||||
log_addr(const struct bgpd_addr *addr)
|
||||
{
|
||||
|
@ -235,6 +233,26 @@ log_aspa(struct aspa_set *aspa)
|
|||
return errbuf;
|
||||
}
|
||||
|
||||
const char *
|
||||
log_aspath_error(int error)
|
||||
{
|
||||
static char buf[20];
|
||||
|
||||
switch (error) {
|
||||
case AS_ERR_LEN:
|
||||
return "inconsitent lenght";
|
||||
case AS_ERR_TYPE:
|
||||
return "unknown segment type";
|
||||
case AS_ERR_BAD:
|
||||
return "invalid encoding";
|
||||
case AS_ERR_SOFT:
|
||||
return "soft failure";
|
||||
default:
|
||||
snprintf(buf, sizeof(buf), "unknown %d", error);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
log_rtr_error(enum rtr_error err)
|
||||
{
|
||||
|
@ -286,7 +304,7 @@ log_policy(enum role role)
|
|||
}
|
||||
}
|
||||
|
||||
const char *
|
||||
static const char *
|
||||
aspath_delim(uint8_t seg_type, int closing)
|
||||
{
|
||||
static char db[8];
|
||||
|
@ -318,42 +336,38 @@ aspath_delim(uint8_t seg_type, int closing)
|
|||
}
|
||||
}
|
||||
|
||||
int
|
||||
aspath_snprint(char *buf, size_t size, void *data, uint16_t len)
|
||||
static int
|
||||
aspath_snprint(char *buf, size_t size, struct ibuf *in)
|
||||
{
|
||||
#define UPDATE() \
|
||||
do { \
|
||||
if (r < 0) \
|
||||
return (-1); \
|
||||
total_size += r; \
|
||||
if ((unsigned int)r < size) { \
|
||||
size -= r; \
|
||||
buf += r; \
|
||||
} else { \
|
||||
buf += size; \
|
||||
size = 0; \
|
||||
} \
|
||||
#define UPDATE() \
|
||||
do { \
|
||||
if (r < 0 || (unsigned int)r >= size) \
|
||||
return (-1); \
|
||||
size -= r; \
|
||||
buf += r; \
|
||||
} while (0)
|
||||
uint8_t *seg;
|
||||
int r, total_size;
|
||||
uint16_t seg_size;
|
||||
uint8_t i, seg_type, seg_len;
|
||||
|
||||
total_size = 0;
|
||||
seg = data;
|
||||
for (; len > 0; len -= seg_size, seg += seg_size) {
|
||||
seg_type = seg[0];
|
||||
seg_len = seg[1];
|
||||
seg_size = 2 + sizeof(uint32_t) * seg_len;
|
||||
struct ibuf data;
|
||||
uint32_t as;
|
||||
int r, n = 0;
|
||||
uint8_t i, seg_type, seg_len;
|
||||
|
||||
r = snprintf(buf, size, "%s%s",
|
||||
total_size != 0 ? " " : "",
|
||||
ibuf_from_ibuf(&data, in);
|
||||
while (ibuf_size(&data) > 0) {
|
||||
if (ibuf_get_n8(&data, &seg_type) == -1 ||
|
||||
ibuf_get_n8(&data, &seg_len) == -1 ||
|
||||
seg_len == 0)
|
||||
return (-1);
|
||||
|
||||
r = snprintf(buf, size, "%s%s", n++ != 0 ? " " : "",
|
||||
aspath_delim(seg_type, 0));
|
||||
UPDATE();
|
||||
|
||||
for (i = 0; i < seg_len; i++) {
|
||||
r = snprintf(buf, size, "%s",
|
||||
log_as(aspath_extract(seg, i)));
|
||||
if (ibuf_get_n32(&data, &as) == -1)
|
||||
return -1;
|
||||
|
||||
r = snprintf(buf, size, "%s", log_as(as));
|
||||
UPDATE();
|
||||
if (i + 1 < seg_len) {
|
||||
r = snprintf(buf, size, " ");
|
||||
|
@ -364,73 +378,68 @@ aspath_snprint(char *buf, size_t size, void *data, uint16_t len)
|
|||
UPDATE();
|
||||
}
|
||||
/* ensure that we have a valid C-string especially for empty as path */
|
||||
if (size > 0)
|
||||
*buf = '\0';
|
||||
|
||||
return (total_size);
|
||||
*buf = '\0';
|
||||
return (0);
|
||||
#undef UPDATE
|
||||
}
|
||||
|
||||
int
|
||||
aspath_asprint(char **ret, void *data, uint16_t len)
|
||||
static ssize_t
|
||||
aspath_strsize(struct ibuf *in)
|
||||
{
|
||||
size_t slen;
|
||||
int plen;
|
||||
|
||||
slen = aspath_strlen(data, len) + 1;
|
||||
*ret = malloc(slen);
|
||||
if (*ret == NULL)
|
||||
return (-1);
|
||||
|
||||
plen = aspath_snprint(*ret, slen, data, len);
|
||||
if (plen == -1) {
|
||||
free(*ret);
|
||||
*ret = NULL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
size_t
|
||||
aspath_strlen(void *data, uint16_t len)
|
||||
{
|
||||
uint8_t *seg;
|
||||
int total_size;
|
||||
struct ibuf buf;
|
||||
ssize_t total_size = 0;
|
||||
uint32_t as;
|
||||
uint16_t seg_size;
|
||||
uint8_t i, seg_type, seg_len;
|
||||
|
||||
total_size = 0;
|
||||
seg = data;
|
||||
for (; len > 0; len -= seg_size, seg += seg_size) {
|
||||
seg_type = seg[0];
|
||||
seg_len = seg[1];
|
||||
seg_size = 2 + sizeof(uint32_t) * seg_len;
|
||||
ibuf_from_ibuf(&buf, in);
|
||||
while (ibuf_size(&buf) > 0) {
|
||||
if (ibuf_get_n8(&buf, &seg_type) == -1 ||
|
||||
ibuf_get_n8(&buf, &seg_len) == -1 ||
|
||||
seg_len == 0)
|
||||
return (-1);
|
||||
|
||||
if (seg_type == AS_SET)
|
||||
if (total_size != 0)
|
||||
total_size += 3;
|
||||
else
|
||||
total_size += 2;
|
||||
else if (total_size != 0)
|
||||
if (total_size != 0)
|
||||
total_size += 1;
|
||||
total_size += strlen(aspath_delim(seg_type, 0));
|
||||
|
||||
for (i = 0; i < seg_len; i++) {
|
||||
as = aspath_extract(seg, i);
|
||||
if (ibuf_get_n32(&buf, &as) == -1)
|
||||
return (-1);
|
||||
|
||||
do {
|
||||
total_size++;
|
||||
} while ((as = as / 10) != 0);
|
||||
|
||||
if (i + 1 < seg_len)
|
||||
total_size += 1;
|
||||
}
|
||||
total_size += seg_len - 1;
|
||||
|
||||
if (seg_type == AS_SET)
|
||||
total_size += 2;
|
||||
total_size += strlen(aspath_delim(seg_type, 1));
|
||||
}
|
||||
return (total_size);
|
||||
return (total_size + 1);
|
||||
}
|
||||
|
||||
int
|
||||
aspath_asprint(char **ret, struct ibuf *data)
|
||||
{
|
||||
ssize_t slen;
|
||||
|
||||
if ((slen = aspath_strsize(data)) == -1) {
|
||||
*ret = NULL;
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
*ret = malloc(slen);
|
||||
if (*ret == NULL)
|
||||
return (-1);
|
||||
|
||||
if (aspath_snprint(*ret, slen, data) == -1) {
|
||||
free(*ret);
|
||||
*ret = NULL;
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -456,32 +465,31 @@ aspath_extract(const void *seg, int pos)
|
|||
* Verify that the aspath is correctly encoded.
|
||||
*/
|
||||
int
|
||||
aspath_verify(void *data, uint16_t len, int as4byte, int noset)
|
||||
aspath_verify(struct ibuf *in, int as4byte, int noset)
|
||||
{
|
||||
uint8_t *seg = data;
|
||||
uint16_t seg_size, as_size = 2;
|
||||
struct ibuf buf;
|
||||
int pos, error = 0;
|
||||
uint8_t seg_len, seg_type;
|
||||
int error = 0;
|
||||
|
||||
if (len & 1)
|
||||
ibuf_from_ibuf(&buf, in);
|
||||
if (ibuf_size(&buf) & 1) {
|
||||
/* odd length aspath are invalid */
|
||||
return (AS_ERR_BAD);
|
||||
error = AS_ERR_BAD;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (as4byte)
|
||||
as_size = 4;
|
||||
while (ibuf_size(&buf) > 0) {
|
||||
if (ibuf_get_n8(&buf, &seg_type) == -1 ||
|
||||
ibuf_get_n8(&buf, &seg_len) == -1) {
|
||||
error = AS_ERR_LEN;
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (; len > 0; len -= seg_size, seg += seg_size) {
|
||||
const uint8_t *ptr;
|
||||
int pos;
|
||||
|
||||
if (len < 2) /* header length check */
|
||||
return (AS_ERR_BAD);
|
||||
seg_type = seg[0];
|
||||
seg_len = seg[1];
|
||||
|
||||
if (seg_len == 0)
|
||||
if (seg_len == 0) {
|
||||
/* empty aspath segments are not allowed */
|
||||
return (AS_ERR_BAD);
|
||||
error = AS_ERR_BAD;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/*
|
||||
* BGP confederations should not show up but consider them
|
||||
|
@ -497,70 +505,75 @@ aspath_verify(void *data, uint16_t len, int as4byte, int noset)
|
|||
if (noset && seg_type == AS_SET)
|
||||
error = AS_ERR_SOFT;
|
||||
if (seg_type != AS_SET && seg_type != AS_SEQUENCE &&
|
||||
seg_type != AS_CONFED_SEQUENCE && seg_type != AS_CONFED_SET)
|
||||
return (AS_ERR_TYPE);
|
||||
|
||||
seg_size = 2 + as_size * seg_len;
|
||||
|
||||
if (seg_size > len)
|
||||
return (AS_ERR_LEN);
|
||||
seg_type != AS_CONFED_SEQUENCE &&
|
||||
seg_type != AS_CONFED_SET) {
|
||||
error = AS_ERR_TYPE;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* RFC 7607 - AS 0 is considered malformed */
|
||||
ptr = seg + 2;
|
||||
for (pos = 0; pos < seg_len; pos++) {
|
||||
uint32_t as;
|
||||
|
||||
memcpy(&as, ptr, as_size);
|
||||
if (as4byte) {
|
||||
if (ibuf_get_n32(&buf, &as) == -1) {
|
||||
error = AS_ERR_LEN;
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
uint16_t tmp;
|
||||
if (ibuf_get_n16(&buf, &tmp) == -1) {
|
||||
error = AS_ERR_LEN;
|
||||
goto done;
|
||||
}
|
||||
as = tmp;
|
||||
}
|
||||
if (as == 0)
|
||||
error = AS_ERR_SOFT;
|
||||
ptr += as_size;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
return (error); /* aspath is valid but probably not loop free */
|
||||
}
|
||||
|
||||
/*
|
||||
* convert a 2 byte aspath to a 4 byte one.
|
||||
*/
|
||||
u_char *
|
||||
aspath_inflate(void *data, uint16_t len, uint16_t *newlen)
|
||||
struct ibuf *
|
||||
aspath_inflate(struct ibuf *in)
|
||||
{
|
||||
uint8_t *seg, *nseg, *ndata;
|
||||
uint16_t seg_size, olen, nlen;
|
||||
uint8_t seg_len;
|
||||
struct ibuf *out;
|
||||
uint16_t short_as;
|
||||
uint8_t seg_type, seg_len;
|
||||
|
||||
/* first calculate the length of the aspath */
|
||||
seg = data;
|
||||
nlen = 0;
|
||||
for (olen = len; olen > 0; olen -= seg_size, seg += seg_size) {
|
||||
seg_len = seg[1];
|
||||
seg_size = 2 + sizeof(uint16_t) * seg_len;
|
||||
nlen += 2 + sizeof(uint32_t) * seg_len;
|
||||
|
||||
if (seg_size > olen) {
|
||||
errno = ERANGE;
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
*newlen = nlen;
|
||||
if ((ndata = malloc(nlen)) == NULL)
|
||||
/* allocate enough space for the worst case */
|
||||
if ((out = ibuf_open(ibuf_size(in) * 2)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
/* then copy the aspath */
|
||||
seg = data;
|
||||
for (nseg = ndata; nseg < ndata + nlen; ) {
|
||||
*nseg++ = *seg++;
|
||||
*nseg++ = seg_len = *seg++;
|
||||
while (ibuf_size(in) > 0) {
|
||||
if (ibuf_get_n8(in, &seg_type) == -1 ||
|
||||
ibuf_get_n8(in, &seg_len) == -1 ||
|
||||
seg_len == 0)
|
||||
goto fail;
|
||||
if (ibuf_add_n8(out, seg_type) == -1 ||
|
||||
ibuf_add_n8(out, seg_len) == -1)
|
||||
goto fail;
|
||||
|
||||
for (; seg_len > 0; seg_len--) {
|
||||
*nseg++ = 0;
|
||||
*nseg++ = 0;
|
||||
*nseg++ = *seg++;
|
||||
*nseg++ = *seg++;
|
||||
if (ibuf_get_n16(in, &short_as) == -1)
|
||||
goto fail;
|
||||
if (ibuf_add_n32(out, short_as) == -1)
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
return (ndata);
|
||||
return (out);
|
||||
|
||||
fail:
|
||||
ibuf_free(out);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static const u_char addrmask[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue