Net-MRT
view release on metacpan or search on metacpan
if (iPrefixBits > 0) {
mrt_copy_next(&pBgpAttributes, &sa6, (int)ceil((double)iBits/8), &iBgpAttributesRemainLen);
iAttributeRemainLen -= (int)ceil((double)iBits/8);
}
inet_ntop((AFI == 1 ? AF_INET : AF_INET6), &sa6, cIpAddress, INET6_ADDRSTRLEN);
snprintf(sbuff, SBUFF, "%s/%d", cIpAddress, iBits);
av_push(avTmpAv, newSVpv(sbuff, 0));
} // end while (iAttributeRemainLen > 0)
}
pBgpAttributes += iAttributeRemainLen;
iBgpAttributesRemainLen -= iAttributeRemainLen;
} else if (SvOK(USE_RFC4760) && SvIV(USE_RFC4760) == -1) {
pBgpAttributes += iAttributeLen;
iBgpAttributesRemainLen -= iAttributeLen;
} else {
// Use RFC 6396
iTmpU8 = (AF == AF_INET ? 4 : 16); // Store size of IP address for AF
// Read size of MRT MP_REACH_NLRI
mrt_copy_next(&pBgpAttributes, &iAttributeRemainLen, 1, &iBgpAttributesRemainLen);
# ifdef _DEBUG_
printf("mrt_decode_single(): Attribute 14 have %u bytes for AF. Remain %d bytes\n", iTmpU8, iAttributeRemainLen);
# endif
while (iAttributeRemainLen > 0)
{
iAttributeRemainLen -= iTmpU8;
memset(&sa6, 0, sizeof(sa6));
mrt_copy_next(&pBgpAttributes, &sa6, iTmpU8, &iBgpAttributesRemainLen);
inet_ntop(AF, &sa6, cIpAddress, INET6_ADDRSTRLEN);
av_push(avNextHop, newSVpv(cIpAddress, 0));
}
} // end else if RFC4760
break;// 14 MP_REACH_NLRI [RFC4760]
default:
hv_store(hvEntry, sbuff, strlen(sbuff), &PL_sv_undef, 0);
pBgpAttributes += iAttributeLen;
iBgpAttributesRemainLen -= iAttributeLen;
} // switch (attribute_code)
} // iBgpAttributesRemainLen > 0
} // while (iEntries > 0)
break; // subtype = IPv4/6 UNICAST/MULTICAST
default:
snprintf(sbuff, SBUFF, "Unsupported MRT type %d subtype %d in message at %lli", mh->type, mh->subtype, (intmax_t)msgpos);
hv_stores(rt, "error", newSVpv(sbuff, 0));
} // switch subtype
break; // MT_TABLE_DUMP_V2
default:
snprintf(sbuff, SBUFF, "Unsupported MRT type %d in message at %lli", mh->type, (intmax_t)msgpos);
hv_stores(rt, "error", newSVpv(sbuff, 0));
} // switch message type
return;
}
MODULE = Net::MRT PACKAGE = Net::MRT
void
mrt_read_next(f)
PerlIO * f;
PROTOTYPE: *
PPCODE:
# Definitions
Off_t msgpos = PerlIO_tell(f); // Store message position & check for proper handle
int sz;
MRT_MESSAGE mh;
char sbuff[SBUFF] = {};
HV* rt;
if (msgpos == -1)
croak("Invalid filehandle passed to mrt_read_next");
sz = PerlIO_read(f, &mh, 12);
if (sz == 0)
{
# No data to read
ST(0) = &PL_sv_undef;
XSRETURN(1);
} else {
# Network to host for MH
mh.timestamp = ntohl(mh.timestamp);
mh.type = ntohs(mh.type);
mh.subtype = ntohs(mh.subtype);
mh.length = ntohl(mh.length);
# Create resulting HASHREF
rt = newHV();
hv_stores(rt, "timestamp", newSVuv(mh.timestamp));
hv_stores(rt, "type", newSVuv(mh.type));
hv_stores(rt, "subtype", newSVuv(mh.subtype));
# Decode header
# Check for length to be less than buffer
if (mh.length > BUFFER_SIZE)
{
snprintf(sbuff, SBUFF, "Message length too big at %lli", (intmax_t)msgpos);
hv_stores(rt, "error", newSVpv(sbuff, 0));
while (mh.length > 0) {
auto remainder = (BUFFER_SIZE < mh.length ? BUFFER_SIZE : mh.length);
printf("remaining: %d to do: %d %d\n", mh.length, remainder, BUFFER_SIZE); fflush(stdout);
sz = PerlIO_read(f, &mh.message, remainder);
mh.length -= remainder;
}
} else {
# Try to read message
if (mh.length > 0)
sz = PerlIO_read(f, &mh.message, mh.length);
if ((mh.length > 0) && (sz != mh.length))
croak("Unable to read %d bytes in message at pos %lli", mh.length, (intmax_t)msgpos);
# Try to decode
mrt_decode(rt, msgpos, &mh);
}
ST(0) = sv_2mortal((SV*)newRV_noinc((SV*)rt));
XSRETURN(1);
}
void
mrt_get_next(f)
PerlIO * f;
PROTOTYPE: *
PPCODE:
# Definitions
Off_t msgpos = PerlIO_tell(f); // Store message position & check for proper handle
int sz;
MRT_MESSAGE mh;
char sbuff[SBUFF] = {};
HV* rt;
if (msgpos == -1)
croak("Invalid filehandle passed to mrt_read_next");
sz = PerlIO_read(f, &mh, 12);
if (sz == 0)
{
# No data to read
ST(0) = &PL_sv_undef;
XSRETURN(1);
} else {
# Network to host for MH
mh.timestamp = ntohl(mh.timestamp);
mh.type = ntohs(mh.type);
mh.subtype = ntohs(mh.subtype);
mh.length = ntohl(mh.length);
# Decode header
# Check for length to be less than buffer
ST(0) = newSVuv(mh.type);
ST(1) = newSVuv(mh.subtype);
if (mh.length > BUFFER_SIZE)
{
snprintf(sbuff, SBUFF, "Message length too big at %lli", (intmax_t)msgpos);
while (mh.length > 0) {
auto remainder = (BUFFER_SIZE < mh.length ? BUFFER_SIZE : mh.length);
printf("remaining: %d to do: %d %d\n", mh.length, remainder, BUFFER_SIZE); fflush(stdout);
sz = PerlIO_read(f, &mh.message, remainder);
mh.length -= remainder;
}
ST(2) = newSVuv(-1);
ST(3) = newSVpv(sbuff, strlen(sbuff));
} else {
# Try to read message
if (mh.length > 0)
sz = PerlIO_read(f, &mh.message, mh.length);
if ((mh.length > 0) && (sz != mh.length))
croak("Unable to read %d bytes in message at pos %lli", mh.length, (intmax_t)msgpos);
ST(2) = newSVuv(mh.length);
ST(3) = newSVpv(mh.message, mh.length);
}
XSRETURN(4);
}
HV*
mrt_decode_single(type, subtype, message)
uint16_t type;
uint16_t subtype;
SV* message;
CODE:
MRT_MESSAGE mh;
char* msg;
// Prepare returning variable(s)
( run in 1.930 second using v1.01-cache-2.11-cpan-71847e10f99 )