/** * Insert a ContentObject into a btree node * * The caller has presumably already done a lookup and found that the * object is not there. * * The caller is responsible for provinding a valid content parse (pc). * * The flatname buffer should hold the correct full name, including the * digest. * * @returns the new entry count or, -1 for error. */ int ccn_btree_insert_content(struct ccn_btree_node *node, int ndx, uint_least64_t cobid, const unsigned char *content_object, struct ccn_parsed_ContentObject *pc, struct ccn_charbuf *flatname) { struct ccn_btree_content_payload payload; struct ccn_btree_content_payload *e = &payload; int ncomp; int res; unsigned size; unsigned flags = 0; const unsigned char *blob = NULL; size_t blob_size = 0; size = pc->offset[CCN_PCO_E]; ncomp = ccn_flatname_ncomps(flatname->buf, flatname->length); if (ncomp != pc->name_ncomps + 1) return(-1); memset(e, 'U', sizeof(*e)); MYSTORE(e, magic, CCN_BT_CONTENT_MAGIC); MYSTORE(e, ctype, pc->type); MYSTORE(e, cobsz, size); MYSTORE(e, ncomp, ncomp); MYSTORE(e, flags, flags); // XXX - need to set CCN_RCFLAG_LASTBLOCK MYSTORE(e, ttpad, 0); MYSTORE(e, timex, 0); res = ccn_ref_tagged_BLOB(CCN_DTAG_Timestamp, content_object, pc->offset[CCN_PCO_B_Timestamp], pc->offset[CCN_PCO_E_Timestamp], &blob, &blob_size); if (res < 0 || blob_size > sizeof(e->timex)) return(-1); memcpy(e->timex + sizeof(e->timex) - blob_size, blob, blob_size); // XXX - need to set accession time. Should we pass it in? MYSTORE64(e, cobid, cobid); res = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest, content_object, pc->offset[CCN_PCO_B_PublisherPublicKeyDigest], pc->offset[CCN_PCO_E_PublisherPublicKeyDigest], &blob, &blob_size); if (res < 0 || blob_size != sizeof(e->ppkdg)) return(-1); memcpy(e->ppkdg, blob, sizeof(e->ppkdg)); /* Now actually do the insert */ res = ccn_btree_insert_entry(node, ndx, flatname->buf, flatname->length, e, sizeof(*e)); return(res); }
HashPtr ParsedContentObject::publisherPublicKeyDigest() const { const unsigned char *buf = NULL; size_t size = 0; ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest, head(m_bytes), m_pco.offset[CCN_PCO_B_PublisherPublicKeyDigest], m_pco.offset[CCN_PCO_E_PublisherPublicKeyDigest], &buf, &size); return boost::make_shared<Hash>(buf, size); }
int ccn_content_get_value(const unsigned char *data, size_t data_size, const struct ccn_parsed_ContentObject *content, const unsigned char **value, size_t *value_size) { int res; res = ccn_ref_tagged_BLOB(CCN_DTAG_Content, data, content->offset[CCN_PCO_B_Content], content->offset[CCN_PCO_E_Content], value, value_size); return(res); }
void NdnMediaProcess::initPipe(struct ccn_closure *selfp, struct ccn_upcall_info *info, UserDataBuf *userBuf) { fprintf(stderr, "initializing pipe\n"); // get seq const unsigned char *ccnb = info->content_ccnb; size_t ccnb_size = info->pco->offset[CCN_PCO_E]; struct ccn_indexbuf *comps = info->content_comps; long seq; const unsigned char *seqptr = NULL; char *endptr = NULL; size_t seq_size = 0; int k = comps->n - 2; if (userBuf->seq < 0) { seq = ccn_ref_tagged_BLOB(CCN_DTAG_Component, ccnb, comps->buf[k], comps->buf[k + 1], &seqptr, &seq_size); if (seq >= 0) { seq = strtol((const char *)seqptr, &endptr, 10); if (endptr != ((const char *)seqptr) + seq_size) seq = -1; } if (seq >= 0) { userBuf->seq = seq; } else { return; } } fprintf(stderr, "fetched content with seq %d\n", seq); // send hint-ahead interests for (int i = 0; i < hint_ahead; i ++) { userBuf->seq++; struct ccn_charbuf *pathbuf = ccn_charbuf_create(); ccn_name_init(pathbuf); ccn_name_append_components(pathbuf, ccnb, comps->buf[0], comps->buf[k]); struct ccn_charbuf *temp = ccn_charbuf_create(); ccn_charbuf_putf(temp, "%ld", userBuf->seq); ccn_name_append(pathbuf, temp->buf, temp->length); // no need to trylock as we already have the lock // this should use pipe callback, selfp is normal callback int res = ccn_express_interest(info->h, pathbuf, userBuf->data_buf.pipe_callback, NULL); if (res < 0) { fprintf(stderr, "Sending interest failed at normal processor\n"); std::exit(1); } ccn_charbuf_destroy(&pathbuf); ccn_charbuf_destroy(&temp); } }
void CcnCC_fetchCcndid(CcnCC self) { int res; struct ccn_charbuf* name = ccn_charbuf_create(); struct ccn_charbuf* resultbuf = ccn_charbuf_create(); struct ccn_parsed_ContentObject pcobuf = {0}; const uint8_t* ccndid_result; static size_t ccndid_result_size; ccn_name_from_uri(name, "ccnx:/%C1.M.S.localhost/%C1.M.SRV/ccnd/KEY"); res = ccn_get(self->ccnh, name, CcnH_localScopeTempl(), 4500, resultbuf, &pcobuf, NULL, 0); if (res >= 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest, resultbuf->buf, pcobuf.offset[CCN_PCO_B_PublisherPublicKeyDigest], pcobuf.offset[CCN_PCO_E_PublisherPublicKeyDigest], &ccndid_result, &ccndid_result_size); } if (res >= 0 && ccndid_result_size == CCNDID_length) { memcpy((void*)self->ccndid, ccndid_result, CCNDID_length); } else { self->error = true; } ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&resultbuf); }
/** * Produce a ccnd debug trace entry. * Output is produced by calling ccnd_msg. * @param h the ccnd handle * @param lineno caller's source line number (usually __LINE__) * @param msg a short text tag to identify the entry * @param face handle of associated face; may be NULL * @param ccnb points to ccnb-encoded Interest or ContentObject * @param ccnb_size is in bytes */ void ccnd_debug_ccnb(struct ccnd_handle *h, int lineno, const char *msg, struct face *face, const unsigned char *ccnb, size_t ccnb_size) { struct ccn_charbuf *c; struct ccn_parsed_interest pi; const unsigned char *nonce = NULL; size_t nonce_size = 0; size_t i; if (h != NULL && h->debug == 0) return; c = ccn_charbuf_create(); ccn_charbuf_putf(c, "debug.%d %s ", lineno, msg); if (face != NULL) ccn_charbuf_putf(c, "%u ", face->faceid); ccn_uri_append(c, ccnb, ccnb_size, 1); ccn_charbuf_putf(c, " (%u bytes)", (unsigned)ccnb_size); if (ccn_parse_interest(ccnb, ccnb_size, &pi, NULL) >= 0) { const char *p = ""; ccn_ref_tagged_BLOB(CCN_DTAG_Nonce, ccnb, pi.offset[CCN_PI_B_Nonce], pi.offset[CCN_PI_E_Nonce], &nonce, &nonce_size); if (nonce_size > 0) { ccn_charbuf_putf(c, " "); if (nonce_size == 12) p = "CCC-P-F-T-NN"; for (i = 0; i < nonce_size; i++) ccn_charbuf_putf(c, "%s%02X", (*p) && (*p++)=='-' ? "-" : "", nonce[i]); } } ccnd_msg(h, "%s", ccn_charbuf_as_string(c)); ccn_charbuf_destroy(&c); }
PUBLIC int r_store_content_field_access(struct ccnr_handle *h, struct content_entry *content, enum ccn_dtag dtag, const unsigned char **bufp, size_t *sizep) { int res = -1; const unsigned char *content_msg; struct ccn_parsed_ContentObject pco = {0}; content_msg = r_store_content_base(h, content); if (content_msg == NULL) return(-1); res = ccn_parse_ContentObject(content_msg, content->size, &pco, NULL); if (res < 0) return(-1); if (dtag == CCN_DTAG_Content) res = ccn_ref_tagged_BLOB(CCN_DTAG_Content, content_msg, pco.offset[CCN_PCO_B_Content], pco.offset[CCN_PCO_E_Content], bufp, sizep); return(res); }
static seg_t GetNumberFromInfo(const unsigned char *ccnb, enum ccn_dtag tt, size_t start, size_t stop) { // gets the binary number for the info // based on the tag and the start and stop indexes // returns -1 if the number does not appear to exist // must be called from inside of CallMe if (start < stop) { size_t len = 0; const unsigned char *data = NULL; ccn_ref_tagged_BLOB(tt, ccnb, start, stop, &data, &len); if (len > 0 && data != NULL) { // parse big-endian encoded number seg_t n = 0; size_t i; for (i = 0; i < len; i++) { n = n * 256 + data[i]; } return n; } } return -1; }
/** * * Get ccnd id * */ static int get_ccndid(struct ccn *h, struct ccn_charbuf *local_scope_template, unsigned char *ccndid) { struct ccn_charbuf *name = NULL; struct ccn_charbuf *resultbuf = NULL; struct ccn_parsed_ContentObject pcobuf = {0}; char ccndid_uri[] = "ccnx:/%C1.M.S.localhost/%C1.M.SRV/ccnd/KEY"; const unsigned char *ccndid_result; static size_t ccndid_result_size; int res; name = ccn_charbuf_create(); resultbuf = ccn_charbuf_create(); res = ccn_name_from_uri(name, ccndid_uri); ON_ERROR_EXIT(res, "Unable to parse service locator URI for ccnd key\n"); /* get Data */ res = ccn_get(h, name, local_scope_template, 4500, resultbuf, &pcobuf, NULL, 0); ON_ERROR_EXIT(res, "Unable to get key from ccnd\n"); /* extract from Data */ res = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest, resultbuf->buf, pcobuf.offset[CCN_PCO_B_PublisherPublicKeyDigest], pcobuf.offset[CCN_PCO_E_PublisherPublicKeyDigest], &ccndid_result, &ccndid_result_size); ON_ERROR_EXIT(res, "Unable to parse ccnd response for ccnd id\n"); memcpy((void *)ccndid, ccndid_result, ccndid_result_size); ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&resultbuf); return (ccndid_result_size); }
int main(int argc, char **argv) { struct ccn *h = NULL; struct ccn_charbuf *name = NULL; struct ccn_charbuf *null_name = NULL; struct ccn_charbuf *name_prefix = NULL; struct ccn_charbuf *newface = NULL; struct ccn_charbuf *prefixreg = NULL; struct ccn_charbuf *resultbuf = NULL; struct ccn_charbuf *temp = NULL; struct ccn_charbuf *templ = NULL; const unsigned char *ptr = NULL; size_t length = 0; const char *arg = NULL; const char *progname = NULL; struct ccn_parsed_ContentObject pcobuf = {0}; struct ccn_face_instance face_instance_storage = {0}; struct ccn_face_instance *face_instance = &face_instance_storage; struct ccn_forwarding_entry forwarding_entry_storage = {0}; struct ccn_forwarding_entry *forwarding_entry = &forwarding_entry_storage; struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT; struct ccn_charbuf *keylocator_templ = NULL; struct ccn_keystore *keystore = NULL; long expire = -1; int ipproto; unsigned char ccndid_storage[32] = {0}; const unsigned char *ccndid = NULL; size_t ccndid_size = 0; int res; int opt; progname = argv[0]; while ((opt = getopt(argc, argv, "h")) != -1) { switch (opt) { case 'h': default: usage(progname); } } /* Sanity check the URI and argument count */ arg = argv[optind]; if (arg == NULL) usage(progname); name = ccn_charbuf_create(); res = ccn_name_from_uri(name, arg); if (res < 0) { fprintf(stderr, "%s: bad ccn URI: %s\n", progname, arg); exit(1); } if (argc - optind < 3 || argc - optind > 4) usage(progname); h = ccn_create(); res = ccn_connect(h, NULL); if (res < 0) { ccn_perror(h, "ccn_connect"); exit(1); } newface = ccn_charbuf_create(); temp = ccn_charbuf_create(); templ = ccn_charbuf_create(); keylocator_templ = ccn_charbuf_create(); resultbuf = ccn_charbuf_create(); name_prefix = ccn_charbuf_create(); null_name = ccn_charbuf_create(); CHKRES(ccn_name_init(null_name)); keystore = ccn_keystore_create(); /* We need to figure out our local ccnd's CCIDID */ /* Set up our Interest template to indicate scope 1 */ ccn_charbuf_reset(templ); ccnb_element_begin(templ, CCN_DTAG_Interest); ccnb_element_begin(templ, CCN_DTAG_Name); ccnb_element_end(templ); /* </Name> */ ccnb_tagged_putf(templ, CCN_DTAG_Scope, "1"); ccnb_element_end(templ); /* </Interest> */ ccn_charbuf_reset(name); CHKRES(res = ccn_name_from_uri(name, "ccnx:/%C1.M.S.localhost/%C1.M.SRV/ccnd/KEY")); CHKRES(res = ccn_get(h, name, templ, 200, resultbuf, &pcobuf, NULL, 0)); res = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest, resultbuf->buf, pcobuf.offset[CCN_PCO_B_PublisherPublicKeyDigest], pcobuf.offset[CCN_PCO_E_PublisherPublicKeyDigest], &ccndid, &ccndid_size); CHKRES(res); if (ccndid_size > sizeof(ccndid_storage)) CHKRES(-1); memcpy(ccndid_storage, ccndid, ccndid_size); ccndid = ccndid_storage; face_instance->action = "newface"; face_instance->ccnd_id = ccndid; face_instance->ccnd_id_size = ccndid_size; if (strcmp(argv[optind + 1], "tcp") == 0) ipproto = 6; else if (strcmp(argv[optind + 1], "udp") == 0) ipproto = 17; else ipproto = atoi(argv[optind + 1]); face_instance->descr.ipproto = ipproto; // XXX - 6 = tcp or 17 = udp face_instance->descr.address = argv[optind + 2]; face_instance->descr.port = argv[optind + 3]; if (face_instance->descr.port == NULL) face_instance->descr.port = CCN_DEFAULT_UNICAST_PORT; face_instance->descr.mcast_ttl = -1; face_instance->lifetime = (~0U) >> 1; CHKRES(res = ccnb_append_face_instance(newface, face_instance)); temp->length = 0; CHKRES(ccn_charbuf_putf(temp, "%s/.ccnx/.ccnx_keystore", getenv("HOME"))); res = ccn_keystore_init(keystore, ccn_charbuf_as_string(temp), "Th1s1sn0t8g00dp8ssw0rd."); CHKRES(res); ccnb_element_begin(keylocator_templ, CCN_DTAG_SignedInfo); ccnb_element_begin(keylocator_templ, CCN_DTAG_KeyLocator); ccnb_element_begin(keylocator_templ, CCN_DTAG_Key); CHKRES(ccn_append_pubkey_blob(keylocator_templ, ccn_keystore_public_key(keystore))); ccnb_element_end(keylocator_templ); /* </Key> */ ccnb_element_end(keylocator_templ); /* </KeyLocator> */ ccnb_element_end(keylocator_templ); /* </SignedInfo> */ sp.template_ccnb = keylocator_templ; sp.sp_flags |= CCN_SP_TEMPL_KEY_LOCATOR; sp.freshness = expire; ccn_charbuf_reset(temp); res = ccn_sign_content(h, temp, null_name, &sp, newface->buf, newface->length); CHKRES(res); /* Create the new face */ CHKRES(ccn_name_init(name)); CHKRES(ccn_name_append_str(name, "ccnx")); CHKRES(ccn_name_append(name, ccndid, ccndid_size)); CHKRES(ccn_name_append(name, "newface", 7)); CHKRES(ccn_name_append(name, temp->buf, temp->length)); res = ccn_get(h, name, templ, 1000, resultbuf, &pcobuf, NULL, 0); if (res < 0) { fprintf(stderr, "no response from face creation request\n"); exit(1); } ptr = resultbuf->buf; length = resultbuf->length; res = ccn_content_get_value(resultbuf->buf, resultbuf->length, &pcobuf, &ptr, &length); CHKRES(res); face_instance = ccn_face_instance_parse(ptr, length); if (face_instance == NULL) CHKRES(res = -1); CHKRES(face_instance->faceid); /* Finally, register the prefix */ ccn_charbuf_reset(name_prefix); CHKRES(ccn_name_from_uri(name_prefix, arg)); forwarding_entry->action = "prefixreg"; forwarding_entry->name_prefix = name_prefix; forwarding_entry->ccnd_id = ccndid; forwarding_entry->ccnd_id_size = ccndid_size; forwarding_entry->faceid = face_instance->faceid; forwarding_entry->flags = -1; /* let ccnd decide */ forwarding_entry->lifetime = (~0U) >> 1; prefixreg = ccn_charbuf_create(); CHKRES(res = ccnb_append_forwarding_entry(prefixreg, forwarding_entry)); ccn_charbuf_reset(temp); res = ccn_sign_content(h, temp, null_name, &sp, prefixreg->buf, prefixreg->length); CHKRES(res); CHKRES(ccn_name_init(name)); CHKRES(ccn_name_append_str(name, "ccnx")); CHKRES(ccn_name_append(name, ccndid, ccndid_size)); CHKRES(ccn_name_append_str(name, "prefixreg")); CHKRES(ccn_name_append(name, temp->buf, temp->length)); res = ccn_get(h, name, templ, 1000, resultbuf, &pcobuf, NULL, 0); if (res < 0) { fprintf(stderr, "no response from prefix registration request\n"); exit(1); } fprintf(stderr, "Prefix %s will be forwarded to face %d\n", arg, face_instance->faceid); /* We're about to exit, so don't bother to free everything. */ ccn_destroy(&h); exit(res < 0); }
/** * Handle the incoming content messages. Extracts the data, and * requests the next block in sequence if the received block was * not the final one. */ enum ccn_upcall_res incoming_content(struct ccn_closure *selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info *info) { struct ccn_charbuf *name = NULL; struct ccn_charbuf *templ = NULL; const unsigned char *ccnb = NULL; size_t ccnb_size = 0; const unsigned char *data = NULL; size_t data_size = 0; size_t written; const unsigned char *ib = NULL; /* info->interest_ccnb */ struct ccn_indexbuf *ic = NULL; int res; struct mydata *md = selfp->data; if (kind == CCN_UPCALL_FINAL) { if (md != NULL) { selfp->data = NULL; free(md); md = NULL; } return(CCN_UPCALL_RESULT_OK); } if (kind == CCN_UPCALL_INTEREST_TIMED_OUT) return(CCN_UPCALL_RESULT_REEXPRESS); if (kind == CCN_UPCALL_CONTENT_UNVERIFIED) return(CCN_UPCALL_RESULT_VERIFY); if (kind != CCN_UPCALL_CONTENT) return(CCN_UPCALL_RESULT_ERR); if (md == NULL) selfp->data = md = calloc(1, sizeof(*md)); ccnb = info->content_ccnb; ccnb_size = info->pco->offset[CCN_PCO_E]; ib = info->interest_ccnb; ic = info->interest_comps; res = ccn_content_get_value(ccnb, ccnb_size, info->pco, &data, &data_size); if (res < 0) abort(); if (info->pco->type != CCN_CONTENT_DATA) { /* For us this is spam. For now, give up. */ fprintf(stderr, "*** spammed at block %d\n", (int)selfp->intdata); exit(1); } /* OK, we will accept this block. */ if (data_size == 0) *(md->done) = 1; else { written = fwrite(data, data_size, 1, stdout); if (written != 1) exit(1); } // XXX The test below should get refactored into the library if (info->pco->offset[CCN_PCO_B_FinalBlockID] != info->pco->offset[CCN_PCO_E_FinalBlockID]) { const unsigned char *finalid = NULL; size_t finalid_size = 0; const unsigned char *nameid = NULL; size_t nameid_size = 0; struct ccn_indexbuf *cc = info->content_comps; ccn_ref_tagged_BLOB(CCN_DTAG_FinalBlockID, ccnb, info->pco->offset[CCN_PCO_B_FinalBlockID], info->pco->offset[CCN_PCO_E_FinalBlockID], &finalid, &finalid_size); if (cc->n < 2) abort(); ccn_ref_tagged_BLOB(CCN_DTAG_Component, ccnb, cc->buf[cc->n - 2], cc->buf[cc->n - 1], &nameid, &nameid_size); if (finalid_size == nameid_size && 0 == memcmp(finalid, nameid, nameid_size)) *(md->done) = 1; } if (*(md->done)) { ccn_set_run_timeout(info->h, 0); return(CCN_UPCALL_RESULT_OK); } /* Ask for the next fragment */ name = ccn_charbuf_create(); ccn_name_init(name); if (ic->n < 2) abort(); res = ccn_name_append_components(name, ib, ic->buf[0], ic->buf[ic->n - 2]); if (res < 0) abort(); ccn_name_append_numeric(name, CCN_MARKER_SEQNUM, ++(selfp->intdata)); templ = make_template(md, info); res = ccn_express_interest(info->h, name, selfp, templ); if (res < 0) abort(); ccn_charbuf_destroy(&templ); ccn_charbuf_destroy(&name); return(CCN_UPCALL_RESULT_OK); }
static int dissect_ccn_contentobject(const unsigned char *ccnb, size_t ccnb_size, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *signature_tree; proto_tree *name_tree; proto_tree *signedinfo_tree; proto_tree *content_tree; proto_item *titem; struct ccn_parsed_ContentObject co; struct ccn_parsed_ContentObject *pco = &co; struct ccn_charbuf *c; struct ccn_indexbuf *comps; const unsigned char *comp; size_t comp_size; size_t blob_size; const unsigned char *blob; int l; unsigned int i; double dt; nstime_t timestamp; int res; comps = ccn_indexbuf_create(); res = ccn_parse_ContentObject(ccnb, ccnb_size, pco, comps); if (res < 0) return (-1); /* Signature */ l = pco->offset[CCN_PCO_E_Signature] - pco->offset[CCN_PCO_B_Signature]; titem = proto_tree_add_item(tree, hf_ccn_signature, tvb, pco->offset[CCN_PCO_B_Signature], l, FALSE); signature_tree = proto_item_add_subtree(titem, ett_signature); /* DigestAlgorithm */ l = pco->offset[CCN_PCO_E_DigestAlgorithm] - pco->offset[CCN_PCO_B_DigestAlgorithm]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_DigestAlgorithm, ccnb, pco->offset[CCN_PCO_B_DigestAlgorithm], pco->offset[CCN_PCO_E_DigestAlgorithm], &blob, &blob_size); titem = proto_tree_add_item(signature_tree, hf_ccn_signaturedigestalg, tvb, blob - ccnb, blob_size, FALSE); } /* Witness */ l = pco->offset[CCN_PCO_E_Witness] - pco->offset[CCN_PCO_B_Witness]; if (l > 0) { /* add the witness item to the signature tree */ } /* Signature bits */ l = pco->offset[CCN_PCO_E_SignatureBits] - pco->offset[CCN_PCO_B_SignatureBits]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_SignatureBits, ccnb, pco->offset[CCN_PCO_B_SignatureBits], pco->offset[CCN_PCO_E_SignatureBits], &blob, &blob_size); titem = proto_tree_add_bytes(signature_tree, hf_ccn_signaturebits, tvb, blob - ccnb, blob_size, blob); } /* /Signature */ /* Name */ l = pco->offset[CCN_PCO_E_Name] - pco->offset[CCN_PCO_B_Name]; c = ccn_charbuf_create(); ccn_uri_append(c, ccnb, ccnb_size, 1); titem = proto_tree_add_string(tree, hf_ccn_name, tvb, pco->offset[CCN_PCO_B_Name], l, ccn_charbuf_as_string(c)); name_tree = proto_item_add_subtree(titem, ett_name); ccn_charbuf_destroy(&c); /* Name Components */ for (i = 0; i < comps->n - 1; i++) { res = ccn_name_comp_get(ccnb, comps, i, &comp, &comp_size); titem = proto_tree_add_item(name_tree, hf_ccn_name_components, tvb, comp - ccnb, comp_size, FALSE); } /* /Name */ /* SignedInfo */ l = pco->offset[CCN_PCO_E_SignedInfo] - pco->offset[CCN_PCO_B_SignedInfo]; titem = proto_tree_add_text(tree, tvb, pco->offset[CCN_PCO_B_SignedInfo], l, "SignedInfo"); signedinfo_tree = proto_item_add_subtree(titem, ett_signedinfo); /* PublisherPublicKeyDigest */ l = pco->offset[CCN_PCO_E_PublisherPublicKeyDigest] - pco->offset[CCN_PCO_B_PublisherPublicKeyDigest]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest, ccnb, pco->offset[CCN_PCO_B_PublisherPublicKeyDigest], pco->offset[CCN_PCO_E_PublisherPublicKeyDigest], &blob, &blob_size); titem = proto_tree_add_bytes(signedinfo_tree, hf_ccn_publisherpublickeydigest, tvb, blob - ccnb, blob_size, blob); } /* Timestamp */ l = pco->offset[CCN_PCO_E_Timestamp] - pco->offset[CCN_PCO_B_Timestamp]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_Timestamp, ccnb, pco->offset[CCN_PCO_B_Timestamp], pco->offset[CCN_PCO_E_Timestamp], &blob, &blob_size); dt = 0.0; for (i = 0; i < blob_size; i++) dt = dt * 256.0 + (double)blob[i]; dt /= 4096.0; timestamp.secs = dt; /* truncates */ timestamp.nsecs = (dt - (double) timestamp.secs) * 1000000000.0; titem = proto_tree_add_time(signedinfo_tree, hf_ccn_timestamp, tvb, blob - ccnb, blob_size, ×tamp); } /* Type */ l = pco->offset[CCN_PCO_E_Type] - pco->offset[CCN_PCO_B_Type]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_Type, ccnb, pco->offset[CCN_PCO_B_Type], pco->offset[CCN_PCO_E_Type], &blob, &blob_size); titem = proto_tree_add_int(signedinfo_tree, hf_ccn_contenttype, tvb, blob - ccnb, blob_size, pco->type); } else { titem = proto_tree_add_int(signedinfo_tree, hf_ccn_contenttype, NULL, 0, 0, pco->type); } /* FreshnessSeconds */ l = pco->offset[CCN_PCO_E_FreshnessSeconds] - pco->offset[CCN_PCO_B_FreshnessSeconds]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_FreshnessSeconds, ccnb, pco->offset[CCN_PCO_B_FreshnessSeconds], pco->offset[CCN_PCO_E_FreshnessSeconds], &blob, &blob_size); i = ccn_fetch_tagged_nonNegativeInteger(CCN_DTAG_FreshnessSeconds, ccnb, pco->offset[CCN_PCO_B_FreshnessSeconds], pco->offset[CCN_PCO_E_FreshnessSeconds]); titem = proto_tree_add_uint(signedinfo_tree, hf_ccn_freshnessseconds, tvb, blob - ccnb, blob_size, i); } /* FinalBlockID */ l = pco->offset[CCN_PCO_E_FinalBlockID] - pco->offset[CCN_PCO_B_FinalBlockID]; if (l > 0) { res = ccn_ref_tagged_BLOB(CCN_DTAG_FinalBlockID, ccnb, pco->offset[CCN_PCO_B_FinalBlockID], pco->offset[CCN_PCO_E_FinalBlockID], &blob, &blob_size); titem = proto_tree_add_item(signedinfo_tree, hf_ccn_finalblockid, tvb, blob - ccnb, blob_size, FALSE); } /* TODO: KeyLocator */ /* /SignedInfo */ /* Content */ l = pco->offset[CCN_PCO_E_Content] - pco->offset[CCN_PCO_B_Content]; res = ccn_ref_tagged_BLOB(CCN_DTAG_Content, ccnb, pco->offset[CCN_PCO_B_Content], pco->offset[CCN_PCO_E_Content], &blob, &blob_size); titem = proto_tree_add_text(tree, tvb, pco->offset[CCN_PCO_B_Content], l, "Content: %d bytes", blob_size); if (blob_size > 0) { content_tree = proto_item_add_subtree(titem, ett_content); titem = proto_tree_add_item(content_tree, hf_ccn_contentdata, tvb, blob - ccnb, blob_size, FALSE); } return (ccnb_size); }
/* does that mean the last component is the implicit digest ? */ enum ccn_upcall_res packet_handler(struct ccn_closure *selfp, enum ccn_upcall_kind upcall_kind, struct ccn_upcall_info *info) { handler_data* h_data = (handler_data*) selfp->data; // Client data returned fprintf(stderr, "\nUpcall from %s handle\n", (info->h==(*h_data->ccn_rec))? "receiver":"publisher"); ccn_set_run_timeout(info->h, 0); // Return to client faster switch(upcall_kind) { case CCN_UPCALL_FINAL: fprintf(stderr, "CCN_UPCALL_FINAL\n"); return (CCN_UPCALL_RESULT_OK); case CCN_UPCALL_INTEREST_TIMED_OUT: fprintf(stderr, "CCN_UPCALL_INTEREST_TIMED_OUT\n"); (*h_data->complete) = 1; // End the main loop, some sort of problem return (CCN_UPCALL_RESULT_OK); case CCN_UPCALL_CONTENT: fprintf(stderr, "CCN_UPCALL_CONTENT\n"); const unsigned char* content = NULL; size_t content_bytes = 0; ccn_ref_tagged_BLOB(CCN_DTAG_Content, info->content_ccnb, info->pco->offset[CCN_PCO_B_Content], info->pco->offset[CCN_PCO_E_Content], &content, &content_bytes); fprintf(stderr, "\tContent: %s\n", content); (*h_data->outstanding_interests)--; return (CCN_UPCALL_RESULT_OK); case CCN_UPCALL_CONTENT_UNVERIFIED: fprintf(stderr, "CCN_UPCALL_CONTENT_UNVERIFIED\n"); return (CCN_UPCALL_RESULT_OK); case CCN_UPCALL_CONTENT_BAD: fprintf(stderr, "CCN_UPCALL_CONTENT_BAD\n"); return (CCN_UPCALL_RESULT_OK); case CCN_UPCALL_CONSUMED_INTEREST: fprintf(stderr, "CCN_UPCALL_CONSUMED_INTEREST\n"); return (CCN_UPCALL_RESULT_OK); case CCN_UPCALL_INTEREST: fprintf(stderr, "CCN_UPCALL_INTEREST, (matched comp == %d)\n", info->matched_comps); fprintf(stderr, " (interest comps == %zu)\n", info->interest_comps->n); int res = 0; // Corrected 20-May-2011 to support interests with additional components after prefix // if (info->interest_comps->n < 3) { // Name + signature + implicit digest, minimum fprintf(stderr, "\tnot enough components, %zu<3\n", info->interest_comps->n); } else { // Verify the interest res = verify_signed_interest(info->interest_ccnb, info->interest_comps, info->interest_comps->n-2, info->interest_comps->buf[0], info->interest_comps->buf[info->interest_comps->n-2], (*h_data->public_key)); fprintf(stderr, "\tverify_signed_interest == %d (%s)\n", res, (res==1)?"verified":"unverified"); } // Based on the results, // create and send a reply using default key & algorithm for the receiving handle // to sign the content object. // char* reply_data = (res==1) ? "OK" : "AUTH_FAIL"; // A modest content. struct ccn_charbuf* reply = ccn_charbuf_create(); struct ccn_charbuf* name = ccn_charbuf_create(); struct ccn_signing_params sp = CCN_SIGNING_PARAMS_INIT; ccn_name_init(name); // Don't need to create a new name, could just index into the buffer. res = ccn_name_append_components(name, info->interest_ccnb, info->interest_comps->buf[0], info->interest_comps->buf[info->interest_comps->n - 1]); ccn_sign_content(info->h, reply, name, &sp, (void*)reply_data, strlen(reply_data)+1); res = ccn_put(info->h, reply->buf, reply->length); ccn_charbuf_destroy(&reply); ccn_charbuf_destroy(&name); if (res >= 0) { fprintf (stderr, "\tReturned Content: %s\n", reply_data); return (CCN_UPCALL_RESULT_INTEREST_CONSUMED); } return (CCN_UPCALL_RESULT_OK); } return (CCN_UPCALL_RESULT_ERR); }
enum ccn_upcall_res ccn_text_handler(struct ccn_closure *selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info *info) { UserDataBuf *userBuf = (UserDataBuf *)selfp->data; if (userBuf == NULL || userBuf->iNeedDestroy) { //if (userBuf != NULL) delete userBuf; //selfp->data = NULL; return CCN_UPCALL_RESULT_OK; } switch (kind) { case CCN_UPCALL_INTEREST_TIMED_OUT: { // if it's short Interest without seq, reexpress // TODO: check whether the user is still in the conference // don't re-express if it is not return (CCN_UPCALL_RESULT_REEXPRESS); } case CCN_UPCALL_CONTENT_UNVERIFIED: fprintf(stderr, "unverified content received\n"); return CCN_UPCALL_RESULT_OK; case CCN_UPCALL_FINAL: return CCN_UPCALL_RESULT_OK; case CCN_UPCALL_CONTENT: break; default: return CCN_UPCALL_RESULT_OK; } struct data_buffer *buffer = &userBuf->data_buf; const unsigned char *content_value; size_t len; NDNState *state = buffer->state; const unsigned char *ccnb = info->content_ccnb; size_t ccnb_size = info->pco->offset[CCN_PCO_E]; struct ccn_indexbuf *comps = info->content_comps; ccn_content_get_value(ccnb, ccnb_size, info->pco, &content_value, &len); unsigned char *msg = (unsigned char *)calloc((len + 1), sizeof(char)); memcpy(msg, content_value, len); msg[len] = '\0'; QString textMsg = (const char *)msg; state->emitTextMsgArrival(userBuf->user_name, textMsg); free(msg); long seq; const unsigned char *seqptr = NULL; char *endptr = NULL; size_t seq_size = 0; int k = comps->n - 2; seq = ccn_ref_tagged_BLOB(CCN_DTAG_Component, ccnb, comps->buf[k], comps->buf[k + 1], &seqptr, &seq_size); if (seq >= 0) { seq = strtol((const char *)seqptr, &endptr, 10); if (endptr != ((const char *)seqptr) + seq_size) seq = -1; } if (seq < 0) { return CCN_UPCALL_RESULT_OK; } seq++; struct ccn_charbuf *path = ccn_charbuf_create(); ccn_name_init(path); ccn_name_append_components(path, ccnb, comps->buf[0], comps->buf[k]); struct ccn_charbuf *temp = ccn_charbuf_create(); ccn_charbuf_putf(temp, "%ld", seq); ccn_name_append(path, temp->buf, temp->length); int res = ccn_express_interest(info->h, path, selfp, NULL); if (res < 0) { fprintf(stderr, "sending the first interest failed\n"); exit(1); } ccn_charbuf_destroy(&path); ccn_charbuf_destroy(&temp); return CCN_UPCALL_RESULT_OK; }
/** * Main working loop for stuff coming in from the CCNx network * * The only kind of content we work with are data messages. They are in response to the * interest messages we send out. The work involves 2 pieces: packing the data from ccn message * sizes into buffer sizes we use internally, and detecting when the stream of data is done. * * The first is fairly simple. Each internal buffer we 'fill' is placed onto the fifo queue * so the main thread can take it off and reply to the pipeline request for more data. * * Determining the end of stream at the moment is a bit of a hack and could use some work. * \todo volunteers? 8-) * * \param selfp -> a context structure we created when registering this call-back * \param kind specifies the type of call-back being processed, see the \b switch statement * \param info context information about the call-back itself; interests, data, etc. * \return a response as to how successful we were in processing the call-back * \retval CCN_UPCALL_RESULT_OK things went well * \retval CCN_UPCALL_RESULT_VERIFY need to verify the contents of what we received * \retval CCN_UPCALL_RESULT_REEXPRESS an interest timedout waiting for data, so we try again * \retval CCN_UPCALL_RESULT_ERR some error was encountered */ static enum ccn_upcall_res incoming_content (struct ccn_closure *selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info *info) { Gstccnxsrc *me = GST_CCNXSRC (selfp->data); const unsigned char *ccnb = NULL; size_t ccnb_size = 0; const unsigned char *ib = NULL; /* info->interest_ccnb */ struct ccn_indexbuf *ic = NULL; unsigned int i; uintmax_t segment; CcnxInterestState *istate = NULL; gint res; const unsigned char *cp; size_t sz; const unsigned char *data = NULL; size_t data_size = 0; gboolean b_last = FALSE; GST_INFO ("content has arrived!"); /* Do some basic sanity and type checks to see if we want to process this data */ if (CCN_UPCALL_FINAL == kind) { GST_LOG_OBJECT (me, "CCN upcall final %p", selfp); if (me->i_bufoffset > 0) { GST_BUFFER_SIZE (me->buf) = me->i_bufoffset; fifo_put (me, me->buf); me->buf = gst_buffer_new_and_alloc (CCN_FIFO_BLOCK_SIZE); me->i_bufoffset = 0; } /* * Should emit an eos here instead of the empty buffer */ GST_BUFFER_SIZE (me->buf) = 0; fifo_put (me, me->buf); me->i_bufoffset = 0; return (CCN_UPCALL_RESULT_OK); } if (!info) return CCN_UPCALL_RESULT_ERR; // Now why would this happen? // show_comps( info->content_ccnb, info->content_comps); if (CCN_UPCALL_INTEREST_TIMED_OUT == kind) { if (selfp != me->ccn_closure) { GST_LOG_OBJECT (me, "CCN Interest timed out on dead closure %p", selfp); return (CCN_UPCALL_RESULT_OK); } segment = ccn_ccnb_fetch_segment (info->interest_ccnb, info->interest_comps); GST_INFO ("...looks to be for segment: %d", segment); GST_LOG_OBJECT (me, "CCN upcall reexpress -- timed out"); istate = fetchSegmentInterest (me, segment); if (istate) { if (istate->timeouts > 5) { GST_LOG_OBJECT (me, "CCN upcall reexpress -- too many reexpressions"); if (segment == me->post_seg) // We have been waiting for this one...process as an empty block to trigger other activity process_or_queue (me, me->post_seg, NULL, 0, FALSE); else freeInterestState (me, istate); post_next_interest (me); // make sure to ask for new stuff if needed, or else we stall waiting for nothing return (CCN_UPCALL_RESULT_OK); } else { istate->timeouts++; return (CCN_UPCALL_RESULT_REEXPRESS); } } else { GST_LOG_OBJECT (me, "segment not found in cache: %d", segment); return (CCN_UPCALL_RESULT_OK); } } else if (CCN_UPCALL_CONTENT_UNVERIFIED == kind) { if (selfp != me->ccn_closure) { GST_LOG_OBJECT (me, "CCN unverified content on dead closure %p", selfp); return (CCN_UPCALL_RESULT_OK); } return (CCN_UPCALL_RESULT_VERIFY); } else if (CCN_UPCALL_CONTENT != kind) { GST_LOG_OBJECT (me, "CCN upcall result error"); return (CCN_UPCALL_RESULT_ERR); } segment = ccn_ccnb_fetch_segment (info->content_ccnb, info->content_comps); GST_INFO ("...looks to be for segment: %d", segment); if (selfp != me->ccn_closure) { GST_LOG_OBJECT (me, "CCN content on dead closure %p", selfp); return (CCN_UPCALL_RESULT_OK); } /* At this point it seems we have a data message we want to process */ ccnb = info->content_ccnb; ccnb_size = info->pco->offset[CCN_PCO_E]; /* spit out some debug information */ for (i = 0; i < 5; ++i) { GST_DEBUG ("%3d: ", i); if (0 > ccn_name_comp_get (info->content_ccnb, info->content_comps, i, &cp, &sz)) { // fprintf(stderr, "could not get comp\n"); } else { // hDump( DUMP_ADDR( cp ), DUMP_SIZE( sz ) ); } } /* go get the data and process it...note that the data pointer here is only temporary, a copy is needed to keep the data */ ib = info->interest_ccnb; ic = info->interest_comps; res = ccn_content_get_value (ccnb, ccnb_size, info->pco, &data, &data_size); if (res < 0) { GST_LOG_OBJECT (me, "CCN error on get value of size"); process_or_queue (me, segment, NULL, 0, FALSE); // process null block to adjust interest array queue post_next_interest (me); // Keep the data flowing return (CCN_UPCALL_RESULT_ERR); } /* was this the last block? [code taken from a ccnx tool */ /* \todo the test below should get refactored into the library */ if (info->pco->offset[CCN_PCO_B_FinalBlockID] != info->pco->offset[CCN_PCO_E_FinalBlockID]) { const unsigned char *finalid = NULL; size_t finalid_size = 0; const unsigned char *nameid = NULL; size_t nameid_size = 0; struct ccn_indexbuf *cc = info->content_comps; ccn_ref_tagged_BLOB (CCN_DTAG_FinalBlockID, ccnb, info->pco->offset[CCN_PCO_B_FinalBlockID], info->pco->offset[CCN_PCO_E_FinalBlockID], &finalid, &finalid_size); if (cc->n < 2) abort (); // \todo we need to behave better than this ccn_ref_tagged_BLOB (CCN_DTAG_Component, ccnb, cc->buf[cc->n - 2], cc->buf[cc->n - 1], &nameid, &nameid_size); if (finalid_size == nameid_size && 0 == memcmp (finalid, nameid, nameid_size)) { b_last = TRUE; } } /* a short block can also indicate the end, if the client isn't using FinalBlockID */ if (data_size < CCN_CHUNK_SIZE) b_last = TRUE; /* something to process */ process_or_queue (me, segment, data, data_size, b_last); post_next_interest (me); if (!b_last) return post_next_interest (me); return (CCN_UPCALL_RESULT_OK); }
/** * Load a link to the repo policy from the repoPolicy file and load the link * target to extract the actual policy. * If a policy file does not exist a new one is created, with a link to a policy * based either on the environment variable CCNR_GLOBAL_PREFIX or the system * default value of ccnx:/parc.com/csl/ccn/Repos, plus the system defaults for * other fields. * This routine must be called after the btree code is initialized and capable * of returning content objects. * Sets the parsed_policy field of the handle to be the new policy. */ static int load_policy(struct ccnr_handle *ccnr) { int fd; ssize_t res; struct content_entry *content = NULL; const unsigned char *content_msg = NULL; struct ccn_parsed_ContentObject pco = {0}; struct ccn_parsed_Link pl = {0}; struct ccn_indexbuf *nc = NULL; struct ccn_charbuf *basename = NULL; struct ccn_charbuf *policy = NULL; struct ccn_charbuf *policy_cob = NULL; struct ccn_charbuf *policyFileName; const char *global_prefix; const unsigned char *buf = NULL; size_t length = 0; int segment = 0; int final = 0; struct ccn_buf_decoder decoder; struct ccn_buf_decoder *d; policyFileName = ccn_charbuf_create(); ccn_charbuf_putf(policyFileName, "%s/repoPolicy", ccnr->directory); ccnr->parsed_policy = ccnr_parsed_policy_create(); fd = open(ccn_charbuf_as_string(policyFileName), O_RDONLY); if (fd >= 0) { ccnr->policy_link_cob = ccn_charbuf_create(); ccn_charbuf_reserve(ccnr->policy_link_cob, 4096); // limits the size of the policy link ccnr->policy_link_cob->length = 0; // clear the buffer res = read(fd, ccnr->policy_link_cob->buf, ccnr->policy_link_cob->limit - ccnr->policy_link_cob->length); close(fd); if (res == -1) { r_init_fail(ccnr, __LINE__, "Error reading repoPolicy file.", errno); ccn_charbuf_destroy(&ccnr->policy_link_cob); ccn_charbuf_destroy(&policyFileName); return(-1); } ccnr->policy_link_cob->length = res; nc = ccn_indexbuf_create(); res = ccn_parse_ContentObject(ccnr->policy_link_cob->buf, ccnr->policy_link_cob->length, &pco, nc); res = ccn_ref_tagged_BLOB(CCN_DTAG_Content, ccnr->policy_link_cob->buf, pco.offset[CCN_PCO_B_Content], pco.offset[CCN_PCO_E_Content], &buf, &length); d = ccn_buf_decoder_start(&decoder, buf, length); res = ccn_parse_Link(d, &pl, NULL); if (res <= 0) { ccnr_msg(ccnr, "Policy link is malformed."); goto CreateNewPolicy; } basename = ccn_charbuf_create(); ccn_charbuf_append(basename, buf + pl.offset[CCN_PL_B_Name], pl.offset[CCN_PL_E_Name] - pl.offset[CCN_PL_B_Name]); ccnr->policy_name = ccn_charbuf_create(); // to detect writes to this name ccn_charbuf_append_charbuf(ccnr->policy_name, basename); // has version ccn_name_chop(ccnr->policy_name, NULL, -1); // get rid of version policy = ccn_charbuf_create(); // if we fail to retrieve the link target, report and then create a new one do { ccn_name_append_numeric(basename, CCN_MARKER_SEQNUM, segment++); content = r_store_lookup_ccnb(ccnr, basename->buf, basename->length); if (content == NULL) { ccnr_debug_ccnb(ccnr, __LINE__, "policy lookup failed for", NULL, basename->buf, basename->length); break; } ccn_name_chop(basename, NULL, -1); content_msg = r_store_content_base(ccnr, content); if (content_msg == NULL) { ccnr_debug_ccnb(ccnr, __LINE__, "Unable to read policy object", NULL, basename->buf, basename->length); break; } res = ccn_parse_ContentObject(content_msg, r_store_content_size(ccnr, content), &pco, nc); res = ccn_ref_tagged_BLOB(CCN_DTAG_Content, content_msg, pco.offset[CCN_PCO_B_Content], pco.offset[CCN_PCO_E_Content], &buf, &length); ccn_charbuf_append(policy, buf, length); final = ccn_is_final_pco(content_msg, &pco, nc); } while (!final && segment < 100);
static int dissect_ccn_interest(const unsigned char *ccnb, size_t ccnb_size, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *name_tree; proto_tree *exclude_tree; proto_item *titem; struct ccn_parsed_interest interest; struct ccn_parsed_interest *pi = &interest; struct ccn_charbuf *c; struct ccn_indexbuf *comps; const unsigned char *comp; size_t comp_size; const unsigned char *blob; size_t blob_size; ssize_t l; unsigned int i; int res; comps = ccn_indexbuf_create(); res = ccn_parse_interest(ccnb, ccnb_size, pi, comps); /* Name */ l = pi->offset[CCN_PI_E_Name] - pi->offset[CCN_PI_B_Name]; c = ccn_charbuf_create(); ccn_uri_append(c, ccnb, ccnb_size, 1); titem = proto_tree_add_string(tree, hf_ccn_name, tvb, pi->offset[CCN_PI_B_Name], l, ccn_charbuf_as_string(c)); name_tree = proto_item_add_subtree(titem, ett_name); ccn_charbuf_destroy(&c); for (i = 0; i < comps->n - 1; i++) { res = ccn_name_comp_get(ccnb, comps, i, &comp, &comp_size); titem = proto_tree_add_item(name_tree, hf_ccn_name_components, tvb, comp - ccnb, comp_size, FALSE); } /* MinSuffixComponents */ l = pi->offset[CCN_PI_E_MinSuffixComponents] - pi->offset[CCN_PI_B_MinSuffixComponents]; if (l > 0) { i = pi->min_suffix_comps; titem = proto_tree_add_uint(tree, hf_ccn_minsuffixcomponents, tvb, pi->offset[CCN_PI_B_MinSuffixComponents], l, i); } /* MaxSuffixComponents */ l = pi->offset[CCN_PI_E_MaxSuffixComponents] - pi->offset[CCN_PI_B_MaxSuffixComponents]; if (l > 0) { i = pi->max_suffix_comps; titem = proto_tree_add_uint(tree, hf_ccn_maxsuffixcomponents, tvb, pi->offset[CCN_PI_B_MaxSuffixComponents], l, i); } /* PublisherIDKeyDigest? */ /* Exclude */ l = pi->offset[CCN_PI_E_Exclude] - pi->offset[CCN_PI_B_Exclude]; if (l > 0) { titem = proto_tree_add_text(tree, tvb, pi->offset[CCN_PI_B_Exclude], l, "Exclude"); exclude_tree = proto_item_add_subtree(titem, ett_exclude); } /* ChildSelector */ l = pi->offset[CCN_PI_E_ChildSelector] - pi->offset[CCN_PI_B_ChildSelector]; if (l > 0) { i = pi->orderpref; titem = proto_tree_add_uint(tree, hf_ccn_childselector, tvb, pi->offset[CCN_PI_B_ChildSelector], l, i); proto_item_append_text(titem, ", %s", val_to_str(i & 1, VALS(childselectordirection_vals), "")); } /* AnswerOriginKind */ l = pi->offset[CCN_PI_E_AnswerOriginKind] - pi->offset[CCN_PI_B_AnswerOriginKind]; if (l > 0) { i = pi->answerfrom; titem = proto_tree_add_uint(tree, hf_ccn_answeroriginkind, tvb, pi->offset[CCN_PI_B_AnswerOriginKind], l, i); } /* Scope */ l = pi->offset[CCN_PI_E_Scope] - pi->offset[CCN_PI_B_Scope]; if (l > 0) { i = pi->scope; titem = proto_tree_add_uint(tree, hf_ccn_scope, tvb, pi->offset[CCN_PI_B_Scope], l, i); } /* Nonce */ /* Nonce */ l = pi->offset[CCN_PI_E_Nonce] - pi->offset[CCN_PI_B_Nonce]; if (l > 0) { i = ccn_ref_tagged_BLOB(CCN_DTAG_Nonce, ccnb, pi->offset[CCN_PI_B_Nonce], pi->offset[CCN_PI_E_Nonce], &blob, &blob_size); if (check_col(pinfo->cinfo, COL_INFO)) { col_append_str(pinfo->cinfo, COL_INFO, ", <"); for (i = 0; i < blob_size; i++) col_append_fstr(pinfo->cinfo, COL_INFO, "%02x", blob[i]); col_append_str(pinfo->cinfo, COL_INFO, ">"); } titem = proto_tree_add_item(tree, hf_ccn_nonce, tvb, blob - ccnb, blob_size, FALSE); } return (1); }
PyObject * SignedInfo_obj_from_ccn(PyObject *py_signed_info) { struct ccn_charbuf *signed_info; PyObject *py_obj_SignedInfo, *py_o; struct ccn_buf_decoder decoder, *d; size_t start, stop, size; const unsigned char *ptr; int r; signed_info = CCNObject_Get(SIGNED_INFO, py_signed_info); debug("SignedInfo_from_ccn start, size=%zd\n", signed_info->length); // 1) Create python object py_obj_SignedInfo = PyObject_CallObject(g_type_SignedInfo, NULL); if (!py_obj_SignedInfo) return NULL; // 2) Set ccn_data to a cobject pointing to the c struct // and ensure proper destructor is set up for the c object. r = PyObject_SetAttrString(py_obj_SignedInfo, "ccn_data", py_signed_info); JUMP_IF_NEG(r, error); // 3) Parse c structure and fill python attributes // using PyObject_SetAttrString // based on chk_signing_params // from ccn_client.c // //outputs: // Note, it is ok that non-filled optional elements // are initialized to None (through the .py file __init__) // d = ccn_buf_decoder_start(&decoder, signed_info->buf, signed_info->length); if (!ccn_buf_match_dtag(d, CCN_DTAG_SignedInfo)) { PyErr_Format(g_PyExc_CCNSignedInfoError, "Error finding" " CCN_DTAG_SignedInfo (decoder state: %d)", d->decoder.state); goto error; } ccn_buf_advance(d); /* PublisherPublic Key */ //XXX: should we check for case when PublishePublicKeyDigest is not present? -dk start = d->decoder.token_index; ccn_parse_required_tagged_BLOB(d, CCN_DTAG_PublisherPublicKeyDigest, 16, 64); stop = d->decoder.token_index; r = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest, d->buf, start, stop, &ptr, &size); if (r < 0) { PyErr_Format(g_PyExc_CCNSignedInfoError, "Error parsing" " CCN_DTAG_PublisherPublicKey (decoder state %d)", d->decoder.state); goto error; } // self.publisherPublicKeyDigest = None # SHA256 hash debug("PyObject_SetAttrString publisherPublicKeyDigest\n"); py_o = PyBytes_FromStringAndSize((const char*) ptr, size); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_SignedInfo, "publisherPublicKeyDigest", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); /* Timestamp */ start = d->decoder.token_index; ccn_parse_required_tagged_BLOB(d, CCN_DTAG_Timestamp, 1, -1); stop = d->decoder.token_index; r = ccn_ref_tagged_BLOB(CCN_DTAG_Timestamp, d->buf, start, stop, &ptr, &size); if (r < 0) { PyErr_Format(g_PyExc_CCNSignedInfoError, "Error parsing" " CCN_DTAG_Timestamp (decoder state %d)", d->decoder.state); goto error; } // self.timeStamp = None # CCNx timestamp debug("PyObject_SetAttrString timeStamp\n"); py_o = PyBytes_FromStringAndSize((const char*) ptr, size); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_SignedInfo, "timeStamp", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); /* Type */ assert(d->decoder.state >= 0); r = ccn_parse_optional_tagged_binary_number(d, CCN_DTAG_Type, 3, 3, CCN_CONTENT_DATA); if (d->decoder.state < 0) { PyErr_SetString(g_PyExc_CCNSignedInfoError, "Unable to parse type"); goto error; } py_o = _pyccn_Int_FromLong(r); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_SignedInfo, "type", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); /* start = d->decoder.token_index; ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_Type, 1, -1); stop = d->decoder.token_index; r = ccn_ref_tagged_BLOB(CCN_DTAG_Type, d->buf, start, stop, &ptr, &size); if (r == 0) { // type = None # CCNx type // TODO: Provide a string representation with the Base64 mnemonic? debug("PyObject_SetAttrString type\n"); py_o = PyByteArray_FromStringAndSize((const char*) ptr, size); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_SignedInfo, "type", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); } */ /* FreshnessSeconds */ r = ccn_parse_optional_tagged_nonNegativeInteger(d, CCN_DTAG_FreshnessSeconds); if (r >= 0) { // self.freshnessSeconds = None debug("PyObject_SetAttrString freshnessSeconds\n"); py_o = _pyccn_Int_FromLong(r); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_SignedInfo, "freshnessSeconds", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); } /* FinalBlockID */ #if 0 /* old code (left in case mine is wrong - dk) */ if (ccn_buf_match_dtag(d, CCN_DTAG_FinalBlockID)) { ccn_buf_advance(d); start = d->decoder.token_index; if (ccn_buf_match_some_blob(d)) ccn_buf_advance(d); stop = d->decoder.token_index; ccn_buf_check_close(d); if (d->decoder.state >= 0 && stop > start) { // self.finalBlockID = None fprintf(stderr, "PyObject_SetAttrString finalBlockID, len=%zd\n", stop - start); py_o = PyByteArray_FromStringAndSize((const char*) (d->buf + start), stop - start); PyObject_SetAttrString(py_obj_SignedInfo, "finalBlockID", py_o); Py_INCREF(py_o); } } #endif start = d->decoder.token_index; ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_FinalBlockID, 1, -1); stop = d->decoder.token_index; r = ccn_ref_tagged_BLOB(CCN_DTAG_FinalBlockID, d->buf, start, stop, &ptr, &size); if (r == 0) { // self.finalBlockID = None debug("PyObject_SetAttrString finalBlockID, len=%zd\n", size); py_o = PyBytes_FromStringAndSize((const char*) ptr, size); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_SignedInfo, "finalBlockID", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); } /* KeyLocator */ #if 0 /* Old code in case mine is wrong - dk */ start = d->decoder.token_index; if (ccn_buf_match_dtag(d, CCN_DTAG_KeyLocator)) ccn_buf_advance_past_element(d); stop = d->decoder.token_index; if (d->decoder.state >= 0 && stop > start) { fprintf(stderr, "PyObject_SetAttrString keyLocator, len=%zd\n", stop - start); struct ccn_charbuf* keyLocator = ccn_charbuf_create(); ccn_charbuf_append(keyLocator, d->buf + start, stop - start); // self.keyLocator = None py_o = KeyLocator_obj_from_ccn(keyLocator); // it will free PyObject_SetAttrString(py_obj_SignedInfo, "keyLocator", py_o); Py_INCREF(py_o); } #endif /* * KeyLocator is not a BLOB, but an another structure, this requires * us to parse it differently */ start = d->decoder.token_index; if (ccn_buf_match_dtag(d, CCN_DTAG_KeyLocator)) { struct ccn_charbuf *key_locator; PyObject *py_key_locator; r = ccn_buf_advance_past_element(d); if (r < 0) { PyErr_Format(g_PyExc_CCNSignedInfoError, "Error locating" " CCN_DTAG_KeyLocator (decoder state: %d, r: %d)", d->decoder.state, r); goto error; } stop = d->decoder.token_index; /* debug("element_index = %zd size = %zd nest = %d numval = %zd state = %d" " token_index %zd\n", d->decoder.element_index, d->decoder.index, d->decoder.nest, d->decoder.numval, d->decoder.state, d->decoder.token_index); assert(d->decoder.state >= 0); */ ptr = d->buf + start; size = stop - start; assert(size > 0); debug("PyObject_SetAttrString keyLocator, len=%zd\n", size); py_key_locator = CCNObject_New_charbuf(KEY_LOCATOR, &key_locator); JUMP_IF_NULL(py_key_locator, error); r = ccn_charbuf_append(key_locator, ptr, size); if (r < 0) { Py_DECREF(py_key_locator); PyErr_NoMemory(); goto error; } // self.keyLocator = None py_o = KeyLocator_obj_from_ccn(py_key_locator); Py_DECREF(py_key_locator); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_SignedInfo, "keyLocator", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); } ccn_buf_check_close(d); if (d->decoder.state < 0) { PyErr_Format(g_PyExc_CCNSignedInfoError, "SignedInfo decoding error" " (decoder state: %d, numval: %zd)", d->decoder.state, d->decoder.numval); goto error; } // 4) Return the created object debug("SignedInfo_from_ccn ends\n"); return py_obj_SignedInfo; error: Py_DECREF(py_obj_SignedInfo); return NULL; }
int ccn_verify_signature(const unsigned char *msg, size_t size, const struct ccn_parsed_ContentObject *co, const struct ccn_pkey *verification_pubkey) { EVP_MD_CTX verc; EVP_MD_CTX *ver_ctx = &verc; X509_SIG *digest_info = NULL; MP_info *merkle_path_info = NULL; unsigned char *root_hash; size_t root_hash_size; int res; const EVP_MD *digest = EVP_md_null(); const EVP_MD *merkle_path_digest = EVP_md_null(); const unsigned char *signature_bits = NULL; size_t signature_bits_size = 0; const unsigned char *witness = NULL; size_t witness_size = 0; EVP_PKEY *pkey = (EVP_PKEY *)verification_pubkey; #ifdef DEBUG int x, h; #endif res = ccn_ref_tagged_BLOB(CCN_DTAG_SignatureBits, msg, co->offset[CCN_PCO_B_SignatureBits], co->offset[CCN_PCO_E_SignatureBits], &signature_bits, &signature_bits_size); if (res < 0) return (-1); if (co->offset[CCN_PCO_B_DigestAlgorithm] == co->offset[CCN_PCO_E_DigestAlgorithm]) { digest = EVP_sha256(); } else { /* XXX - figure out what algorithm the OID represents */ fprintf(stderr, "not a DigestAlgorithm I understand right now\n"); return (-1); } EVP_MD_CTX_init(ver_ctx); res = EVP_VerifyInit_ex(ver_ctx, digest, NULL); if (!res) return (-1); if (co->offset[CCN_PCO_B_Witness] != co->offset[CCN_PCO_E_Witness]) { /* The witness is a DigestInfo, where the octet-string therein encapsulates * a sequence of [integer (origin 1 node#), sequence of [octet-string]] * where the inner octet-string is the concatenated hashes on the merkle-path */ res = ccn_ref_tagged_BLOB(CCN_DTAG_Witness, msg, co->offset[CCN_PCO_B_Witness], co->offset[CCN_PCO_E_Witness], &witness, &witness_size); if (res < 0) return (-1); digest_info = d2i_X509_SIG(NULL, &witness, witness_size); /* digest_info->algor->algorithm->{length, data} * digest_info->digest->{length, type, data} */ /* ...2.2 is an MHT w/ SHA256 */ ASN1_OBJECT *merkle_hash_tree_oid = OBJ_txt2obj("1.2.840.113550.11.1.2.2", 1); if (0 != OBJ_cmp(digest_info->algor->algorithm, merkle_hash_tree_oid)) { fprintf(stderr, "A witness is present without an MHT OID!\n"); ASN1_OBJECT_free(merkle_hash_tree_oid); return (-1); } /* we're doing an MHT */ ASN1_OBJECT_free(merkle_hash_tree_oid); merkle_path_digest = EVP_sha256(); /* DER-encoded in the digest_info's digest ASN.1 octet string is the Merkle path info */ merkle_path_info = d2i_MP_info(NULL, (const unsigned char **)&(digest_info->digest->data), digest_info->digest->length); #ifdef DEBUG int node = ASN1_INTEGER_get(merkle_path_info->node); int hash_count = merkle_path_info->hashes->num; ASN1_OCTET_STRING *hash; fprintf(stderr, "A witness is present with an MHT OID\n"); fprintf(stderr, "This is node %d, with %d hashes\n", node, hash_count); for (h = 0; h < hash_count; h++) { hash = (ASN1_OCTET_STRING *)merkle_path_info->hashes->data[h]; fprintf(stderr, " hashes[%d] len = %d data = ", h, hash->length); for (x = 0; x < hash->length; x++) { fprintf(stderr, "%02x", hash->data[x]); } fprintf(stderr, "\n"); } #endif /* In the MHT signature case, we signed/verify the root hash */ root_hash_size = EVP_MD_size(merkle_path_digest); root_hash = calloc(1, root_hash_size); res = ccn_merkle_root_hash(msg, size, co, merkle_path_digest, merkle_path_info, root_hash, root_hash_size); res = EVP_VerifyUpdate(ver_ctx, root_hash, root_hash_size); res = EVP_VerifyFinal(ver_ctx, signature_bits, signature_bits_size, pkey); EVP_MD_CTX_cleanup(ver_ctx); } else { /* * In the simple signature case, we signed/verify from the name through * the end of the content. */ size_t signed_size = co->offset[CCN_PCO_E_Content] - co->offset[CCN_PCO_B_Name]; res = EVP_VerifyUpdate(ver_ctx, msg + co->offset[CCN_PCO_B_Name], signed_size); res = EVP_VerifyFinal(ver_ctx, signature_bits, signature_bits_size, pkey); EVP_MD_CTX_cleanup(ver_ctx); } if (res == 1) return (1); else return (0); }
static int dissect_ccn_interest(const unsigned char *ccnb, size_t ccnb_size, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { proto_tree *name_tree; proto_tree *exclude_tree; proto_item *titem; struct ccn_parsed_interest interest; struct ccn_parsed_interest *pi = &interest; struct ccn_buf_decoder decoder; struct ccn_buf_decoder *d; const unsigned char *bloom; size_t bloom_size = 0; struct ccn_charbuf *c; struct ccn_indexbuf *comps; const unsigned char *comp; size_t comp_size; const unsigned char *blob; size_t blob_size; ssize_t l; unsigned int i; double lifetime; int res; comps = ccn_indexbuf_create(); res = ccn_parse_interest(ccnb, ccnb_size, pi, comps); if (res < 0) return (res); /* Name */ l = pi->offset[CCN_PI_E_Name] - pi->offset[CCN_PI_B_Name]; c = ccn_charbuf_create(); ccn_uri_append(c, ccnb, ccnb_size, 1); titem = proto_tree_add_string(tree, hf_ccn_name, tvb, pi->offset[CCN_PI_B_Name], l, ccn_charbuf_as_string(c)); name_tree = proto_item_add_subtree(titem, ett_name); ccn_charbuf_destroy(&c); for (i = 0; i < comps->n - 1; i++) { res = ccn_name_comp_get(ccnb, comps, i, &comp, &comp_size); titem = proto_tree_add_item(name_tree, hf_ccn_name_components, tvb, comp - ccnb, comp_size, FALSE); } /* MinSuffixComponents */ l = pi->offset[CCN_PI_E_MinSuffixComponents] - pi->offset[CCN_PI_B_MinSuffixComponents]; if (l > 0) { i = pi->min_suffix_comps; titem = proto_tree_add_uint(tree, hf_ccn_minsuffixcomponents, tvb, pi->offset[CCN_PI_B_MinSuffixComponents], l, i); } /* MaxSuffixComponents */ l = pi->offset[CCN_PI_E_MaxSuffixComponents] - pi->offset[CCN_PI_B_MaxSuffixComponents]; if (l > 0) { i = pi->max_suffix_comps; titem = proto_tree_add_uint(tree, hf_ccn_maxsuffixcomponents, tvb, pi->offset[CCN_PI_B_MaxSuffixComponents], l, i); } /* PublisherPublicKeyDigest */ /* Exclude */ l = pi->offset[CCN_PI_E_Exclude] - pi->offset[CCN_PI_B_Exclude]; if (l > 0) { c = ccn_charbuf_create(); d = ccn_buf_decoder_start(&decoder, ccnb + pi->offset[CCN_PI_B_Exclude], l); if (!ccn_buf_match_dtag(d, CCN_DTAG_Exclude)) { ccn_charbuf_destroy(&c); return(-1); } ccn_charbuf_append_string(c, "Exclude: "); ccn_buf_advance(d); if (ccn_buf_match_dtag(d, CCN_DTAG_Any)) { ccn_buf_advance(d); ccn_charbuf_append_string(c, "* "); ccn_buf_check_close(d); } else if (ccn_buf_match_dtag(d, CCN_DTAG_Bloom)) { ccn_buf_advance(d); if (ccn_buf_match_blob(d, &bloom, &bloom_size)) ccn_buf_advance(d); ccn_charbuf_append_string(c, "? "); ccn_buf_check_close(d); } while (ccn_buf_match_dtag(d, CCN_DTAG_Component)) { ccn_buf_advance(d); comp_size = 0; if (ccn_buf_match_blob(d, &comp, &comp_size)) ccn_buf_advance(d); ccn_uri_append_percentescaped(c, comp, comp_size); ccn_charbuf_append_string(c, " "); ccn_buf_check_close(d); if (ccn_buf_match_dtag(d, CCN_DTAG_Any)) { ccn_buf_advance(d); ccn_charbuf_append_string(c, "* "); ccn_buf_check_close(d); } else if (ccn_buf_match_dtag(d, CCN_DTAG_Bloom)) { ccn_buf_advance(d); if (ccn_buf_match_blob(d, &bloom, &bloom_size)) ccn_buf_advance(d); ccn_charbuf_append_string(c, "? "); ccn_buf_check_close(d); } } titem = proto_tree_add_text(tree, tvb, pi->offset[CCN_PI_B_Exclude], l, "%s", ccn_charbuf_as_string(c)); exclude_tree = proto_item_add_subtree(titem, ett_exclude); ccn_charbuf_destroy(&c); } /* ChildSelector */ l = pi->offset[CCN_PI_E_ChildSelector] - pi->offset[CCN_PI_B_ChildSelector]; if (l > 0) { i = pi->orderpref; titem = proto_tree_add_uint(tree, hf_ccn_childselector, tvb, pi->offset[CCN_PI_B_ChildSelector], l, i); proto_item_append_text(titem, ", %s", val_to_str(i & 1, VALS(childselectordirection_vals), "")); } /* AnswerOriginKind */ l = pi->offset[CCN_PI_E_AnswerOriginKind] - pi->offset[CCN_PI_B_AnswerOriginKind]; if (l > 0) { i = pi->answerfrom; titem = proto_tree_add_uint(tree, hf_ccn_answeroriginkind, tvb, pi->offset[CCN_PI_B_AnswerOriginKind], l, i); } /* Scope */ l = pi->offset[CCN_PI_E_Scope] - pi->offset[CCN_PI_B_Scope]; if (l > 0) { i = pi->scope; titem = proto_tree_add_uint(tree, hf_ccn_scope, tvb, pi->offset[CCN_PI_B_Scope], l, i); } /* InterestLifetime */ l = pi->offset[CCN_PI_E_InterestLifetime] - pi->offset[CCN_PI_B_InterestLifetime]; if (l > 0) { i = ccn_ref_tagged_BLOB(CCN_DTAG_InterestLifetime, ccnb, pi->offset[CCN_PI_B_InterestLifetime], pi->offset[CCN_PI_E_InterestLifetime], &blob, &blob_size); lifetime = 0.0; for (i = 0; i < blob_size; i++) lifetime = lifetime * 256.0 + (double)blob[i]; lifetime /= 4096.0; titem = proto_tree_add_double(tree, hf_ccn_interestlifetime, tvb, blob - ccnb, blob_size, lifetime); } /* Nonce */ l = pi->offset[CCN_PI_E_Nonce] - pi->offset[CCN_PI_B_Nonce]; if (l > 0) { i = ccn_ref_tagged_BLOB(CCN_DTAG_Nonce, ccnb, pi->offset[CCN_PI_B_Nonce], pi->offset[CCN_PI_E_Nonce], &blob, &blob_size); if (check_col(pinfo->cinfo, COL_INFO)) { col_append_str(pinfo->cinfo, COL_INFO, ", <"); for (i = 0; i < blob_size; i++) col_append_fstr(pinfo->cinfo, COL_INFO, "%02x", blob[i]); col_append_str(pinfo->cinfo, COL_INFO, ">"); } titem = proto_tree_add_item(tree, hf_ccn_nonce, tvb, blob - ccnb, blob_size, FALSE); } return (1); }
PyObject * Signature_obj_from_ccn(PyObject *py_signature) { struct ccn_charbuf *signature; PyObject *py_obj_signature, *py_o; struct ccn_buf_decoder decoder, *d; size_t start, stop, size; const unsigned char *ptr; int r; assert(CCNObject_IsValid(SIGNATURE, py_signature)); signature = CCNObject_Get(SIGNATURE, py_signature); debug("Signature_from_ccn start, len=%zd\n", signature->length); // 1) Create python object py_obj_signature = PyObject_CallObject(g_type_Signature, NULL); if (!py_obj_signature) return NULL; // 2) Set ccn_data to a cobject pointing to the c struct // and ensure proper destructor is set up for the c object. r = PyObject_SetAttrString(py_obj_signature, "ccn_data", py_signature); JUMP_IF_NEG(r, error); // 3) Parse c structure and fill python attributes // Neither DigestAlgorithm nor Witness are included in the packet // from ccnput, so they are apparently both optional d = ccn_buf_decoder_start(&decoder, signature->buf, signature->length); if (!ccn_buf_match_dtag(d, CCN_DTAG_Signature)) { PyErr_Format(g_PyExc_CCNSignatureError, "Error finding" " CCN_DTAG_Signature (decoder state: %d)", d->decoder.state); goto error; } debug("Is a signature\n"); ccn_buf_advance(d); /* CCN_DTAG_DigestAlgorithm */ start = d->decoder.token_index; ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_DigestAlgorithm, 1, -1); stop = d->decoder.token_index; r = ccn_ref_tagged_BLOB(CCN_DTAG_DigestAlgorithm, d->buf, start, stop, &ptr, &size); if (r == 0) { debug("PyObject_SetAttrString digestAlgorithm\n"); py_o = PyBytes_FromStringAndSize((const char*) ptr, size); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_signature, "digestAlgorithm", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); } /* CCN_DTAG_Witness */ start = d->decoder.token_index; ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_Witness, 1, -1); stop = d->decoder.token_index; debug("witness start %zd stop %zd\n", start, stop); r = ccn_ref_tagged_BLOB(CCN_DTAG_Witness, d->buf, start, stop, &ptr, &size); if (r == 0) { // The Witness is represented as a DER-encoded PKCS#1 DigestInfo, // which contains an AlgorithmIdentifier (an OID, together with any necessary parameters) // and a byte array (OCTET STRING) containing the digest information to be interpreted according to that OID. // http://www.ccnx.org/releases/latest/doc/technical/SignatureGeneration.html debug("PyObject_SetAttrString witness\n"); py_o = PyBytes_FromStringAndSize((const char*) ptr, size); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_signature, "witness", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); } /* CCN_DTAG_SignatureBits */ start = d->decoder.token_index; ccn_parse_required_tagged_BLOB(d, CCN_DTAG_SignatureBits, 1, -1); stop = d->decoder.token_index; r = ccn_ref_tagged_BLOB(CCN_DTAG_SignatureBits, d->buf, start, stop, &ptr, &size); if (r < 0) { PyErr_Format(g_PyExc_CCNSignatureError, "Error parsing" " CCN_DTAG_SignatureBits (decoder state %d)", d->decoder.state); goto error; } assert(r == 0); debug("PyObject_SetAttrString signatureBits\n"); py_o = PyBytes_FromStringAndSize((const char*) ptr, size); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_signature, "signatureBits", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); ccn_buf_check_close(d); if (d->decoder.state < 0) { PyErr_Format(g_PyExc_CCNSignatureError, "Signature decoding error" " (decoder state: %d, numval: %zd)", d->decoder.state, d->decoder.numval); goto error; } // 4) Return the created object debug("Signature_from_ccn ends\n"); return py_obj_signature; error: Py_DECREF(py_obj_signature); return NULL; }
PyObject * Interest_obj_from_ccn(PyObject *py_interest) { struct ccn_charbuf *interest; struct ccn_parsed_interest *pi; PyObject *py_obj_Interest, *py_o; int r; debug("Interest_from_ccn_parsed start\n"); interest = CCNObject_Get(INTEREST, py_interest); // 1) Create python object py_obj_Interest = PyObject_CallObject(g_type_Interest, NULL); if (!py_obj_Interest) return NULL; pi = _pyccn_interest_get_pi(py_interest); JUMP_IF_NULL(pi, error); // 2) Set ccn_data to a cobject pointing to the c struct // and ensure proper destructor is set up for the c object. r = PyObject_SetAttrString(py_obj_Interest, "ccn_data", py_interest); JUMP_IF_NEG(r, error); // 3) Parse c structure and fill python attributes // using PyObject_SetAttrString ssize_t len; const unsigned char *blob; size_t blob_size, start, end; struct ccn_charbuf * cb; // Best decoding examples are in packet-ccn.c for wireshark plugin? // self.name = None # Start from None to use for templates? len = pi->offset[CCN_PI_E_Name] - pi->offset[CCN_PI_B_Name]; if (len > 0) { PyObject *py_cname; py_cname = CCNObject_New_charbuf(NAME, &cb); JUMP_IF_NULL(py_cname, error); r = ccn_charbuf_append(cb, interest->buf + pi->offset[CCN_PI_B_Name], len); JUMP_IF_NEG_MEM(r, error); py_o = Name_obj_from_ccn(py_cname); Py_DECREF(py_cname); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_Interest, "name", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); } else { PyErr_SetString(g_PyExc_CCNInterestError, "Got interest without a" " name!"); goto error; } // self.minSuffixComponents = None # default 0 len = pi->offset[CCN_PI_E_MinSuffixComponents] - pi->offset[CCN_PI_B_MinSuffixComponents]; if (len > 0) { r = ccn_fetch_tagged_nonNegativeInteger(CCN_DTAG_MinSuffixComponents, interest->buf, pi->offset[CCN_PI_B_MinSuffixComponents], pi->offset[CCN_PI_E_MinSuffixComponents]); if (r < 0) { PyErr_SetString(g_PyExc_CCNInterestError, "Invalid" " MinSuffixComponents value"); goto error; } py_o = _pyccn_Int_FromLong(r); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_Interest, "minSuffixComponents", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); } // self.maxSuffixComponents = None # default infinity len = pi->offset[CCN_PI_E_MaxSuffixComponents] - pi->offset[CCN_PI_B_MaxSuffixComponents]; if (len > 0) { r = ccn_fetch_tagged_nonNegativeInteger(CCN_DTAG_MaxSuffixComponents, interest->buf, pi->offset[CCN_PI_B_MaxSuffixComponents], pi->offset[CCN_PI_E_MaxSuffixComponents]); if (r < 0) { PyErr_SetString(g_PyExc_CCNInterestError, "Invalid" " MaxSuffixComponents value"); goto error; } py_o = _pyccn_Int_FromLong(r); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_Interest, "maxSuffixComponents", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); } // self.publisherPublicKeyDigest = None # SHA256 hash // TODO: what is CN_PI_B_PublisherID? -- looks like it is the data including // the tags while PublisherIDKeyDigest // is just the raw digest -- dk start = pi->offset[CCN_PI_B_PublisherID]; end = pi->offset[CCN_PI_E_PublisherID]; len = end - start; if (len > 0) { r = ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest, interest->buf, start, end, &blob, &blob_size); if (r < 0) { PyErr_SetString(g_PyExc_CCNInterestError, "Invalid" " PublisherPublicKeyDigest value"); goto error; } py_o = PyBytes_FromStringAndSize((const char*) blob, blob_size); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_Interest, "publisherPublicKeyDigest", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); } // self.exclude = None len = pi->offset[CCN_PI_E_Exclude] - pi->offset[CCN_PI_B_Exclude]; if (len > 0) { PyObject *py_exclusion_filter; py_exclusion_filter = CCNObject_New_charbuf(EXCLUSION_FILTER, &cb); JUMP_IF_NULL(py_exclusion_filter, error); r = ccn_charbuf_append(cb, interest->buf + pi->offset[CCN_PI_B_Exclude], len); JUMP_IF_NEG_MEM(r, error); py_o = ExclusionFilter_obj_from_ccn(py_exclusion_filter); Py_DECREF(py_exclusion_filter); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_Interest, "exclude", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); } // self.childSelector = None len = pi->offset[CCN_PI_E_ChildSelector] - pi->offset[CCN_PI_B_ChildSelector]; if (len > 0) { r = ccn_fetch_tagged_nonNegativeInteger(CCN_DTAG_ChildSelector, interest->buf, pi->offset[CCN_PI_B_ChildSelector], pi->offset[CCN_PI_E_ChildSelector]); if (r < 0) { PyErr_SetString(g_PyExc_CCNInterestError, "Invalid" " ChildSelector value"); goto error; } py_o = _pyccn_Int_FromLong(r); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_Interest, "childSelector", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); } // self.answerOriginKind = None len = pi->offset[CCN_PI_E_AnswerOriginKind] - pi->offset[CCN_PI_B_AnswerOriginKind]; if (len > 0) { r = ccn_fetch_tagged_nonNegativeInteger(CCN_DTAG_AnswerOriginKind, interest->buf, pi->offset[CCN_PI_B_AnswerOriginKind], pi->offset[CCN_PI_E_AnswerOriginKind]); if (r < 0) { PyErr_SetString(g_PyExc_CCNInterestError, "Invalid" " AnswerOriginKind value"); goto error; } py_o = _pyccn_Int_FromLong(r); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_Interest, "answerOriginKind", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); } // self.scope = None len = pi->offset[CCN_PI_E_Scope] - pi->offset[CCN_PI_B_Scope]; if (len > 0) { r = ccn_fetch_tagged_nonNegativeInteger(CCN_DTAG_Scope, interest->buf, pi->offset[CCN_PI_B_Scope], pi->offset[CCN_PI_E_Scope]); if (r < 0) { PyErr_SetString(g_PyExc_CCNInterestError, "Invalid" " Scope value"); goto error; } py_o = _pyccn_Int_FromLong(r); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_Interest, "scope", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); } // self.interestLifetime = None len = pi->offset[CCN_PI_E_InterestLifetime] - pi->offset[CCN_PI_B_InterestLifetime]; if (len > 0) { double lifetime; // From packet-ccn.c r = ccn_ref_tagged_BLOB(CCN_DTAG_InterestLifetime, interest->buf, pi->offset[CCN_PI_B_InterestLifetime], pi->offset[CCN_PI_E_InterestLifetime], &blob, &blob_size); if (r < 0) { PyErr_SetString(g_PyExc_CCNInterestError, "Invalid" " InterestLifetime value"); goto error; } /* XXX: probably won't work with bigendian */ lifetime = 0.0; for (size_t i = 0; i < blob_size; i++) lifetime = lifetime * 256.0 + (double) blob[i]; lifetime /= 4096.0; py_o = PyFloat_FromDouble(lifetime); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_Interest, "interestLifetime", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); } // self.nonce = None len = pi->offset[CCN_PI_E_Nonce] - pi->offset[CCN_PI_B_Nonce]; if (len > 0) { r = ccn_ref_tagged_BLOB(CCN_DTAG_Nonce, interest->buf, pi->offset[CCN_PI_B_Nonce], pi->offset[CCN_PI_E_Nonce], &blob, &blob_size); if (r < 0) { PyErr_SetString(g_PyExc_CCNInterestError, "Invalid" " Nonce value"); goto error; } py_o = PyBytes_FromStringAndSize((const char *) blob, blob_size); JUMP_IF_NULL(py_o, error); r = PyObject_SetAttrString(py_obj_Interest, "nonce", py_o); Py_DECREF(py_o); JUMP_IF_NEG(r, error); } r = PyObject_SetAttrString(py_obj_Interest, "ccn_data_dirty", Py_False); JUMP_IF_NEG(r, error); // 4) Return the created object debug("Interest_from_ccn ends\n"); return py_obj_Interest; error: Py_DECREF(py_obj_Interest); return NULL; }
// creates a full structure without action, if proto == "face" only the // faceid (from cmd_host parameter) and lifetime will be filled in. struct ccn_face_instance * parse_ccn_face_instance(struct ccndc_data *self, const char *cmd_proto, const char *cmd_host, const char *cmd_port, const char *cmd_mcastttl, const char *cmd_mcastif, int freshness) { struct ccn_face_instance *entry; struct addrinfo hints = {.ai_family = AF_UNSPEC, .ai_flags = (AI_ADDRCONFIG)}; struct addrinfo mcasthints = {.ai_family = AF_UNSPEC, .ai_flags = (AI_ADDRCONFIG | AI_NUMERICHOST)}; struct addrinfo *raddrinfo = NULL; struct addrinfo *mcastifaddrinfo = NULL; char rhostnamebuf [NI_MAXHOST]; char rhostportbuf [NI_MAXSERV]; int off_address = -1, off_port = -1, off_source_address = -1; int res; int socktype; entry = calloc(1, sizeof(*entry)); if (entry == NULL) { ccndc_warn(__LINE__, "Fatal error: memory allocation failed"); goto ExitOnError; } // allocate storage for Face data entry->store = ccn_charbuf_create(); if (entry->store == NULL) { ccndc_warn(__LINE__, "Fatal error: memory allocation failed"); goto ExitOnError; } // copy static info entry->ccnd_id = (const unsigned char *)self->ccnd_id; entry->ccnd_id_size = self->ccnd_id_size; if (cmd_proto == NULL) { ccndc_warn(__LINE__, "command error, missing address type\n"); goto ExitOnError; } if (strcasecmp(cmd_proto, "udp") == 0) { entry->descr.ipproto = IPPROTO_UDP; socktype = SOCK_DGRAM; } else if (strcasecmp(cmd_proto, "tcp") == 0) { entry->descr.ipproto = IPPROTO_TCP; socktype = SOCK_STREAM; } else if (strcasecmp(cmd_proto, "face") == 0) { errno = 0; unsigned long faceid = strtoul(cmd_host, (char **)NULL, 10); if (errno == ERANGE || errno == EINVAL || faceid > UINT_MAX || faceid == 0) { ccndc_warn(__LINE__, "command error, face number invalid or out of range '%s'\n", cmd_host); goto ExitOnError; } entry->faceid = (unsigned) faceid; entry->lifetime = freshness; return (entry); } else { ccndc_warn(__LINE__, "command error, unrecognized address type '%s'\n", cmd_proto); goto ExitOnError; } if (cmd_host == NULL) { ccndc_warn(__LINE__, "command error, missing hostname\n"); goto ExitOnError; } if (cmd_port == NULL || cmd_port[0] == 0) cmd_port = CCN_DEFAULT_UNICAST_PORT; hints.ai_socktype = socktype; res = getaddrinfo(cmd_host, cmd_port, &hints, &raddrinfo); if (res != 0 || raddrinfo == NULL) { ccndc_warn(__LINE__, "command error, getaddrinfo for host [%s] port [%s]: %s\n", cmd_host, cmd_port, gai_strerror(res)); goto ExitOnError; } res = getnameinfo(raddrinfo->ai_addr, raddrinfo->ai_addrlen, rhostnamebuf, sizeof(rhostnamebuf), rhostportbuf, sizeof(rhostportbuf), NI_NUMERICHOST | NI_NUMERICSERV); freeaddrinfo(raddrinfo); if (res != 0) { ccndc_warn(__LINE__, "command error, getnameinfo: %s\n", gai_strerror(res)); goto ExitOnError; } off_address = entry->store->length; res = ccn_charbuf_append(entry->store, rhostnamebuf, strlen(rhostnamebuf)+1); if (res != 0) { ccndc_warn(__LINE__, "Cannot append to charbuf"); goto ExitOnError; } off_port = entry->store->length; res = ccn_charbuf_append(entry->store, rhostportbuf, strlen(rhostportbuf)+1); if (res != 0) { ccndc_warn(__LINE__, "Cannot append to charbuf"); goto ExitOnError; } entry->descr.mcast_ttl = -1; if (cmd_mcastttl != NULL) { char *endptr; entry->descr.mcast_ttl = strtol(cmd_mcastttl, &endptr, 10); if ((endptr != &cmd_mcastttl[strlen(cmd_mcastttl)]) || entry->descr.mcast_ttl < 0 || entry->descr.mcast_ttl > 255) { ccndc_warn(__LINE__, "command error, invalid multicast ttl: %s\n", cmd_mcastttl); goto ExitOnError; } } if (cmd_mcastif != NULL) { res = getaddrinfo(cmd_mcastif, NULL, &mcasthints, &mcastifaddrinfo); if (res != 0) { ccndc_warn(__LINE__, "command error, incorrect multicat interface [%s]: " "mcastifaddr getaddrinfo: %s\n", cmd_mcastif, gai_strerror(res)); goto ExitOnError; } res = getnameinfo(mcastifaddrinfo->ai_addr, mcastifaddrinfo->ai_addrlen, rhostnamebuf, sizeof(rhostnamebuf), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); freeaddrinfo(mcastifaddrinfo); if (res != 0) { ccndc_warn(__LINE__, "command error, getnameinfo: %s\n", gai_strerror(res)); goto ExitOnError; } off_source_address = entry->store->length; res = ccn_charbuf_append(entry->store, rhostnamebuf, strlen(rhostnamebuf)+1); if (res != 0) { ccndc_warn(__LINE__, "Cannot append to charbuf"); goto ExitOnError; } } entry->descr.address = (const char *)(entry->store->buf + off_address); entry->descr.port = (const char *)(entry->store->buf + off_port); if (off_source_address >= 0) { entry->descr.source_address = (const char *)(entry->store->buf + off_source_address); } entry->lifetime = freshness; return entry; ExitOnError: ccn_face_instance_destroy(&entry); return (NULL); } struct ccn_face_instance * parse_ccn_face_instance_from_face(struct ccndc_data *self, const char *cmd_faceid) { struct ccn_face_instance *entry = calloc(1, sizeof(*entry)); // allocate storage for Face data entry->store = ccn_charbuf_create(); // copy static info entry->ccnd_id = (const unsigned char *)self->ccnd_id; entry->ccnd_id_size = self->ccnd_id_size; /* destroy a face - the URI field will hold the face number */ if (cmd_faceid == NULL) { ccndc_warn(__LINE__, "command error, missing face number for destroyface\n"); goto ExitOnError; } char *endptr; int facenumber = strtol(cmd_faceid, &endptr, 10); if ((endptr != &cmd_faceid[strlen(cmd_faceid)]) || facenumber < 0) { ccndc_warn(__LINE__, "command error invalid face number for destroyface: %d\n", facenumber); goto ExitOnError; } entry->faceid = facenumber; return entry; ExitOnError: ccn_face_instance_destroy(&entry); return (NULL); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// // "private section /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// int ccndc_get_ccnd_id(struct ccndc_data *self) { struct ccn_charbuf *name = NULL; struct ccn_charbuf *resultbuf = NULL; struct ccn_parsed_ContentObject pcobuf = {0}; char ccndid_uri[] = "ccnx:/%C1.M.S.localhost/%C1.M.SRV/ccnd/KEY"; const unsigned char *ccndid_result; int res = 0; name = ccn_charbuf_create(); if (name == NULL) { ccndc_warn(__LINE__, "Unable to allocate storage for service locator name charbuf\n"); return -1; } resultbuf = ccn_charbuf_create(); if (resultbuf == NULL) { ccndc_warn(__LINE__, "Unable to allocate storage for result charbuf"); res = -1; goto Cleanup; } res = ccn_name_from_uri(name, ccndid_uri); if (res < 0) { ccndc_warn(__LINE__, "Unable to parse service locator URI for ccnd key"); goto Cleanup; } res = ccn_get(self->ccn_handle, name, self->local_scope_template, 4500, resultbuf, &pcobuf, NULL, 0); if (res < 0) { ccndc_warn(__LINE__, "Unable to get key from ccnd"); goto Cleanup; } res = ccn_ref_tagged_BLOB (CCN_DTAG_PublisherPublicKeyDigest, resultbuf->buf, pcobuf.offset[CCN_PCO_B_PublisherPublicKeyDigest], pcobuf.offset[CCN_PCO_E_PublisherPublicKeyDigest], &ccndid_result, &self->ccnd_id_size); if (res < 0) { ccndc_warn(__LINE__, "Unable to parse ccnd response for ccnd id"); goto Cleanup; } if (self->ccnd_id_size > sizeof (self->ccnd_id)) { ccndc_warn(__LINE__, "Incorrect size for ccnd id in response"); goto Cleanup; } memcpy(self->ccnd_id, ccndid_result, self->ccnd_id_size); Cleanup: ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&resultbuf); return (res); } struct ccn_face_instance * ccndc_do_face_action(struct ccndc_data *self, const char *action, struct ccn_face_instance *face_instance) { struct ccn_charbuf *newface = NULL; struct ccn_charbuf *signed_info = NULL; struct ccn_charbuf *temp = NULL; struct ccn_charbuf *name = NULL; struct ccn_charbuf *resultbuf = NULL; struct ccn_parsed_ContentObject pcobuf = {0}; struct ccn_face_instance *new_face_instance = NULL; const unsigned char *ptr = NULL; size_t length = 0; int res = 0; face_instance->action = action; /* Encode the given face instance */ newface = ccn_charbuf_create(); ON_NULL_CLEANUP(newface); ON_ERROR_CLEANUP(ccnb_append_face_instance(newface, face_instance)); temp = ccn_charbuf_create(); ON_NULL_CLEANUP(temp); res = ccn_sign_content(self->ccn_handle, temp, self->no_name, NULL, newface->buf, newface->length); ON_ERROR_CLEANUP(res); resultbuf = ccn_charbuf_create(); ON_NULL_CLEANUP(resultbuf); /* Construct the Interest name that will create the face */ name = ccn_charbuf_create(); ON_NULL_CLEANUP(name); ON_ERROR_CLEANUP(ccn_name_init(name)); ON_ERROR_CLEANUP(ccn_name_append_str(name, "ccnx")); ON_ERROR_CLEANUP(ccn_name_append(name, face_instance->ccnd_id, face_instance->ccnd_id_size)); ON_ERROR_CLEANUP(ccn_name_append_str(name, face_instance->action)); ON_ERROR_CLEANUP(ccn_name_append(name, temp->buf, temp->length)); res = ccn_get(self->ccn_handle, name, self->local_scope_template, 1000, resultbuf, &pcobuf, NULL, 0); ON_ERROR_CLEANUP(res); ON_ERROR_CLEANUP(ccn_content_get_value(resultbuf->buf, resultbuf->length, &pcobuf, &ptr, &length)); new_face_instance = ccn_face_instance_parse(ptr, length); ON_NULL_CLEANUP(new_face_instance); ccn_charbuf_destroy(&newface); ccn_charbuf_destroy(&signed_info); ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&resultbuf); ccn_charbuf_destroy(&name); return (new_face_instance); Cleanup: ccn_charbuf_destroy(&newface); ccn_charbuf_destroy(&signed_info); ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&resultbuf); ccn_charbuf_destroy(&name); ccn_face_instance_destroy(&new_face_instance); return (NULL); } int ccndc_do_prefix_action(struct ccndc_data *self, const char *action, struct ccn_forwarding_entry *forwarding_entry) { struct ccn_charbuf *temp = NULL; struct ccn_charbuf *resultbuf = NULL; struct ccn_charbuf *signed_info = NULL; struct ccn_charbuf *name = NULL; struct ccn_charbuf *prefixreg = NULL; struct ccn_parsed_ContentObject pcobuf = {0}; struct ccn_forwarding_entry *new_forwarding_entry = NULL; const unsigned char *ptr = NULL; size_t length = 0; int res; forwarding_entry->action = action; prefixreg = ccn_charbuf_create(); ON_NULL_CLEANUP(prefixreg); ON_ERROR_CLEANUP(ccnb_append_forwarding_entry(prefixreg, forwarding_entry)); temp = ccn_charbuf_create(); ON_NULL_CLEANUP(temp); res = ccn_sign_content(self->ccn_handle, temp, self->no_name, NULL, prefixreg->buf, prefixreg->length); ON_ERROR_CLEANUP(res); resultbuf = ccn_charbuf_create(); ON_NULL_CLEANUP(resultbuf); name = ccn_charbuf_create(); ON_ERROR_CLEANUP(ccn_name_init(name)); ON_ERROR_CLEANUP(ccn_name_append_str(name, "ccnx")); ON_ERROR_CLEANUP(ccn_name_append(name, forwarding_entry->ccnd_id, forwarding_entry->ccnd_id_size)); ON_ERROR_CLEANUP(ccn_name_append_str(name, forwarding_entry->action)); ON_ERROR_CLEANUP(ccn_name_append(name, temp->buf, temp->length)); res = ccn_get(self->ccn_handle, name, self->local_scope_template, 1000, resultbuf, &pcobuf, NULL, 0); ON_ERROR_CLEANUP(res); ON_ERROR_CLEANUP(ccn_content_get_value(resultbuf->buf, resultbuf->length, &pcobuf, &ptr, &length)); new_forwarding_entry = ccn_forwarding_entry_parse(ptr, length); ON_NULL_CLEANUP(new_forwarding_entry); res = new_forwarding_entry->faceid; ccn_forwarding_entry_destroy(&new_forwarding_entry); ccn_charbuf_destroy(&signed_info); ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&resultbuf); ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&prefixreg); return (res); /* This is where ON_ERROR_CLEANUP sends us in case of an error * and we must free any storage we allocated before returning. */ Cleanup: ccn_charbuf_destroy(&signed_info); ccn_charbuf_destroy(&temp); ccn_charbuf_destroy(&resultbuf); ccn_charbuf_destroy(&name); ccn_charbuf_destroy(&prefixreg); return (-1); }
/** * Test for a match between the ContentObject described by a btree * index entry and an Interest, assuming that it is already known that * there is a prefix match. * * This does not need access to the actual ContentObject, since the index * entry contains everything that we know to know to do the match. * * @param node leaf node * @param ndx index of entry within leaf node * @param interest_msg ccnb-encoded Interest * @param pi corresponding parsed interest * @param scratch for scratch use * * @result 1 for match, 0 for no match, -1 for error. */ int ccn_btree_match_interest(struct ccn_btree_node *node, int ndx, const unsigned char *interest_msg, const struct ccn_parsed_interest *pi, struct ccn_charbuf *scratch) { const unsigned char *blob = NULL; const unsigned char *nextcomp = NULL; int i; int n; int ncomps; int pubidend; int pubidstart; int res; int rnc; size_t blob_size = 0; size_t nextcomp_size = 0; size_t size; struct ccn_btree_content_payload *e = NULL; unsigned char *flatname = NULL; e = ccn_btree_node_getentry(sizeof(*e), node, ndx); if (e == NULL || e->magic[0] != CCN_BT_CONTENT_MAGIC) return(-1); ncomps = MYFETCH(e, ncomp); if (ncomps < pi->prefix_comps + pi->min_suffix_comps) return(0); if (ncomps > pi->prefix_comps + pi->max_suffix_comps) return(0); /* Check that the publisher id matches */ pubidstart = pi->offset[CCN_PI_B_PublisherID]; pubidend = pi->offset[CCN_PI_E_PublisherID]; if (pubidstart < pubidend) { blob_size = 0; ccn_ref_tagged_BLOB(CCN_DTAG_PublisherPublicKeyDigest, interest_msg, pubidstart, pubidend, &blob, &blob_size); if (blob_size != sizeof(e->ppkdg)) return(0); if (0 != memcmp(blob, e->ppkdg, blob_size)) return(0); } /* Do Exclude processing if necessary */ if (pi->offset[CCN_PI_E_Exclude] > pi->offset[CCN_PI_B_Exclude]) { res = ccn_btree_key_fetch(scratch, node, ndx); if (res < 0) return(-1); flatname = scratch->buf; size = scratch->length; nextcomp = NULL; nextcomp_size = 0; for (i = 0, n = 0; i < size; i += CCNFLATSKIP(rnc), n++) { rnc = ccn_flatname_next_comp(flatname + i, size - i); if (rnc <= 0) return(-1); if (n == pi->prefix_comps) { nextcomp = flatname + i + CCNFLATDELIMSZ(rnc); nextcomp_size = CCNFLATDATASZ(rnc); break; } } if (nextcomp == NULL) return(0); if (ccn_excluded(interest_msg + pi->offset[CCN_PI_B_Exclude], (pi->offset[CCN_PI_E_Exclude] - pi->offset[CCN_PI_B_Exclude]), nextcomp, nextcomp_size)) return(0); } /* * At this point the prefix matches and exclude-by-next-component is done. */ // test any other qualifiers here return(1); }