[lonetix/*,tools/bgpgrep/*] Correct handling of extended timestamps during filtering, decode and dump
This commit is contained in:
parent
39dac63d82
commit
db129a0d39
|
@ -153,6 +153,12 @@ static const char *Bgp_KnownCommunityToString(BgpCommCode code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void NormalizeExtendedTimestamp(Dumpfmtctx *ctx)
|
||||||
|
{
|
||||||
|
ctx->timestamp += ctx->microsecs / 1000000;
|
||||||
|
ctx->microsecs %= 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
static void DumpUnknown(Stmbuf *sb, BgpType type)
|
static void DumpUnknown(Stmbuf *sb, BgpType type)
|
||||||
{
|
{
|
||||||
Bufio_Putc(sb, UNKNOWN_MARKER);
|
Bufio_Putc(sb, UNKNOWN_MARKER);
|
||||||
|
@ -420,7 +426,7 @@ static void DumpMrtInfoTrailer(Stmbuf *sb, const Dumpfmtctx *ctx)
|
||||||
Bufio_Putu(sb, ctx->timestamp);
|
Bufio_Putu(sb, ctx->timestamp);
|
||||||
if (ctx->microsecs > 0) {
|
if (ctx->microsecs > 0) {
|
||||||
Utoa(ctx->microsecs, buf);
|
Utoa(ctx->microsecs, buf);
|
||||||
Df_strpadl(buf, '0', 9);
|
Df_strpadl(buf, '0', 6);
|
||||||
|
|
||||||
Bufio_Putc(sb, '.');
|
Bufio_Putc(sb, '.');
|
||||||
Bufio_Puts(sb, buf);
|
Bufio_Puts(sb, buf);
|
||||||
|
@ -941,14 +947,25 @@ static Sint64 Isolario_DumpBgp4mp(const Mrthdr *hdr,
|
||||||
ctx.isAsn32bit = BGP4MP_ISASN32BIT(hdr->subtype);
|
ctx.isAsn32bit = BGP4MP_ISASN32BIT(hdr->subtype);
|
||||||
ctx.isAddPath = BGP4MP_ISADDPATH(hdr->subtype);
|
ctx.isAddPath = BGP4MP_ISADDPATH(hdr->subtype);
|
||||||
ctx.timestamp = beswap32(hdr->timestamp);
|
ctx.timestamp = beswap32(hdr->timestamp);
|
||||||
if (hdr->type == MRT_BGP4MP_ET)
|
if (hdr->type == MRT_BGP4MP_ET) {
|
||||||
|
// Length must account for extended timestamp
|
||||||
|
if (len < 4) goto corrupt;
|
||||||
|
|
||||||
ctx.microsecs = beswap32(((const Mrthdrex *) hdr)->microsecs);
|
ctx.microsecs = beswap32(((const Mrthdrex *) hdr)->microsecs);
|
||||||
|
len -= 4;
|
||||||
|
|
||||||
|
NormalizeExtendedTimestamp(&ctx);
|
||||||
|
}
|
||||||
|
|
||||||
ctx.hdr = hdr;
|
ctx.hdr = hdr;
|
||||||
|
|
||||||
if (ctx.isAsn32bit) {
|
if (ctx.isAsn32bit) {
|
||||||
|
if (len < sizeof(bgp4mp->a32)) goto corrupt;
|
||||||
|
|
||||||
ctx.peerAs = beswap32(bgp4mp->a32.peerAs);
|
ctx.peerAs = beswap32(bgp4mp->a32.peerAs);
|
||||||
if (bgp4mp->a32.afi == AFI_IP) {
|
if (bgp4mp->a32.afi == AFI_IP) {
|
||||||
|
if (len < sizeof(bgp4mp->a32v4)) goto corrupt;
|
||||||
|
|
||||||
ctx.peerAddr.family = IP4;
|
ctx.peerAddr.family = IP4;
|
||||||
ctx.peerAddr.v4 = bgp4mp->a32v4.peerAddr;
|
ctx.peerAddr.v4 = bgp4mp->a32v4.peerAddr;
|
||||||
|
|
||||||
|
@ -956,14 +973,20 @@ static Sint64 Isolario_DumpBgp4mp(const Mrthdr *hdr,
|
||||||
} else {
|
} else {
|
||||||
assert(bgp4mp->a32.afi == AFI_IP6);
|
assert(bgp4mp->a32.afi == AFI_IP6);
|
||||||
|
|
||||||
|
if (len < sizeof(bgp4mp->a32v6)) goto corrupt;
|
||||||
|
|
||||||
ctx.peerAddr.family = IP6;
|
ctx.peerAddr.family = IP6;
|
||||||
ctx.peerAddr.v6 = bgp4mp->a32v6.peerAddr;
|
ctx.peerAddr.v6 = bgp4mp->a32v6.peerAddr;
|
||||||
|
|
||||||
offset = sizeof(bgp4mp->a32v6);
|
offset = sizeof(bgp4mp->a32v6);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
if (len < sizeof(bgp4mp->a16)) goto corrupt;
|
||||||
|
|
||||||
ctx.peerAs = beswap16(bgp4mp->a16.peerAs);
|
ctx.peerAs = beswap16(bgp4mp->a16.peerAs);
|
||||||
if (bgp4mp->a16.afi == AFI_IP) {
|
if (bgp4mp->a16.afi == AFI_IP) {
|
||||||
|
if (len < sizeof(bgp4mp->a16v4)) goto corrupt;
|
||||||
|
|
||||||
ctx.peerAddr.family = IP4;
|
ctx.peerAddr.family = IP4;
|
||||||
ctx.peerAddr.v4 = bgp4mp->a16v4.peerAddr;
|
ctx.peerAddr.v4 = bgp4mp->a16v4.peerAddr;
|
||||||
|
|
||||||
|
@ -971,6 +994,8 @@ static Sint64 Isolario_DumpBgp4mp(const Mrthdr *hdr,
|
||||||
} else {
|
} else {
|
||||||
assert(bgp4mp->a16.afi == AFI_IP6);
|
assert(bgp4mp->a16.afi == AFI_IP6);
|
||||||
|
|
||||||
|
if (len < sizeof(bgp4mp->a16v6)) goto corrupt;
|
||||||
|
|
||||||
ctx.peerAddr.family = IP6;
|
ctx.peerAddr.family = IP6;
|
||||||
ctx.peerAddr.v6 = bgp4mp->a16v6.peerAddr;
|
ctx.peerAddr.v6 = bgp4mp->a16v6.peerAddr;
|
||||||
|
|
||||||
|
@ -984,10 +1009,13 @@ static Sint64 Isolario_DumpBgp4mp(const Mrthdr *hdr,
|
||||||
if (BGP4MP_ISSTATECHANGE(hdr->subtype)) {
|
if (BGP4MP_ISSTATECHANGE(hdr->subtype)) {
|
||||||
// Dump state change
|
// Dump state change
|
||||||
BgpFsmState chng[2];
|
BgpFsmState chng[2];
|
||||||
memcpy(chng, (Uint8 *) bgp4mp + offset, sizeof(chng));
|
|
||||||
|
|
||||||
Bufio_Putc(&sb, STATE_CHANGE_MARKER);
|
Bufio_Putc(&sb, STATE_CHANGE_MARKER);
|
||||||
Bufio_Putc(&sb, SEP_CHAR);
|
Bufio_Putc(&sb, SEP_CHAR);
|
||||||
|
if (len < offset + sizeof(chng)) goto corrupt;
|
||||||
|
|
||||||
|
memcpy(chng, (Uint8 *) bgp4mp + offset, sizeof(chng));
|
||||||
|
|
||||||
Bufio_Putu(&sb, beswap16(chng[0]));
|
Bufio_Putu(&sb, beswap16(chng[0]));
|
||||||
Bufio_Putc(&sb, '-');
|
Bufio_Putc(&sb, '-');
|
||||||
Bufio_Putu(&sb, beswap16(chng[1]));
|
Bufio_Putu(&sb, beswap16(chng[1]));
|
||||||
|
@ -1000,17 +1028,14 @@ static Sint64 Isolario_DumpBgp4mp(const Mrthdr *hdr,
|
||||||
size_t nbytes = len - offset;
|
size_t nbytes = len - offset;
|
||||||
|
|
||||||
nbytes = Bgp_CheckMsgHdr(msg, nbytes, /*allowExtendedSize=*/TRUE);
|
nbytes = Bgp_CheckMsgHdr(msg, nbytes, /*allowExtendedSize=*/TRUE);
|
||||||
if (nbytes != 0) {
|
if (nbytes == 0) {
|
||||||
// Header is OK
|
|
||||||
nbytes -= BGP_HDRSIZ;
|
|
||||||
DumpBgp(&sb, msg->type, msg + 1, nbytes, table, &ctx);
|
|
||||||
} else {
|
|
||||||
// Corrupted BGP4MP with invalid BGP data
|
// Corrupted BGP4MP with invalid BGP data
|
||||||
Bufio_Putc(&sb, UNKNOWN_MARKER);
|
Bufio_Putc(&sb, UNKNOWN_MARKER);
|
||||||
Bufio_Putc(&sb, SEP_CHAR);
|
Bufio_Putc(&sb, SEP_CHAR);
|
||||||
WarnCorrupted(&sb, &ctx);
|
goto corrupt;
|
||||||
DumpMrtInfoTrailer(&sb, &ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DumpBgp(&sb, msg->type, msg + 1, nbytes - BGP_HDRSIZ, table, &ctx);
|
||||||
} else {
|
} else {
|
||||||
// Deprecated/Unknown type
|
// Deprecated/Unknown type
|
||||||
Bufio_Putc(&sb, UNKNOWN_MARKER);
|
Bufio_Putc(&sb, UNKNOWN_MARKER);
|
||||||
|
@ -1019,6 +1044,11 @@ static Sint64 Isolario_DumpBgp4mp(const Mrthdr *hdr,
|
||||||
}
|
}
|
||||||
|
|
||||||
return Bufio_Flush(&sb);
|
return Bufio_Flush(&sb);
|
||||||
|
|
||||||
|
corrupt:
|
||||||
|
WarnCorrupted(&sb, &ctx);
|
||||||
|
DumpMrtInfoTrailer(&sb, &ctx);
|
||||||
|
return Bufio_Flush(&sb);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Sint64 Isolario_DumpZebra(const Mrthdr *hdr,
|
static Sint64 Isolario_DumpZebra(const Mrthdr *hdr,
|
||||||
|
|
|
@ -16,9 +16,13 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
static void *MRT_DATAPTR(const Mrtrecord *rec)
|
static void *MRT_DATAPTR(const Mrtrecord *rec, size_t *len)
|
||||||
{
|
{
|
||||||
return rec->buf + MRT_HDRSIZ + (MRT_ISEXHDRTYPE(MRT_HDR(rec)->type) << 2);
|
const Mrthdr *hdr = MRT_HDR(rec);
|
||||||
|
Uint32 off = MRT_ISEXHDRTYPE(hdr->type) << 2;
|
||||||
|
|
||||||
|
*len = beswap32(hdr->len) - off;
|
||||||
|
return rec->buf + MRT_HDRSIZ + off;
|
||||||
}
|
}
|
||||||
|
|
||||||
Judgement Bgp_MrtFromBuf(Mrtrecord *rec, const void *buf, size_t nbytes)
|
Judgement Bgp_MrtFromBuf(Mrtrecord *rec, const void *buf, size_t nbytes)
|
||||||
|
@ -28,9 +32,9 @@ Judgement Bgp_MrtFromBuf(Mrtrecord *rec, const void *buf, size_t nbytes)
|
||||||
|
|
||||||
const Mrthdr *hdr = (const Mrthdr *) buf;
|
const Mrthdr *hdr = (const Mrthdr *) buf;
|
||||||
|
|
||||||
size_t left = beswap32(hdr->len);
|
size_t left = beswap32(hdr->len); // NOTE: Includes extended timestamp size, if any!
|
||||||
if (MRT_ISEXHDRTYPE(hdr->type))
|
if (left < 4 && MRT_ISEXHDRTYPE(hdr->type)) // ...so check it
|
||||||
left += 4; // account for extended timestamp
|
return Bgp_SetErrStat(BGPETRUNCMRT);
|
||||||
|
|
||||||
size_t siz = sizeof(*hdr) + left;
|
size_t siz = sizeof(*hdr) + left;
|
||||||
if (siz > nbytes)
|
if (siz > nbytes)
|
||||||
|
@ -63,12 +67,12 @@ Judgement Bgp_ReadMrt(Mrtrecord *rec, void *streamp, const StmOps *ops)
|
||||||
if ((size_t) n != sizeof(hdr))
|
if ((size_t) n != sizeof(hdr))
|
||||||
return Bgp_SetErrStat(BGPEIO);
|
return Bgp_SetErrStat(BGPEIO);
|
||||||
|
|
||||||
size_t left = beswap32(hdr.len);
|
size_t left = beswap32(hdr.len); // NOTE: Includes extended timestamp size, if any!
|
||||||
if (MRT_ISEXHDRTYPE(hdr.type))
|
if (left < 4 && MRT_ISEXHDRTYPE(hdr.type)) // ...so check it
|
||||||
left += 4; // account for extended timestamp
|
return Bgp_SetErrStat(BGPETRUNCMRT);
|
||||||
|
|
||||||
// Allocate buffer
|
// Allocate buffer
|
||||||
// NOTE: MRT header length doesn't account for header size itself
|
// NOTE: ...but MRT header length doesn't account for header size itself
|
||||||
size_t siz = sizeof(hdr) + left;
|
size_t siz = sizeof(hdr) + left;
|
||||||
const MemOps *memOps = MRT_MEMOPS(rec);
|
const MemOps *memOps = MRT_MEMOPS(rec);
|
||||||
|
|
||||||
|
@ -517,11 +521,12 @@ Bgp4mphdr *Bgp_GetBgp4mpHdr(Mrtrecord *rec, size_t *nbytes)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t len = beswap32(hdr->len);
|
size_t len;
|
||||||
size_t offset = 0;
|
|
||||||
Afi afi;
|
Afi afi;
|
||||||
|
|
||||||
Bgp4mphdr *bgp4mp = (Bgp4mphdr *) MRT_DATAPTR(rec);
|
size_t offset = 0;
|
||||||
|
|
||||||
|
Bgp4mphdr *bgp4mp = (Bgp4mphdr *) MRT_DATAPTR(rec, &len);
|
||||||
if (BGP4MP_ISASN32BIT(hdr->subtype)) {
|
if (BGP4MP_ISASN32BIT(hdr->subtype)) {
|
||||||
offset += 2 * 4;
|
offset += 2 * 4;
|
||||||
offset += 2 + 2;
|
offset += 2 + 2;
|
||||||
|
@ -572,8 +577,8 @@ Judgement Bgp_UnwrapBgp4mp(Mrtrecord *rec, Bgpmsg *dest, unsigned flags)
|
||||||
if (!BGP4MP_ISMESSAGE(hdr->subtype))
|
if (!BGP4MP_ISMESSAGE(hdr->subtype))
|
||||||
return Bgp_SetErrStat(BGPEBADMRTTYPE);
|
return Bgp_SetErrStat(BGPEBADMRTTYPE);
|
||||||
|
|
||||||
Uint32 len = beswap32(hdr->len);
|
size_t len;
|
||||||
Uint8 *base = (Uint8 *) MRT_DATAPTR(rec);
|
Uint8 *base = (Uint8 *) MRT_DATAPTR(rec, &len);
|
||||||
|
|
||||||
// Skip header
|
// Skip header
|
||||||
size_t siz = BGP4MP_ISASN32BIT(hdr->subtype) ? 2*4 : 2*2; // skip ASN
|
size_t siz = BGP4MP_ISASN32BIT(hdr->subtype) ? 2*4 : 2*2; // skip ASN
|
||||||
|
|
|
@ -678,7 +678,7 @@ typedef ALIGNED(1, union) {
|
||||||
|
|
||||||
FORCE_INLINE Bgp4mphdr *BGP4MP_HDR(const Mrthdr *hdr)
|
FORCE_INLINE Bgp4mphdr *BGP4MP_HDR(const Mrthdr *hdr)
|
||||||
{
|
{
|
||||||
return (hdr->subtype == MRT_BGP4MP_ET) ?
|
return (hdr->type == MRT_BGP4MP_ET) ?
|
||||||
(Bgp4mphdr *) ((const Mrthdrex *) hdr + 1) :
|
(Bgp4mphdr *) ((const Mrthdrex *) hdr + 1) :
|
||||||
(Bgp4mphdr *) (hdr + 1);
|
(Bgp4mphdr *) (hdr + 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,6 +65,12 @@ static void FixBgpAttributeTableForRib(Bgpattrtab tab, Boolean isRibv2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void NormalizeExtendedTimestamp(void)
|
||||||
|
{
|
||||||
|
S.timestampSecs += S.timestampMicrosecs / 1000000;
|
||||||
|
S.timestampMicrosecs %= 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
static void OutputBgp4mp(const Mrthdr *hdr, Bgpattrtab tab)
|
static void OutputBgp4mp(const Mrthdr *hdr, Bgpattrtab tab)
|
||||||
{
|
{
|
||||||
S.lenientBgpErrors = TRUE;
|
S.lenientBgpErrors = TRUE;
|
||||||
|
@ -90,8 +96,10 @@ void BgpgrepD_Bgp4mp(void)
|
||||||
S.peerAs = BGP4MP_GETPEERADDR(hdr->subtype, &S.peerAddr, bgp4mp);
|
S.peerAs = BGP4MP_GETPEERADDR(hdr->subtype, &S.peerAddr, bgp4mp);
|
||||||
S.timestampSecs = beswap32(hdr->timestamp);
|
S.timestampSecs = beswap32(hdr->timestamp);
|
||||||
S.timestampMicrosecs = 0;
|
S.timestampMicrosecs = 0;
|
||||||
if (hdr->subtype == MRT_BGP4MP_ET)
|
if (hdr->type == MRT_BGP4MP_ET) {
|
||||||
S.timestampMicrosecs = beswap32(((const Mrthdrex *) hdr)->microsecs);
|
S.timestampMicrosecs = beswap32(((const Mrthdrex *) hdr)->microsecs);
|
||||||
|
NormalizeExtendedTimestamp();
|
||||||
|
}
|
||||||
|
|
||||||
// Dump MRT data
|
// Dump MRT data
|
||||||
Bgp_UnwrapBgp4mp(&S.rec, &S.msg, /*flags=*/BGPF_UNOWNED);
|
Bgp_UnwrapBgp4mp(&S.rec, &S.msg, /*flags=*/BGPF_UNOWNED);
|
||||||
|
|
|
@ -43,13 +43,13 @@ static Uint32 ParseFrac(const char *s, const char *p, char **ep)
|
||||||
if (res != NCVENOERR)
|
if (res != NCVENOERR)
|
||||||
FATALF("%s: Expecting fractional portion of a second after '.'", s);
|
FATALF("%s: Expecting fractional portion of a second after '.'", s);
|
||||||
|
|
||||||
int ndigs = endp - p;
|
int ndigs = endp - p;
|
||||||
double frac = pow(10, ndigs);
|
long double frac = pow(10, ndigs);
|
||||||
|
|
||||||
if (ep)
|
if (ep)
|
||||||
*ep = endp;
|
*ep = endp;
|
||||||
|
|
||||||
return (Uint32) trunc((n / frac) * 100000.0);
|
return (Uint32) truncl(n / frac * 1000000.0L);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Boolean ParseRfc3339(const char *s, Timestampop *dest)
|
static Boolean ParseRfc3339(const char *s, Timestampop *dest)
|
||||||
|
|
Loading…
Reference in New Issue