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; }
// return 1 for Reply, 0 for Request, -1 if invalid int iottlv_isReply(unsigned char *buf, int len) { int enc = 1, suite; unsigned int typ; int vallen; while (!ccnl_switch_dehead(&buf, &len, &enc)); suite = ccnl_enc2suite(enc); if (suite != CCNL_SUITE_IOTTLV) return -1; DEBUGMSG(DEBUG, "suite ok\n"); if (len < 1 || ccnl_iottlv_dehead(&buf, &len, &typ, &vallen) < 0) return -1; DEBUGMSG(DEBUG, "typ=%d, len=%d\n", typ, vallen); if (typ == IOT_TLV_Reply) return 1; if (typ == IOT_TLV_Request) return 0; return -1; }
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); }
// we use one extraction routine for both request and reply pkts struct ccnl_pkt_s* ccnl_iottlv_bytes2pkt(int pkttype, unsigned char *start, unsigned char **data, int *datalen) { struct ccnl_pkt_s *pkt; unsigned char *cp, tmp[10]; int cplen, len2; unsigned int typ, len, state; DEBUGMSG_PIOT(DEBUG, "ccnl_iottlv_extract len=%d\n", *datalen); /* { int fd = open("s.bin", O_WRONLY|O_CREAT|O_TRUNC); write(fd, *data, *datalen); close(fd); } */ pkt = (struct ccnl_pkt_s*) ccnl_calloc(1, sizeof(*pkt)); if (!pkt) return NULL; pkt->suite = CCNL_SUITE_IOTTLV; pkt->val.final_block_id = -1; pkt->s.iottlv.ttl = -1; #define IOTPS(C,L) (((C)<<4)|(L)) // parse state: combines current state while (*datalen) { if (ccnl_iottlv_dehead(data, datalen, &typ, &len)) goto Bail; state = IOTPS(pkttype, typ); DEBUGMSG_CFWD(TRACE, " state = 0x%04x\n", state); switch (state) { case IOTPS(IOT_TLV_Request, IOT_TLV_R_OptHeader): case IOTPS(IOT_TLV_Reply, IOT_TLV_R_OptHeader): { cp = *data; cplen = len; while (cplen > 0 && !ccnl_iottlv_dehead(&cp, &cplen, &typ, (unsigned int *)&len2)) { if (typ == IOT_TLV_H_HopLim && len2 == 1) { if (*cp > 0) *cp -= 1; pkt->s.iottlv.ttl = *cp; } cp += len2; cplen -= len2; } break; } case IOTPS(IOT_TLV_Request, IOT_TLV_R_Name): case IOTPS(IOT_TLV_Reply, IOT_TLV_R_Name): cp = *data; cplen = len; while (cplen > 0 && !ccnl_iottlv_dehead(&cp, &cplen, &typ, (unsigned int *)&len2)) { if (typ == IOT_TLV_N_PathName) { if (!pkt->pfx) pkt->pfx = ccnl_iottlv_parseHierarchicalName(cp, len2); if (!pkt->pfx) goto Bail; } cp += len2; cplen -= len2; } break; case IOTPS(IOT_TLV_Fragment, IOT_TLV_F_FlagsAndSeq): { uint16_t fragFields; if (len < 2) { DEBUGMSG_CFWD(DEBUG, " no flags and seqno found (%d)\n", typ); goto Bail; } fragFields = ntohs(*(uint16_t*) *data); pkt->val.seqno = fragFields & 0x7ff; pkt->flags |= (fragFields >> 14) << 2; break; } case IOTPS(IOT_TLV_Request, IOT_TLV_R_Payload): case IOTPS(IOT_TLV_Reply, IOT_TLV_R_Payload): cp = *data; cplen = len; if (!ccnl_iottlv_dehead(&cp, &cplen, &typ, (unsigned int *)&len2)) { if (typ == IOT_TLV_PL_Data) { pkt->content = cp; pkt->contlen = len2; } } break; case IOTPS(IOT_TLV_Fragment, IOT_TLV_F_Data): pkt->content = *data; pkt->contlen = len; break; /* #ifdef USE_FRAG if (ccnl_iottlv_peekType(*data, *datalen) == IOT_TLV_Fragment) { uint16_t tmp; unsigned int payloadlen; if (ccnl_iottlv_dehead(data, datalen, &typ, &len)) // IOT_TLV_Fragment return -1; if (ccnl_iottlv_dehead(data, datalen, &typ, &len)) return -1; if (typ == IOT_TLV_F_OptFragHdr) { // skip it for the time being *data += len; *datalen -= len; if (ccnl_iottlv_dehead(data, datalen, &typ, &len)) return -1; } if (typ != IOT_TLV_F_FlagsAndSeq || len < 2) { DEBUGMSG_CFWD(DEBUG, " no flags and seqrn found (%d)\n", typ); return -1; } tmp = ntohs(*(uint16_t*) *data); *data += len; *datalen -= len; if (ccnl_iottlv_dehead(data, datalen, &typ, &payloadlen)) return -1; if (typ != IOT_TLV_F_Payload) { DEBUGMSG_CFWD(DEBUG, " no payload (%d)\n", typ); return -1; } *datalen -= payloadlen; ccnl_frag_RX_Sequenced2015(ccnl_iottlv_forwarder, relay, from, relay->ifs[from->ifndx].mtu, tmp >> 14, tmp & 0x7ff, data, (int*) &payloadlen); *datalen += payloadlen; DEBUGMSG_CFWD(TRACE, " returning after fragment: %d bytes\n", *datalen); return 0; } else #endif */ default: fprintf(stderr, " iottlv unknown state 0x%04x\n", state); break; } *data += len; *datalen -= len; } if (*datalen > 0) goto Bail; // if we received a naked packet (without switch code), we need to add // a switch code when creating the packet buffer if (*start != 0x80) { len = sizeof(tmp); len2 = ccnl_switch_prependCoding(CCNL_ENC_IOT2014, (int*) &len, tmp); if (len2 < 0) { DEBUGMSG(ERROR, "prending code should not return -1\n"); len2 = 0; } start -= len2; } else len2 = 0; pkt->buf = ccnl_buf_new(start, *data - start); if (!pkt->buf) goto Bail; if (pkt->buf && len2) memcpy(pkt->buf->data, tmp + len, len2); // carefully rebase ptrs to new buf because of 64bit pointers: if (pkt->content) pkt->content = pkt->buf->data + (pkt->content - start); if (pkt->pfx) { int i; for (i = 0; i < pkt->pfx->compcnt; i++) pkt->pfx->comp[i] = pkt->buf->data + (pkt->pfx->comp[i] - start); if (pkt->pfx->nameptr) pkt->pfx->nameptr = pkt->buf->data + (pkt->pfx->nameptr - start); } return pkt; Bail: free_packet(pkt); return NULL; }