/* * This appends a tagged, valid, fully-saturated Bloom filter, useful for * excluding everything between two 'fenceposts' in an Exclude construct. */ static void append_bf_all(struct ccn_charbuf *c) { unsigned char bf_all[9] = { 3, 1, 'A', 0, 0, 0, 0, 0, 0xFF }; const struct ccn_bloom_wire *b = ccn_bloom_validate_wire(bf_all, sizeof(bf_all)); if (b == NULL) abort(); ccnb_append_tagged_blob(c, CCN_DTAG_Bloom, bf_all, sizeof(bf_all)); }
/* * This appends a tagged, valid, fully-saturated Bloom filter, useful for * excluding everything between two 'fenceposts' in an Exclude construct. */ static void append_bf_all(struct ccn_charbuf *c) { unsigned char bf_all[9] = { 3, 1, 'A', 0, 0, 0, 0, 0, 0xFF }; const struct ccn_bloom_wire *b = ccn_bloom_validate_wire(bf_all, sizeof(bf_all)); if (b == NULL) abort(); ccn_charbuf_append_tt(c, CCN_DTAG_Bloom, CCN_DTAG); ccn_charbuf_append_tt(c, sizeof(bf_all), CCN_BLOB); ccn_charbuf_append(c, bf_all, sizeof(bf_all)); ccn_charbuf_append_closer(c); }
/** * Test for a match between a ContentObject and an Interest * * @param content_object ccnb-encoded ContentObject * @param content_object_size its size in bytes * @param implicit_content_digest boolean indicating whether the * final name component is implicit (as in * the on-wire format) or explicit (as within * ccnd's content store). * @param pc Valid parse information may be provided to * speed things up. If NULL it will be * reconstructed internally. * @param interest_msg ccnb-encoded Interest * @param interest_msg_size its size in bytes * @param pi see _pc_ * * @result 1 if the ccnb-encoded content_object matches the * ccnb-encoded interest_msg, otherwise 0. */ int ccn_content_matches_interest(const unsigned char *content_object, size_t content_object_size, int implicit_content_digest, struct ccn_parsed_ContentObject *pc, const unsigned char *interest_msg, size_t interest_msg_size, const struct ccn_parsed_interest *pi) { struct ccn_parsed_ContentObject pc_store; struct ccn_parsed_interest pi_store; int res; int ncomps; int prefixstart; int prefixbytes; int namecompstart; int namecompbytes; int checkdigest = 0; struct ccn_buf_decoder decoder; struct ccn_buf_decoder *d; const unsigned char *nextcomp; size_t nextcomp_size = 0; const unsigned char *comp; size_t comp_size = 0; const unsigned char *bloom; size_t bloom_size = 0; unsigned char match_any[2] = "-"; if (pc == NULL) { res = ccn_parse_ContentObject(content_object, content_object_size, &pc_store, NULL); if (res < 0) return(0); pc = &pc_store; } if (pi == NULL) { res = ccn_parse_interest(interest_msg, interest_msg_size, &pi_store, NULL); if (res < 0) return(0); pi = &pi_store; } if (!ccn_pubid_matches(content_object, pc, interest_msg, pi)) return(0); ncomps = pc->name_ncomps + (implicit_content_digest ? 1 : 0); if (ncomps < pi->prefix_comps + pi->min_suffix_comps) return(0); if (ncomps > pi->prefix_comps + pi->max_suffix_comps) return(0); prefixstart = pi->offset[CCN_PI_B_Component0]; prefixbytes = pi->offset[CCN_PI_E_LastPrefixComponent] - prefixstart; namecompstart = pc->offset[CCN_PCO_B_Component0]; namecompbytes = pc->offset[CCN_PCO_E_ComponentLast] - namecompstart; if (prefixbytes > namecompbytes) { /* * The only way for this to be a match is if the implicit * content digest name component comes into play. */ if (implicit_content_digest && pi->offset[CCN_PI_B_LastPrefixComponent] - prefixstart == namecompbytes && (pi->offset[CCN_PI_E_LastPrefixComponent] - pi->offset[CCN_PI_B_LastPrefixComponent]) == 1 + 2 + 32 + 1) { prefixbytes = namecompbytes; checkdigest = 1; } else return(0); } if (0 != memcmp(interest_msg + prefixstart, content_object + namecompstart, prefixbytes)) return(0); if (checkdigest) { /* * The Exclude by next component is not relevant in this case, * since there is no next component present. */ ccn_digest_ContentObject(content_object, pc); d = ccn_buf_decoder_start(&decoder, interest_msg + pi->offset[CCN_PI_B_LastPrefixComponent], (pi->offset[CCN_PI_E_LastPrefixComponent] - pi->offset[CCN_PI_B_LastPrefixComponent])); comp_size = 0; if (ccn_buf_match_dtag(d, CCN_DTAG_Component)) { ccn_buf_advance(d); ccn_buf_match_blob(d, &comp, &comp_size); } if (comp_size != pc->digest_bytes) abort(); if (0 != memcmp(comp, pc->digest, comp_size)) return(0); } else if (pi->offset[CCN_PI_E_Exclude] > pi->offset[CCN_PI_B_Exclude]) { if (prefixbytes < namecompbytes) { /* pick out the next component in the content object name */ d = ccn_buf_decoder_start(&decoder, content_object + (namecompstart + prefixbytes), pc->offset[CCN_PCO_E_ComponentLast] - (namecompstart + prefixbytes)); if (ccn_buf_match_dtag(d, CCN_DTAG_Component)) { ccn_buf_advance(d); ccn_buf_match_blob(d, &nextcomp, &nextcomp_size); } else return(0); } else if (!implicit_content_digest) goto exclude_checked; else if (prefixbytes == namecompbytes) { /* use the digest name as the next component */ ccn_digest_ContentObject(content_object, pc); nextcomp_size = pc->digest_bytes; nextcomp = pc->digest; } else abort(); /* bug - should have returned already */ d = ccn_buf_decoder_start(&decoder, interest_msg + pi->offset[CCN_PI_B_Exclude], pi->offset[CCN_PI_E_Exclude] - pi->offset[CCN_PI_B_Exclude]); if (!ccn_buf_match_dtag(d, CCN_DTAG_Exclude)) abort(); ccn_buf_advance(d); bloom = NULL; bloom_size = 0; if (ccn_buf_match_dtag(d, CCN_DTAG_Any)) { ccn_buf_advance(d); bloom = match_any; ccn_buf_check_close(d); } else if (ccn_buf_match_dtag(d, CCN_DTAG_Bloom)) { ccn_buf_advance(d); if (ccn_buf_match_blob(d, &bloom, &bloom_size)) ccn_buf_advance(d); ccn_buf_check_close(d); } while (ccn_buf_match_dtag(d, CCN_DTAG_Component)) { ccn_buf_advance(d); comp_size = 0; if (ccn_buf_match_blob(d, &comp, &comp_size)) ccn_buf_advance(d); ccn_buf_check_close(d); if (comp_size > nextcomp_size) break; if (comp_size == nextcomp_size) { res = memcmp(comp, nextcomp, comp_size); if (res == 0) return(0); /* One of the explicit excludes */ if (res > 0) break; } bloom = NULL; bloom_size = 0; if (ccn_buf_match_dtag(d, CCN_DTAG_Any)) { ccn_buf_advance(d); bloom = match_any; ccn_buf_check_close(d); } else if (ccn_buf_match_dtag(d, CCN_DTAG_Bloom)) { ccn_buf_advance(d); if (ccn_buf_match_blob(d, &bloom, &bloom_size)) ccn_buf_advance(d); ccn_buf_check_close(d); } } /* * Now we have isolated the applicable filter (Any or Bloom or none). */ if (bloom == match_any) return(0); else if (bloom_size != 0) { const struct ccn_bloom_wire *f = ccn_bloom_validate_wire(bloom, bloom_size); /* If not a valid filter, treat like a false positive */ if (f == NULL) return(0); if (ccn_bloom_match_wire(f, nextcomp, nextcomp_size)) return(0); } exclude_checked: {} } /* * At this point the prefix matches and exclude-by-next-component is done. */ // test any other qualifiers here return(1); }