/** * * @param ccnl * @param content * @param content_len * @param sig * @param sig_len * @param callback function which should be called when crypto system returns * for a new callback function you have to extend ccnl_crypto()!!!! * @return */ int ccnl_crypto_verify(struct ccnl_relay_s *ccnl, char *content, int content_len, char *sig, int sig_len, char* callback, int sequnum) { char *msg = 0; int len = 0, ret = 0; struct ccnl_buf_s *retbuf; //int plen; //unsigned char *buf; plen = 0; memset(buf,0,sizeof(buf)); if(!ccnl->crypto_face) return ret; msg = (char *)ccnl_malloc(sizeof(char)*(content_len+sig_len)+3000); len = ccnl_crypto_create_ccnl_sign_verify_msg("verify", sequnum, content, content_len, sig, sig_len, msg, callback); if(len > CCNL_MAX_PACKET_SIZE){ DEBUGMSG(DEBUG,"Ignored, packet size too large"); return 0; } //send ccn_msg to crytoserver retbuf = ccnl_buf_new((char *)msg, len); ccnl_face_enqueue(ccnl, ccnl->crypto_face, retbuf); if(msg) ccnl_free(msg); return ret; }
// 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; }
// consumes the result stack, exports its content to a buffer struct ccnl_buf_s* Krivine_exportResultStack(struct ccnl_relay_s *ccnl, struct configuration_s *config) { char res[64000]; //TODO longer??? int pos = 0; struct stack_s *stack; struct ccnl_content_s *cont; while ((stack = pop_or_resolve_from_result_stack(ccnl, config))) { if (stack->type == STACK_TYPE_PREFIX) { cont = ccnl_nfn_local_content_search(ccnl, config, stack->content); if (cont) { memcpy(res+pos, (char*)cont->pkt->content, cont->pkt->contlen); pos += cont->pkt->contlen; } } else if (stack->type == STACK_TYPE_PREFIXRAW) { cont = ccnl_nfn_local_content_search(ccnl, config, stack->content); if (cont) { /* DEBUGMSG(DEBUG, " PREFIXRAW packet: %p %d\n", (void*) cont->buf, cont->buf ? cont->buf->datalen : -1); */ memcpy(res+pos, (char*)cont->pkt->buf->data, cont->pkt->buf->datalen); pos += cont->pkt->buf->datalen; } } else if (stack->type == STACK_TYPE_INT) { //h = ccnl_buf_new(NULL, 10); //sprintf((char*)h->data, "%d", *(int*)stack->content); //h->datalen = strlen((char*)h->data); pos += sprintf(res + pos, "%d", *(int*)stack->content); } ccnl_free(stack->content); ccnl_free(stack); } return ccnl_buf_new(res, pos); }
int ccnl_nonce_find_or_append(struct ccnl_relay_s *ccnl, struct ccnl_buf_s *nonce) { struct ccnl_buf_s *n, *n2 = 0; int i; DEBUGMSG_CORE(TRACE, "ccnl_nonce_find_or_append\n"); for (n = ccnl->nonces, i = 0; n; n = n->next, i++) { if (buf_equal(n, nonce)) return -1; if (n->next) n2 = n; } n = ccnl_buf_new(nonce->data, nonce->datalen); if (n) { n->next = ccnl->nonces; ccnl->nonces = n; if (i >= CCNL_MAX_NONCES && n2) { ccnl_free(n2->next); n2->next = 0; } } return 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; }
int ccnl_frag_RX_BeginEnd2015(RX_datagram callback, struct ccnl_relay_s *relay, struct ccnl_face_s *from, int mtu, unsigned int bits, unsigned int seqno, unsigned char **data, int *datalen) { struct ccnl_buf_s *buf = NULL; struct ccnl_frag_s *e; DEBUGMSG_EFRA(DEBUG, "ccnl_frag_RX_BeginEnd2015 (%d bytes), seqno=%d\n", *datalen, seqno); if (!from) { DEBUGMSG_EFRA(WARNING, "RX_BeginEnd2015: no from value\n"); return 0; } if (!from->frag) from->frag = ccnl_frag_new(CCNL_FRAG_BEGINEND2015, mtu); if (!from->frag) { DEBUGMSG_EFRA(WARNING, "no frag alloc\n"); return 0; } if (from->frag->protocol != CCNL_FRAG_BEGINEND2015) { DEBUGMSG_EFRA(WARNING, "WRONG FRAG PROTOCOL\n"); return 0; } e = from->frag; if (e->recvseq != seqno) { // should increase error counter here DEBUGMSG_EFRA(WARNING, " >> seqnum mismatch: rcvd %d, expected %d\n", seqno, e->recvseq); if (e->defrag) { DEBUGMSG_EFRA(WARNING, " >> had to drop defrag buf\n"); ccnl_free(e->defrag); e->defrag = NULL; } e->recvseq = seqno; } switch(bits & (CCNL_BEFRAG_FLAG_MASK)) { case CCNL_BEFRAG_FLAG_SINGLE: // single packet DEBUGMSG_EFRA(VERBOSE, " >> single fragment seqno=%d (%d bytes)\n", seqno, *datalen); if (e->defrag) { DEBUGMSG_EFRA(WARNING, " had to drop defrag buf\n"); ccnl_free(e->defrag); e->defrag = NULL; } e->recvseq++; // no need to copy the buffer: callback(relay, from, data, datalen); return 1; case CCNL_BEFRAG_FLAG_FIRST: // start of fragment sequence DEBUGMSG_EFRA(VERBOSE, " >> start of fragment series\n"); if (e->defrag) { DEBUGMSG_EFRA(WARNING, " had to drop defrag buf\n"); ccnl_free(e->defrag); } e->defrag = ccnl_buf_new(*data, *datalen); break; case CCNL_BEFRAG_FLAG_LAST: // end of fragment sequence DEBUGMSG_EFRA(VERBOSE, " >> last fragment of a series\n"); if (!e->defrag) { DEBUGMSG_EFRA(WARNING, " >> no e->defrag?\n"); break; } buf = ccnl_buf_new(NULL, e->defrag->datalen + *datalen); if (buf) { memcpy(buf->data, e->defrag->data, e->defrag->datalen); memcpy(buf->data + e->defrag->datalen, *data, *datalen); } ccnl_free(e->defrag); e->defrag = NULL; break; case CCNL_BEFRAG_FLAG_MID: // fragment in the middle of a squence default: DEBUGMSG_EFRA(VERBOSE, " >> fragment in the middle of a series\n"); if (!e->defrag) break; buf = ccnl_buf_new(NULL, e->defrag->datalen + *datalen); if (buf) { memcpy(buf->data, e->defrag->data, e->defrag->datalen); memcpy(buf->data + e->defrag->datalen, *data, *datalen); ccnl_free(e->defrag); e->defrag = buf; buf = NULL; } else { ccnl_free(e->defrag); e->defrag = NULL; } break; } *data += *datalen; *datalen = 0; e->recvseq++; if (buf) { unsigned char *frag = buf->data; int fraglen = buf->datalen; DEBUGMSG_EFRA(DEBUG, " >> reassembled fragment is %d bytes\n", buf->datalen); // FIXME: loop over multiple packets in this reassembled frame? callback(relay, from, &frag, &fraglen); ccnl_free(buf); } return 1; }
// processes a SEQENCED fragment. Once fully assembled we call the callback void ccnl_frag_RX_serialfragment(RX_datagram callback, struct ccnl_relay_s *relay, struct ccnl_face_s *from, struct serialFragPDU_s *s) { struct ccnl_buf_s *buf = NULL; struct ccnl_frag_s *e = from->frag; DEBUGMSG_EFRA(VERBOSE, " frag %p protocol=%d, flags=%04x, seq=%d (%d)\n", (void*)e, e->protocol, s->flags, s->ourseq, e->recvseq); if (e->recvseq != s->ourseq) { // should increase error counter here if (e->defrag) { DEBUGMSG_EFRA(WARNING, " >> seqnum mismatch (%d/%d), dropped defrag buf\n", s->ourseq, e->recvseq); ccnl_free(e->defrag); e->defrag = NULL; } if (e->recvseq > s->ourseq) // old and dup fragment: ignore return; } switch(s->flags & (CCNL_DTAG_FRAG_FLAG_FIRST|CCNL_DTAG_FRAG_FLAG_LAST)) { case CCNL_DTAG_FRAG_FLAG_SINGLE: // single packet DEBUGMSG_EFRA(VERBOSE, " >> single fragment (%d bytes)\n", s->contlen); if (e->defrag) { DEBUGMSG_EFRA(WARNING, " had to drop defrag buf\n"); ccnl_free(e->defrag); e->defrag = NULL; } // no need to copy the buffer: callback(relay, from, &s->content, &s->contlen); return; case CCNL_DTAG_FRAG_FLAG_FIRST: // start of fragment sequence DEBUGMSG_EFRA(VERBOSE, " >> start of fragment series\n"); if (e->defrag) { DEBUGMSG_EFRA(WARNING, " had to drop defrag buf\n"); ccnl_free(e->defrag); } e->defrag = ccnl_buf_new(s->content, s->contlen); s->content += s->contlen; s->contlen = 0; break; case CCNL_DTAG_FRAG_FLAG_LAST: // end of fragment sequence DEBUGMSG_EFRA(VERBOSE, " >> last fragment of a series\n"); if (!e->defrag) { DEBUGMSG_EFRA(VERBOSE, " >> no e->defrag?\n"); break; } buf = ccnl_buf_new(NULL, e->defrag->datalen + s->contlen); if (buf) { memcpy(buf->data, e->defrag->data, e->defrag->datalen); memcpy(buf->data + e->defrag->datalen, s->content, s->contlen); } ccnl_free(e->defrag); e->defrag = NULL; s->content += s->contlen; s->contlen = 0; break; case CCNL_DTAG_FRAG_FLAG_MID: // fragment in the middle of a squence default: DEBUGMSG_EFRA(VERBOSE, " >> fragment in the middle of a series\n"); if (!e->defrag) break; buf = ccnl_buf_new(NULL, e->defrag->datalen + s->contlen); if (buf) { memcpy(buf->data, e->defrag->data, e->defrag->datalen); memcpy(buf->data + e->defrag->datalen, s->content, s->contlen); ccnl_free(e->defrag); e->defrag = buf; buf = NULL; } else { ccnl_free(e->defrag); e->defrag = NULL; } s->content += s->contlen; s->contlen = 0; break; } // FIXME: we should only bump recvseq if s->ourseq is ahead, or 0 e->recvseq = s->ourseq + 1; DEBUGMSG_EFRA(VERBOSE, ">>> seq from %d to %d (w=%d)\n", s->ourseq, e->recvseq, s->ourseqwidth); if (buf) { unsigned char *frag = buf->data; int fraglen = buf->datalen; DEBUGMSG_EFRA(VERBOSE, " >> reassembled fragment is %d bytes\n", buf->datalen); // FIXME: loop over multiple packets in this reassembled frame? callback(relay, from, &frag, &fraglen); ccnl_free(buf); } }
struct ccnl_buf_s* ccnl_frag_getnextCCNx2013(struct ccnl_frag_s *fr, int *ifndx, sockunion *su) { struct ccnl_buf_s *buf = 0; unsigned char header[256]; int hdrlen, blobtaglen, flagoffs; unsigned int datalen; // switch among encodings of fragments here (ccnb, TLV, etc) hdrlen = ccnl_ccnb_mkHeader(header, CCNL_DTAG_FRAGMENT2013, CCN_TT_DTAG); // fragment hdrlen += ccnl_ccnb_mkHeader(header + hdrlen, CCNL_DTAG_FRAG2013_TYPE, CCN_TT_DTAG); hdrlen += ccnl_ccnb_mkHeader(header + hdrlen, 3, CCN_TT_BLOB); memcpy(header + hdrlen, CCNL_FRAG_TYPE_CCNx2013_VAL, 3); // "FHBH" header[hdrlen + 3] = '\0'; hdrlen += 4; hdrlen += ccnl_ccnb_mkBinaryInt(header+hdrlen, CCNL_DTAG_FRAG2013_SEQNR, CCN_TT_DTAG, fr->sendseq, fr->sendseqwidth); hdrlen += ccnl_ccnb_mkBinaryInt(header+hdrlen, CCNL_DTAG_FRAG2013_FLAGS, CCN_TT_DTAG, 0, fr->flagwidth); flagoffs = hdrlen - 2; // most significant byte of flag element // other optional fields would go here hdrlen += ccnl_ccnb_mkHeader(header+hdrlen, CCN_DTAG_CONTENT, CCN_TT_DTAG); blobtaglen = ccnl_ccnb_mkHeader(header + hdrlen, fr->mtu - hdrlen - 2, CCN_TT_BLOB); datalen = fr->mtu - hdrlen - blobtaglen - 2; if (datalen > (fr->bigpkt->datalen - fr->sendoffs)) datalen = fr->bigpkt->datalen - fr->sendoffs; hdrlen += ccnl_ccnb_mkHeader(header + hdrlen, datalen, CCN_TT_BLOB); buf = ccnl_buf_new(NULL, hdrlen + datalen + 2); if (!buf) return NULL; memcpy(buf->data, header, hdrlen); memcpy(buf->data + hdrlen, fr->bigpkt->data + fr->sendoffs, datalen); buf->data[hdrlen + datalen] = '\0'; // end of content field buf->data[hdrlen + datalen + 1] = '\0'; // end of fragment // patch flag field: if (datalen >= fr->bigpkt->datalen) { // single buf->data[flagoffs] = CCNL_DTAG_FRAG_FLAG_SINGLE; ccnl_free(fr->bigpkt); fr->bigpkt = NULL; } else if (fr->sendoffs == 0) // start buf->data[flagoffs] = CCNL_DTAG_FRAG_FLAG_FIRST; else if(datalen >= (fr->bigpkt->datalen - fr->sendoffs)) { // end buf->data[flagoffs] = CCNL_DTAG_FRAG_FLAG_LAST; ccnl_free(fr->bigpkt); fr->bigpkt = NULL; } else buf->data[flagoffs] = CCNL_DTAG_FRAG_FLAG_MID; fr->sendoffs += datalen; fr->sendseq++; if (ifndx) *ifndx = fr->ifndx; if (su) memcpy(su, &fr->dest, sizeof(*su)); return buf; }
struct ccnl_buf_s* ccnl_frag_getnextSEQD2012(struct ccnl_frag_s *e, int *ifndx, sockunion *su) { struct ccnl_buf_s *buf = 0; unsigned char header[256]; int hdrlen = 0, blobtaglen, flagoffs; unsigned int datalen; DEBUGMSG_EFRA(TRACE, "ccnl_frag_getnextSEQD2012 e=%p, mtu=%d\n", (void*)e, e->mtu); DEBUGMSG_EFRA(TRACE, " %d bytes to fragment, offset=%d\n", e->bigpkt->datalen, e->sendoffs); hdrlen = ccnl_ccnb_mkHeader(header, CCNL_DTAG_FRAGMENT2012, CCN_TT_DTAG); hdrlen += ccnl_ccnb_mkBinaryInt(header + hdrlen, CCNL_DTAG_FRAG2012_FLAGS, CCN_TT_DTAG, 0, e->flagwidth); flagoffs = hdrlen - 2; hdrlen += ccnl_ccnb_mkBinaryInt(header + hdrlen, CCNL_DTAG_FRAG2012_YSEQN, CCN_TT_DTAG, e->recvseq, e->recvseqwidth); hdrlen += ccnl_ccnb_mkBinaryInt(header+hdrlen, CCNL_DTAG_FRAG2012_OLOSS, CCN_TT_DTAG, e->losscount, e->losscountwidth); hdrlen += ccnl_ccnb_mkBinaryInt(header + hdrlen, CCNL_DTAG_FRAG2012_SEQNR, CCN_TT_DTAG, e->sendseq, e->sendseqwidth); hdrlen += ccnl_ccnb_mkHeader(header+hdrlen, CCN_DTAG_CONTENT, CCN_TT_DTAG); blobtaglen = ccnl_ccnb_mkHeader(header+hdrlen, e->mtu - hdrlen - 2, CCN_TT_BLOB); datalen = e->mtu - hdrlen - blobtaglen - 2; if (datalen > (e->bigpkt->datalen - e->sendoffs)) datalen = e->bigpkt->datalen - e->sendoffs; hdrlen += ccnl_ccnb_mkHeader(header + hdrlen, datalen, CCN_TT_BLOB); buf = ccnl_buf_new(NULL, hdrlen + datalen + 2); if (!buf) return NULL; memcpy(buf->data, header, hdrlen); memcpy(buf->data + hdrlen, e->bigpkt->data + e->sendoffs, datalen); buf->data[hdrlen + datalen] = '\0'; // end of content/any field buf->data[hdrlen + datalen + 1] = '\0'; // end of fragment/pdu if (datalen >= e->bigpkt->datalen) { // fits in a single fragment buf->data[flagoffs + e->flagwidth - 1] = CCNL_DTAG_FRAG_FLAG_FIRST | CCNL_DTAG_FRAG_FLAG_LAST; ccnl_free(e->bigpkt); e->bigpkt = NULL; } else if (e->sendoffs == 0) // this is the start fragment buf->data[flagoffs + e->flagwidth - 1] = CCNL_DTAG_FRAG_FLAG_FIRST; else if(datalen >= (e->bigpkt->datalen - e->sendoffs)) { // the end buf->data[flagoffs + e->flagwidth - 1] = CCNL_DTAG_FRAG_FLAG_LAST; ccnl_free(e->bigpkt); e->bigpkt = NULL; } else // in the middle buf->data[flagoffs + e->flagwidth - 1] = 0x00; e->sendoffs += datalen; e->sendseq++; DEBUGMSG_EFRA(TRACE, " e->offset now %d\n", e->sendoffs); if (ifndx) *ifndx = e->ifndx; if (su) memcpy(su, &e->dest, sizeof(*su)); return buf; }
// we use one extraction routine for both request and reply pkts struct ccnl_pkt_s* ccnl_iottlv_bytes2pkt(int pkttype, unsigned char *start, unsigned char **data, int *datalen) { struct ccnl_pkt_s *pkt; unsigned char *cp, tmp[10]; int cplen, len2; unsigned int typ, len, state; DEBUGMSG_PIOT(DEBUG, "ccnl_iottlv_extract len=%d\n", *datalen); /* { int fd = open("s.bin", O_WRONLY|O_CREAT|O_TRUNC); write(fd, *data, *datalen); close(fd); } */ pkt = (struct ccnl_pkt_s*) ccnl_calloc(1, sizeof(*pkt)); if (!pkt) return NULL; pkt->suite = CCNL_SUITE_IOTTLV; pkt->val.final_block_id = -1; pkt->s.iottlv.ttl = -1; #define IOTPS(C,L) (((C)<<4)|(L)) // parse state: combines current state while (*datalen) { if (ccnl_iottlv_dehead(data, datalen, &typ, &len)) goto Bail; state = IOTPS(pkttype, typ); DEBUGMSG_CFWD(TRACE, " state = 0x%04x\n", state); switch (state) { case IOTPS(IOT_TLV_Request, IOT_TLV_R_OptHeader): case IOTPS(IOT_TLV_Reply, IOT_TLV_R_OptHeader): { cp = *data; cplen = len; while (cplen > 0 && !ccnl_iottlv_dehead(&cp, &cplen, &typ, (unsigned int *)&len2)) { if (typ == IOT_TLV_H_HopLim && len2 == 1) { if (*cp > 0) *cp -= 1; pkt->s.iottlv.ttl = *cp; } cp += len2; cplen -= len2; } break; } case IOTPS(IOT_TLV_Request, IOT_TLV_R_Name): case IOTPS(IOT_TLV_Reply, IOT_TLV_R_Name): cp = *data; cplen = len; while (cplen > 0 && !ccnl_iottlv_dehead(&cp, &cplen, &typ, (unsigned int *)&len2)) { if (typ == IOT_TLV_N_PathName) { if (!pkt->pfx) pkt->pfx = ccnl_iottlv_parseHierarchicalName(cp, len2); if (!pkt->pfx) goto Bail; } cp += len2; cplen -= len2; } break; case IOTPS(IOT_TLV_Fragment, IOT_TLV_F_FlagsAndSeq): { uint16_t fragFields; if (len < 2) { DEBUGMSG_CFWD(DEBUG, " no flags and seqno found (%d)\n", typ); goto Bail; } fragFields = ntohs(*(uint16_t*) *data); pkt->val.seqno = fragFields & 0x7ff; pkt->flags |= (fragFields >> 14) << 2; break; } case IOTPS(IOT_TLV_Request, IOT_TLV_R_Payload): case IOTPS(IOT_TLV_Reply, IOT_TLV_R_Payload): cp = *data; cplen = len; if (!ccnl_iottlv_dehead(&cp, &cplen, &typ, (unsigned int *)&len2)) { if (typ == IOT_TLV_PL_Data) { pkt->content = cp; pkt->contlen = len2; } } break; case IOTPS(IOT_TLV_Fragment, IOT_TLV_F_Data): pkt->content = *data; pkt->contlen = len; break; /* #ifdef USE_FRAG if (ccnl_iottlv_peekType(*data, *datalen) == IOT_TLV_Fragment) { uint16_t tmp; unsigned int payloadlen; if (ccnl_iottlv_dehead(data, datalen, &typ, &len)) // IOT_TLV_Fragment return -1; if (ccnl_iottlv_dehead(data, datalen, &typ, &len)) return -1; if (typ == IOT_TLV_F_OptFragHdr) { // skip it for the time being *data += len; *datalen -= len; if (ccnl_iottlv_dehead(data, datalen, &typ, &len)) return -1; } if (typ != IOT_TLV_F_FlagsAndSeq || len < 2) { DEBUGMSG_CFWD(DEBUG, " no flags and seqrn found (%d)\n", typ); return -1; } tmp = ntohs(*(uint16_t*) *data); *data += len; *datalen -= len; if (ccnl_iottlv_dehead(data, datalen, &typ, &payloadlen)) return -1; if (typ != IOT_TLV_F_Payload) { DEBUGMSG_CFWD(DEBUG, " no payload (%d)\n", typ); return -1; } *datalen -= payloadlen; ccnl_frag_RX_Sequenced2015(ccnl_iottlv_forwarder, relay, from, relay->ifs[from->ifndx].mtu, tmp >> 14, tmp & 0x7ff, data, (int*) &payloadlen); *datalen += payloadlen; DEBUGMSG_CFWD(TRACE, " returning after fragment: %d bytes\n", *datalen); return 0; } else #endif */ default: fprintf(stderr, " iottlv unknown state 0x%04x\n", state); break; } *data += len; *datalen -= len; } if (*datalen > 0) goto Bail; // if we received a naked packet (without switch code), we need to add // a switch code when creating the packet buffer if (*start != 0x80) { len = sizeof(tmp); len2 = ccnl_switch_prependCoding(CCNL_ENC_IOT2014, (int*) &len, tmp); if (len2 < 0) { DEBUGMSG(ERROR, "prending code should not return -1\n"); len2 = 0; } start -= len2; } else len2 = 0; pkt->buf = ccnl_buf_new(start, *data - start); if (!pkt->buf) goto Bail; if (pkt->buf && len2) memcpy(pkt->buf->data, tmp + len, len2); // carefully rebase ptrs to new buf because of 64bit pointers: if (pkt->content) pkt->content = pkt->buf->data + (pkt->content - start); if (pkt->pfx) { int i; for (i = 0; i < pkt->pfx->compcnt; i++) pkt->pfx->comp[i] = pkt->buf->data + (pkt->pfx->comp[i] - start); if (pkt->pfx->nameptr) pkt->pfx->nameptr = pkt->buf->data + (pkt->pfx->nameptr - start); } return pkt; Bail: free_packet(pkt); return NULL; }
// 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; }
struct ccnl_buf_s * ccnl_extract_prefix_nonce_ppkd(unsigned char **data, int *datalen, int *scope, int *aok, int *min, int *max, struct ccnl_prefix_s **prefix, struct ccnl_buf_s **nonce, struct ccnl_buf_s **ppkd, unsigned char **content, int *contlen) { unsigned char *start = *data - 2, *cp; int num, typ, len; struct ccnl_prefix_s *p; struct ccnl_buf_s *buf, *n = 0, *pub = 0; DEBUGMSG(99, "ccnl_extract_prefix\n"); p = (struct ccnl_prefix_s *) ccnl_calloc(1, sizeof(struct ccnl_prefix_s)); if (!p) { puts("can't get more memory from malloc, dropping ccn msg..."); return NULL; } p->comp = (unsigned char **) ccnl_malloc( CCNL_MAX_NAME_COMP * sizeof(unsigned char **)); p->complen = (int *) ccnl_malloc(CCNL_MAX_NAME_COMP * sizeof(int)); if (!p->comp || !p->complen) { puts("can't get more memory from malloc, dropping ccn msg..."); goto Bail; } while (dehead(data, datalen, &num, &typ) == 0) { if (num == 0 && typ == 0) { break; // end } if (typ == CCN_TT_DTAG) { if (num == CCN_DTAG_NAME) { while (1) { if (dehead(data, datalen, &num, &typ) != 0) { goto Bail; } if (num == 0 && typ == 0) { break; } if (typ == CCN_TT_DTAG && num == CCN_DTAG_COMPONENT && p->compcnt < CCNL_MAX_NAME_COMP) { if (hunt_for_end(data, datalen, p->comp + p->compcnt, p->complen + p->compcnt) < 0) { goto Bail; } p->compcnt++; } else { if (consume(typ, num, data, datalen, 0, 0) < 0) { goto Bail; } } } continue; } if (num == CCN_DTAG_SCOPE || num == CCN_DTAG_NONCE || num == CCN_DTAG_MINSUFFCOMP || num == CCN_DTAG_MAXSUFFCOMP || num == CCN_DTAG_PUBPUBKDIGEST) { if (hunt_for_end(data, datalen, &cp, &len) < 0) { goto Bail; } if (num == CCN_DTAG_SCOPE && len == 1 && scope) { *scope = isdigit(*cp) && (*cp < '3') ? *cp - '0' : -1; } if (num == CCN_DTAG_ANSWERORIGKIND && aok) { *aok = data2uint(cp, len); } if (num == CCN_DTAG_MINSUFFCOMP && min) { *min = data2uint(cp, len); } if (num == CCN_DTAG_MAXSUFFCOMP && max) { *max = data2uint(cp, len); } if (num == CCN_DTAG_NONCE && !n) { n = ccnl_buf_new(cp, len); } if (num == CCN_DTAG_PUBPUBKDIGEST && !pub) { pub = ccnl_buf_new(cp, len); } if (num == CCN_DTAG_EXCLUDE) { DEBUGMSG(49, "warning: 'exclude' field ignored\n"); } else { continue; } } if (num == CCN_DTAG_CONTENT || num == CCN_DTAG_CONTENTOBJ) { if (consume(typ, num, data, datalen, content, contlen) < 0) { goto Bail; } continue; } } if (consume(typ, num, data, datalen, 0, 0) < 0) { goto Bail; } } if (prefix) { p->comp[p->compcnt] = NULL; *prefix = p; } else { free_prefix(p); } if (nonce) { *nonce = n; } else { ccnl_free(n); } if (ppkd) { *ppkd = pub; } else { ccnl_free(pub); } buf = ccnl_buf_new(start, *data - start); if (!buf) { puts("can't get more memory from malloc, dropping ccn msg..."); goto Bail; } // carefully rebase ptrs to new buf because of 64bit pointers: if (content) { *content = buf->data + (*content - start); } for (num = 0; num < p->compcnt; num++) { p->comp[num] = buf->data + (p->comp[num] - start); } return buf; Bail: free_prefix(p); free_2ptr_list(n, pub); return NULL; }
struct ccnl_buf_s *buf_dup(struct ccnl_buf_s *B) { return (B) ? ccnl_buf_new(B->data, B->datalen) : NULL; }
void ccnl_frag_RX_serialfragment(RX_datagram callback, struct ccnl_relay_s *relay, struct ccnl_face_s *from, struct serialFragPDU_s *s) { struct ccnl_buf_s *buf = NULL; struct ccnl_frag_s *e = from->frag; DEBUGMSG(8, " frag %p protocol=%d, flags=%04x, seq=%d (%d)\n", (void *) e, e->protocol, s->flags, s->ourseq, e->recvseq); if (e->recvseq != s->ourseq) { /* should increase error counter here */ if (e->defrag) { DEBUGMSG(17, " >> seqnum mismatch (%d/%d), dropped defrag buf\n", s->ourseq, e->recvseq); ccnl_free(e->defrag); e->defrag = NULL; } } switch (s->flags & (CCNL_DTAG_FRAG_FLAG_FIRST | CCNL_DTAG_FRAG_FLAG_LAST)) { case CCNL_DTAG_FRAG_FLAG_SINGLE: /* single packet */ DEBUGMSG(17, " >> single fragment\n"); if (e->defrag) { DEBUGMSG(18, " had to drop defrag buf\n"); ccnl_free(e->defrag); e->defrag = NULL; } /* no need to copy the buffer: */ callback(relay, from, &s->content, &s->contlen); return; case CCNL_DTAG_FRAG_FLAG_FIRST: /* start of fragment sequence */ DEBUGMSG(17, " >> start of fragment series\n"); if (e->defrag) { DEBUGMSG(18, " had to drop defrag buf\n"); ccnl_free(e->defrag); } e->defrag = ccnl_buf_new(s->content, s->contlen); break; case CCNL_DTAG_FRAG_FLAG_LAST: /* end of fragment sequence */ DEBUGMSG(17, " >> last fragment of a series\n"); if (!e->defrag) { break; } buf = ccnl_buf_new(NULL, e->defrag->datalen + s->contlen); if (buf) { memcpy(buf->data, e->defrag->data, e->defrag->datalen); memcpy(buf->data + e->defrag->datalen, s->content, s->contlen); } ccnl_free(e->defrag); e->defrag = NULL; break; case CCNL_DTAG_FRAG_FLAG_MID: /* fragment in the middle of a squence */ default: DEBUGMSG(17, " >> fragment in the middle of a series\n"); if (!e->defrag) { break; } buf = ccnl_buf_new(NULL, e->defrag->datalen + s->contlen); if (buf) { memcpy(buf->data, e->defrag->data, e->defrag->datalen); memcpy(buf->data + e->defrag->datalen, s->content, s->contlen); ccnl_free(e->defrag); e->defrag = buf; buf = NULL; } else { ccnl_free(e->defrag); e->defrag = NULL; } break; } /* FIXME: we should only bump recvseq if s->ourseq is ahead, or 0 */ e->recvseq = s->ourseq + 1; DEBUGMSG(1, ">>> seq from %d to %d (w=%d)\n", s->ourseq, e->recvseq, s->ourseqwidth); if (buf) { unsigned char *frag = buf->data; int fraglen = buf->datalen; DEBUGMSG(1, " >> reassembled fragment is %d bytes\n", buf->datalen); callback(relay, from, &frag, &fraglen); ccnl_free(buf); } DEBUGMSG(1, "leaving function\n"); }
// produces a full FRAG packet. It does not write, just read the fields in *fr struct ccnl_buf_s* ccnl_iottlv_mkFrag(struct ccnl_frag_s *fr, unsigned int *consumed) { unsigned char test[20]; int offset, hdrlen, len, len2; unsigned int datalen; struct ccnl_buf_s *buf; uint16_t tmp = 0; // test size, first datalen = fr->bigpkt->datalen - fr->sendoffs - 9; if (datalen > fr->mtu) datalen = fr->mtu; offset = sizeof(test); len = datalen + ccnl_iottlv_prependTL(IOT_TLV_F_Data, datalen, &offset, test); len += ccnl_iottlv_prependTL(IOT_TLV_F_FlagsAndSeq, 2, &offset, test) + 2; ccnl_iottlv_prependTL(IOT_TLV_Fragment, len, &offset, test); hdrlen = sizeof(test) - offset + 2 + 2; // adj for flagAndSeq, switch code // with real values: datalen = fr->bigpkt->datalen - fr->sendoffs; if (datalen > (fr->mtu - hdrlen)) datalen = fr->mtu - hdrlen; buf = ccnl_buf_new(NULL, hdrlen + datalen); // 2 bytes for switch code if (!buf) return 0; offset = buf->datalen; len = ccnl_iottlv_prependBlob(IOT_TLV_F_Data, fr->bigpkt->data + fr->sendoffs, datalen, &offset, buf->data); if (len <= 0) { ccnl_free(buf); return NULL; } // flags and sequence number if (datalen >= fr->bigpkt->datalen) { // single tmp |= CCNL_DTAG_FRAG_FLAG_SINGLE << 14; } else if (fr->sendoffs == 0) // start tmp |= CCNL_DTAG_FRAG_FLAG_FIRST << 14; else if(datalen >= (fr->bigpkt->datalen - fr->sendoffs)) { // end tmp |= CCNL_DTAG_FRAG_FLAG_LAST << 14; } else tmp |= CCNL_DTAG_FRAG_FLAG_MID << 14; tmp |= fr->sendseq & 0x07ff; tmp = htons(tmp); len2 = ccnl_iottlv_prependBlob(IOT_TLV_F_FlagsAndSeq, (unsigned char*) &tmp, sizeof(tmp), &offset, buf->data); if (len2 <= 0) { ccnl_free(buf); return NULL; } len += len2; // main header len2 = ccnl_iottlv_prependTL(IOT_TLV_Fragment, len, &offset, buf->data); if (len2 <= 0) { ccnl_free(buf); return NULL; } len += len2; // encoding switch: len2 = ccnl_switch_prependCoding(CCNL_ENC_IOT2014, &offset, buf->data); if (len2 < 0) { DEBUGMSG(ERROR, " prending code should not return -1\n"); ccnl_free(buf); return NULL; } len += len2; if (offset > 0) { DEBUGMSG(TRACE, " iottlv fragment: shift by %d bytes\n", offset); memmove(buf->data, buf->data + offset, len); buf->datalen = len; } *consumed = datalen; return buf; }
int ccnl_mgmt_crypto(struct ccnl_relay_s *ccnl, char *type, unsigned char *buf, int buflen) { struct ccnl_face_s *from; DEBUGMSG(DEBUG,"ccnl_crypto type: %s\n", type); if(!strcmp(type, "verify")){ int seqnum = 0; int verified = ccnl_crypto_extract_verify_reply(&buf, &buflen, &seqnum); unsigned char *msg, *msg2; char cmd[500]; int len = ccnl_crypto_extract_msg(&buf, &buflen, &msg), len2 = 0; struct ccnl_face_s *from; //DEBUGMSG(DEBUG,"VERIFIED: %d, MSG_LEN: %d\n", verified, len); int scope=3, aok=3, minsfx=0, maxsfx=CCNL_MAX_NAME_COMP, contlen; struct ccnl_buf_s *buf1 = 0, *nonce=0, *ppkd=0; struct ccnl_prefix_s *p = 0; struct ccnl_buf_s *msg2_buf; unsigned char *content = 0; msg2 = (char *) ccnl_malloc(sizeof(char) * len + 200); len2 = ccnl_ccnb_mkHeader(msg2,CCN_DTAG_NAME, CCN_TT_DTAG); memcpy(msg2+len2, msg, len); len2 +=len; msg2[len2++] = 0; from = ccnl->faces; while(from){ if(from->faceid == seqnum) break; from = from->next; } buf1 = ccnl_ccnb_extract(&msg2, &len2, &scope, &aok, &minsfx, &maxsfx, &p, &nonce, &ppkd, &content, &contlen); if (p->complen[2] < sizeof(cmd)) { memcpy(cmd, p->comp[2], p->complen[2]); cmd[p->complen[2]] = '\0'; } else strcpy(cmd, "cmd-is-too-long-to-display"); msg2_buf = ccnl_buf_new((char *)msg2, len2); ccnl_mgmt_handle(ccnl, msg2_buf, p, from, cmd, verified); ccnl_free(msg2_buf); }else if(!strcmp(type, "sign")){ char *sig = (char *) ccnl_malloc(sizeof(char)* CCNL_MAX_PACKET_SIZE); unsigned char *out; unsigned char *msg; int siglen = 0, seqnum = 0, len, len1; struct ccnl_buf_s *retbuf; ccnl_crypto_extract_sign_reply(&buf, &buflen, sig, &siglen, &seqnum); len = ccnl_crypto_extract_msg(&buf, &buflen, &msg); out = (char *) ccnl_malloc(sizeof(unsigned char)*len + sizeof(unsigned char)*siglen + 4096); len1 = ccnl_ccnb_mkHeader(out, CCN_DTAG_CONTENTOBJ, CCN_TT_DTAG); // content if(siglen > 0) len1 += ccnl_crypto_add_signature(out+len1, sig, siglen); memcpy(out+len1, msg, len); len1 +=len; out[len1++] = 0; // end-of-interest from = ccnl->faces; while(from){ if(from->faceid == seqnum) break; from = from->next; } retbuf = ccnl_buf_new((char *)out, len1); if(seqnum >= 0){ ccnl_face_enqueue(ccnl, from, retbuf); }else{ struct ccnl_prefix_s *prefix_a = 0; struct ccnl_content_s *c = 0; struct ccnl_buf_s *nonce=0, *ppkd=0, *pkt = 0; unsigned char *content = 0; char *ht = (char *) ccnl_malloc(sizeof(char)*20); int contlen; pkt = ccnl_ccnb_extract(&out, &len1, 0, 0, 0, 0, &prefix_a, &nonce, &ppkd, &content, &contlen); if (!pkt) { DEBUGMSG(WARNING, " parsing error\n"); goto Done; } if (prefix_a) { //DEBUGMSG(DEBUG, "%s", prefix_a->comp); //ccnl_free(prefix_a); } //prefix_a = (struct ccnl_prefix_s *)ccnl_malloc(sizeof(struct ccnl_prefix_s)); prefix_a->compcnt = 2; prefix_a->comp = (unsigned char **) ccnl_malloc(sizeof(unsigned char*)*2); prefix_a->comp[0] = "mgmt"; sprintf(ht, "seqnum-%d", -seqnum); prefix_a->comp[1] = ht; prefix_a->complen = (int *) ccnl_malloc(sizeof(int)*2); prefix_a->complen[0] = strlen("mgmt"); prefix_a->complen[1] = strlen(ht); c = ccnl_content_new(ccnl, CCNL_SUITE_CCNB, &pkt, &prefix_a, &ppkd, content, contlen); if (!c) goto Done; ccnl_content_serve_pending(ccnl, c); ccnl_content_add2cache(ccnl, c); } Done: ccnl_free(out); } return 0; }
struct ccnl_buf_s* ccnl_ccnb_extract(unsigned char **data, int *datalen, int *scope, int *aok, int *min, int *max, struct ccnl_prefix_s **prefix, struct ccnl_buf_s **nonce, struct ccnl_buf_s **ppkd, unsigned char **content, int *contlen) { unsigned char *start = *data - 2 /* account for outer TAG hdr */, *cp; int num, typ, len; struct ccnl_prefix_s *p; struct ccnl_buf_s *buf, *n = 0, *pub = 0; DEBUGMSG(99, "ccnl_ccnb_extract\n"); p = (struct ccnl_prefix_s *) ccnl_calloc(1, sizeof(struct ccnl_prefix_s)); if (!p) return NULL; p->comp = (unsigned char**) ccnl_malloc(CCNL_MAX_NAME_COMP * sizeof(unsigned char**)); p->complen = (int*) ccnl_malloc(CCNL_MAX_NAME_COMP * sizeof(int)); if (!p->comp || !p->complen) goto Bail; while (ccnl_ccnb_dehead(data, datalen, &num, &typ) == 0) { if (num==0 && typ==0) break; // end if (typ == CCN_TT_DTAG) { if (num == CCN_DTAG_NAME) { for (;;) { if (ccnl_ccnb_dehead(data, datalen, &num, &typ) != 0) goto Bail; if (num==0 && typ==0) break; if (typ == CCN_TT_DTAG && num == CCN_DTAG_COMPONENT && p->compcnt < CCNL_MAX_NAME_COMP) { if (ccnl_ccnb_hunt_for_end(data, datalen, p->comp + p->compcnt, p->complen + p->compcnt) < 0) goto Bail; p->compcnt++; } else { if (ccnl_ccnb_consume(typ, num, data, datalen, 0, 0) < 0) goto Bail; } } continue; } if (num == CCN_DTAG_SCOPE || num == CCN_DTAG_NONCE || num == CCN_DTAG_MINSUFFCOMP || num == CCN_DTAG_MAXSUFFCOMP || num == CCN_DTAG_PUBPUBKDIGEST) { if (ccnl_ccnb_hunt_for_end(data, datalen, &cp, &len) < 0) goto Bail; if (num == CCN_DTAG_SCOPE && len == 1 && scope) *scope = isdigit(*cp) && (*cp < '3') ? *cp - '0' : -1; if (num == CCN_DTAG_ANSWERORIGKIND && aok) *aok = ccnl_ccnb_data2uint(cp, len); if (num == CCN_DTAG_MINSUFFCOMP && min) *min = ccnl_ccnb_data2uint(cp, len); if (num == CCN_DTAG_MAXSUFFCOMP && max) *max = ccnl_ccnb_data2uint(cp, len); if (num == CCN_DTAG_NONCE && !n) n = ccnl_buf_new(cp, len); if (num == CCN_DTAG_PUBPUBKDIGEST && !pub) pub = ccnl_buf_new(cp, len); if (num == CCN_DTAG_EXCLUDE) { DEBUGMSG(49, "warning: 'exclude' field ignored\n"); } else continue; } if (num == CCN_DTAG_CONTENT) { if (ccnl_ccnb_consume(typ, num, data, datalen, content, contlen) < 0) goto Bail; continue; } } if (ccnl_ccnb_consume(typ, num, data, datalen, 0, 0) < 0) goto Bail; } if (prefix) *prefix = p; else free_prefix(p); if (nonce) *nonce = n; else ccnl_free(n); if (ppkd) *ppkd = pub; else ccnl_free(pub); buf = ccnl_buf_new(start, *data - start); // carefully rebase ptrs to new buf because of 64bit pointers: if (content) *content = buf->data + (*content - start); for (num = 0; num < p->compcnt; num++) p->comp[num] = buf->data + (p->comp[num] - start); return buf; Bail: free_prefix(p); free_2ptr_list(n, pub); return NULL; }