// 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; }
// 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; }