Net-MRT

 view release on metacpan or  search on metacpan

MRT.xs  view on Meta::CPAN

                                                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 )