// executes (loops over) a Lambda expression: tries to run to termination, // or returns after having emitted further remote lookup/reduction requests // the return val is a buffer with the result stack's (concatenated) content struct ccnl_buf_s* Krivine_reduction(struct ccnl_relay_s *ccnl, char *expression, int start_locally, struct configuration_s **config, struct ccnl_prefix_s *prefix, int suite) { int steps = 0, halt = 0, restart = 1; int len = strlen("CLOSURE(HALT);RESOLVENAME()") + strlen(expression) + 1; char *dummybuf; DEBUGMSG(TRACE, "Krivine_reduction()\n"); if (!*config && strlen(expression) == 0) return 0; dummybuf = ccnl_malloc(2000); if (!*config) { char *prog; struct environment_s *global_dict = NULL; prog = ccnl_malloc(len*sizeof(char)); sprintf(prog, "CLOSURE(HALT);RESOLVENAME(%s)", expression); setup_global_environment(&global_dict); DEBUGMSG(DEBUG, "PREFIX %s\n", ccnl_prefix_to_path(prefix)); *config = new_config(ccnl, prog, global_dict, start_locally, prefix, ccnl->km->configid, suite); DBL_LINKED_LIST_ADD(ccnl->km->configuration_list, (*config)); restart = 0; --ccnl->km->configid; } DEBUGMSG(INFO, "Prog: %s\n", (*config)->prog); while ((*config)->prog && !halt) { char *oldprog = (*config)->prog; steps++; DEBUGMSG(DEBUG, "Step %d (%d/%d): %s\n", steps, stack_len((*config)->argument_stack), stack_len((*config)->result_stack), (*config)->prog); (*config)->prog = ZAM_term(ccnl, *config, &halt, dummybuf, &restart); ccnl_free(oldprog); } ccnl_free(dummybuf); if (halt < 0) { //HALT < 0 means pause computation DEBUGMSG(INFO,"Pause computation: %d\n", -(*config)->configid); return NULL; } //HALT > 0 means computation finished DEBUGMSG(INFO, "end-of-computation (%d/%d)\n", stack_len((*config)->argument_stack), stack_len((*config)->result_stack)); /* print_argument_stack((*config)->argument_stack); print_result_stack((*config)->result_stack); */ return Krivine_exportResultStack(ccnl, *config); }
struct ccnl_prefix_s * ccnl_iottlv_parseHierarchicalName(unsigned char *data, int datalen) { int len = datalen; unsigned int typ, len2; struct ccnl_prefix_s *p; p = (struct ccnl_prefix_s *) ccnl_calloc(1, sizeof(struct ccnl_prefix_s)); if (!p) return NULL; p->suite = CCNL_SUITE_IOTTLV; p->comp = (unsigned char**) ccnl_malloc(CCNL_MAX_NAME_COMP * sizeof(unsigned char**)); p->complen = (int*) ccnl_malloc(CCNL_MAX_NAME_COMP * sizeof(int)); if (!p->comp || !p->complen) return NULL; p->nameptr = data; p->namelen = len; while (len > 0) { if (ccnl_iottlv_dehead(&data, &len, &typ, &len2)) goto Bail; if (typ == IOT_TLV_PN_Component && p->compcnt < CCNL_MAX_NAME_COMP) { p->comp[p->compcnt] = data; p->complen[p->compcnt] = len2; p->compcnt++; } data += len2; len -= len2; } datalen -= p->namelen; #ifdef USE_NFN if (p->compcnt > 0 && p->complen[p->compcnt-1] == 3 && !memcmp(p->comp[p->compcnt-1], "NFN", 3)) { p->nfnflags |= CCNL_PREFIX_NFN; p->compcnt--; if (p->compcnt > 0 && p->complen[p->compcnt-1] == 5 && !memcmp(p->comp[p->compcnt-1], "THUNK", 5)) { p->nfnflags |= CCNL_PREFIX_THUNK; p->compcnt--; } } #endif return p; Bail: free_prefix(p); return NULL; }
int riot_send_msg(uint8_t *buf, uint16_t size, uint16_t to) { DEBUGMSG(1, "this is a RIOT MSG based connection\n"); DEBUGMSG(1, "size=%" PRIu16 " to=%" PRIu16 "\n", size, to); uint8_t *buf2 = ccnl_malloc(sizeof(riot_ccnl_msg_t) + size); if (!buf2) { DEBUGMSG(1, " malloc failed...dorpping msg!\n"); return 0; } riot_ccnl_msg_t *rmsg = (riot_ccnl_msg_t *) buf2; rmsg->payload = buf2 + sizeof(riot_ccnl_msg_t); rmsg->size = size; memcpy(rmsg->payload, buf, size); msg_t m; m.type = CCNL_RIOT_MSG; m.content.ptr = (char *) rmsg; DEBUGMSG(1, "sending msg to pid=%" PRIkernel_pid "\n", to); msg_send(&m, to); return size; }
/** * * @param ccnl * @param content * @param content_len * @param sig * @param sig_len * @param callback function which should be called when crypto system returns * for a new callback function you have to extend ccnl_crypto()!!!! * @return */ int ccnl_crypto_verify(struct ccnl_relay_s *ccnl, char *content, int content_len, char *sig, int sig_len, char* callback, int sequnum) { char *msg = 0; int len = 0, ret = 0; struct ccnl_buf_s *retbuf; //int plen; //unsigned char *buf; plen = 0; memset(buf,0,sizeof(buf)); if(!ccnl->crypto_face) return ret; msg = (char *)ccnl_malloc(sizeof(char)*(content_len+sig_len)+3000); len = ccnl_crypto_create_ccnl_sign_verify_msg("verify", sequnum, content, content_len, sig, sig_len, msg, callback); if(len > CCNL_MAX_PACKET_SIZE){ DEBUGMSG(DEBUG,"Ignored, packet size too large"); return 0; } //send ccn_msg to crytoserver retbuf = ccnl_buf_new((char *)msg, len); ccnl_face_enqueue(ccnl, ccnl->crypto_face, retbuf); if(msg) ccnl_free(msg); return ret; }
char* ccnl_lambdaParseVar(char **cpp) { char *p; int len, string = 0; p = *cpp; if (*p && *p == '\''){ // Parse a String between '' string = 1; p++; while(*p != '\''){ p++; } } else{ while (*p && (isalnum(*p) || *p == '_' || *p == '=' || *p == '/' || *p == '.')){ p++; } } len = p - *cpp + string; p = ccnl_malloc(len+1); if (!p) return 0; memcpy(p, *cpp, len); p[len] = '\0'; *cpp += len; return p; }
static int ccnl_crypto_create_ccnl_sign_verify_msg(char *typ, int txid, char *content, int content_len, char *sig, int sig_len, char *msg, char *callback) { int len = 0, len2 = 0, len3 = 0; char *component_buf, *contentobj_buf; char h[100]; component_buf = ccnl_malloc(sizeof(char)*(content_len)+2000); contentobj_buf = ccnl_malloc(sizeof(char)*(content_len)+1000); len = ccnl_ccnb_mkHeader(msg, CCN_DTAG_INTEREST, CCN_TT_DTAG); // interest len += ccnl_ccnb_mkHeader(msg+len, CCN_DTAG_NAME, CCN_TT_DTAG); // name len += ccnl_ccnb_mkStrBlob(msg+len, CCN_DTAG_COMPONENT, CCN_TT_DTAG, "ccnx"); len += ccnl_ccnb_mkStrBlob(msg+len, CCN_DTAG_COMPONENT, CCN_TT_DTAG, "crypto"); // prepare FACEINSTANCE len3 += ccnl_ccnb_mkStrBlob(component_buf+len3, CCNL_DTAG_CALLBACK, CCN_TT_DTAG, callback); len3 += ccnl_ccnb_mkStrBlob(component_buf+len3, CCN_DTAG_TYPE, CCN_TT_DTAG, typ); memset(h, 0, 100); sprintf(h, "%d", txid); len3 += ccnl_ccnb_mkStrBlob(component_buf+len3, CCN_DTAG_SEQNO, CCN_TT_DTAG, h); if(!strcmp(typ, "verify")) len3 += ccnl_ccnb_mkBlob(component_buf+len3, CCN_DTAG_SIGNATURE, CCN_TT_DTAG, // content (char*) sig, sig_len); len3 += ccnl_ccnb_mkBlob(component_buf+len3, CCN_DTAG_CONTENTDIGEST, CCN_TT_DTAG, // content (char*) content, content_len); // prepare CONTENTOBJ with CONTENT len2 = ccnl_ccnb_mkHeader(contentobj_buf, CCN_DTAG_CONTENTOBJ, CCN_TT_DTAG); // contentobj len2 += ccnl_ccnb_mkBlob(contentobj_buf+len2, CCN_DTAG_CONTENT, CCN_TT_DTAG, // content (char*) component_buf, len3); contentobj_buf[len2++] = 0; // end-of-contentobj // add CONTENTOBJ as the final name component len += ccnl_ccnb_mkBlob(msg+len, CCN_DTAG_COMPONENT, CCN_TT_DTAG, // comp (char*) contentobj_buf, len2); msg[len++] = 0; // end-of-name msg[len++] = 0; // end-o ccnl_free(component_buf); ccnl_free(contentobj_buf); return len; }
struct ccnl_prefix_s* ccnl_prefix_new(int suite, int cnt) { struct ccnl_prefix_s *p; p = (struct ccnl_prefix_s *) ccnl_calloc(1, sizeof(struct ccnl_prefix_s)); if (!p) return NULL; p->comp = (unsigned char**) ccnl_malloc(cnt * sizeof(unsigned char*)); p->complen = (int*) ccnl_malloc(cnt * sizeof(int)); if (!p->comp || !p->complen) { free_prefix(p); return NULL; } p->compcnt = cnt; p->suite = suite; p->chunknum = NULL; return p; }
struct ccnl_nonce_s *ccnl_nonce_new(struct ccnl_buf_s *that) { struct ccnl_nonce_s *n = (struct ccnl_nonce_s *) ccnl_malloc(sizeof(struct ccnl_nonce_s)); n->buf = buf_dup(that); ccnl_get_timeval(&n->created); n->next = NULL; n->prev = NULL; return n; }
struct ccnl_prefix_s* ccnl_prefix_dup(struct ccnl_prefix_s *prefix) { int i = 0, len; struct ccnl_prefix_s *p; if (!prefix) return NULL; p = ccnl_prefix_new(prefix->suite, prefix->compcnt); if (!p) return p; p->compcnt = prefix->compcnt; p->chunknum = prefix->chunknum; #ifdef USE_NFN p->nfnflags = prefix->nfnflags; #endif for (i = 0, len = 0; i < prefix->compcnt; i++) len += prefix->complen[i]; p->bytes = (unsigned char*) ccnl_malloc(len); if (!p->bytes) { free_prefix(p); return NULL; } for (i = 0, len = 0; i < prefix->compcnt; i++) { p->complen[i] = prefix->complen[i]; p->comp[i] = p->bytes + len; memcpy(p->bytes + len, prefix->comp[i], p->complen[i]); len += p->complen[i]; } if (prefix->chunknum) { p->chunknum = ccnl_malloc(sizeof(int)); *p->chunknum = *prefix->chunknum; } return p; }
int ccnl_prefix_appendCmp(struct ccnl_prefix_s *prefix, unsigned char *cmp, int cmplen) { int lastcmp = prefix->compcnt, i; int *oldcomplen = prefix->complen; unsigned char **oldcomp = prefix->comp; unsigned char *oldbytes = prefix->bytes; int prefixlen = 0; if (prefix->compcnt + 1 > CCNL_MAX_NAME_COMP) return -1; for (i = 0; i < lastcmp; i++) { prefixlen += prefix->complen[i]; } prefix->compcnt++; prefix->comp = (unsigned char**) ccnl_malloc(prefix->compcnt * sizeof(unsigned char*)); prefix->complen = (int*) ccnl_malloc(prefix->compcnt * sizeof(int)); prefix->bytes = (unsigned char*) ccnl_malloc(prefixlen + cmplen); memcpy(prefix->bytes, oldbytes, prefixlen); memcpy(prefix->bytes + prefixlen, cmp, cmplen); prefixlen = 0; for (i = 0; i < lastcmp; i++) { prefix->comp[i] = &prefix->bytes[prefixlen]; prefix->complen[i] = oldcomplen[i]; prefixlen += oldcomplen[i]; } prefix->comp[lastcmp] = &prefix->bytes[prefixlen]; prefix->complen[lastcmp] = cmplen; ccnl_free(oldcomp); ccnl_free(oldcomplen); ccnl_free(oldbytes); return 0; }
struct ccnl_buf_s* ccnl_buf_new(void *data, int len) { struct ccnl_buf_s *b = ccnl_malloc(sizeof(*b) + len); if (!b) return NULL; b->next = NULL; b->datalen = len; if (data) memcpy(b->data, data, len); return b; }
struct ccnl_buf_s* ccnl_buf_new(void *data, size_t len) { struct ccnl_buf_s *b = (struct ccnl_buf_s*) ccnl_malloc(sizeof(*b) + len); if (!b) { return NULL; } b->next = NULL; b->datalen = len; if (data) { memcpy(b->data, data, len); } return b; }
char* op_builtin_add(struct ccnl_relay_s *ccnl, struct configuration_s *config, int *restart, int *halt, char *prog, char *pending, struct stack_s **stack) { int i1=0, i2=0, *h; DEBUGMSG(DEBUG, "---to do: OP_ADD <%s> pending: %s\n", prog+7, pending); pop2int(); h = ccnl_malloc(sizeof(int)); *h = i1 + i2; push_to_stack(stack, h, STACK_TYPE_INT); return pending ? ccnl_strdup(pending) : NULL; }
// executes a ZAM instruction, returns the term to continue working on char* ZAM_term(struct ccnl_relay_s *ccnl, struct configuration_s *config, int *halt, char *dummybuf, int *restart) { // struct ccnl_lambdaTerm_s *t; // char *pending, *p, *cp, *prog = config->prog; // int len; char *prog = config->prog; struct builtin_s *bp; char *arg, *contd; int tok; //pop closure if (!prog || strlen(prog) == 0) { if (config->result_stack) { prog = ccnl_malloc(strlen((char*)config->result_stack->content)+1); strcpy(prog, config->result_stack->content); return prog; } DEBUGMSG(DEBUG, "no result returned\n"); return NULL; } tok = ZAM_nextToken(prog, &arg, &contd); // TODO: count opening/closing parentheses when hunting for ';' ? /* pending = strchr(prog, ';'); p = strchr(prog, '('); */ switch (tok) { case ZAM_ACCESS: { struct closure_s *closure = search_in_environment(config->env, arg); DEBUGMSG(DEBUG, "---to do: access <%s>\n", arg); if (!closure) { // TODO: is the following needed? Above search should have // visited global_dict, already! closure = search_in_environment(config->global_dict, arg); if (!closure) { DEBUGMSG(WARNING, "?? could not lookup var %s\n", arg); ccnl_free(arg); return NULL; } } ccnl_free(arg); closure = new_closure(ccnl_strdup(closure->term), closure->env); push_to_stack(&config->argument_stack, closure, STACK_TYPE_CLOSURE); return ccnl_strdup(contd); } case ZAM_APPLY: { struct stack_s *fct = pop_from_stack(&config->argument_stack); struct stack_s *par = pop_from_stack(&config->argument_stack); struct closure_s *fclosure, *aclosure; char *code; DEBUGMSG(DEBUG, "---to do: apply\n"); if (!fct || !par) return NULL; fclosure = (struct closure_s *) fct->content; aclosure = (struct closure_s *) par->content; if (!fclosure || !aclosure) return NULL; ccnl_free(fct); ccnl_free(par); code = aclosure->term; if (config->env) ccnl_nfn_releaseEnvironment(&config->env); config->env = aclosure->env; ccnl_free(aclosure); push_to_stack(&config->argument_stack, fclosure, STACK_TYPE_CLOSURE); if (contd) sprintf(dummybuf, "%s;%s", code, contd); else strcat(dummybuf, code); ccnl_free(code); return ccnl_strdup(dummybuf); } case ZAM_CALL: { struct stack_s *h = pop_or_resolve_from_result_stack(ccnl, config); int i, offset, num_params = *(int *)h->content; char name[5]; DEBUGMSG(DEBUG, "---to do: CALL <%s>\n", arg); ccnl_free(h->content); ccnl_free(h); sprintf(dummybuf, "CLOSURE(FOX);RESOLVENAME(@op("); // ... @x(@y y x 2 op)));TAILAPPLY"; offset = strlen(dummybuf); for (i = 0; i < num_params; ++i) { sprintf(name, "x%d", i); offset += sprintf(dummybuf+offset, "@%s(", name); } for (i = num_params - 1; i >= 0; --i) { sprintf(name, "x%d", i); offset += sprintf(dummybuf+offset, " %s", name); } offset += sprintf(dummybuf + offset, " %d", num_params); offset += sprintf(dummybuf+offset, " op"); for (i = 0; i < num_params+2; ++i) offset += sprintf(dummybuf + offset, ")"); if (contd) sprintf(dummybuf + offset, ";%s", contd); return ccnl_strdup(dummybuf); } case ZAM_CLOSURE: { struct closure_s *closure; DEBUGMSG(DEBUG, "---to do: closure <%s> (contd=%s)\n", arg, contd); if (!config->argument_stack && !strncmp(arg, "RESOLVENAME(", 12)) { char v[500], *c; int len; c = strchr(arg+12, ')'); if (!c) goto normal; len = c - (arg+12); memcpy(v, arg+12, len); v[len] = '\0'; closure = search_in_environment(config->env, v); if (!closure) goto normal; if (!strcmp(closure->term, arg)) { DEBUGMSG(WARNING, "** detected tail recursion case %s/%s\n", closure->term, arg); } else goto normal; } else { normal: closure = new_closure(arg, config->env); //configuration->env = NULL;//FIXME new environment? push_to_stack(&config->argument_stack, closure, STACK_TYPE_CLOSURE); arg = NULL; } if (contd) { ccnl_free(arg); return ccnl_strdup(contd); } DEBUGMSG(ERROR, "** not implemented, see line %d\n", __LINE__); return arg; } case ZAM_FOX: return ZAM_fox(ccnl, config, restart, halt, prog, arg, contd); case ZAM_GRAB: { struct stack_s *stack = pop_from_stack(&config->argument_stack); DEBUGMSG(DEBUG, "---to do: grab <%s>\n", arg); add_to_environment(&config->env, arg, stack->content); ccnl_free(stack); return ccnl_strdup(contd); } case ZAM_HALT: ccnl_nfn_freeStack(config->argument_stack); //ccnl_nfn_freeStack(config->result_stack); config->argument_stack = /*config->result_stack =*/ NULL; *halt = 1; return ccnl_strdup(contd); case ZAM_RESOLVENAME: return ZAM_resolvename(config, dummybuf, arg, contd); case ZAM_TAILAPPLY: { struct stack_s *stack = pop_from_stack(&config->argument_stack); struct closure_s *closure = (struct closure_s *) stack->content; char *code = closure->term; DEBUGMSG(DEBUG, "---to do: tailapply\n"); ccnl_free(stack); if (contd) //build new term sprintf(dummybuf, "%s;%s", code, contd); else strcpy(dummybuf, code); if (config->env) ccnl_nfn_releaseEnvironment(&config->env); config->env = closure->env; //set environment from closure ccnl_free(code); ccnl_free(closure); return ccnl_strdup(dummybuf); } case ZAM_UNKNOWN: break; default: DEBUGMSG(DEBUG, "builtin: %s (%s/%s)\n", bifs[-tok - 1].name, prog, contd); return bifs[-tok - 1].fct(ccnl, config, restart, halt, prog, contd, &config->result_stack); } ccnl_free(arg); // iterate through all extension operations for (bp = op_extensions; bp; bp = bp->next) if (!strncmp(prog, bp->name, strlen(bp->name))) return (bp->fct)(ccnl, config, restart, halt, prog, contd, &config->result_stack); DEBUGMSG(INFO, "unknown (built-in) command <%s>\n", prog); return NULL; }
// We use one extraction procedure for both interest and data pkts. // This proc assumes that the packet header was already processed and consumed struct ccnl_pkt_s* ccnl_ccntlv_bytes2pkt(unsigned char *start, unsigned char **data, int *datalen) { struct ccnl_pkt_s *pkt; int i, len; unsigned int typ, oldpos; struct ccnl_prefix_s *p; #ifdef USE_HMAC256 int validAlgoIsHmac256 = 0; #endif DEBUGMSG_PCNX(TRACE, "ccnl_ccntlv_bytes2pkt len=%d\n", *datalen); pkt = (struct ccnl_pkt_s*) ccnl_calloc(1, sizeof(*pkt)); if (!pkt) return NULL; pkt->pfx = p = ccnl_prefix_new(CCNL_SUITE_CCNTLV, CCNL_MAX_NAME_COMP); if (!p) { ccnl_free(pkt); return NULL; } p->compcnt = 0; #ifdef USE_HMAC256 pkt->hmacStart = *data; #endif // We ignore the TL types of the message for now: // content and interests are filled in both cases (and only one exists). // Validation info is now collected if (ccnl_ccntlv_dehead(data, datalen, &typ, (unsigned int*) &len) || (int) len > *datalen) goto Bail; pkt->type = typ; pkt->suite = CCNL_SUITE_CCNTLV; pkt->val.final_block_id = -1; // XXX this parsing is not safe for all input data - needs more bound // checks, as some packets with wrong L values can bring this to crash oldpos = *data - start; while (ccnl_ccntlv_dehead(data, datalen, &typ, (unsigned int*) &len) == 0) { unsigned char *cp = *data, *cp2; int len2 = len; int len3; if ( (int)len > *datalen) goto Bail; switch (typ) { case CCNX_TLV_M_Name: p->nameptr = start + oldpos; while (len2 > 0) { cp2 = cp; if (ccnl_ccntlv_dehead(&cp, &len2, &typ, (unsigned int*) &len3) || (int)len>*datalen) goto Bail; switch (typ) { case CCNX_TLV_N_Chunk: // We extract the chunknum to the prefix but keep it // in the name component for now. In the future we // possibly want to remove the chunk segment from the // name components and rely on the chunknum field in // the prefix. p->chunknum = (int*) ccnl_malloc(sizeof(int)); if (ccnl_ccnltv_extractNetworkVarInt(cp, len3, (unsigned int*) p->chunknum) < 0) { DEBUGMSG_PCNX(WARNING, "Error in NetworkVarInt for chunk\n"); goto Bail; } if (p->compcnt < CCNL_MAX_NAME_COMP) { p->comp[p->compcnt] = cp2; p->complen[p->compcnt] = cp - cp2 + len3; p->compcnt++; } // else out of name component memory: skip break; case CCNX_TLV_N_NameSegment: if (p->compcnt < CCNL_MAX_NAME_COMP) { p->comp[p->compcnt] = cp2; p->complen[p->compcnt] = cp - cp2 + len3; p->compcnt++; } // else out of name component memory: skip break; case CCNX_TLV_N_Meta: if (ccnl_ccntlv_dehead(&cp, &len2, &typ, (unsigned int*) &len3) || (int)len > *datalen) { DEBUGMSG_PCNX(WARNING, "error when extracting CCNX_TLV_M_MetaData\n"); goto Bail; } break; default: break; } cp += len3; len2 -= len3; } p->namelen = *data - p->nameptr; #ifdef USE_NFN if (p->compcnt > 0 && p->complen[p->compcnt-1] == 7 && !memcmp(p->comp[p->compcnt-1], "\x00\x01\x00\x03NFN", 7)) { p->nfnflags |= CCNL_PREFIX_NFN; p->compcnt--; } #endif break; case CCNX_TLV_M_ENDChunk: if (ccnl_ccnltv_extractNetworkVarInt(cp, len, (unsigned int*) &(pkt->val.final_block_id)) < 0) { DEBUGMSG_PCNX(WARNING, "error when extracting CCNX_TLV_M_ENDChunk\n"); goto Bail; } break; case CCNX_TLV_M_Payload: pkt->content = *data; pkt->contlen = len; break; #ifdef USE_HMAC256 case CCNX_TLV_TL_ValidationAlgo: cp = *data; len2 = len; if (ccnl_ccntlv_dehead(&cp, &len2, &typ, (unsigned*) &len3) || len>*datalen) goto Bail; if (typ == CCNX_VALIDALGO_HMAC_SHA256) { // ignore keyId and other algo dependent data ... && len3 == 0) validAlgoIsHmac256 = 1; } break; case CCNX_TLV_TL_ValidationPayload: if (pkt->hmacStart && validAlgoIsHmac256 && len == 32) { pkt->hmacLen = *data - pkt->hmacStart - 4; pkt->hmacSignature = *data; } break; #endif default: break; } *data += len; *datalen -= len; oldpos = *data - start; } if (*datalen > 0) goto Bail; pkt->pfx = p; pkt->buf = ccnl_buf_new(start, *data - start); if (!pkt->buf) goto Bail; // carefully rebase ptrs to new buf because of 64bit pointers: if (pkt->content) pkt->content = pkt->buf->data + (pkt->content - start); for (i = 0; i < p->compcnt; i++) p->comp[i] = pkt->buf->data + (p->comp[i] - start); if (p->nameptr) p->nameptr = pkt->buf->data + (p->nameptr - start); #ifdef USE_HMAC256 pkt->hmacStart = pkt->buf->data + (pkt->hmacStart - start); pkt->hmacSignature = pkt->buf->data + (pkt->hmacSignature - start); #endif return pkt; Bail: free_packet(pkt); return NULL; }
char* op_builtin_find(struct ccnl_relay_s *ccnl, struct configuration_s *config, int *restart, int *halt, char *prog, char *pending, struct stack_s **stack) { int local_search = 0; struct stack_s *h; char *cp = NULL; struct ccnl_prefix_s *prefix; struct ccnl_content_s *c = NULL; if (*restart) { DEBUGMSG(DEBUG, "---to do: OP_FIND restart\n"); *restart = 0; local_search = 1; } else { DEBUGMSG(DEBUG, "---to do: OP_FIND <%s> <%s>\n", prog+7, pending); h = pop_from_stack(&config->result_stack); // if (h->type != STACK_TYPE_PREFIX) ... config->fox_state->num_of_params = 1; config->fox_state->params = ccnl_malloc(sizeof(struct ccnl_stack_s *)); config->fox_state->params[0] = h; config->fox_state->it_routable_param = 0; } prefix = config->fox_state->params[0]->content; //check if result is now available //loop by reentering (with local_search) after timeout of the interest... DEBUGMSG(DEBUG, "FIND: Checking if result was received\n"); c = ccnl_nfn_local_content_search(ccnl, config, prefix); if (!c) { struct ccnl_prefix_s *copy; struct ccnl_interest_s *interest; if (local_search) { DEBUGMSG(INFO, "FIND: no content\n"); return NULL; } //Result not in cache, search over the network // struct ccnl_interest_s *interest = mkInterestObject(ccnl, config, prefix); copy = ccnl_prefix_dup(prefix); interest = ccnl_nfn_query2interest(ccnl, ©, config); DEBUGMSG(DEBUG, "FIND: sending new interest from Face ID: %d\n", interest->from->faceid); if (interest) ccnl_interest_propagate(ccnl, interest); //wait for content, return current program to continue later *halt = -1; //set halt to -1 for async computations return ccnl_strdup(prog); } DEBUGMSG(INFO, "FIND: result was found ---> handle it (%s), prog=%s, pending=%s\n", ccnl_prefix_to_path(prefix), prog, pending); #ifdef USE_NACK /* if (!strncmp((char*)c->content, ":NACK", 5)) { DEBUGMSG(DEBUG, "NACK RECEIVED, going to next parameter\n"); ++config->fox_state->it_routable_param; return prog ? ccnl_strdup(prog) : NULL; } */ #endif prefix = ccnl_prefix_dup(prefix); push_to_stack(&config->result_stack, prefix, STACK_TYPE_PREFIX); if (pending) { DEBUGMSG(DEBUG, "Pending: %s\n", pending); cp = ccnl_strdup(pending); } return cp; }
char* op_builtin_nstrans(struct ccnl_relay_s *ccnl, struct configuration_s *config, int *restart, int *halt, char *prog, char *pending, struct stack_s **stack) { char *cp = NULL; struct stack_s *s1, *s2; DEBUGMSG(DEBUG, "---to do: OP_NSTRANS\n"); s1 = pop_or_resolve_from_result_stack(ccnl, config); if (!s1) { *halt = -1; return prog; } s2 = pop_or_resolve_from_result_stack(ccnl, config); if (!s2) { ccnl_nfn_freeStack(s1); *halt = -1; return prog; } if (s2->type == STACK_TYPE_CONST && s1->type == STACK_TYPE_PREFIX) { struct ccnl_prefix_s *p = (struct ccnl_prefix_s*) s1->content; struct const_s *con = (struct const_s *) s2->content; int suite = -1; DEBUGMSG(DEBUG, " original packet format: %s\n", con->str); if (!strcmp(con->str, "ccnb")) suite = CCNL_SUITE_CCNB; else if (!strcmp(con->str, "ccnx2014")) suite = CCNL_SUITE_CCNTLV; else if (!strcmp(con->str, "ndn2013")) suite = CCNL_SUITE_NDNTLV; if (suite < 0) goto out; DEBUGMSG(DEBUG, " >> changing PREFIX suite from %d to %d\n", p->suite, suite); p->nfnflags = 0; p->suite = suite; push_to_stack(stack, s1->content, STACK_TYPE_PREFIX); ccnl_free(s1); s1 = NULL; if (pending) { cp = ccnl_malloc(strlen(pending)+1); strcpy(cp, pending); } } else { out: *halt = -1; cp = prog; } if (s1) ccnl_nfn_freeStack(s1); ccnl_nfn_freeStack(s2); return cp; }
void ccnl_populate_cache(struct ccnl_relay_s *ccnl, char *path) { DIR *dir; struct dirent *de; int datalen; DEBUGMSG(99, "ccnl_populate_cache %s\n", path); dir = opendir(path); if (!dir) return; while ((de = readdir(dir))) { if (!fnmatch("*.ccnb", de->d_name, FNM_NOESCAPE)) { char fname[1000]; struct stat s; strcpy(fname, path); strcat(fname, "/"); strcat(fname, de->d_name); if (stat(fname, &s)) { perror("stat"); } else { struct ccnl_buf_s *buf = 0; int fd; DEBUGMSG(6, "loading file %s, %d bytes\n", de->d_name, (int) s.st_size); fd = open(fname, O_RDONLY); if (!fd) { perror("open"); continue; } buf = (struct ccnl_buf_s *) ccnl_malloc(sizeof(*buf) + s.st_size); datalen = read(fd, buf->data, s.st_size); close(fd); if (datalen == s.st_size && datalen >= 2 && buf->data[0] == 0x04 && buf->data[1] == 0x82) { struct ccnl_prefix_s *prefix = 0; struct ccnl_content_s *c = 0; struct ccnl_buf_s *nonce=0, *ppkd=0, *pkt = 0; unsigned char *content, *data = buf->data + 2; int contlen; buf->datalen = datalen; datalen -= 2; pkt = ccnl_extract_prefix_nonce_ppkd(&data, &datalen, 0, 0, 0, 0, &prefix, &nonce, &ppkd, &content, &contlen); if (!pkt) { DEBUGMSG(6, " parsing error\n"); goto Done; } if (!prefix) { DEBUGMSG(6, " no prefix error\n"); goto Done; } c = ccnl_content_new(ccnl, &pkt, &prefix, &ppkd, content, contlen); if (!c) goto Done; ccnl_content_add2cache(ccnl, c); c->flags |= CCNL_CONTENT_FLAGS_STATIC; Done: free_prefix(prefix); ccnl_free(buf); ccnl_free(pkt); ccnl_free(nonce); ccnl_free(ppkd); } else { DEBUGMSG(6, " not a content object\n"); ccnl_free(buf); } } } } }
int main(int argc, char *argv[]) { // char *private_key_path = 0; // char *witness = 0; unsigned char out[65*1024]; char *publisher = 0; char *infname = 0, *outdirname = 0, *outfname; int f, fout, contentlen = 0, opt, plen; // int suite = CCNL_SUITE_DEFAULT; int suite = CCNL_SUITE_CCNTLV; int chunk_size = CCNL_MAX_CHUNK_SIZE; struct ccnl_prefix_s *name; while ((opt = getopt(argc, argv, "hc:f:i:o:p:k:w:s:v:")) != -1) { switch (opt) { case 'c': chunk_size = atoi(optarg); if (chunk_size > CCNL_MAX_CHUNK_SIZE) { DEBUGMSG(WARNING, "max chunk size is %d (%d is to large), using max chunk size\n", CCNL_MAX_CHUNK_SIZE, chunk_size); chunk_size = CCNL_MAX_CHUNK_SIZE; } break; case 'f': outfname = optarg; break; case 'i': infname = optarg; break; case 'o': outdirname = optarg; break; /* case 'k': private_key_path = optarg; break; case 'w': witness = optarg; break; */ case 'p': publisher = optarg; plen = unescape_component(publisher); if (plen != 32) { DEBUGMSG(ERROR, "publisher key digest has wrong length (%d instead of 32)\n", plen); exit(-1); } break; case 's': suite = ccnl_str2suite(optarg); break; case 'v': #ifdef USE_LOGGING if (isdigit(optarg[0])) debug_level = atoi(optarg); else debug_level = ccnl_debug_str2level(optarg); #endif break; case 'h': default: Usage: fprintf(stderr, "Creates a chunked content object stream for the input data and writes them to stdout.\n" "usage: %s [options] URL\n" " -c SIZE size for each chunk (max %d)\n" " -f FNAME filename of the chunks when using -o\n" " -i FNAME input file (instead of stdin)\n" " -o DIR output dir (instead of stdout), filename default is cN, otherwise specify -f\n" " -p DIGEST publisher fingerprint\n" " -s SUITE (ccnb, ccnx2015, cisco2015, iot2014, ndn2013)\n" #ifdef USE_LOGGING " -v DEBUG_LEVEL (fatal, error, warning, info, debug, verbose, trace)\n" #endif , argv[0], CCNL_MAX_CHUNK_SIZE); exit(1); } } if (!ccnl_isSuite(suite)) goto Usage; // mandatory url if (!argv[optind]) goto Usage; char *url_orig = argv[optind]; char url[strlen(url_orig)]; optind++; // optional nfn char *nfnexpr = argv[optind]; int status; struct stat st_buf; if(outdirname) { // Check if outdirname is a directory and open it as a file status = stat(outdirname, &st_buf); if (status != 0) { // DEBUGMSG (ERROR, "Error (%d) when opening file %s\n", errno, outdirname); DEBUGMSG(ERROR, "Error (%d) when opening output dir %s (probaby does not exist)\n", errno, outdirname); goto Usage; } if (S_ISREG (st_buf.st_mode)) { // DEBUGMSG (ERROR, "Error: %s is a file and not a directory.\n", argv[optind]); DEBUGMSG(ERROR, "Error: output dir %s is a file and not a directory.\n", outdirname); goto Usage; } } if(infname) { // Check if outdirname is a directory and open it as a file status = stat(infname, &st_buf); if (status != 0) { // DEBUGMSG (ERROR, "Error (%d) when opening file %s\n", errno, outdirname); DEBUGMSG(ERROR, "Error (%d) when opening input file %s (probaby does not exist)\n", errno, infname); goto Usage; } if (S_ISDIR (st_buf.st_mode)) { // DEBUGMSG (ERROR, "Error: %s is a file and not a directory.\n", argv[optind]); DEBUGMSG(ERROR, "Error: input file %s is a directory and not a file.\n", infname); goto Usage; } f = open(infname, O_RDONLY); if (f < 0) { perror("file open:"); } } else { f = 0; } char default_file_name[2] = "c"; if (!outfname) { outfname = default_file_name; } else if(!outdirname) { DEBUGMSG(WARNING, "filename -f without -o output dir does nothing\n"); } char *chunk_buf; chunk_buf = ccnl_malloc(chunk_size * sizeof(unsigned char)); int chunk_len, is_last = 0, offs = -1; unsigned int chunknum = 0; char outpathname[255]; char fileext[10]; switch (suite) { case CCNL_SUITE_CCNB: strcpy(fileext, "ccnb"); break; case CCNL_SUITE_CCNTLV: strcpy(fileext, "ccntlv"); break; case CCNL_SUITE_CISTLV: strcpy(fileext, "cistlv"); break; case CCNL_SUITE_IOTTLV: strcpy(fileext, "iottlv"); break; case CCNL_SUITE_NDNTLV: strcpy(fileext, "ndntlv"); break; default: DEBUGMSG(ERROR, "fileext for suite %d not implemented\n", suite); } chunk_len = 1; chunk_len = read(f, chunk_buf, chunk_size); while (!is_last && chunk_len > 0) { if (chunk_len < chunk_size) { is_last = 1; } strcpy(url, url_orig); offs = CCNL_MAX_PACKET_SIZE; name = ccnl_URItoPrefix(url, suite, nfnexpr, &chunknum); switch (suite) { case CCNL_SUITE_CCNTLV: contentlen = ccnl_ccntlv_prependContentWithHdr(name, (unsigned char *)chunk_buf, chunk_len, is_last ? &chunknum : NULL, NULL, // int *contentpos &offs, out); break; case CCNL_SUITE_CISTLV: contentlen = ccnl_cistlv_prependContentWithHdr(name, (unsigned char *)chunk_buf, chunk_len, is_last ? &chunknum : NULL, &offs, NULL, // int *contentpos out); break; case CCNL_SUITE_IOTTLV: ccnl_iottlv_prependReply(name, (unsigned char *) chunk_buf, chunk_len, &offs, NULL, is_last ? &chunknum : NULL, out); ccnl_switch_prependCoding(CCNL_ENC_IOT2014, &offs, out); contentlen = CCNL_MAX_PACKET_SIZE - offs; break; case CCNL_SUITE_NDNTLV: contentlen = ccnl_ndntlv_prependContent(name, (unsigned char *) chunk_buf, chunk_len, NULL, is_last ? &chunknum : NULL, &offs, out); break; default: DEBUGMSG(ERROR, "produce for suite %i is not implemented\n", suite); goto Error; break; } if (outdirname) { sprintf(outpathname, "%s/%s%d.%s", outdirname, outfname, chunknum, fileext); // DEBUGMSG(INFO, "%s/%s%d.%s\n", outdirname, outfname, chunknum, fileext); DEBUGMSG(INFO, "writing chunk %d to file %s\n", chunknum, outpathname); fout = creat(outpathname, 0666); write(fout, out + offs, contentlen); close(fout); } else { DEBUGMSG(INFO, "writing chunk %d\n", chunknum); fwrite(out + offs, sizeof(unsigned char),contentlen, stdout); } chunknum++; if (!is_last) { chunk_len = read(f, chunk_buf, chunk_size); } } close(f); ccnl_free(chunk_buf); return 0; Error: close(f); ccnl_free(chunk_buf); return -1; }
struct ccnl_buf_s * ccnl_extract_prefix_nonce_ppkd(unsigned char **data, int *datalen, int *scope, int *aok, int *min, int *max, struct ccnl_prefix_s **prefix, struct ccnl_buf_s **nonce, struct ccnl_buf_s **ppkd, unsigned char **content, int *contlen) { unsigned char *start = *data - 2, *cp; int num, typ, len; struct ccnl_prefix_s *p; struct ccnl_buf_s *buf, *n = 0, *pub = 0; DEBUGMSG(99, "ccnl_extract_prefix\n"); p = (struct ccnl_prefix_s *) ccnl_calloc(1, sizeof(struct ccnl_prefix_s)); if (!p) { puts("can't get more memory from malloc, dropping ccn msg..."); return NULL; } p->comp = (unsigned char **) ccnl_malloc( CCNL_MAX_NAME_COMP * sizeof(unsigned char **)); p->complen = (int *) ccnl_malloc(CCNL_MAX_NAME_COMP * sizeof(int)); if (!p->comp || !p->complen) { puts("can't get more memory from malloc, dropping ccn msg..."); goto Bail; } while (dehead(data, datalen, &num, &typ) == 0) { if (num == 0 && typ == 0) { break; // end } if (typ == CCN_TT_DTAG) { if (num == CCN_DTAG_NAME) { while (1) { if (dehead(data, datalen, &num, &typ) != 0) { goto Bail; } if (num == 0 && typ == 0) { break; } if (typ == CCN_TT_DTAG && num == CCN_DTAG_COMPONENT && p->compcnt < CCNL_MAX_NAME_COMP) { if (hunt_for_end(data, datalen, p->comp + p->compcnt, p->complen + p->compcnt) < 0) { goto Bail; } p->compcnt++; } else { if (consume(typ, num, data, datalen, 0, 0) < 0) { goto Bail; } } } continue; } if (num == CCN_DTAG_SCOPE || num == CCN_DTAG_NONCE || num == CCN_DTAG_MINSUFFCOMP || num == CCN_DTAG_MAXSUFFCOMP || num == CCN_DTAG_PUBPUBKDIGEST) { if (hunt_for_end(data, datalen, &cp, &len) < 0) { goto Bail; } if (num == CCN_DTAG_SCOPE && len == 1 && scope) { *scope = isdigit(*cp) && (*cp < '3') ? *cp - '0' : -1; } if (num == CCN_DTAG_ANSWERORIGKIND && aok) { *aok = data2uint(cp, len); } if (num == CCN_DTAG_MINSUFFCOMP && min) { *min = data2uint(cp, len); } if (num == CCN_DTAG_MAXSUFFCOMP && max) { *max = data2uint(cp, len); } if (num == CCN_DTAG_NONCE && !n) { n = ccnl_buf_new(cp, len); } if (num == CCN_DTAG_PUBPUBKDIGEST && !pub) { pub = ccnl_buf_new(cp, len); } if (num == CCN_DTAG_EXCLUDE) { DEBUGMSG(49, "warning: 'exclude' field ignored\n"); } else { continue; } } if (num == CCN_DTAG_CONTENT || num == CCN_DTAG_CONTENTOBJ) { if (consume(typ, num, data, datalen, content, contlen) < 0) { goto Bail; } continue; } } if (consume(typ, num, data, datalen, 0, 0) < 0) { goto Bail; } } if (prefix) { p->comp[p->compcnt] = NULL; *prefix = p; } else { free_prefix(p); } if (nonce) { *nonce = n; } else { ccnl_free(n); } if (ppkd) { *ppkd = pub; } else { ccnl_free(pub); } buf = ccnl_buf_new(start, *data - start); if (!buf) { puts("can't get more memory from malloc, dropping ccn msg..."); goto Bail; } // carefully rebase ptrs to new buf because of 64bit pointers: if (content) { *content = buf->data + (*content - start); } for (num = 0; num < p->compcnt; num++) { p->comp[num] = buf->data + (p->comp[num] - start); } return buf; Bail: free_prefix(p); free_2ptr_list(n, pub); return NULL; }
// TODO: This function should probably be moved to another file to indicate that it should only be used by application level programs // and not in the ccnl core. Chunknumbers for NDNTLV are only a convention and there no specification on the packet encoding level. int ccnl_prefix_addChunkNum(struct ccnl_prefix_s *prefix, unsigned int chunknum) { if (chunknum >= 0xff) { DEBUGMSG_CPFX(WARNING, "addChunkNum is only implemented for " "chunknum smaller than 0xff (%d)\n", chunknum); return -1; } switch(prefix->suite) { #ifdef USE_SUITE_NDNTLV case CCNL_SUITE_NDNTLV: { unsigned char cmp[2]; cmp[0] = NDN_Marker_SegmentNumber; // TODO: this only works for chunknums smaller than 255 cmp[1] = chunknum; if(ccnl_prefix_appendCmp(prefix, cmp, 2) < 0) return -1; if (prefix->chunknum) ccnl_free(prefix->chunknum); prefix->chunknum = ccnl_malloc(sizeof(int)); *prefix->chunknum = chunknum; } break; #endif #ifdef USE_SUITE_CCNTLV case CCNL_SUITE_CCNTLV: { unsigned char cmp[5]; cmp[0] = 0; // TODO: this only works for chunknums smaller than 255 cmp[1] = CCNX_TLV_N_Chunk; cmp[2] = 0; cmp[3] = 1; cmp[4] = chunknum; if(ccnl_prefix_appendCmp(prefix, cmp, 5) < 0) return -1; if (prefix->chunknum) ccnl_free(prefix->chunknum); prefix->chunknum = ccnl_malloc(sizeof(int)); *prefix->chunknum = chunknum; } break; #endif #ifdef USE_SUITE_CISTLV case CCNL_SUITE_CISTLV: { unsigned char cmp[5]; // TODO: this only works for chunknums smaller than 255 cmp[0] = 0; cmp[1] = CISCO_TLV_NameSegment; cmp[2] = 0; cmp[3] = 1; cmp[4] = chunknum; if (ccnl_prefix_appendCmp(prefix, cmp, 5) < 0) return -1; if (prefix->chunknum) ccnl_free(prefix->chunknum); prefix->chunknum = ccnl_malloc(sizeof(int)); *prefix->chunknum = chunknum; } break; #endif default: DEBUGMSG_CPFX(WARNING, "add chunk number not implemented for suite %d\n", prefix->suite); return -1; } return 0; }
// turn an URI into an internal prefix (watch out: this modifies the uri string) struct ccnl_prefix_s * ccnl_URItoPrefix(char* uri, int suite, char *nfnexpr, unsigned int *chunknum) { struct ccnl_prefix_s *p; char *compvect[CCNL_MAX_NAME_COMP]; unsigned int complens[CCNL_MAX_NAME_COMP]; int cnt, i, len, tlen; DEBUGMSG_CPFX(TRACE, "ccnl_URItoPrefix(suite=%s, uri=%s, nfn=%s)\n", ccnl_suite2str(suite), uri, nfnexpr); if (strlen(uri)) cnt = ccnl_URItoComponents(compvect, complens, uri); else cnt = 0; if (nfnexpr && *nfnexpr) cnt += 1; p = ccnl_prefix_new(suite, cnt); if (!p) return NULL; for (i = 0, len = 0; i < cnt; i++) { if (i == (cnt-1) && nfnexpr && *nfnexpr) len += strlen(nfnexpr); else len += complens[i];//strlen(compvect[i]); } #ifdef USE_SUITE_CCNTLV if (suite == CCNL_SUITE_CCNTLV) len += cnt * 4; // add TL size #endif #ifdef USE_SUITE_CISTLV if (suite == CCNL_SUITE_CISTLV) len += cnt * 4; // add TL size #endif p->bytes = (unsigned char*) ccnl_malloc(len); if (!p->bytes) { free_prefix(p); return NULL; } for (i = 0, len = 0, tlen = 0; i < cnt; i++) { int isnfnfcomp = i == (cnt-1) && nfnexpr && *nfnexpr; char *cp = isnfnfcomp ? nfnexpr : (char*) compvect[i]; if (isnfnfcomp) tlen = strlen(nfnexpr); else tlen = complens[i]; p->comp[i] = p->bytes + len; tlen = ccnl_pkt_mkComponent(suite, p->comp[i], cp, tlen); p->complen[i] = tlen; len += tlen; } p->compcnt = cnt; #ifdef USE_NFN if (nfnexpr && *nfnexpr) p->nfnflags |= CCNL_PREFIX_NFN; #endif if(chunknum) { p->chunknum = ccnl_malloc(sizeof(int)); *p->chunknum = *chunknum; } return p; }
void ccnl_populate_cache(struct ccnl_relay_s *ccnl, char *path) { DIR *dir; struct dirent *de; dir = opendir(path); if (!dir) { DEBUGMSG(ERROR, "could not open directory %s\n", path); return; } DEBUGMSG(INFO, "populating cache from directory %s\n", path); while ((de = readdir(dir))) { char fname[1000]; struct stat s; struct ccnl_buf_s *buf = 0; // , *nonce=0, *ppkd=0, *pkt = 0; struct ccnl_content_s *c = 0; int fd, datalen, suite, skip; unsigned char *data; (void) data; // silence compiler warning (if any USE_SUITE_* is not set) #if defined(USE_SUITE_IOTTLV) || defined(USE_SUITE_NDNTLV) unsigned int typ; int len; #endif struct ccnl_pkt_s *pk; if (de->d_name[0] == '.') continue; strcpy(fname, path); strcat(fname, "/"); strcat(fname, de->d_name); if (stat(fname, &s)) { perror("stat"); continue; } if (S_ISDIR(s.st_mode)) continue; DEBUGMSG(INFO, "loading file %s, %d bytes\n", de->d_name, (int) s.st_size); fd = open(fname, O_RDONLY); if (!fd) { perror("open"); continue; } buf = (struct ccnl_buf_s *) ccnl_malloc(sizeof(*buf) + s.st_size); if (buf) datalen = read(fd, buf->data, s.st_size); else datalen = -1; close(fd); if (!buf || datalen != s.st_size || datalen < 2) { DEBUGMSG(WARNING, "size mismatch for file %s, %d/%d bytes\n", de->d_name, datalen, (int) s.st_size); continue; } buf->datalen = datalen; suite = ccnl_pkt2suite(buf->data, datalen, &skip); pk = NULL; switch (suite) { #ifdef USE_SUITE_CCNB case CCNL_SUITE_CCNB: { unsigned char *start; data = start = buf->data + skip; datalen -= skip; if (data[0] != 0x04 || data[1] != 0x82) goto notacontent; data += 2; datalen -= 2; pk = ccnl_ccnb_bytes2pkt(start, &data, &datalen); break; } #endif #ifdef USE_SUITE_CCNTLV case CCNL_SUITE_CCNTLV: { int hdrlen; unsigned char *start; data = start = buf->data + skip; datalen -= skip; hdrlen = ccnl_ccntlv_getHdrLen(data, datalen); data += hdrlen; datalen -= hdrlen; pk = ccnl_ccntlv_bytes2pkt(start, &data, &datalen); break; } #endif #ifdef USE_SUITE_CISTLV case CCNL_SUITE_CISTLV: { int hdrlen; unsigned char *start; data = start = buf->data + skip; datalen -= skip; hdrlen = ccnl_cistlv_getHdrLen(data, datalen); data += hdrlen; datalen -= hdrlen; pk = ccnl_cistlv_bytes2pkt(start, &data, &datalen); break; } #endif #ifdef USE_SUITE_IOTTLV case CCNL_SUITE_IOTTLV: { unsigned char *olddata; data = olddata = buf->data + skip; datalen -= skip; if (ccnl_iottlv_dehead(&data, &datalen, &typ, &len) || typ != IOT_TLV_Reply) goto notacontent; pk = ccnl_iottlv_bytes2pkt(typ, olddata, &data, &datalen); break; } #endif #ifdef USE_SUITE_NDNTLV case CCNL_SUITE_NDNTLV: { unsigned char *olddata; data = olddata = buf->data + skip; datalen -= skip; if (ccnl_ndntlv_dehead(&data, &datalen, (int*) &typ, &len) || typ != NDN_TLV_Data) goto notacontent; pk = ccnl_ndntlv_bytes2pkt(typ, olddata, &data, &datalen); break; } #endif default: DEBUGMSG(WARNING, "unknown packet format (%s)\n", de->d_name); goto Done; } if (!pk) { DEBUGMSG(DEBUG, " parsing error in %s\n", de->d_name); goto Done; } c = ccnl_content_new(ccnl, &pk); if (!c) { DEBUGMSG(WARNING, "could not create content (%s)\n", de->d_name); goto Done; } ccnl_content_add2cache(ccnl, c); c->flags |= CCNL_CONTENT_FLAGS_STATIC; Done: free_packet(pk); ccnl_free(buf); continue; #if defined(USE_SUITE_CCNB) || defined(USE_SUITE_IOTTLV) || defined(USE_SUITE_NDNTLV) notacontent: DEBUGMSG(WARNING, "not a content object (%s)\n", de->d_name); ccnl_free(buf); #endif } closedir(dir); }
int main(int argc, char *argv[]) { // char *private_key_path = 0; // char *witness = 0; uint8_t out[65*1024]; char *publisher = 0; char *infname = 0, *outdirname = 0, *outfname = 0; size_t contentlen = 0, plen; int f, fout, opt; // int suite = CCNL_SUITE_DEFAULT; int suite = CCNL_SUITE_CCNTLV; size_t chunk_size = CCNL_MAX_CHUNK_SIZE; struct ccnl_prefix_s *name; ccnl_data_opts_u data_opts; while ((opt = getopt(argc, argv, "hc:f:i:o:p:k:w:s:v:")) != -1) { switch (opt) { case 'c': chunk_size = (size_t) strtol(optarg, (char **) NULL, 10); if (chunk_size > CCNL_MAX_CHUNK_SIZE) { DEBUGMSG(WARNING, "max chunk size is %d (%zu is to large), using max chunk size\n", CCNL_MAX_CHUNK_SIZE, chunk_size); chunk_size = CCNL_MAX_CHUNK_SIZE; } break; case 'f': outfname = optarg; break; case 'i': infname = optarg; break; case 'o': outdirname = optarg; break; /* case 'k': private_key_path = optarg; break; case 'w': witness = optarg; break; */ case 'p': publisher = optarg; plen = unescape_component(publisher); if (plen != 32) { DEBUGMSG(ERROR, "publisher key digest has wrong length (%zu instead of 32)\n", plen); exit(-1); } break; case 's': suite = ccnl_str2suite(optarg); break; case 'v': #ifdef USE_LOGGING if (isdigit(optarg[0])) debug_level = (int)strtol(optarg, (char **)NULL, 10); else debug_level = ccnl_debug_str2level(optarg); #endif break; case 'h': default: Usage: fprintf(stderr, "Creates a chunked content object stream for the input data and writes them to stdout.\n" "usage: %s [options] URL\n" " -c SIZE size for each chunk (max %d)\n" " -f FNAME filename of the chunks when using -o\n" " -i FNAME input file (instead of stdin)\n" " -o DIR output dir (instead of stdout), filename default is cN, otherwise specify -f\n" " -p DIGEST publisher fingerprint\n" " -s SUITE (ccnb, ccnx2015, ndn2013)\n" #ifdef USE_LOGGING " -v DEBUG_LEVEL (fatal, error, warning, info, debug, verbose, trace)\n" #endif , argv[0], CCNL_MAX_CHUNK_SIZE); exit(1); } } if (!ccnl_isSuite(suite)) { goto Usage; } // mandatory url if (!argv[optind]) { goto Usage; } char *url_orig = argv[optind]; char url[strlen(url_orig)]; optind++; int status; struct stat st_buf; if (outdirname) { // Check if outdirname is a directory and open it as a file status = stat(outdirname, &st_buf); if (status != 0) { // DEBUGMSG (ERROR, "Error (%d) when opening file %s\n", errno, outdirname); DEBUGMSG(ERROR, "Error (%d) when opening output dir %s (probaby does not exist)\n", errno, outdirname); goto Usage; } if (S_ISREG (st_buf.st_mode)) { // DEBUGMSG (ERROR, "Error: %s is a file and not a directory.\n", argv[optind]); DEBUGMSG(ERROR, "Error: output dir %s is a file and not a directory.\n", outdirname); goto Usage; } } if (infname) { // Check if outdirname is a directory and open it as a file status = stat(infname, &st_buf); if (status != 0) { // DEBUGMSG (ERROR, "Error (%d) when opening file %s\n", errno, outdirname); DEBUGMSG(ERROR, "Error (%d) when opening input file %s (probaby does not exist)\n", errno, infname); goto Usage; } if (S_ISDIR (st_buf.st_mode)) { // DEBUGMSG (ERROR, "Error: %s is a file and not a directory.\n", argv[optind]); DEBUGMSG(ERROR, "Error: input file %s is a directory and not a file.\n", infname); goto Usage; } f = open(infname, O_RDONLY); if (f < 0) { perror("file open:"); } } else { f = 0; } char default_file_name[2] = "c"; if (!outfname) { outfname = default_file_name; } else if(!outdirname) { DEBUGMSG(WARNING, "filename -f without -o output dir does nothing\n"); } uint8_t *chunk_buf; chunk_buf = ccnl_malloc(chunk_size * sizeof(uint8_t)); if (!chunk_buf) { DEBUGMSG(ERROR, "Error: Failed to allocate memory\n"); exit(1); } size_t chunk_len; ssize_t s_chunk_len; int8_t is_last = 0; size_t offs; uint32_t chunknum = 0; char outpathname[255]; char fileext[10]; switch (suite) { case CCNL_SUITE_CCNB: strcpy(fileext, "ccnb"); break; case CCNL_SUITE_CCNTLV: strcpy(fileext, "ccntlv"); break; case CCNL_SUITE_NDNTLV: strcpy(fileext, "ndntlv"); break; default: DEBUGMSG(ERROR, "fileext for suite %d not implemented\n", suite); } FILE *fp = fopen(infname, "r"); fseek(fp, 0L, SEEK_END); long sz = ftell(fp); size_t isz; if (sz < 0) { DEBUGMSG(ERROR, "Error reading input file offset; error: %d\n", errno); exit(1); } if ((unsigned long) sz > SIZE_MAX) { DEBUGMSG(ERROR, "Input file offset exceeds bounds: %ld", sz); exit(1); } isz = (size_t) sz; rewind(fp); fclose(fp); size_t lastchunknum_s = (isz / chunk_size); if (lastchunknum_s > UINT32_MAX) { DEBUGMSG(ERROR, "lastchunknum exceeds bounds: %zu", lastchunknum_s); exit(1); } uint32_t lastchunknum = (uint32_t) lastchunknum_s; if (sz % chunk_size == 0) { --lastchunknum; } s_chunk_len = read(f, chunk_buf, chunk_size); if (s_chunk_len < 0) { DEBUGMSG(ERROR, "Error reading input file; error: %d\n", errno); exit(1); } chunk_len = (size_t) s_chunk_len; while (!is_last && chunk_len > 0) { if (chunk_len < chunk_size) { is_last = 1; } strcpy(url, url_orig); offs = CCNL_MAX_PACKET_SIZE; name = ccnl_URItoPrefix(url, suite, &chunknum); switch (suite) { case CCNL_SUITE_CCNTLV: if (ccnl_ccntlv_prependContentWithHdr(name, chunk_buf, chunk_len, &lastchunknum, //is_last ? &chunknum : NULL, NULL, // int *contentpos &offs, out, &contentlen)) { goto Error; } break; case CCNL_SUITE_NDNTLV: data_opts.ndntlv.finalblockid = lastchunknum; if (ccnl_ndntlv_prependContent(name, chunk_buf, chunk_len, NULL, &(data_opts.ndntlv),// is_last ? &chunknum : NULL, &offs, out, &contentlen)) { goto Error; } break; default: DEBUGMSG(ERROR, "produce for suite %i is not implemented\n", suite); goto Error; break; } if (outdirname) { sprintf(outpathname, "%s/%s%d.%s", outdirname, outfname, chunknum, fileext); DEBUGMSG(INFO, "writing chunk %d to file %s\n", chunknum, outpathname); fout = creat(outpathname, 0666); write(fout, out + offs, contentlen); close(fout); } else { DEBUGMSG(INFO, "writing chunk %d\n", chunknum); fwrite(out + offs, sizeof(unsigned char),contentlen, stdout); } chunknum++; if (!is_last) { s_chunk_len = read(f, chunk_buf, chunk_size); if (s_chunk_len < 0) { DEBUGMSG(ERROR, "Error reading input file; error: %d\n", errno); exit(1); } chunk_len = (size_t) s_chunk_len; } } close(f); ccnl_free(chunk_buf); return 0; Error: close(f); ccnl_free(chunk_buf); return -1; }
char* ZAM_resolvename(struct configuration_s *config, char *dummybuf, char *arg, char *contd) { struct ccnl_lambdaTerm_s *t; char res[1000], *cp = arg; int len; DEBUGMSG(DEBUG, "---to do: resolveNAME <%s>\n", arg); //function definition if (!strncmp(cp, "let", 3)) { int i, end = 0, cp2len, namelength, lambdalen; char *h, *cp2, *name, *lambda_expr, *resolveterm; DEBUGMSG(DEBUG, " fct definition: %s\n", cp); strcpy(res, cp+3); for (i = 0; i < strlen(res); ++i) { if (!strncmp(res+i, "endlet", 6)) { end = i; break; } } cp2len = strlen(res+end) + strlen("RESOLVENAME()"); h = strchr(cp, '='); namelength = h - cp; lambda_expr = ccnl_malloc(strlen(h)); name = ccnl_malloc(namelength); cp2 = ccnl_malloc(cp2len); memset(cp2, 0, cp2len); memset(name, 0, namelength); memset(lambda_expr, 0, strlen(h)); sprintf(cp2, "RESOLVENAME(%s)", res+end+7); //add 7 to overcome endlet memcpy(name, cp+3, namelength-3); //copy name without let and endlet trim(name); lambdalen = strlen(h)-strlen(cp2)+11-6; memcpy(lambda_expr, h+1, lambdalen); //copy lambda expression without = trim(lambda_expr); resolveterm = ccnl_malloc(strlen("RESOLVENAME()")+strlen(lambda_expr)); sprintf(resolveterm, "RESOLVENAME(%s)", lambda_expr); add_to_environment(&config->env, name, new_closure(resolveterm, NULL)); ccnl_free(cp); return strdup(contd); } //check if term can be made available, if yes enter it as a var //try with searching in global env for an added term! t = ccnl_lambdaStrToTerm(0, &cp, NULL); ccnl_free(arg); if (term_is_var(t)) { char *end = 0; cp = t->v; if (isdigit(*cp)) { // is disgit... int *integer = ccnl_malloc(sizeof(int)); *integer = strtol(cp, &end, 0); if (end && *end) end = 0; if (end) push_to_stack(&config->result_stack, integer, STACK_TYPE_INT); else ccnl_free(integer); } else if (*cp == '\'') { // quoted name (constant) //determine size struct const_s *con = ccnl_nfn_krivine_str2const(cp); push_to_stack(&config->result_stack, con, STACK_TYPE_CONST); end = (char*)1; } else if (iscontentname(cp)) { // is content... struct ccnl_prefix_s *prefix; prefix = ccnl_URItoPrefix(cp, config->suite, NULL, NULL); push_to_stack(&config->result_stack, prefix, STACK_TYPE_PREFIX); end = (char*)1; } if (end) { if (contd) sprintf(res, "TAILAPPLY;%s", contd); else sprintf(res, "TAILAPPLY"); } else { if (contd) sprintf(res, "ACCESS(%s);TAILAPPLY;%s", t->v, contd); else sprintf(res, "ACCESS(%s);TAILAPPLY", t->v); } ccnl_lambdaFreeTerm(t); return ccnl_strdup(res); } if (term_is_lambda(t)) { char *var; var = t->v; ccnl_lambdaTermToStr(dummybuf, t->m, 0); if (contd) sprintf(res, "GRAB(%s);RESOLVENAME(%s);%s", var, dummybuf, contd); else sprintf(res, "GRAB(%s);RESOLVENAME(%s)", var, dummybuf); ccnl_lambdaFreeTerm(t); return ccnl_strdup(res); } if (term_is_app(t)) { ccnl_lambdaTermToStr(dummybuf, t->n, 0); len = sprintf(res, "CLOSURE(RESOLVENAME(%s));", dummybuf); ccnl_lambdaTermToStr(dummybuf, t->m, 0); len += sprintf(res+len, "RESOLVENAME(%s)", dummybuf); if (contd) len += sprintf(res+len, ";%s", contd); ccnl_lambdaFreeTerm(t); return ccnl_strdup(res); } return NULL; }
struct ccnl_buf_s* ccnl_ccnb_extract(unsigned char **data, int *datalen, int *scope, int *aok, int *min, int *max, struct ccnl_prefix_s **prefix, struct ccnl_buf_s **nonce, struct ccnl_buf_s **ppkd, unsigned char **content, int *contlen) { unsigned char *start = *data - 2 /* account for outer TAG hdr */, *cp; int num, typ, len; struct ccnl_prefix_s *p; struct ccnl_buf_s *buf, *n = 0, *pub = 0; DEBUGMSG(99, "ccnl_ccnb_extract\n"); p = (struct ccnl_prefix_s *) ccnl_calloc(1, sizeof(struct ccnl_prefix_s)); if (!p) return NULL; p->comp = (unsigned char**) ccnl_malloc(CCNL_MAX_NAME_COMP * sizeof(unsigned char**)); p->complen = (int*) ccnl_malloc(CCNL_MAX_NAME_COMP * sizeof(int)); if (!p->comp || !p->complen) goto Bail; while (ccnl_ccnb_dehead(data, datalen, &num, &typ) == 0) { if (num==0 && typ==0) break; // end if (typ == CCN_TT_DTAG) { if (num == CCN_DTAG_NAME) { for (;;) { if (ccnl_ccnb_dehead(data, datalen, &num, &typ) != 0) goto Bail; if (num==0 && typ==0) break; if (typ == CCN_TT_DTAG && num == CCN_DTAG_COMPONENT && p->compcnt < CCNL_MAX_NAME_COMP) { if (ccnl_ccnb_hunt_for_end(data, datalen, p->comp + p->compcnt, p->complen + p->compcnt) < 0) goto Bail; p->compcnt++; } else { if (ccnl_ccnb_consume(typ, num, data, datalen, 0, 0) < 0) goto Bail; } } continue; } if (num == CCN_DTAG_SCOPE || num == CCN_DTAG_NONCE || num == CCN_DTAG_MINSUFFCOMP || num == CCN_DTAG_MAXSUFFCOMP || num == CCN_DTAG_PUBPUBKDIGEST) { if (ccnl_ccnb_hunt_for_end(data, datalen, &cp, &len) < 0) goto Bail; if (num == CCN_DTAG_SCOPE && len == 1 && scope) *scope = isdigit(*cp) && (*cp < '3') ? *cp - '0' : -1; if (num == CCN_DTAG_ANSWERORIGKIND && aok) *aok = ccnl_ccnb_data2uint(cp, len); if (num == CCN_DTAG_MINSUFFCOMP && min) *min = ccnl_ccnb_data2uint(cp, len); if (num == CCN_DTAG_MAXSUFFCOMP && max) *max = ccnl_ccnb_data2uint(cp, len); if (num == CCN_DTAG_NONCE && !n) n = ccnl_buf_new(cp, len); if (num == CCN_DTAG_PUBPUBKDIGEST && !pub) pub = ccnl_buf_new(cp, len); if (num == CCN_DTAG_EXCLUDE) { DEBUGMSG(49, "warning: 'exclude' field ignored\n"); } else continue; } if (num == CCN_DTAG_CONTENT) { if (ccnl_ccnb_consume(typ, num, data, datalen, content, contlen) < 0) goto Bail; continue; } } if (ccnl_ccnb_consume(typ, num, data, datalen, 0, 0) < 0) goto Bail; } if (prefix) *prefix = p; else free_prefix(p); if (nonce) *nonce = n; else ccnl_free(n); if (ppkd) *ppkd = pub; else ccnl_free(pub); buf = ccnl_buf_new(start, *data - start); // carefully rebase ptrs to new buf because of 64bit pointers: if (content) *content = buf->data + (*content - start); for (num = 0; num < p->compcnt; num++) p->comp[num] = buf->data + (p->comp[num] - start); return buf; Bail: free_prefix(p); free_2ptr_list(n, pub); return NULL; }
int ccnl_mgmt_crypto(struct ccnl_relay_s *ccnl, char *type, unsigned char *buf, int buflen) { struct ccnl_face_s *from; DEBUGMSG(DEBUG,"ccnl_crypto type: %s\n", type); if(!strcmp(type, "verify")){ int seqnum = 0; int verified = ccnl_crypto_extract_verify_reply(&buf, &buflen, &seqnum); unsigned char *msg, *msg2; char cmd[500]; int len = ccnl_crypto_extract_msg(&buf, &buflen, &msg), len2 = 0; struct ccnl_face_s *from; //DEBUGMSG(DEBUG,"VERIFIED: %d, MSG_LEN: %d\n", verified, len); int scope=3, aok=3, minsfx=0, maxsfx=CCNL_MAX_NAME_COMP, contlen; struct ccnl_buf_s *buf1 = 0, *nonce=0, *ppkd=0; struct ccnl_prefix_s *p = 0; struct ccnl_buf_s *msg2_buf; unsigned char *content = 0; msg2 = (char *) ccnl_malloc(sizeof(char) * len + 200); len2 = ccnl_ccnb_mkHeader(msg2,CCN_DTAG_NAME, CCN_TT_DTAG); memcpy(msg2+len2, msg, len); len2 +=len; msg2[len2++] = 0; from = ccnl->faces; while(from){ if(from->faceid == seqnum) break; from = from->next; } buf1 = ccnl_ccnb_extract(&msg2, &len2, &scope, &aok, &minsfx, &maxsfx, &p, &nonce, &ppkd, &content, &contlen); if (p->complen[2] < sizeof(cmd)) { memcpy(cmd, p->comp[2], p->complen[2]); cmd[p->complen[2]] = '\0'; } else strcpy(cmd, "cmd-is-too-long-to-display"); msg2_buf = ccnl_buf_new((char *)msg2, len2); ccnl_mgmt_handle(ccnl, msg2_buf, p, from, cmd, verified); ccnl_free(msg2_buf); }else if(!strcmp(type, "sign")){ char *sig = (char *) ccnl_malloc(sizeof(char)* CCNL_MAX_PACKET_SIZE); unsigned char *out; unsigned char *msg; int siglen = 0, seqnum = 0, len, len1; struct ccnl_buf_s *retbuf; ccnl_crypto_extract_sign_reply(&buf, &buflen, sig, &siglen, &seqnum); len = ccnl_crypto_extract_msg(&buf, &buflen, &msg); out = (char *) ccnl_malloc(sizeof(unsigned char)*len + sizeof(unsigned char)*siglen + 4096); len1 = ccnl_ccnb_mkHeader(out, CCN_DTAG_CONTENTOBJ, CCN_TT_DTAG); // content if(siglen > 0) len1 += ccnl_crypto_add_signature(out+len1, sig, siglen); memcpy(out+len1, msg, len); len1 +=len; out[len1++] = 0; // end-of-interest from = ccnl->faces; while(from){ if(from->faceid == seqnum) break; from = from->next; } retbuf = ccnl_buf_new((char *)out, len1); if(seqnum >= 0){ ccnl_face_enqueue(ccnl, from, retbuf); }else{ struct ccnl_prefix_s *prefix_a = 0; struct ccnl_content_s *c = 0; struct ccnl_buf_s *nonce=0, *ppkd=0, *pkt = 0; unsigned char *content = 0; char *ht = (char *) ccnl_malloc(sizeof(char)*20); int contlen; pkt = ccnl_ccnb_extract(&out, &len1, 0, 0, 0, 0, &prefix_a, &nonce, &ppkd, &content, &contlen); if (!pkt) { DEBUGMSG(WARNING, " parsing error\n"); goto Done; } if (prefix_a) { //DEBUGMSG(DEBUG, "%s", prefix_a->comp); //ccnl_free(prefix_a); } //prefix_a = (struct ccnl_prefix_s *)ccnl_malloc(sizeof(struct ccnl_prefix_s)); prefix_a->compcnt = 2; prefix_a->comp = (unsigned char **) ccnl_malloc(sizeof(unsigned char*)*2); prefix_a->comp[0] = "mgmt"; sprintf(ht, "seqnum-%d", -seqnum); prefix_a->comp[1] = ht; prefix_a->complen = (int *) ccnl_malloc(sizeof(int)*2); prefix_a->complen[0] = strlen("mgmt"); prefix_a->complen[1] = strlen(ht); c = ccnl_content_new(ccnl, CCNL_SUITE_CCNB, &pkt, &prefix_a, &ppkd, content, contlen); if (!c) goto Done; ccnl_content_serve_pending(ccnl, c); ccnl_content_add2cache(ccnl, c); } Done: ccnl_free(out); } return 0; }
void ccnl_populate_cache(struct ccnl_relay_s *ccnl, char *path, int suite) { DIR *dir; struct dirent *de; int datalen; char *suffix; DEBUGMSG(99, "ccnl_populate_cache %s\n", path); switch (suite) { #ifdef USE_SUITE_CCNB case CCNL_SUITE_CCNB: suffix = "*.ccnb"; break; #endif #ifdef USE_SUITE_NDNTLV case CCNL_SUITE_NDNTLV: suffix = "*.ndntlv"; break; #endif default: fprintf(stderr, "unknown suite and encoding, cannot populate cache.\n"); return; } dir = opendir(path); if (!dir) return; while ((de = readdir(dir))) { if (!fnmatch(suffix, de->d_name, FNM_NOESCAPE)) { char fname[1000]; struct stat s; strcpy(fname, path); strcat(fname, "/"); strcat(fname, de->d_name); if (stat(fname, &s)) { perror("stat"); } else { struct ccnl_buf_s *buf = 0; int fd; DEBUGMSG(6, "loading file %s, %d bytes\n", de->d_name, (int) s.st_size); fd = open(fname, O_RDONLY); if (!fd) { perror("open"); continue; } buf = (struct ccnl_buf_s *) ccnl_malloc(sizeof(*buf) + s.st_size); datalen = read(fd, buf->data, s.st_size); close(fd); if (datalen == s.st_size && datalen >= 2) { struct ccnl_prefix_s *prefix = 0; struct ccnl_content_s *c = 0; struct ccnl_buf_s *nonce=0, *ppkd=0, *pkt = 0; unsigned char *content, *data; int contlen, typ, len; buf->datalen = datalen; switch (suite) { #ifdef USE_SUITE_CCNB case CCNL_SUITE_CCNB: if (buf->data[0] != 0x04 || buf->data[1] != 0x82) goto notacontent; data = buf->data + 2; datalen -= 2; pkt = ccnl_ccnb_extract(&data, &datalen, 0, 0, 0, 0, &prefix, &nonce, &ppkd, &content, &contlen); break; #endif #ifdef USE_SUITE_NDNTLV case CCNL_SUITE_NDNTLV: data = buf->data; if (ccnl_ndntlv_dehead(&data, &datalen, &typ, &len) || typ != NDN_TLV_Data) goto notacontent; pkt = ccnl_ndntlv_extract(data - buf->data, &data, &datalen, 0, 0, 0, 0, &prefix, &nonce, &ppkd, &content, &contlen); break; #endif default: goto Done; } if (!pkt) { DEBUGMSG(6, " parsing error\n"); goto Done; } if (!prefix) { DEBUGMSG(6, " no prefix error\n"); goto Done; } c = ccnl_content_new(ccnl, suite, &pkt, &prefix, &ppkd, content, contlen); if (!c) goto Done; ccnl_content_add2cache(ccnl, c); c->flags |= CCNL_CONTENT_FLAGS_STATIC; Done: free_prefix(prefix); ccnl_free(buf); ccnl_free(pkt); ccnl_free(nonce); ccnl_free(ppkd); } else { notacontent: DEBUGMSG(6, " not a content object\n"); ccnl_free(buf); } } } } }
int ccnl_http_status(struct ccnl_relay_s *ccnl, struct ccnl_http_s *http) { static char txt[64000]; char *hdr = "HTTP/1.1 200 OK\n\r" "Content-Type: text/html; charset=utf-8\n\r" "Connection: close\n\r\n\r", *cp; int len = strlen(hdr), i, j, cnt; time_t t; struct utsname uts; struct ccnl_face_s *f; struct ccnl_forward_s *fwd; struct ccnl_interest_s *ipt; struct ccnl_buf_s *bpt; strcpy(txt, hdr); len += sprintf(txt+len, "<html><head><title>ccn-lite-relay status</title>\n" "<style type=\"text/css\">\n" "body {font-family: sans-serif;}\n" "</style>\n" "</head><body>\n"); len += sprintf(txt+len, "\n<table borders=0>\n<tr><td>" "<a href=\"\">[refresh]</a> <td>" "ccn-lite-relay Status Page "); uname(&uts); len += sprintf(txt+len, "node <strong>%s (%d)</strong>\n", uts.nodename, getpid()); t = time(NULL); cp = ctime(&t); cp[strlen(cp)-1] = 0; len += sprintf(txt+len, "<tr><td><td><font size=-1>%s ", cp); cp = ctime(&ccnl->startup_time); cp[strlen(cp)-1] = 0; len += sprintf(txt+len, " (started %s)</font>\n</table>\n", cp); len += sprintf(txt+len, "\n<p><table borders=0 width=100%% bgcolor=#e0e0ff>" "<tr><td><em>Forwarding Table</em></table><ul>\n"); for (fwd = ccnl->fib, cnt = 0; fwd; fwd = fwd->next, cnt++); if (cnt > 0) { struct ccnl_forward_s **fwda; fwda = (struct ccnl_forward_s**) ccnl_malloc(cnt * sizeof(fwd)); for (fwd = ccnl->fib, i = 0; fwd; fwd = fwd->next, i++) fwda[i] = fwd; qsort(fwda, cnt, sizeof(fwd), ccnl_cmpfib); for (i = 0; i < cnt; i++) { char fname[10]; sprintf(fname, "f%d", fwda[i]->face->faceid); len += sprintf(txt+len, "<li>via %4s: <font face=courier>%s</font>\n", fname, ccnl_prefix_to_path(fwda[i]->prefix)); } ccnl_free(fwda); } len += sprintf(txt+len, "</ul>\n"); len += sprintf(txt+len, "\n<p><table borders=0 width=100%% bgcolor=#e0e0ff>" "<tr><td><em>Faces</em></table><ul>\n"); for (f = ccnl->faces, cnt = 0; f; f = f->next, cnt++); if (cnt > 0) { struct ccnl_face_s **fa; fa = (struct ccnl_face_s**) ccnl_malloc(cnt * sizeof(f)); for (f = ccnl->faces, i = 0; f; f = f->next, i++) fa[i] = f; qsort(fa, cnt, sizeof(f), ccnl_cmpfaceid); for (i = 0; i < cnt; i++) { len += sprintf(txt+len, "<li><strong>f%d</strong> (via i%d) " "peer=<font face=courier>%s</font> ttl=", fa[i]->faceid, fa[i]->ifndx, ccnl_addr2ascii(&(fa[i]->peer))); if (fa[i]->flags & CCNL_FACE_FLAGS_STATIC) len += sprintf(txt+len, "static"); else len += sprintf(txt+len, "%.1fsec", fa[i]->last_used + CCNL_FACE_TIMEOUT - CCNL_NOW()); for (j = 0, bpt = fa[i]->outq; bpt; bpt = bpt->next, j++); len += sprintf(txt+len, " qlen=%d\n", j); } ccnl_free(fa); } len += sprintf(txt+len, "</ul>\n"); len += sprintf(txt+len, "\n<p><table borders=0 width=100%% bgcolor=#e0e0ff>" "<tr><td><em>Interfaces</em></table><ul>\n"); for (i = 0; i < ccnl->ifcount; i++) { len += sprintf(txt+len, "<li><strong>i%d</strong> " "addr=<font face=courier>%s</font> " "qlen=%d/%d\n", i, ccnl_addr2ascii(&ccnl->ifs[i].addr), ccnl->ifs[i].qlen, CCNL_MAX_IF_QLEN); } len += sprintf(txt+len, "</ul>\n"); len += sprintf(txt+len, "\n<p><table borders=0 width=100%% bgcolor=#e0e0ff>" "<tr><td><em>Misc stats</em></table><ul>\n"); for (cnt = 0, bpt = ccnl->nonces; bpt; bpt = bpt->next, cnt++); len += sprintf(txt+len, "<li>Nonces: %d\n", cnt); for (cnt = 0, ipt = ccnl->pit; ipt; ipt = ipt->next, cnt++); len += sprintf(txt+len, "<li>Pending interests: %d\n", cnt); len += sprintf(txt+len, "<li>Content chunks: %d (max=%d)\n", ccnl->contentcnt, ccnl->max_cache_entries); len += sprintf(txt+len, "</ul>\n"); len += sprintf(txt+len, "\n<p><table borders=0 width=100%% bgcolor=#e0e0ff>" "<tr><td><em>Config</em></table><table borders=0>\n"); len += sprintf(txt+len, "<tr><td>content.timeout:" "<td align=right> %d<td>\n", CCNL_CONTENT_TIMEOUT); len += sprintf(txt+len, "<tr><td>face.timeout:" "<td align=right> %d<td>\n", CCNL_FACE_TIMEOUT); len += sprintf(txt+len, "<tr><td>interest.maxretransmit:" "<td align=right> %d<td>\n", CCNL_MAX_INTEREST_RETRANSMIT); len += sprintf(txt+len, "<tr><td>interest.timeout:" "<td align=right> %d<td>\n", CCNL_INTEREST_TIMEOUT); len += sprintf(txt+len, "<tr><td>nonces.max:" "<td align=right> %d<td>\n", CCNL_MAX_NONCES); len += sprintf(txt+len, "<tr><td>compile.featureset:<td><td> %s\n", compile_string()); len += sprintf(txt+len, "<tr><td>compile.time:" "<td><td>%s %s\n", __DATE__, __TIME__); len += sprintf(txt+len, "<tr><td>compile.ccnl_core_version:" "<td><td>%s\n", CCNL_VERSION); len += sprintf(txt+len, "</table>\n"); len += sprintf(txt+len, "\n<p><hr></body></html>\n"); http->out = (unsigned char*) txt; http->outoffs = 0; http->outlen = len; return 0; }
// we use one extraction routine for both interest and data pkts struct ccnl_pkt_s* ccnl_cistlv_bytes2pkt(unsigned char *start, unsigned char **data, int *datalen) { struct ccnl_pkt_s *pkt; int i; unsigned int len, typ, oldpos; struct ccnl_prefix_s *p; DEBUGMSG(DEBUG, "extracting CISTLV packet (%d, %d bytes)\n", (int)(*data - start), *datalen); pkt = (struct ccnl_pkt_s*) ccnl_calloc(1, sizeof(*pkt)); if (!pkt) return NULL; pkt->pfx = p = ccnl_prefix_new(CCNL_SUITE_CISTLV, CCNL_MAX_NAME_COMP); if (!p) { ccnl_free(pkt); return NULL; } p->compcnt = 0; // We ignore the TL types of the message for now // content and interests are filled in both cases (and only one exists) // validation is ignored if (ccnl_cistlv_dehead(data, datalen, &typ, &len)) goto Bail; pkt->type = typ; pkt->suite = CCNL_SUITE_CISTLV; pkt->val.final_block_id = -1; oldpos = *data - start; while (ccnl_cistlv_dehead(data, datalen, &typ, &len) == 0) { unsigned char *cp = *data, *cp2; int len2 = len; unsigned int len3; switch (typ) { case CISCO_TLV_Name: p->nameptr = start + oldpos; while (len2 > 0) { cp2 = cp; if (ccnl_cistlv_dehead(&cp, &len2, &typ, &len3)) goto Bail; if (typ == CISCO_TLV_NameSegment) { // We extract the chunknum to the prefix but keep it in the name component for now // In the future we possibly want to remove the chunk segment from the name components // and rely on the chunknum field in the prefix. p->chunknum = (unsigned int*) ccnl_malloc(sizeof(int)); if (ccnl_cistlv_extractNetworkVarInt(cp, len2, p->chunknum) < 0) { DEBUGMSG(WARNING, "Error in NetworkVarInt for chunk\n"); goto Bail; } if (p->compcnt < CCNL_MAX_NAME_COMP) { p->comp[p->compcnt] = cp2; p->complen[p->compcnt] = cp - cp2 + len3; p->compcnt++; } // else out of name component memory: skip } else if (typ == CISCO_TLV_NameComponent) { if (p->compcnt < CCNL_MAX_NAME_COMP) { p->comp[p->compcnt] = cp2; p->complen[p->compcnt] = cp - cp2 + len3; p->compcnt++; } // else out of name component memory: skip } cp += len3; len2 -= len3; } p->namelen = *data - p->nameptr; #ifdef USE_NFN if (p->compcnt > 0 && p->complen[p->compcnt-1] == 7 && !memcmp(p->comp[p->compcnt-1], "\x00\x01\x00\x03NFN", 7)) { p->nfnflags |= CCNL_PREFIX_NFN; p->compcnt--; if (p->compcnt > 0 && p->complen[p->compcnt-1] == 9 && !memcmp(p->comp[p->compcnt-1], "\x00\x01\x00\x05THUNK", 9)) { p->nfnflags |= CCNL_PREFIX_THUNK; p->compcnt--; } } #endif break; case CISCO_TLV_FinalSegmentID: if (ccnl_cistlv_extractNetworkVarInt(cp, len2, (unsigned int*) &pkt->val.final_block_id) < 0) { DEBUGMSG(WARNING, "error when extracting CISCO_TLV_FinalSegmentID\n"); goto Bail; } break; case CISCO_TLV_ContentData: pkt->content = *data; pkt->contlen = len; break; default: break; } *data += len; *datalen -= len; oldpos = *data - start; } if (*datalen > 0) goto Bail; pkt->pfx = p; pkt->buf = ccnl_buf_new(start, *data - start); if (!pkt->buf) goto Bail; // carefully rebase ptrs to new buf because of 64bit pointers: if (pkt->content) pkt->content = pkt->buf->data + (pkt->content - start); for (i = 0; i < p->compcnt; i++) p->comp[i] = pkt->buf->data + (p->comp[i] - start); if (p->nameptr) p->nameptr = pkt->buf->data + (p->nameptr - start); return pkt; Bail: free_packet(pkt); return NULL; }