Exemplo n.º 1
0
// produces a full FRAG packet. It does not write, just read the fields in *fr
struct ccnl_buf_s*
ccnl_ccntlv_mkFrag(struct ccnl_frag_s *fr, unsigned int *consumed)
{
    size_t datalen;
    struct ccnl_buf_s *buf;
    struct ccnx_tlvhdr_ccnx2015_s *fp;
    uint16_t tmp;

    DEBUGMSG_PCNX(TRACE, "ccnl_ccntlv_mkFrag seqno=%u\n", fr->sendseq);

    datalen = fr->mtu - sizeof(*fp) - 4;
    if (datalen > (fr->bigpkt->datalen - fr->sendoffs)) {
        datalen = fr->bigpkt->datalen - fr->sendoffs;
    }
    if (datalen > UINT16_MAX) {
        return NULL;
    }

    buf = ccnl_buf_new(NULL, sizeof(*fp) + 4 + datalen);
    if (!buf) {
        return NULL;
    }
    fp = (struct ccnx_tlvhdr_ccnx2015_s*) buf->data;
    memset(fp, 0, sizeof(*fp));
    fp->version = CCNX_TLV_V1;
    fp->pkttype = CCNX_PT_Fragment;
    fp->hdrlen = sizeof(*fp);
    fp->pktlen = htons(sizeof(*fp) + 4 + datalen);

    tmp = htons(CCNX_TLV_TL_Fragment);
    memcpy(fp+1, &tmp, 2);
    tmp = htons((uint16_t) datalen);
    memcpy((char*)(fp+1) + 2, &tmp, 2);
    memcpy((char*)(fp+1) + 4, fr->bigpkt->data + fr->sendoffs, datalen);

    tmp = fr->sendseq & 0x03fff;
    if (datalen >= fr->bigpkt->datalen) {   // single
        tmp |= CCNL_BEFRAG_FLAG_SINGLE << 14;
    } else if (fr->sendoffs == 0) {          // start
        tmp |= CCNL_BEFRAG_FLAG_FIRST  << 14;
    } else if(datalen >= (fr->bigpkt->datalen - fr->sendoffs)) { // end
        tmp |= CCNL_BEFRAG_FLAG_LAST   << 14;
    } else {                                  // middle
        tmp |= CCNL_BEFRAG_FLAG_MID    << 14;
    }
    tmp = htons(tmp);
    memcpy(fp->fill, &tmp, 2);

    *consumed = datalen;
    return buf;
}
Exemplo n.º 2
0
// We use one extraction procedure for both interest and data pkts.
// This proc assumes that the packet header was already processed and consumed
struct ccnl_pkt_s*
ccnl_ccntlv_bytes2pkt(unsigned char *start, unsigned char **data, int *datalen)
{
    struct ccnl_pkt_s *pkt;
    int i, len;
    unsigned int typ, oldpos;
    struct ccnl_prefix_s *p;
#ifdef USE_HMAC256
    int validAlgoIsHmac256 = 0;
#endif

    DEBUGMSG_PCNX(TRACE, "ccnl_ccntlv_bytes2pkt len=%d\n", *datalen);

    pkt = (struct ccnl_pkt_s*) ccnl_calloc(1, sizeof(*pkt));
    if (!pkt)
        return NULL;

    pkt->pfx = p = ccnl_prefix_new(CCNL_SUITE_CCNTLV, CCNL_MAX_NAME_COMP);
    if (!p) {
        ccnl_free(pkt);
        return NULL;
    }
    p->compcnt = 0;

#ifdef USE_HMAC256
    pkt->hmacStart = *data;
#endif
    // We ignore the TL types of the message for now:
    // content and interests are filled in both cases (and only one exists).
    // Validation info is now collected
    if (ccnl_ccntlv_dehead(data, datalen, &typ, (unsigned int*) &len) || (int) len > *datalen)
        goto Bail;

    pkt->type = typ;
    pkt->suite = CCNL_SUITE_CCNTLV;
    pkt->val.final_block_id = -1;

    // XXX this parsing is not safe for all input data - needs more bound
    // checks, as some packets with wrong L values can bring this to crash
    oldpos = *data - start;
    while (ccnl_ccntlv_dehead(data, datalen, &typ, (unsigned int*) &len) == 0) {
        unsigned char *cp = *data, *cp2;
        int len2 = len;
        int len3;

        if ( (int)len > *datalen)
            goto Bail;
        switch (typ) {
        case CCNX_TLV_M_Name:
            p->nameptr = start + oldpos;
            while (len2 > 0) {
                cp2 = cp;
                if (ccnl_ccntlv_dehead(&cp, &len2, &typ, (unsigned int*) &len3) || (int)len>*datalen)
                    goto Bail;

                switch (typ) {
                case CCNX_TLV_N_Chunk:
                    // We extract the chunknum to the prefix but keep it
                    // in the name component for now. In the future we
                    // possibly want to remove the chunk segment from the
                    // name components and rely on the chunknum field in
                    // the prefix.
                  p->chunknum = (int*) ccnl_malloc(sizeof(int));

                    if (ccnl_ccnltv_extractNetworkVarInt(cp, len3,
                                                         (unsigned int*) p->chunknum) < 0) {
                        DEBUGMSG_PCNX(WARNING, "Error in NetworkVarInt for chunk\n");
                        goto Bail;
                    }
                    if (p->compcnt < CCNL_MAX_NAME_COMP) {
                        p->comp[p->compcnt] = cp2;
                        p->complen[p->compcnt] = cp - cp2 + len3;
                        p->compcnt++;
                    } // else out of name component memory: skip
                    break;
                case CCNX_TLV_N_NameSegment:
                    if (p->compcnt < CCNL_MAX_NAME_COMP) {
                        p->comp[p->compcnt] = cp2;
                        p->complen[p->compcnt] = cp - cp2 + len3;
                        p->compcnt++;
                    } // else out of name component memory: skip
                    break;
                case CCNX_TLV_N_Meta:
                    if (ccnl_ccntlv_dehead(&cp, &len2, &typ, (unsigned int*) &len3) ||
                        (int)len > *datalen) {
                        DEBUGMSG_PCNX(WARNING, "error when extracting CCNX_TLV_M_MetaData\n");
                        goto Bail;
                    }
                    break;
                default:
                    break;
                }
                cp += len3;
                len2 -= len3;
            }
            p->namelen = *data - p->nameptr;
#ifdef USE_NFN
            if (p->compcnt > 0 && p->complen[p->compcnt-1] == 7 &&
                    !memcmp(p->comp[p->compcnt-1], "\x00\x01\x00\x03NFN", 7)) {
                p->nfnflags |= CCNL_PREFIX_NFN;
                p->compcnt--;
            }
#endif
            break;
        case CCNX_TLV_M_ENDChunk:
            if (ccnl_ccnltv_extractNetworkVarInt(cp, len,
                              (unsigned int*) &(pkt->val.final_block_id)) < 0) {
                DEBUGMSG_PCNX(WARNING, "error when extracting CCNX_TLV_M_ENDChunk\n");
                goto Bail;
            }
            break;
        case CCNX_TLV_M_Payload:
            pkt->content = *data;
            pkt->contlen = len;
            break;
#ifdef USE_HMAC256
        case CCNX_TLV_TL_ValidationAlgo:
            cp = *data;
            len2 = len;
            if (ccnl_ccntlv_dehead(&cp, &len2, &typ, (unsigned*) &len3) || len>*datalen)
                goto Bail;
            if (typ == CCNX_VALIDALGO_HMAC_SHA256) {
                // ignore keyId and other algo dependent data ... && len3 == 0)
                validAlgoIsHmac256 = 1;
            }
            break;
        case CCNX_TLV_TL_ValidationPayload:
            if (pkt->hmacStart && validAlgoIsHmac256 && len == 32) {
                pkt->hmacLen = *data - pkt->hmacStart - 4;
                pkt->hmacSignature = *data;
            }
            break;
#endif
        default:
            break;
        }
        *data += len;
        *datalen -= len;
        oldpos = *data - start;
    }
    if (*datalen > 0)
        goto Bail;

    pkt->pfx = p;
    pkt->buf = ccnl_buf_new(start, *data - start);
    if (!pkt->buf)
        goto Bail;
    // carefully rebase ptrs to new buf because of 64bit pointers:
    if (pkt->content)
        pkt->content = pkt->buf->data + (pkt->content - start);
    for (i = 0; i < p->compcnt; i++)
        p->comp[i] = pkt->buf->data + (p->comp[i] - start);
    if (p->nameptr)
        p->nameptr = pkt->buf->data + (p->nameptr - start);
#ifdef USE_HMAC256
    pkt->hmacStart = pkt->buf->data + (pkt->hmacStart - start);
    pkt->hmacSignature = pkt->buf->data + (pkt->hmacSignature - start);
#endif

    return pkt;
Bail:
    free_packet(pkt);
    return NULL;
}