struct ccnl_prefix_s* ccnl_prefix_dup(struct ccnl_prefix_s *prefix) { int i = 0, len; struct ccnl_prefix_s *p; if (!prefix) return NULL; p = ccnl_prefix_new(prefix->suite, prefix->compcnt); if (!p) return p; p->compcnt = prefix->compcnt; p->chunknum = prefix->chunknum; #ifdef USE_NFN p->nfnflags = prefix->nfnflags; #endif for (i = 0, len = 0; i < prefix->compcnt; i++) len += prefix->complen[i]; p->bytes = (unsigned char*) ccnl_malloc(len); if (!p->bytes) { free_prefix(p); return NULL; } for (i = 0, len = 0; i < prefix->compcnt; i++) { p->complen[i] = prefix->complen[i]; p->comp[i] = p->bytes + len; memcpy(p->bytes + len, prefix->comp[i], p->complen[i]); len += p->complen[i]; } if (prefix->chunknum) { p->chunknum = ccnl_malloc(sizeof(int)); *p->chunknum = *prefix->chunknum; } return p; }
// 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; }
// turn an URI into an internal prefix (watch out: this modifies the uri string) struct ccnl_prefix_s * ccnl_URItoPrefix(char* uri, int suite, char *nfnexpr, unsigned int *chunknum) { struct ccnl_prefix_s *p; char *compvect[CCNL_MAX_NAME_COMP]; unsigned int complens[CCNL_MAX_NAME_COMP]; int cnt, i, len, tlen; DEBUGMSG_CPFX(TRACE, "ccnl_URItoPrefix(suite=%s, uri=%s, nfn=%s)\n", ccnl_suite2str(suite), uri, nfnexpr); if (strlen(uri)) cnt = ccnl_URItoComponents(compvect, complens, uri); else cnt = 0; if (nfnexpr && *nfnexpr) cnt += 1; p = ccnl_prefix_new(suite, cnt); if (!p) return NULL; for (i = 0, len = 0; i < cnt; i++) { if (i == (cnt-1) && nfnexpr && *nfnexpr) len += strlen(nfnexpr); else len += complens[i];//strlen(compvect[i]); } #ifdef USE_SUITE_CCNTLV if (suite == CCNL_SUITE_CCNTLV) len += cnt * 4; // add TL size #endif #ifdef USE_SUITE_CISTLV if (suite == CCNL_SUITE_CISTLV) len += cnt * 4; // add TL size #endif p->bytes = (unsigned char*) ccnl_malloc(len); if (!p->bytes) { free_prefix(p); return NULL; } for (i = 0, len = 0, tlen = 0; i < cnt; i++) { int isnfnfcomp = i == (cnt-1) && nfnexpr && *nfnexpr; char *cp = isnfnfcomp ? nfnexpr : (char*) compvect[i]; if (isnfnfcomp) tlen = strlen(nfnexpr); else tlen = complens[i]; p->comp[i] = p->bytes + len; tlen = ccnl_pkt_mkComponent(suite, p->comp[i], cp, tlen); p->complen[i] = tlen; len += tlen; } p->compcnt = cnt; #ifdef USE_NFN if (nfnexpr && *nfnexpr) p->nfnflags |= CCNL_PREFIX_NFN; #endif if(chunknum) { p->chunknum = ccnl_malloc(sizeof(int)); *p->chunknum = *chunknum; } return p; }
// we use one extraction routine for both interest and data pkts struct ccnl_pkt_s* ccnl_cistlv_bytes2pkt(unsigned char *start, unsigned char **data, int *datalen) { struct ccnl_pkt_s *pkt; int i; unsigned int len, typ, oldpos; struct ccnl_prefix_s *p; DEBUGMSG(DEBUG, "extracting CISTLV packet (%d, %d bytes)\n", (int)(*data - start), *datalen); pkt = (struct ccnl_pkt_s*) ccnl_calloc(1, sizeof(*pkt)); if (!pkt) return NULL; pkt->pfx = p = ccnl_prefix_new(CCNL_SUITE_CISTLV, CCNL_MAX_NAME_COMP); if (!p) { ccnl_free(pkt); return NULL; } p->compcnt = 0; // We ignore the TL types of the message for now // content and interests are filled in both cases (and only one exists) // validation is ignored if (ccnl_cistlv_dehead(data, datalen, &typ, &len)) goto Bail; pkt->type = typ; pkt->suite = CCNL_SUITE_CISTLV; pkt->val.final_block_id = -1; oldpos = *data - start; while (ccnl_cistlv_dehead(data, datalen, &typ, &len) == 0) { unsigned char *cp = *data, *cp2; int len2 = len; unsigned int len3; switch (typ) { case CISCO_TLV_Name: p->nameptr = start + oldpos; while (len2 > 0) { cp2 = cp; if (ccnl_cistlv_dehead(&cp, &len2, &typ, &len3)) goto Bail; if (typ == CISCO_TLV_NameSegment) { // 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 = (unsigned int*) ccnl_malloc(sizeof(int)); if (ccnl_cistlv_extractNetworkVarInt(cp, len2, p->chunknum) < 0) { DEBUGMSG(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 } else if (typ == CISCO_TLV_NameComponent) { 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 } 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--; if (p->compcnt > 0 && p->complen[p->compcnt-1] == 9 && !memcmp(p->comp[p->compcnt-1], "\x00\x01\x00\x05THUNK", 9)) { p->nfnflags |= CCNL_PREFIX_THUNK; p->compcnt--; } } #endif break; case CISCO_TLV_FinalSegmentID: if (ccnl_cistlv_extractNetworkVarInt(cp, len2, (unsigned int*) &pkt->val.final_block_id) < 0) { DEBUGMSG(WARNING, "error when extracting CISCO_TLV_FinalSegmentID\n"); goto Bail; } break; case CISCO_TLV_ContentData: pkt->content = *data; pkt->contlen = len; break; 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); return pkt; Bail: free_packet(pkt); return NULL; }