/* * utility, may need to be exported, to parse the buffer into a given slice * structure. */ static int slice_parse(struct ccns_slice *s, const unsigned char *p, size_t size) { int res = 0; struct ccn_buf_decoder decoder; struct ccn_buf_decoder *d = ccn_buf_decoder_start(&decoder, p, size); uintmax_t version; int op; int start; struct ccn_charbuf *clause = NULL; if (!ccn_buf_match_dtag(d, CCN_DTAG_SyncConfigSlice)) return (-1); ccn_buf_advance(d); if (!ccn_buf_match_dtag(d, CCN_DTAG_SyncVersion)) return (-1); ccn_buf_advance(d); ccn_parse_uintmax(d, &version); ccn_buf_check_close(d); if (version != SLICE_VERSION) return (-1); start = d->decoder.token_index; if (ccn_parse_Name(d, NULL) < 0) return(-1); ccn_charbuf_reset(s->topo); res = ccn_charbuf_append(s->topo, p + start, d->decoder.token_index - start); if (res < 0) return(-1); start = d->decoder.token_index; if (ccn_parse_Name(d, NULL) < 0) return(-1); ccn_charbuf_reset(s->prefix); res = ccn_charbuf_append(s->prefix, p + start, d->decoder.token_index - start); if (res < 0) return(-1); if (!ccn_buf_match_dtag(d, CCN_DTAG_SyncConfigSliceList)) return(-1); ccn_buf_advance(d); clause = ccn_charbuf_create(); if (clause == NULL) return(-1); while (ccn_buf_match_dtag(d, CCN_DTAG_SyncConfigSliceOp)) { ccn_buf_advance(d); op = ccn_parse_nonNegativeInteger(d); // op is a small integer ccn_buf_check_close(d); if (op != 0) break; ccn_charbuf_reset(clause); start = d->decoder.token_index; if (ccn_parse_Name(d, NULL) < 0) break; res = ccn_charbuf_append(clause, p + start, d->decoder.token_index - start); ccns_slice_add_clause(s, clause); } ccn_charbuf_destroy(&clause); ccn_buf_check_close(d); /* </SyncConfigSliceList> */ ccn_buf_check_close(d); /* </SyncConfigSlice> */ if (d->decoder.index != size || !CCN_FINAL_DSTATE(d->decoder.state)) return(-1); return(0); }
int ccn_parse_ContentObject(const unsigned char *msg, size_t size, struct ccn_parsed_ContentObject *x, struct ccn_indexbuf *components) { struct ccn_buf_decoder decoder; struct ccn_buf_decoder *d = ccn_buf_decoder_start(&decoder, msg, size); int res; x->magic = 20090415; x->digest_bytes = 0; if (ccn_buf_match_dtag(d, CCN_DTAG_ContentObject)) { ccn_buf_advance(d); res = ccn_parse_Signature(d, x); x->offset[CCN_PCO_B_Name] = d->decoder.token_index; x->offset[CCN_PCO_B_Component0] = d->decoder.index; res = ccn_parse_Name(d, components); if (res < 0) d->decoder.state = -__LINE__; x->name_ncomps = res; x->offset[CCN_PCO_E_ComponentLast] = d->decoder.token_index - 1; x->offset[CCN_PCO_E_Name] = d->decoder.token_index; ccn_parse_SignedInfo(d, x); x->offset[CCN_PCO_B_Content] = d->decoder.token_index; ccn_parse_required_tagged_BLOB(d, CCN_DTAG_Content, 0, -1); x->offset[CCN_PCO_E_Content] = d->decoder.token_index; ccn_buf_check_close(d); x->offset[CCN_PCO_E] = d->decoder.index; } else d->decoder.state = -__LINE__; if (d->decoder.index != size || !CCN_FINAL_DSTATE(d->decoder.state)) return (CCN_DSTATE_ERR_CODING); return(0); }
int gen_test(struct ccn_charbuf **name, struct ccn_indexbuf **comps) { int res; intmax_t secs = 1234567890; int nsecs = 6000000; *name = ccn_charbuf_create(); ccn_name_init(*name); res = ccn_create_version(NULL, *name, 0, secs, nsecs); if (res < 0) { printf("Unable to create version\n"); return(-__LINE__); } *comps = ccn_indexbuf_create(); struct ccn_buf_decoder decoder; struct ccn_buf_decoder *d = &decoder; ccn_buf_decoder_start(d, (*name)->buf, (*name)->length); res = ccn_parse_Name(d, *comps); if (res < 0) { printf("Unable to parse name\n"); return(-__LINE__); } return(0); }
int ccn_dhcp_content_parse(const unsigned char *p, size_t size, struct ccn_dhcp_entry *tail) { struct ccn_buf_decoder decoder; struct ccn_buf_decoder *d = ccn_buf_decoder_start(&decoder, p, size); int i; int count; struct ccn_dhcp_entry *de = tail; if (ccn_buf_match_dtag(d, CCN_DTAG_Entry)) { ccn_buf_advance(d); count = ccn_parse_optional_tagged_nonNegativeInteger(d, CCN_DTAG_Count); for (i = 0; i < count; i ++) { struct ccn_charbuf *store = ccn_charbuf_create(); size_t start; size_t end; int host_off = -1; int port_off = -1; de->next = calloc(1, sizeof(*de)); de = de->next; memset(de, 0, sizeof(*de)); de->store = store; de->next = NULL; if (ccn_buf_match_dtag(d, CCN_DTAG_Name)) { de->name_prefix = ccn_charbuf_create(); start = d->decoder.token_index; ccn_parse_Name(d, NULL); end = d->decoder.token_index; ccn_charbuf_append(de->name_prefix, p + start, end - start); } else de->name_prefix = NULL; host_off = ccn_parse_tagged_string(d, CCN_DTAG_Host, store); port_off = ccn_parse_tagged_string(d, CCN_DTAG_Port, store); char *b = (char *)store->buf; char *h = b + host_off; char *p = b + port_off; if (host_off >= 0) memcpy((void *)de->address, h, strlen(h)); if (port_off >= 0) memcpy((void *)de->port, p, strlen(p)); } } else d->decoder.state = -__LINE__; if (d->decoder.index != size || !CCN_FINAL_DSTATE(d->decoder.state)) ccn_dhcp_content_destroy(tail->next); return count; }
struct ccn_proxy * ccn_proxy_init(const char *filter_uri, const char *prefix_uri) { struct ccn_proxy *proxy = calloc(1, sizeof(struct ccn_proxy)); struct ccn_buf_decoder decoder; struct ccn_buf_decoder *d = &decoder; int res; DEBUG_PRINT("IN %d %s\n", __LINE__, __func__); /* Convert URI to name this proxy is responsible for */ proxy->prefix = ccn_charbuf_create(); res = ccn_name_from_uri(proxy->prefix, prefix_uri); if (res < 0) { DEBUG_PRINT("ABORT %d %s bad ccn URI: %s\n", __LINE__, __func__, prefix_uri); abort(); } d = ccn_buf_decoder_start(d, proxy->prefix->buf, proxy->prefix->length); proxy->prefix_comps = ccn_indexbuf_create(); proxy->prefix_ncomps = ccn_parse_Name(d, proxy->prefix_comps); proxy->filter = ccn_charbuf_create(); res = ccn_name_from_uri(proxy->filter, filter_uri); if (res < 0) { DEBUG_PRINT("ABORT %d %s bad ccn URI: %s\n", __LINE__, __func__, filter_uri); abort(); } /* Initialization should be done by ccn_proxy_connect() */ proxy->handle_name = ccn_charbuf_create(); ccn_charbuf_append_string(proxy->handle_name, "in/outb"); DEBUG_PRINT("OUT %d %s\n", __LINE__, __func__); return(proxy); }
int ccn_parse_Link(struct ccn_buf_decoder *d, struct ccn_parsed_Link *link, struct ccn_indexbuf *components) { int ncomp = 0; int res; if (ccn_buf_match_dtag(d, CCN_DTAG_Link)) { if (components == NULL) { /* We need to have the component offsets. */ components = ccn_indexbuf_create(); if (components == NULL) return(-1); res = ccn_parse_Link(d, link, components); ccn_indexbuf_destroy(&components); return(res); } ccn_buf_advance(d); link->offset[CCN_PL_B_Name] = d->decoder.element_index; link->offset[CCN_PL_B_Component0] = d->decoder.index; ncomp = ccn_parse_Name(d, components); if (d->decoder.state < 0) { memset(link->offset, 0, sizeof(link->offset)); return(d->decoder.state); } link->offset[CCN_PL_E_ComponentLast] = d->decoder.token_index - 1; link->offset[CCN_PL_E_Name] = d->decoder.token_index; link->name_ncomps = ncomp; /* parse optional Label string */ link->offset[CCN_PL_B_Label] = d->decoder.token_index; res = ccn_parse_optional_tagged_UDATA(d, CCN_DTAG_Label); link->offset[CCN_PL_E_Label] = d->decoder.token_index; /* parse optional LinkAuthenticator LinkAuthenticatorType */ if (ccn_buf_match_dtag(d, CCN_DTAG_LinkAuthenticator)) res = ccn_parse_LinkAuthenticator(d, link); ccn_buf_check_close(d); } else return (d->decoder.state = -__LINE__); if (d->decoder.state < 0) return (d->decoder.state); return(ncomp); }
static int ccn_parse_KeyName(struct ccn_buf_decoder *d, struct parsed_KeyName *x) { int res = -1; if (ccn_buf_match_dtag(d, CCN_DTAG_KeyName)) { res = d->decoder.element_index; ccn_buf_advance(d); x->Name = d->decoder.token_index; ccn_parse_Name(d, NULL); x->endName = d->decoder.token_index; x->PublisherID = ccn_parse_PublisherID(d, NULL); x->endPublisherID = d->decoder.token_index; ccn_buf_check_close(d); } else d->decoder.state = -__LINE__; if (d->decoder.state < 0) return (d->decoder.state); return(res); }
int ccn_parse_interest(const unsigned char *msg, size_t size, struct ccn_parsed_interest *interest, struct ccn_indexbuf *components) { struct ccn_buf_decoder decoder; struct ccn_buf_decoder *d = ccn_buf_decoder_start(&decoder, msg, size); int magic = 0; int ncomp = 0; int res; if (ccn_buf_match_dtag(d, CCN_DTAG_Interest) || ccn_buf_match_dtag(d, CCN_DTAG_PersistentInterest)) { if (components == NULL) { /* We need to have the component offsets. */ components = ccn_indexbuf_create(); if (components == NULL) return(-1); res = ccn_parse_interest(msg, size, interest, components); ccn_indexbuf_destroy(&components); return(res); } /*In case of persistent interest*/ if(ccn_buf_match_dtag(d, CCN_DTAG_PersistentInterest)) { interest->persistent = 1; } ccn_buf_advance(d); interest->offset[CCN_PI_B_Name] = d->decoder.element_index; interest->offset[CCN_PI_B_Component0] = d->decoder.index; ncomp = ccn_parse_Name(d, components); if (d->decoder.state < 0) { memset(interest->offset, 0, sizeof(interest->offset)); return(d->decoder.state); } interest->offset[CCN_PI_E_ComponentLast] = d->decoder.token_index - 1; interest->offset[CCN_PI_E_Name] = d->decoder.token_index; interest->prefix_comps = ncomp; interest->offset[CCN_PI_B_LastPrefixComponent] = components->buf[(ncomp > 0) ? (ncomp - 1) : 0]; interest->offset[CCN_PI_E_LastPrefixComponent] = components->buf[ncomp]; /* optional MinSuffixComponents, MaxSuffixComponents */ interest->min_suffix_comps = 0; interest->max_suffix_comps = 32767; interest->offset[CCN_PI_B_MinSuffixComponents] = d->decoder.token_index; res = ccn_parse_optional_tagged_nonNegativeInteger(d, CCN_DTAG_MinSuffixComponents); interest->offset[CCN_PI_E_MinSuffixComponents] = d->decoder.token_index; if (res >= 0) interest->min_suffix_comps = res; interest->offset[CCN_PI_B_MaxSuffixComponents] = d->decoder.token_index; res = ccn_parse_optional_tagged_nonNegativeInteger(d, CCN_DTAG_MaxSuffixComponents); interest->offset[CCN_PI_E_MaxSuffixComponents] = d->decoder.token_index; if (res >= 0) interest->max_suffix_comps = res; if (interest->max_suffix_comps < interest->min_suffix_comps) return (d->decoder.state = -__LINE__); /* optional PublisherID */ res = ccn_parse_PublisherID(d, interest); /* optional Exclude element */ interest->offset[CCN_PI_B_Exclude] = d->decoder.token_index; res = ccn_parse_Exclude(d); interest->offset[CCN_PI_E_Exclude] = d->decoder.token_index; /* optional ChildSelector */ interest->offset[CCN_PI_B_ChildSelector] = d->decoder.token_index; res = ccn_parse_optional_tagged_nonNegativeInteger(d, CCN_DTAG_ChildSelector); if (res < 0) res = 0; interest->orderpref = res; interest->offset[CCN_PI_E_ChildSelector] = d->decoder.token_index; if (interest->orderpref > 5) return (d->decoder.state = -__LINE__); /* optional AnswerOriginKind */ interest->offset[CCN_PI_B_AnswerOriginKind] = d->decoder.token_index; interest->answerfrom = ccn_parse_optional_tagged_nonNegativeInteger(d, CCN_DTAG_AnswerOriginKind); interest->offset[CCN_PI_E_AnswerOriginKind] = d->decoder.token_index; if (interest->answerfrom == -1) interest->answerfrom = CCN_AOK_DEFAULT; else if ((interest->answerfrom & CCN_AOK_NEW) != 0 && (interest->answerfrom & CCN_AOK_CS) == 0) return (d->decoder.state = -__LINE__); /* optional Scope */ interest->offset[CCN_PI_B_Scope] = d->decoder.token_index; interest->scope = ccn_parse_optional_tagged_nonNegativeInteger(d, CCN_DTAG_Scope); interest->offset[CCN_PI_E_Scope] = d->decoder.token_index; if (interest->scope > 9) return (d->decoder.state = -__LINE__); if ((interest->answerfrom & CCN_AOK_EXPIRE) != 0 && interest->scope != 0) return (d->decoder.state = -__LINE__); /* optional InterestLifetime */ interest->offset[CCN_PI_B_InterestLifetime] = d->decoder.token_index; res = ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_InterestLifetime, 1, 8); if (res >= 0) magic |= 20100401; interest->offset[CCN_PI_E_InterestLifetime] = d->decoder.token_index; /* optional Nonce */ interest->offset[CCN_PI_B_Nonce] = d->decoder.token_index; res = ccn_parse_optional_tagged_BLOB(d, CCN_DTAG_Nonce, 4, 64); interest->offset[CCN_PI_E_Nonce] = d->decoder.token_index; /* Allow for no experimental stuff */ interest->offset[CCN_PI_B_OTHER] = d->decoder.token_index; interest->offset[CCN_PI_E_OTHER] = d->decoder.token_index; ccn_buf_check_close(d); interest->offset[CCN_PI_E] = d->decoder.index; } else return (d->decoder.state = -__LINE__); if (d->decoder.state < 0) return (d->decoder.state); if (d->decoder.index != size || !CCN_FINAL_DSTATE(d->decoder.state)) return (CCN_DSTATE_ERR_CODING); if (magic == 0) magic = 20090701; if (!(magic == 20090701 || magic == 20100401)) return (d->decoder.state = -__LINE__); interest->magic = magic; return (ncomp); }
struct ccn_strategy_selection * ccn_strategy_selection_parse(const unsigned char *p, size_t size) { struct ccn_buf_decoder decoder; struct ccn_buf_decoder *d = ccn_buf_decoder_start(&decoder, p, size); struct ccn_strategy_selection *result; struct ccn_charbuf *store = NULL; const unsigned char *val = NULL; size_t sz; size_t start; size_t end; int action_off = -1; int ccnd_id_off = -1; int strategyid_off = -1; int parameters_off = -1; result = calloc(1, sizeof(*result)); if (result == NULL) return(NULL); result->name_prefix = ccn_charbuf_create(); result->store = store = ccn_charbuf_create(); if (result->name_prefix == NULL || result->store == NULL) { ccn_strategy_selection_destroy(&result); return(NULL); } if (ccn_buf_match_dtag(d, CCN_DTAG_StrategySelection)) { ccn_buf_advance(d); action_off = ccn_parse_tagged_string(d, CCN_DTAG_Action, store); if (ccn_buf_match_dtag(d, CCN_DTAG_Name)) { start = d->decoder.token_index; ccn_parse_Name(d, NULL); end = d->decoder.token_index; ccn_charbuf_append(result->name_prefix, p + start, end - start); } else ccn_charbuf_destroy(&result->name_prefix); if (ccn_buf_match_dtag(d, CCN_DTAG_PublisherPublicKeyDigest)) { ccn_buf_advance(d); if (ccn_buf_match_blob(d, &val, &sz)) { ccn_buf_advance(d); if (sz != 32) d->decoder.state = -__LINE__; } ccn_buf_check_close(d); if (d->decoder.state >= 0) { ccnd_id_off = store->length; ccn_charbuf_append(store, val, sz); result->ccnd_id_size = sz; } } strategyid_off = ccn_parse_tagged_string(d, CCN_DTAG_StrategyID, store); parameters_off = ccn_parse_tagged_string(d, CCN_DTAG_StrategyParameters, store); result->lifetime = ccn_parse_optional_tagged_nonNegativeInteger(d, CCN_DTAG_FreshnessSeconds); ccn_buf_check_close(d); } else d->decoder.state = -__LINE__; if (d->decoder.index != size || !CCN_FINAL_DSTATE(d->decoder.state)) ccn_strategy_selection_destroy(&result); else { const char *b = (const char *)result->store->buf; result->action = (action_off == -1) ? NULL : b + action_off; result->ccnd_id = (ccnd_id_off == -1) ? NULL : result->store->buf + ccnd_id_off; result->strategyid = (strategyid_off == -1) ? NULL : b + strategyid_off; result->parameters = (parameters_off == -1) ? NULL : b + parameters_off; } return(result); }
enum ccn_upcall_res andana_client_encap_interest( struct ccn_closure *selfp, enum ccn_upcall_kind kind, struct ccn_upcall_info *info) { int res; enum ccn_upcall_res upcall_res = CCN_UPCALL_RESULT_ERR; struct andana_client *client = selfp->data; struct ccn_proxy *proxy = client->proxy; size_t orig_name_ncomps; struct ccn_charbuf *orig_name = NULL; struct ccn_indexbuf *orig_name_comps = NULL; struct ccn_charbuf *new_name = NULL; struct ccn_indexbuf *new_name_comps = NULL; struct hashtb_enumerator ee; struct hashtb_enumerator *e = ⅇ switch (kind) { case CCN_UPCALL_INTEREST: DEBUG_PRINT("Received Interest\n"); break; case CCN_UPCALL_FINAL: DEBUG_PRINT("Encap: callback final\n"); return(CCN_UPCALL_RESULT_OK); default: return(CCN_UPCALL_RESULT_ERR); } /* Extract Name from Interest */ orig_name_ncomps = ccn_util_extract_name(info->interest_ccnb, info->interest_comps, &orig_name, &orig_name_comps); /* * Need to check this Interest doesn't match what we send out. * Otherwise, we'll just keep encapsulating the same thing over and over. */ int num_matching_comps = ccn_util_name_match(client->proxy->prefix, client->proxy->prefix_comps, orig_name, orig_name_comps); if (num_matching_comps == client->proxy->prefix_ncomps) { DEBUG_PRINT("Interest matches %d of %d components, ignoring interest\n", num_matching_comps, (int)client->proxy->prefix_ncomps); #ifdef PROXYDEBUG ccn_util_println_pc_fmt(orig_name->buf, orig_name->length); DEBUG_PRINT("Name has %lu comps\n", orig_name_comps->n-1); ccn_util_println_pc_fmt(client->proxy->prefix->buf, client->proxy->prefix->length); DEBUG_PRINT("Name has %lu comps\n", client->proxy->prefix_comps->n-1); #endif goto MatchBail; } else { DEBUG_PRINT("Interest matches %d of %d components\n", num_matching_comps, (int)client->proxy->prefix_ncomps); } /* Create a new name encapsulated & encrypted name */ // new_name_comps = ccn_indexbuf_create(); ccn_name_append(orig_name, info->interest_ccnb, info->pi->offset[CCN_PI_E]); ccn_indexbuf_destroy(&orig_name_comps); struct ccn_buf_decoder decoder; struct ccn_buf_decoder *d = &decoder; ccn_buf_decoder_start(d, orig_name->buf, orig_name->length); orig_name_comps = ccn_indexbuf_create(); res = ccn_parse_Name(d, orig_name_comps); if (res <= 0) { DEBUG_PRINT("%d %s error parsing encapsulated name\n", __LINE__, __func__); goto MatchBail; } res = andana_path_encrypt_encap(client->path, orig_name, orig_name_comps, &new_name, &new_name_comps); if (res <= 0) { DEBUG_PRINT("%d %s error encapsulating and encrypting name\n", __LINE__, __func__); goto EncryptBail; } /* Remember the new name so we know how to decrypt & decapsulate it later */ hashtb_start(client->name_to_path, e); res = hashtb_seek(e, new_name->buf, new_name->length, 0); if (res == HT_NEW_ENTRY) { } else if (res == HT_OLD_ENTRY) { DEBUG_PRINT("Interest recording found old entry\n"); upcall_res = CCN_UPCALL_RESULT_OK; goto LookupBail; } else { DEBUG_PRINT("Error in Interest insertion\n"); goto LookupBail; } /* Send out new Interest */ #ifdef PROXYDEBUG struct ccn_charbuf *c = ccn_charbuf_create(); ccn_uri_append(c, new_name->buf, new_name->length, 1); DEBUG_PRINT("name = %s\n", ccn_charbuf_as_string(c)); ccn_charbuf_destroy(&c); #endif res = ccn_express_interest(proxy->handle, new_name, proxy->content_handler, NULL); if(res != 0) { DEBUG_PRINT("express interest res = %d\n",res); } else { struct andana_path **path_ptr = e->data; *path_ptr = andana_path_copy(client->path); upcall_res = CCN_UPCALL_RESULT_INTEREST_CONSUMED; } LookupBail: hashtb_end(e); EncryptBail: ccn_charbuf_destroy(&new_name); ccn_indexbuf_destroy(&new_name_comps); MatchBail: ccn_charbuf_destroy(&orig_name); ccn_indexbuf_destroy(&orig_name_comps); return(upcall_res); }
struct ccn_forwarding_entry * ccn_forwarding_entry_parse(const unsigned char *p, size_t size) { struct ccn_buf_decoder decoder; struct ccn_buf_decoder *d = ccn_buf_decoder_start(&decoder, p, size); struct ccn_charbuf *store = ccn_charbuf_create(); struct ccn_forwarding_entry *result; const unsigned char *val; size_t sz; size_t start; size_t end; int action_off = -1; int ccnd_id_off = -1; if (store == NULL) return(NULL); result = calloc(1, sizeof(*result)); if (result == NULL) { ccn_charbuf_destroy(&store); return(NULL); } if (ccn_buf_match_dtag(d, CCN_DTAG_ForwardingEntry)) { ccn_buf_advance(d); action_off = ccn_parse_tagged_string(d, CCN_DTAG_Action, store); if (ccn_buf_match_dtag(d, CCN_DTAG_Name)) { result->name_prefix = ccn_charbuf_create(); start = d->decoder.token_index; ccn_parse_Name(d, NULL); end = d->decoder.token_index; ccn_charbuf_append(result->name_prefix, p + start, end - start); } else result->name_prefix = NULL; if (ccn_buf_match_dtag(d, CCN_DTAG_PublisherPublicKeyDigest)) { ccn_buf_advance(d); if (ccn_buf_match_blob(d, &val, &sz)) { ccn_buf_advance(d); if (sz != 32) d->decoder.state = -__LINE__; } ccn_buf_check_close(d); if (d->decoder.state >= 0) { ccnd_id_off = store->length; ccn_charbuf_append(store, val, sz); result->ccnd_id_size = sz; } } result->faceid = ccn_parse_optional_tagged_nonNegativeInteger(d, CCN_DTAG_FaceID); result->flags = ccn_parse_optional_tagged_nonNegativeInteger(d, CCN_DTAG_ForwardingFlags); result->lifetime = ccn_parse_optional_tagged_nonNegativeInteger(d, CCN_DTAG_FreshnessSeconds); ccn_buf_check_close(d); } else d->decoder.state = -__LINE__; if (d->decoder.index != size || !CCN_FINAL_DSTATE(d->decoder.state) || store->length > sizeof(result->store)) ccn_forwarding_entry_destroy(&result); else { char *b = (char *)result->store; memcpy(b, store->buf, store->length); result->action = (action_off == -1) ? NULL : b + action_off; result->ccnd_id = (ccnd_id_off == -1) ? NULL : result->store + ccnd_id_off; } ccn_charbuf_destroy(&store); return(result); }